From de8da643a7f441fb2154818cde04b7b24ca76bb4 Mon Sep 17 00:00:00 2001 From: vsr Date: Tue, 11 Jun 2013 06:41:26 +0000 Subject: [PATCH] Merge from V6_main (dev of Anthony GEAY) 11/06/2013 --- resources/CMakeLists.txt | 1 + resources/agitateur.med | Bin 0 -> 1871934 bytes src/INTERP_KERNEL/BBTreeDst.txx | 217 + .../Bases/InterpKernelAutoPtr.hxx | 19 + src/INTERP_KERNEL/CellModel.cxx | 34 +- src/INTERP_KERNEL/CellModel.hxx | 1 + .../Geometric2D/InterpKernelGeo2DEdge.cxx | 14 + .../Geometric2D/InterpKernelGeo2DEdge.hxx | 1 + src/INTERP_KERNEL/Makefile.am | 1 + src/INTERP_KERNEL/VolSurfFormulae.hxx | 59 +- src/INTERP_KERNEL/VolSurfUser.cxx | 34 +- src/INTERP_KERNEL/VolSurfUser.hxx | 2 +- src/INTERP_KERNEL/VolSurfUser.txx | 83 +- src/MEDCalculator/CMakeLists.txt | 5 +- src/MEDCoupling/CMakeLists.txt | 4 +- src/MEDCoupling/MEDCouplingExtrudedMesh.cxx | 14 + src/MEDCoupling/MEDCouplingExtrudedMesh.hxx | 1 + .../MEDCouplingFieldDiscretization.cxx | 46 +- .../MEDCouplingFieldDiscretization.hxx | 23 +- src/MEDCoupling/MEDCouplingFieldDouble.cxx | 3 +- src/MEDCoupling/MEDCouplingMemArray.cxx | 419 +- src/MEDCoupling/MEDCouplingMemArray.hxx | 44 +- src/MEDCoupling/MEDCouplingMemArray.txx | 21 +- src/MEDCoupling/MEDCouplingMemArrayChar.cxx | 209 +- src/MEDCoupling/MEDCouplingMesh.cxx | 102 +- src/MEDCoupling/MEDCouplingMesh.hxx | 5 + src/MEDCoupling/MEDCouplingStructuredMesh.cxx | 10 + src/MEDCoupling/MEDCouplingStructuredMesh.hxx | 1 + .../MEDCouplingTimeDiscretization.cxx | 336 +- .../MEDCouplingTimeDiscretization.hxx | 394 +- src/MEDCoupling/MEDCouplingUMesh.cxx | 245 +- src/MEDCoupling/MEDCouplingUMesh.hxx | 9 +- src/MEDCoupling/MEDCouplingUMeshDesc.cxx | 5 + src/MEDCoupling/MEDCouplingUMeshDesc.hxx | 1 + .../Test/MEDCouplingBasicsTest1.cxx | 16 +- .../Test/MEDCouplingBasicsTest2.cxx | 12 + .../Test/MEDCouplingBasicsTest3.cxx | 6 +- .../Test/MEDCouplingBasicsTest5.cxx | 12 +- .../Test/MEDCouplingExamplesTest.cxx | 4 +- src/MEDCoupling_Swig/CMakeLists.txt | 4 +- src/MEDCoupling_Swig/MEDCouplingBasicsTest.py | 414 +- src/MEDCoupling_Swig/MEDCouplingCommon.i | 104 +- .../MEDCouplingExamplesTest.py | 40 +- src/MEDCoupling_Swig/MEDCouplingMemArray.i | 471 +- src/MEDCoupling_Swig/MEDCouplingNumPyTest.py | 663 ++ src/MEDCoupling_Swig/MEDCouplingNumpyTest.py | 356 - src/MEDCoupling_Swig/MEDCouplingTypemaps.i | 230 +- src/MEDCoupling_Swig/Makefile.am | 2 +- src/MEDLoader/CMakeLists.txt | 4 +- src/MEDLoader/MEDFileData.cxx | 2 +- src/MEDLoader/MEDFileField.cxx | 6345 +++++++++++------ src/MEDLoader/MEDFileField.hxx | 707 +- src/MEDLoader/MEDFileMesh.cxx | 355 +- src/MEDLoader/MEDFileMesh.hxx | 24 +- src/MEDLoader/MEDFileUtilities.cxx | 11 +- src/MEDLoader/MEDFileUtilities.hxx | 2 +- src/MEDLoader/SauvWriter.cxx | 5 +- src/MEDLoader/Swig/CMakeLists.txt | 8 +- src/MEDLoader/Swig/CaseIO.py | 31 + src/MEDLoader/Swig/CaseReader.py | 268 + src/MEDLoader/Swig/CaseWriter.py | 349 + src/MEDLoader/Swig/MEDLoaderCommon.i | 1283 ++-- .../Swig/MEDLoaderCouplingTrainingSession.py | 592 ++ src/MEDLoader/Swig/MEDLoaderDataForTest.py | 97 + src/MEDLoader/Swig/MEDLoaderSplitter.py | 115 + src/MEDLoader/Swig/MEDLoaderTest3.py | 626 +- src/MEDLoader/Swig/MEDLoaderTypemaps.i | 107 +- src/MEDLoader/Swig/Makefile.am | 4 +- src/MEDLoader/Swig/case2med | 54 + src/MEDLoader/Swig/med2case | 63 + src/MEDLoader/Test/SauvLoaderTest.cxx | 15 +- src/RENUMBER/renumbering.cxx | 6 +- 72 files changed, 11662 insertions(+), 4108 deletions(-) create mode 100644 resources/agitateur.med create mode 100644 src/INTERP_KERNEL/BBTreeDst.txx create mode 100644 src/MEDCoupling_Swig/MEDCouplingNumPyTest.py delete mode 100644 src/MEDCoupling_Swig/MEDCouplingNumpyTest.py create mode 100644 src/MEDLoader/Swig/CaseIO.py create mode 100644 src/MEDLoader/Swig/CaseReader.py create mode 100644 src/MEDLoader/Swig/CaseWriter.py create mode 100644 src/MEDLoader/Swig/MEDLoaderCouplingTrainingSession.py create mode 100644 src/MEDLoader/Swig/MEDLoaderSplitter.py create mode 100755 src/MEDLoader/Swig/case2med create mode 100755 src/MEDLoader/Swig/med2case diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index c654afba1..df326a56f 100644 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -206,6 +206,7 @@ SET(MED_RESOURCES_FILES allPillesTest.sauv BDC-714.sauv portico_3subs.sauv + agitateur.med ) IF(MED_ENABLE_GUI) diff --git a/resources/agitateur.med b/resources/agitateur.med new file mode 100644 index 0000000000000000000000000000000000000000..10529512cd8b5617385c84b10e47cf18fbe7d50a GIT binary patch literal 1871934 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

Bbx+;anZI`BV2wBVS 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 z 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%0A3;f=Fy{qrt?^*CWCl0|bPlIy~P5IaGPx@Tn z2RV7Xdf&qrw46*9X^YdB6;q#rea1{j9O_yvX8s6I5TD=?j>FH4Gd1kjbe#BCc!K!; z*Wifp_mG#9UVi{*=e>!zevW>_p?Z<+xHp?*5Tbi8CfinXyI$kzSLQnTAM0MJkhwO^IA%7O!r9R2J zgzER(63naD&%i5Q-9r5GW*_)%d(MQONXU_I5j7!r?3>->M~0iE_bw*oH%Bz++sc!` z%U0GV{e%}Fo1?FhSMj_(WZlyTJTiO?@W?Gm(Fek>6=bnHJp45y$AU*+%LY5UDF^W% z%a3tW@H+COw%vyRtbAke1ZLz3@)Cj}d2st9qz^*+;2V7)Quf1hP_)|!{Hy&U*-hB1 zY)R={-5m?(qAI-i;a@qAMB@(N(-#tehbJ3|bCgeAPv_ka_O*Hc`LXju7F~dIQil7L z&hd*$F#cEL4zc^+^}NxE@1UM4^{D?=T}{C$c)eqnjz5dOd3y@4J9MmS=$r4YyPV_? zKSafeu(zjo6?S|k+*IRUpWBWjk2;w@z4l%H^3`3TCrf>XU7+co{>Y_~7K3k7^B>xG zwpTm6o)KxD8)t8~FInYKb&N*)&eHw~9Qv{I^i3i*ZEPu{-*kB zyD#N`)ZicLkDz+kPo8sh&{CZ9YD-b{wP<+xu`lov zE5UQU)INve>9PF|wQBW!eRF0Z;^GnBqJL$@PSnpnd%$P!_c`MD_{c>+^m^IunLzI& zRxP^V?9H032jSn^zKGY}`)m6{o9NgdJo#>%H+=bD;|X->$M$82{(nTiRJup#dvSFl zQ15vCef!`m^%Y6C5|3Q)-{J}Bw~+nj&cBd82^1IwiLYOx`~Lfl@pn;be(-+d!Z{y@{X6bA zZrx4p{3qXUJR7z^i?5gFANL#IdAjCJ-8onPCfoXdTbRjucM*X;*$90JCk_DeWrIoH zF$}0Oj{usaggo4E(wi}qaQ+aW9@rCT;}Wl`)DN=gGLZC6ke=#EymAAf2_PP^mgenQ zT3^NKPQ3nvW(e`KlYNLcv;vwbgGlZ|cCs8HA4%iDPpG+Pd^+`qjYoNxa|m@SLYtcAO=((3W~4aG2aliL#ABBdFH7U8%Natk(No8; zo;nux)GrG0i`v9%V-c_V{8)g`p^CPG#l#sFmn+9&n|tt%3E>QaPwMJ12F?TF8g z_wZbqOuSo&&*mNr*+!-PXIE1^rlBv!#iI5=lh(r@K;(Cz zE)yRg(U$aEHYOa~0BGkl2ePmofqb*4FQ0q%MJU?G{IMs_q?CW#pY-L;)@0wi5m2S6 z2^2j&c%Tksqi7wGhWdjKrn>0()UWD3<&6b+_Cd!Eu(Rzv{uZlE{OxN1`3P^InBI)W zBT}AhJWv0vrhe56s17C_4z7dd~xbu zxneoRdvFalK#x9G@pX{Lfxajl8Ze1V(vWB%exV1!Yl!@&y&e64e^>>O(Dxk zm1(?4MW8NPo$yjg!sRqBw|dTvW|UXkawg`@T#`kVu8`%4RzUTE{F9XnK^Ef^0ClH0 zK-QJUZF0(&d_(=fMo=BqEIOZLK9X5{U)ag>0?5P01=<%0X*^s(AiGcd#H{Q<<2^n5 zD-`uD+c_QMdabAbK6?5gQ3V>mT^49})*|~{lpp!I8e|cf@}^pQ&ZRq^y7r!rd3Jj> z*_D_9)X~S#xbW=LSmhzB0>mrA*Mls!Q=h9V#LM?j!?+wp_0ww>5l`D?K)Y%oP-mdN zld)+ZvxGhvSLZzW%0}_Y$ew+5bT-+wC3~KScy;wz7-uhNpQ;-zNUt>UnNgGKnx;k=&8`SEkL_$-Umx-f22IRFQdShbHV1=!t@dfpRJB6Zv`~+5bf6i7vb! zvZ`GMc6RbU@QAfZf%@7`k}oeNyI91hH&9+#1CPI@c41z0J`2>cDg0umbCO?CF9K~@ zhIM#BLwehΠ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

B?86G=>341em}%b@F#DBxL~*QUxXVL%u`t%d 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 +#include + +#include +#include +#include + +template +class BBTreeDst +{ +private: + BBTreeDst* _left; + BBTreeDst* _right; + int _level; + double _max_left; + double _min_right; + const double *_bb; + std::vector _elems; + double *_terminal; + int _nbelems; + + static const int MIN_NB_ELEMS=15; + static const int MAX_LEVEL=20; +public: + BBTreeDst(const double* bbs, int* elems, int level, int nbelems): + _left(0),_right(0),_level(level),_bb(bbs),_terminal(0),_nbelems(nbelems) + { + if((nbelems < MIN_NB_ELEMS || level> MAX_LEVEL)) + _terminal=new double[2*dim]; + _elems.resize(nbelems); + for (int i=0; i(nodes, nodes+nbelems/2, nodes+nbelems); + double median = *(nodes+nbelems/2); + delete [] nodes; + std::vector new_elems_left; + std::vector new_elems_right; + + new_elems_left.reserve(nbelems/2+1); + new_elems_right.reserve(nbelems/2+1); + double max_left = -std::numeric_limits::max(); + double min_right= std::numeric_limits::max(); + for(int i=0; imedian) + { + new_elems_right.push_back(elem); + if (minmax_left) max_left = max; + } + } + _max_left=max_left; + _min_right=min_right; + int *tmp; + tmp=0; + if(!new_elems_left.empty()) + tmp=&(new_elems_left[0]); + _left=new BBTreeDst(bbs, tmp, level+1, (int)new_elems_left.size()); + tmp=0; + if(!new_elems_right.empty()) + tmp=&(new_elems_right[0]); + _right=new BBTreeDst(bbs, tmp, level+1, (int)new_elems_right.size()); + } + + ~BBTreeDst() + { + delete _left; + delete _right; + delete [] _terminal; + } + + void getElemsWhoseMinDistanceToPtSmallerThan(const double *pt, double minOfMaxDstsSq, std::vector& elems) const + { + if(_terminal) + { + for(int i=0; i<_nbelems; i++) + { + if(GetMinDistanceFromBBoxToPt(_bb+_elems[i]*2*dim,pt)minOfMaxDsts) + { _left->getElemsWhoseMinDistanceToPtSmallerThan(pt,minOfMaxDstsSq,elems); return ; } + if(pt[_level%dim]-_max_left>minOfMaxDsts) + { _right->getElemsWhoseMinDistanceToPtSmallerThan(pt,minOfMaxDstsSq,elems); return ; } + _left->getElemsWhoseMinDistanceToPtSmallerThan(pt,minOfMaxDstsSq,elems); + _right->getElemsWhoseMinDistanceToPtSmallerThan(pt,minOfMaxDstsSq,elems); + } + } + + void getMinDistanceOfMax(const double *pt, double& minOfMaxDstsSq) const + { + if(_terminal) + { + if(GetMinDistanceFromBBoxToPt(_terminal,pt)>minOfMaxDstsSq)//min it is not a bug + return ; + for(int i=0; i<_nbelems; i++) + { + minOfMaxDstsSq=std::min(minOfMaxDstsSq,GetMaxDistanceFromBBoxToPt(_bb+_elems[i]*2*dim,pt)); + } + } + else + { + double minOfMaxDsts=sqrt(minOfMaxDstsSq); + if(_min_right-pt[_level%dim]>minOfMaxDsts) + { _left->getMinDistanceOfMax(pt,minOfMaxDstsSq); return ; } + if(pt[_level%dim]-_max_left>minOfMaxDsts) + { _right->getMinDistanceOfMax(pt,minOfMaxDstsSq); return ; } + _left->getMinDistanceOfMax(pt,minOfMaxDstsSq); + _right->getMinDistanceOfMax(pt,minOfMaxDstsSq); + } + } + + void fillBBoxTerminal(const double* bbs) + { + for(int j=0;j::max(); + _terminal[2*j+1]=-std::numeric_limits::max(); + } + for(int i=0;i<_nbelems;i++) + { + for(int j=0;jmax -> no cells in this + return std::numeric_limits::max(); + + } + + static double GetMinDistanceFromBBoxToPt(const double *bbox, const double *pt) + { + if(bbox[0]<=bbox[1]) + { + double zeRes=0.; + for (int idim=0; idimmax -> no cells in this + return std::numeric_limits::max(); + } +}; + +#endif diff --git a/src/INTERP_KERNEL/Bases/InterpKernelAutoPtr.hxx b/src/INTERP_KERNEL/Bases/InterpKernelAutoPtr.hxx index a55337293..e49b4df14 100644 --- a/src/INTERP_KERNEL/Bases/InterpKernelAutoPtr.hxx +++ b/src/INTERP_KERNEL/Bases/InterpKernelAutoPtr.hxx @@ -41,6 +41,25 @@ namespace INTERP_KERNEL private: T *_ptr; }; + + template + class AutoCPtr + { + public: + AutoCPtr(T *ptr=0):_ptr(ptr) { } + ~AutoCPtr() { destroyPtr(); } + AutoCPtr &operator=(T *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 destroyPtr() { free(_ptr); } + private: + T *_ptr; + }; } #endif diff --git a/src/INTERP_KERNEL/CellModel.cxx b/src/INTERP_KERNEL/CellModel.cxx index ed283e18e..853e99e24 100644 --- a/src/INTERP_KERNEL/CellModel.cxx +++ b/src/INTERP_KERNEL/CellModel.cxx @@ -397,7 +397,7 @@ namespace INTERP_KERNEL break; case NORM_POLYGON: { - _nb_of_pts=0; _nb_of_sons=0; _dim=2; _dyn=true; _extruded_type=NORM_POLYHED; _is_simplex=false; + _nb_of_pts=0; _nb_of_sons=0; _dim=2; _dyn=true; _extruded_type=NORM_POLYHED; _is_simplex=false; _quadratic_type=NORM_QPOLYG; } break; case NORM_POLYHED: @@ -407,7 +407,7 @@ namespace INTERP_KERNEL break; case NORM_QPOLYG: { - _nb_of_pts=0; _nb_of_sons=0; _dim=2; _dyn=true; _is_simplex=false; _quadratic=true; + _nb_of_pts=0; _nb_of_sons=0; _dim=2; _dyn=true; _is_simplex=false; _quadratic=true; _linear_type=NORM_POLYGON; } break; case NORM_POLYL: @@ -449,6 +449,36 @@ namespace INTERP_KERNEL else//polyhedron return (lgth-std::count(conn,conn+lgth,-1))/2; } + + NormalizedCellType CellModel::getCorrespondingPolyType() const + { + switch(getDimension()) + { + case 0: + return NORM_POINT1; + case 1: + { + if(!isQuadratic()) + return NORM_POLYL; + throw INTERP_KERNEL::Exception("CellModel::getPolyType : no poly type for quadratic 1D !"); + } + case 2: + { + if(!isQuadratic()) + return NORM_POLYGON; + else + return NORM_QPOLYG; + } + case 3: + { + if(!isQuadratic()) + return NORM_POLYHED; + throw INTERP_KERNEL::Exception("CellModel::getPolyType : no poly type for quadratic 3D !"); + } + default: + throw INTERP_KERNEL::Exception("CellModel::getPolyType : only dimension 0, 1, 2, 3 are supported !"); + } + } /*! * Equivalent to getSonType except that this method deals with dynamic type. diff --git a/src/INTERP_KERNEL/CellModel.hxx b/src/INTERP_KERNEL/CellModel.hxx index 662df54f8..d154a2d20 100644 --- a/src/INTERP_KERNEL/CellModel.hxx +++ b/src/INTERP_KERNEL/CellModel.hxx @@ -60,6 +60,7 @@ 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 getCorrespondingPolyType() const; INTERPKERNEL_EXPORT NormalizedCellType getReverseExtrudedType() const { return _reverse_extruded_type; } INTERPKERNEL_EXPORT NormalizedCellType getLinearType() const { return _linear_type; } INTERPKERNEL_EXPORT NormalizedCellType getQuadraticType() const { return _quadratic_type; } diff --git a/src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DEdge.cxx b/src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DEdge.cxx index c1c496925..41c4240c2 100644 --- a/src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DEdge.cxx +++ b/src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DEdge.cxx @@ -542,6 +542,20 @@ void Edge::getNormalVector(double *vectOutput) const vectOutput[1]=-tmp; } +Edge *Edge::BuildEdgeFrom3Points(const double *start, const double *middle, const double *end) +{ + Node *b(new Node(start[0],start[1])),*m(new Node(middle[0],middle[1])),*e(new Node(end[0],end[1])); + EdgeLin *e1(new EdgeLin(b,m)),*e2(new EdgeLin(m,e)); + SegSegIntersector inters(*e1,*e2); bool colinearity=inters.areColinears(); delete e1; delete e2; + Edge *ret=0; + if(colinearity) + ret=new EdgeLin(b,e); + else + ret=new EdgeArcCircle(b,m,e); + b->decrRef(); m->decrRef(); e->decrRef(); + return ret; +} + Edge *Edge::BuildEdgeFrom(Node *start, Node *end) { return new EdgeLin(start,end); diff --git a/src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DEdge.hxx b/src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DEdge.hxx index b270cfa1d..d646efc3c 100644 --- a/src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DEdge.hxx +++ b/src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DEdge.hxx @@ -225,6 +225,7 @@ namespace INTERP_KERNEL static Edge *BuildEdgeFrom(Node *start, Node *end); template static Edge *BuildEdgeFrom(Node *start, Node *middle, Node *end); + static Edge *BuildEdgeFrom3Points(const double *start, const double *middle, const double *end); virtual void update(Node *m) = 0; //! returns area between this and axe Ox delimited along Ox by _start and _end. virtual double getAreaOfZone() const = 0; diff --git a/src/INTERP_KERNEL/Makefile.am b/src/INTERP_KERNEL/Makefile.am index 5f2aeb813..149a7ee2e 100644 --- a/src/INTERP_KERNEL/Makefile.am +++ b/src/INTERP_KERNEL/Makefile.am @@ -29,6 +29,7 @@ lib_LTLIBRARIES = libinterpkernel.la salomeinclude_HEADERS = \ BBTree.txx \ BBTreePts.txx \ +BBTreeDst.txx \ BoundingBox.hxx \ CellModel.hxx \ ConvexIntersector.hxx \ diff --git a/src/INTERP_KERNEL/VolSurfFormulae.hxx b/src/INTERP_KERNEL/VolSurfFormulae.hxx index 6e68ad4d1..b588ec351 100644 --- a/src/INTERP_KERNEL/VolSurfFormulae.hxx +++ b/src/INTERP_KERNEL/VolSurfFormulae.hxx @@ -23,6 +23,8 @@ #include "InterpolationUtils.hxx" #include "InterpKernelException.hxx" +#include "InterpKernelGeo2DEdgeLin.hxx" +#include "InterpKernelGeo2DEdgeArcCircle.hxx" #include "InterpKernelGeo2DQuadraticPolygon.hxx" #include @@ -52,6 +54,18 @@ namespace INTERP_KERNEL return sqrt(ret); } } + + inline double calculateLgthForSeg3(const double *begin, const double *end, const double *middle, int spaceDim) + { + if(spaceDim==2) + { + Edge *ed=Edge::BuildEdgeFrom3Points(begin,middle,end); + double ret=ed->getCurveLength(); ed->decrRef(); + return ret; + } + else + return calculateLgthForSeg2(begin,end,spaceDim); + } // =========================== // Calculate Area for triangle @@ -768,23 +782,54 @@ namespace INTERP_KERNEL bary[i]=temp/nbPts; } } - - template - inline void computePolygonBarycenter2D(const ConnType *connec, int lgth, const double *coords, double *res) + + inline void computePolygonBarycenter2DEngine(double **coords, int lgth, 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])]; + double cp=coords[i][0]*coords[(i+1)%lgth][1]-coords[i][1]*coords[(i+1)%lgth][0]; 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]+=cp*(coords[i][0]+coords[(i+1)%lgth][0]); + res[1]+=cp*(coords[i][1]+coords[(i+1)%lgth][1]); } res[0]/=3.*area; res[1]/=3.*area; } + + template + inline void computePolygonBarycenter2D(const ConnType *connec, int lgth, const double *coords, double *res) + { + double **coords2=new double *[lgth]; + for(int i=0;i(coords+2*OTT::coo2C(connec[i])); + computePolygonBarycenter2DEngine(coords2,lgth,res); + delete [] coords2; + } + + inline void computeQPolygonBarycenter2D(double **coords, int nbOfPtsInPolygs, int spaceDim, double *res) + { + if(nbOfPtsInPolygs%2==0) + { + if(spaceDim==2) + { + std::vector nodes(nbOfPtsInPolygs); + for(int i=0;igetBarycenter(res); + delete pol; + } + else + return computePolygonBarycenter2DEngine(coords,nbOfPtsInPolygs/2,res); + } + else + { + std::ostringstream oss; oss << "INTERP_KERNEL::computeQPolygonBarycenter2D : nb of points in quadratic polygon is " << nbOfPtsInPolygs << " should be even !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } } #endif diff --git a/src/INTERP_KERNEL/VolSurfUser.cxx b/src/INTERP_KERNEL/VolSurfUser.cxx index 5097e47ed..8165dd396 100644 --- a/src/INTERP_KERNEL/VolSurfUser.cxx +++ b/src/INTERP_KERNEL/VolSurfUser.cxx @@ -27,17 +27,18 @@ namespace INTERP_KERNEL { - double SquareDistanceFromPtToSegInSpaceDim2(const double *pt, const double *pt0Seg2, const double *pt1Seg2) throw(INTERP_KERNEL::Exception) + double SquareDistanceFromPtToSegInSpaceDim2(const double *pt, const double *pt0Seg2, const double *pt1Seg2, std::size_t &nbOfHint) throw(INTERP_KERNEL::Exception) { double dx=pt1Seg2[0]-pt0Seg2[0],dy=pt1Seg2[1]-pt0Seg2[1]; double norm=sqrt(dx*dx+dy*dy); if(norm==0.) - return std::numeric_limits::max(); + return (pt[0]-pt0Seg2[0])*(pt[0]-pt0Seg2[0])+(pt[1]-pt0Seg2[1])*(pt[1]-pt0Seg2[1]);//return std::numeric_limits::max(); dx/=norm; dy/=norm; double dx2=pt[0]-pt0Seg2[0],dy2=pt[1]-pt0Seg2[1]; double dotP=(dx2*dx+dy2*dy); if(dotP<0. || dotP>norm) - return std::numeric_limits::max(); + return dotP<0.?(pt[0]-pt0Seg2[0])*(pt[0]-pt0Seg2[0])+(pt[1]-pt0Seg2[1])*(pt[1]-pt0Seg2[1]):(pt[0]-pt1Seg2[0])*(pt[0]-pt1Seg2[0])+(pt[1]-pt1Seg2[1])*(pt[1]-pt1Seg2[1]); + nbOfHint++; double x=pt0Seg2[0]+dotP*dx,y=pt0Seg2[1]+dotP*dy; return (x-pt[0])*(x-pt[0])+(y-pt[1])*(y-pt[1]); } @@ -55,18 +56,16 @@ namespace INTERP_KERNEL xy[1]=matrix[4]*pt[0]+matrix[5]*pt[1]+matrix[6]*pt[2]+matrix[7]; double z=matrix[8]*pt[0]+matrix[9]*pt[1]+matrix[10]*pt[2]+matrix[11]; double ret=std::numeric_limits::max(); - int nbOfHint=0; + std::size_t nbOfHint=0; if(xy[0]>0. && xy[0]::max()) - { ret=std::min(ret,sqrt(z*z+tmp)); nbOfHint++; } - tmp=SquareDistanceFromPtToSegInSpaceDim2(xy,xy2,xy0);//distance pt to edge [pt2Tri3,pt0Tri3] - if(tmp!=std::numeric_limits::max()) - { ret=std::min(ret,sqrt(z*z+tmp)); nbOfHint++; } + { ret=std::min(ret,z*z+xy[1]*xy[1]); nbOfHint++; } //distance pt to edge [pt0Tri3,pt1Tri3] + double tmp=SquareDistanceFromPtToSegInSpaceDim2(xy,xy1,xy2,nbOfHint); //distance pt to edge [pt1Tri3,pt2Tri3] + ret=std::min(ret,z*z+tmp); + tmp=SquareDistanceFromPtToSegInSpaceDim2(xy,xy2,xy0,nbOfHint);//distance pt to edge [pt2Tri3,pt0Tri3] + ret=std::min(ret,z*z+tmp); if(nbOfHint==3) - ret=std::min(ret,fabs(z)); - return ret; + ret=std::min(ret,z*z); + return sqrt(ret); } double DistanceFromPtToPolygonInSpaceDim3(const double *pt, const int *connOfPolygonBg, const int *connOfPolygonEnd, const double *coords) throw(INTERP_KERNEL::Exception) @@ -94,13 +93,12 @@ namespace INTERP_KERNEL std::size_t nbOfHint=0; for(std::size_t i=0;i::max()) - { ret=std::min(ret,sqrt(z*z+tmp)); nbOfHint++; } + double tmp=SquareDistanceFromPtToSegInSpaceDim2(xy,((double *)ptXY)+2*i,((double *)ptXY)+2*((i+1)%nbOfEdges),nbOfHint); + ret=std::min(ret,z*z+tmp); } if(nbOfHint==nbOfEdges) - ret=std::min(ret,fabs(z)); - return ret; + ret=std::min(ret,z*z); + return sqrt(ret); } /*! diff --git a/src/INTERP_KERNEL/VolSurfUser.hxx b/src/INTERP_KERNEL/VolSurfUser.hxx index 18b0f2a2a..695d6a93c 100644 --- a/src/INTERP_KERNEL/VolSurfUser.hxx +++ b/src/INTERP_KERNEL/VolSurfUser.hxx @@ -38,7 +38,7 @@ namespace INTERP_KERNEL template void computeBarycenter2(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords, int spaceDim, double *res); - double SquareDistanceFromPtToSegInSpaceDim2(const double *pt, const double *pt0Seg2, const double *pt1Seg2) throw(INTERP_KERNEL::Exception); + double SquareDistanceFromPtToSegInSpaceDim2(const double *pt, const double *pt0Seg2, const double *pt1Seg2, std::size_t &nbOfHint) throw(INTERP_KERNEL::Exception); double DistanceFromPtToTriInSpaceDim3(const double *pt, const double *pt0Tri3, const double *pt1Tri3, const double *pt2Tri3) throw(INTERP_KERNEL::Exception); diff --git a/src/INTERP_KERNEL/VolSurfUser.txx b/src/INTERP_KERNEL/VolSurfUser.txx index df90d7ffa..4833a91b3 100644 --- a/src/INTERP_KERNEL/VolSurfUser.txx +++ b/src/INTERP_KERNEL/VolSurfUser.txx @@ -34,13 +34,19 @@ namespace INTERP_KERNEL switch(type) { case INTERP_KERNEL::NORM_SEG2 : - case INTERP_KERNEL::NORM_SEG3 : case INTERP_KERNEL::NORM_SEG4 : { 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_SEG3 : + { + int beginNode = OTT::coo2C(connec[0]); + int endNode = OTT::coo2C(connec[1]); + int middleNode = OTT::coo2C(connec[2]); + return INTERP_KERNEL::calculateLgthForSeg3(coords+(SPACEDIM*beginNode),coords+(SPACEDIM*endNode),coords+(SPACEDIM*middleNode),SPACEDIM); + } case INTERP_KERNEL::NORM_TRI3 : { int N1 = OTT::coo2C(connec[0]); @@ -115,6 +121,7 @@ namespace INTERP_KERNEL delete [] pts; return val; } + break; case INTERP_KERNEL::NORM_TETRA4 : case INTERP_KERNEL::NORM_TETRA10 : { @@ -231,7 +238,6 @@ namespace INTERP_KERNEL switch(type) { case NORM_SEG2: - case NORM_SEG3: case NORM_SEG4: { std::copy(coords+SPACEDIM*OTT::coo2C(connec[0]), @@ -240,8 +246,30 @@ namespace INTERP_KERNEL std::transform(res,res+SPACEDIM,res,std::bind2nd(std::multiplies(),0.5)); break; } + case NORM_SEG3: + { + if(SPACEDIM==2) + { + Edge *ed=Edge::BuildEdgeFrom3Points(coords+2*OTT::coo2C(connec[0]),coords+2*OTT::coo2C(connec[2]),coords+2*OTT::coo2C(connec[1])); + ed->getBarycenter(res); + ed->decrRef(); + } + else if(SPACEDIM==1) + { + *res=(coords[OTT::coo2C(connec[0])]+coords[OTT::coo2C(connec[1])])/2.; + } + else if(SPACEDIM==3) + { + 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)); + } + else + throw INTERP_KERNEL::Exception("computeBarycenter for SEG3 only SPACEDIM 1,2 or 3 supported !"); + break; + } case NORM_TRI3: - case NORM_TRI6: case NORM_TRI7: { std::copy(coords+SPACEDIM*OTT::coo2C(connec[0]), @@ -251,6 +279,25 @@ namespace INTERP_KERNEL std::transform(res,res+SPACEDIM,res,std::bind2nd(std::multiplies(),1./3.)); break; } + case NORM_TRI6: + { + if(SPACEDIM==2) + { + double *pts[6]; + pts[0] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[0])); + pts[1] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[1])); + pts[2] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[2])); + pts[3] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[3])); + pts[4] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[4])); + pts[5] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[5])); + computeQPolygonBarycenter2D(pts,6,2,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_QUAD4: case NORM_POLYGON: { @@ -265,13 +312,41 @@ namespace INTERP_KERNEL case NORM_QUAD8: { if(SPACEDIM==2) - computePolygonBarycenter2D(connec,lgth/2,coords,res); + { + double *pts[8]; + pts[0] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[0])); + pts[1] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[1])); + pts[2] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[2])); + pts[3] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[3])); + pts[4] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[4])); + pts[5] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[5])); + pts[6] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[6])); + pts[7] = const_cast(coords+SPACEDIM*OTT::coo2C(connec[7])); + computeQPolygonBarycenter2D(pts,8,2,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 INTERP_KERNEL::NORM_QPOLYG : + { + if(SPACEDIM==2) + { + double **pts=new double *[lgth]; + for(int i=0;i(coords+2*OTT::coo2C(connec[i])); + computeQPolygonBarycenter2D(pts,lgth,2,res); + delete [] pts; + } else if(SPACEDIM==3) computePolygonBarycenter3D(connec,lgth/2,coords,res); else throw INTERP_KERNEL::Exception("Impossible spacedim linked to cell 2D Cell !"); break; } + break; case NORM_TETRA4: { res[0]=coords[3*OTT::coo2C(connec[0])]; diff --git a/src/MEDCalculator/CMakeLists.txt b/src/MEDCalculator/CMakeLists.txt index ba2eab265..0cb6372d1 100644 --- a/src/MEDCalculator/CMakeLists.txt +++ b/src/MEDCalculator/CMakeLists.txt @@ -19,7 +19,10 @@ # Author : Anthony Geay (CEA/DEN) ADD_SUBDIRECTORY(Swig) -ADD_SUBDIRECTORY(Test) + +IF(CPPUNIT_IS_OK) + ADD_SUBDIRECTORY(Test) +ENDIF(CPPUNIT_IS_OK) INCLUDE_DIRECTORIES( ${MED3_INCLUDE_DIRS} diff --git a/src/MEDCoupling/CMakeLists.txt b/src/MEDCoupling/CMakeLists.txt index cb74301ca..f25bc2bf9 100644 --- a/src/MEDCoupling/CMakeLists.txt +++ b/src/MEDCoupling/CMakeLists.txt @@ -18,7 +18,9 @@ # # Author : Anthony Geay (CEA/DEN) -ADD_SUBDIRECTORY(Test) +IF(CPPUNIT_STATUS) + ADD_SUBDIRECTORY(Test) +ENDIF(CPPUNIT_STATUS) INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR}/../.. diff --git a/src/MEDCoupling/MEDCouplingExtrudedMesh.cxx b/src/MEDCoupling/MEDCouplingExtrudedMesh.cxx index 5677bbe7b..2e2b03870 100644 --- a/src/MEDCoupling/MEDCouplingExtrudedMesh.cxx +++ b/src/MEDCoupling/MEDCouplingExtrudedMesh.cxx @@ -284,6 +284,20 @@ DataArrayInt *MEDCouplingExtrudedMesh::computeNbOfNodesPerCell() const throw(INT int *pt=ret3D->getPointer(); for(int i=0;ibegin(),ret2D->end(),pt); + ret3D->applyLin(2,0,0); + return ret3D->renumberR(_mesh3D_ids->begin()); +} + +DataArrayInt *MEDCouplingExtrudedMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret2D=_mesh2D->computeNbOfNodesPerCell(); + int nbOfLevs=_mesh1D->getNumberOfCells(); + int nbOfCells2D=_mesh2D->getNumberOfCells(); + MEDCouplingAutoRefCountObjectPtr ret3D=DataArrayInt::New(); ret3D->alloc(nbOfLevs*nbOfCells2D,1); + int *pt=ret3D->getPointer(); + for(int i=0;ibegin(),ret2D->end(),pt); + ret3D->applyLin(2,2,0); return ret3D->renumberR(_mesh3D_ids->begin()); } diff --git a/src/MEDCoupling/MEDCouplingExtrudedMesh.hxx b/src/MEDCoupling/MEDCouplingExtrudedMesh.hxx index d8d9e55b3..06a5a871e 100644 --- a/src/MEDCoupling/MEDCouplingExtrudedMesh.hxx +++ b/src/MEDCoupling/MEDCouplingExtrudedMesh.hxx @@ -57,6 +57,7 @@ namespace ParaMEDMEM std::set getAllGeoTypes() const; DataArrayInt *giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception); DataArrayInt *computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception); + DataArrayInt *computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception); int getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const; void getNodeIdsOfCell(int cellId, std::vector& conn) const; void getCoordinatesOfNode(int nodeId, std::vector& coo) const throw(INTERP_KERNEL::Exception); diff --git a/src/MEDCoupling/MEDCouplingFieldDiscretization.cxx b/src/MEDCoupling/MEDCouplingFieldDiscretization.cxx index 1c99da1c2..bb7587bc3 100644 --- a/src/MEDCoupling/MEDCouplingFieldDiscretization.cxx +++ b/src/MEDCoupling/MEDCouplingFieldDiscretization.cxx @@ -497,7 +497,7 @@ DataArrayInt *MEDCouplingFieldDiscretizationP0::getOffsetArr(const MEDCouplingMe return ret; } -void MEDCouplingFieldDiscretizationP0::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector& arrays, +void MEDCouplingFieldDiscretizationP0::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector& arrays, const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception) { if(!mesh) @@ -505,13 +505,13 @@ void MEDCouplingFieldDiscretizationP0::renumberArraysForCell(const MEDCouplingMe 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++) + for(std::vector::const_iterator it=arrays.begin();it!=arrays.end();it++) { if(*it) (*it)->renumberInPlace(array); } if(check) - delete [] array; + free(const_cast(array)); } DataArrayDouble *MEDCouplingFieldDiscretizationP0::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const @@ -543,10 +543,10 @@ void MEDCouplingFieldDiscretizationP0::checkCompatibilityWithNature(NatureOfFiel { } -void MEDCouplingFieldDiscretizationP0::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception) +void MEDCouplingFieldDiscretizationP0::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception) { - if(!mesh) - throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::checkCoherencyBetween : NULL input mesh !"); + if(!mesh || !da) + throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::checkCoherencyBetween : NULL input mesh or DataArray !"); if(mesh->getNumberOfCells()!=da->getNumberOfTuples()) { std::ostringstream message; @@ -694,7 +694,7 @@ int MEDCouplingFieldDiscretizationOnNodes::getNumberOfMeshPlaces(const MEDCoupli /*! * Nothing to do here. */ -void MEDCouplingFieldDiscretizationOnNodes::renumberArraysForCell(const MEDCouplingMesh *, const std::vector& arrays, +void MEDCouplingFieldDiscretizationOnNodes::renumberArraysForCell(const MEDCouplingMesh *, const std::vector& arrays, const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception) { } @@ -732,10 +732,10 @@ void MEDCouplingFieldDiscretizationOnNodes::computeMeshRestrictionFromTupleIds(c trueTupleRestriction=ret2.retn(); } -void MEDCouplingFieldDiscretizationOnNodes::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception) +void MEDCouplingFieldDiscretizationOnNodes::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception) { - if(!mesh) - throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::checkCoherencyBetween : NULL input mesh !"); + if(!mesh || !da) + throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::checkCoherencyBetween : NULL input mesh or DataArray !"); if(mesh->getNumberOfNodes()!=da->getNumberOfTuples()) { std::ostringstream message; @@ -1005,12 +1005,12 @@ std::size_t MEDCouplingFieldDiscretizationPerCell::getHeapMemorySize() const return ret; } -void MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception) +void MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception) { if(!_discr_per_cell) throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell has no discretization per cell !"); if(!mesh) - throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween : NULL input mesh !"); + throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween : NULL input mesh or DataArray !"); 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 !"); @@ -1067,7 +1067,7 @@ void MEDCouplingFieldDiscretizationPerCell::renumberCells(const int *old2NewBg, _discr_per_cell=dpc; // if(check) - delete [] const_cast(array); + free(const_cast(array)); } void MEDCouplingFieldDiscretizationPerCell::buildDiscrPerCellIfNecessary(const MEDCouplingMesh *mesh) @@ -1297,7 +1297,7 @@ DataArrayInt *MEDCouplingFieldDiscretizationGauss::getOffsetArr(const MEDCouplin return ret.retn(); } -void MEDCouplingFieldDiscretizationGauss::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector& arrays, +void MEDCouplingFieldDiscretizationGauss::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector& arrays, const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception) { if(!mesh) @@ -1321,12 +1321,12 @@ void MEDCouplingFieldDiscretizationGauss::renumberArraysForCell(const MEDCouplin array2[j]=array3[array[i]]+k; } delete [] array3; - for(std::vector::const_iterator it=arrays.begin();it!=arrays.end();it++) + for(std::vector::const_iterator it=arrays.begin();it!=arrays.end();it++) if(*it) (*it)->renumberInPlace(array2); delete [] array2; if(check) - delete [] const_cast(array); + free(const_cast(array)); } DataArrayDouble *MEDCouplingFieldDiscretizationGauss::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const @@ -1460,10 +1460,10 @@ double MEDCouplingFieldDiscretizationGauss::getIJK(const MEDCouplingMesh *mesh, return da->getIJ(offset+nodeIdInCell,compoId); } -void MEDCouplingFieldDiscretizationGauss::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception) +void MEDCouplingFieldDiscretizationGauss::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception) { - if(!mesh) - throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::checkCoherencyBetween : NULL input mesh !"); + if(!mesh || !da) + throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::checkCoherencyBetween : NULL input mesh or DataArray !"); MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween(mesh,da); for(std::vector::const_iterator iter=_loc.begin();iter!=_loc.end();iter++) (*iter).checkCoherency(); @@ -1969,7 +1969,7 @@ DataArrayInt *MEDCouplingFieldDiscretizationGaussNE::getOffsetArr(const MEDCoupl return ret; } -void MEDCouplingFieldDiscretizationGaussNE::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector& arrays, +void MEDCouplingFieldDiscretizationGaussNE::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector& arrays, const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception) { if(!mesh) @@ -1997,12 +1997,12 @@ void MEDCouplingFieldDiscretizationGaussNE::renumberArraysForCell(const MEDCoupl array2[j]=array3[array[i]]+k; } delete [] array3; - for(std::vector::const_iterator it=arrays.begin();it!=arrays.end();it++) + for(std::vector::const_iterator it=arrays.begin();it!=arrays.end();it++) if(*it) (*it)->renumberInPlace(array2); delete [] array2; if(check) - delete [] const_cast(array); + free(const_cast(array)); } DataArrayDouble *MEDCouplingFieldDiscretizationGaussNE::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const @@ -2209,7 +2209,7 @@ double MEDCouplingFieldDiscretizationGaussNE::getIJK(const MEDCouplingMesh *mesh return da->getIJ(offset+nodeIdInCell,compoId); } -void MEDCouplingFieldDiscretizationGaussNE::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception) +void MEDCouplingFieldDiscretizationGaussNE::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception) { int nbOfTuples=getNumberOfTuples(mesh); if(nbOfTuples!=da->getNumberOfTuples()) diff --git a/src/MEDCoupling/MEDCouplingFieldDiscretization.hxx b/src/MEDCoupling/MEDCouplingFieldDiscretization.hxx index 22e40cea7..962f6fd8c 100644 --- a/src/MEDCoupling/MEDCouplingFieldDiscretization.hxx +++ b/src/MEDCoupling/MEDCouplingFieldDiscretization.hxx @@ -34,6 +34,7 @@ namespace ParaMEDMEM { + class DataArray; class DataArrayInt; class MEDCouplingMesh; class DataArrayDouble; @@ -69,10 +70,10 @@ namespace ParaMEDMEM DataArrayInt *&cellRestriction, DataArrayInt *&trueTupleRestriction) const throw(INTERP_KERNEL::Exception) = 0; virtual void checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception) = 0; virtual void renumberCells(const int *old2NewBg, bool check=true) throw(INTERP_KERNEL::Exception); - virtual void renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector& arrays, + 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 void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception) = 0; virtual MEDCouplingFieldDouble *getMeasureField(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; @@ -122,13 +123,13 @@ namespace ParaMEDMEM int getNumberOfTuples(const MEDCouplingMesh *mesh) const throw(INTERP_KERNEL::Exception); int getNumberOfMeshPlaces(const MEDCouplingMesh *mesh) const; DataArrayInt *getOffsetArr(const MEDCouplingMesh *mesh) const; - void renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector& arrays, + 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 *tupleIdsBg, const int *tupleIdsEnd, DataArrayInt *&cellRestriction, DataArrayInt *&trueTupleRestriction) const throw(INTERP_KERNEL::Exception); - void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception); + void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception); MEDCouplingFieldDouble *getMeasureField(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; @@ -151,12 +152,12 @@ namespace ParaMEDMEM int getNumberOfTuples(const MEDCouplingMesh *mesh) const throw(INTERP_KERNEL::Exception); int getNumberOfMeshPlaces(const MEDCouplingMesh *mesh) const; DataArrayInt *getOffsetArr(const MEDCouplingMesh *mesh) const; - void renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector& arrays, + 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 *tupleIdsBg, const int *tupleIdsEnd, DataArrayInt *&cellRestriction, DataArrayInt *&trueTupleRestriction) const throw(INTERP_KERNEL::Exception); - void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception); + void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception); MEDCouplingMesh *buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const; MEDCouplingMesh *buildSubMeshDataRange(const MEDCouplingMesh *mesh, int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt *&di) const; DataArrayInt *computeTupleIdsToSelectFromCellIds(const MEDCouplingMesh *mesh, const int *startCellIds, const int *endCellIds) const; @@ -205,7 +206,7 @@ namespace ParaMEDMEM ~MEDCouplingFieldDiscretizationPerCell(); void updateTime() const; std::size_t getHeapMemorySize() const; - void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArrayDouble *da) const throw(INTERP_KERNEL::Exception); + void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception); bool isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const; bool isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const; void renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception); @@ -232,7 +233,7 @@ namespace ParaMEDMEM int getNumberOfTuples(const MEDCouplingMesh *mesh) const throw(INTERP_KERNEL::Exception); int getNumberOfMeshPlaces(const MEDCouplingMesh *mesh) const; DataArrayInt *getOffsetArr(const MEDCouplingMesh *mesh) const; - void renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector& arrays, + 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 *tupleIdsBg, const int *tupleIdsEnd, @@ -244,7 +245,7 @@ namespace ParaMEDMEM 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); + void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception); MEDCouplingFieldDouble *getMeasureField(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; @@ -299,7 +300,7 @@ namespace ParaMEDMEM int getNumberOfTuples(const MEDCouplingMesh *mesh) const throw(INTERP_KERNEL::Exception); int getNumberOfMeshPlaces(const MEDCouplingMesh *mesh) const; DataArrayInt *getOffsetArr(const MEDCouplingMesh *mesh) const; - void renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector& arrays, + 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 integral(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, bool isWAbs, double *res) const throw(INTERP_KERNEL::Exception); @@ -307,7 +308,7 @@ namespace ParaMEDMEM DataArrayInt *&cellRestriction, DataArrayInt *&trueTupleRestriction) const throw(INTERP_KERNEL::Exception); 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); + void checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception); MEDCouplingFieldDouble *getMeasureField(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; diff --git a/src/MEDCoupling/MEDCouplingFieldDouble.cxx b/src/MEDCoupling/MEDCouplingFieldDouble.cxx index 4b4399ca0..b31721747 100644 --- a/src/MEDCoupling/MEDCouplingFieldDouble.cxx +++ b/src/MEDCoupling/MEDCouplingFieldDouble.cxx @@ -539,7 +539,8 @@ void MEDCouplingFieldDouble::renumberCellsWithoutMesh(const int *old2NewBg, bool _type->renumberCells(old2NewBg,check); std::vector arrays; _time_discr->getArrays(arrays); - _type->renumberArraysForCell(_mesh,arrays,old2NewBg,check); + std::vector arrays2(arrays.size()); std::copy(arrays.begin(),arrays.end(),arrays2.begin()); + _type->renumberArraysForCell(_mesh,arrays2,old2NewBg,check); // updateTime(); } diff --git a/src/MEDCoupling/MEDCouplingMemArray.cxx b/src/MEDCoupling/MEDCouplingMemArray.cxx index bdcda80b3..7c06c7702 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.cxx +++ b/src/MEDCoupling/MEDCouplingMemArray.cxx @@ -399,6 +399,32 @@ void DataArray::setInfoOnComponent(int i, const char *info) throw(INTERP_KERNEL: } } +/*! + * Sets information on all components. This method can change number of components + * at certain conditions; if the conditions are not respected, an exception is thrown. + * The number of components can be changed provided that \a this is not allocated. + * + * To know more on format of the component information see + * \ref MEDCouplingArrayBasicsCompoName "DataArrays infos". + * \param [in] info - a vector of component infos. + * \throw If \a this->getNumberOfComponents() != \a info.size() && \a this->isAllocated() + */ +void DataArray::setInfoAndChangeNbOfCompo(const std::vector& info) throw(INTERP_KERNEL::Exception) +{ + if(getNumberOfComponents()!=(int)info.size()) + { + if(!isAllocated()) + _info_on_compo=info; + else + { + std::ostringstream oss; oss << "DataArray::setInfoAndChangeNbOfCompo : input is of size " << info.size() << " whereas number of components is equal to " << getNumberOfComponents() << " and this is already allocated !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + else + _info_on_compo=info; +} + void DataArray::checkNbOfTuples(int nbOfTuples, const char *msg) const throw(INTERP_KERNEL::Exception) { if(getNumberOfTuples()!=nbOfTuples) @@ -488,6 +514,45 @@ void DataArray::CheckClosingParInRange(int ref, int value, const char *msg) thro } } +/*! + * This method is useful to slice work among a pool of threads or processes. \a begin, \a end \a step is the input whole slice of work to perform, + * typically it is a whole slice of tuples of DataArray or cells, nodes of a mesh... + * + * The input \a sliceId should be an id in [0, \a nbOfSlices) that specifies the slice of work. + * + * \param [in] start - the start of the input slice of the whole work to perform splitted into slices. + * \param [in] stop - the stop of the input slice of the whole work to perform splitted into slices. + * \param [in] step - the step (that can be <0) of the input slice of the whole work to perform splitted into slices. + * \param [in] sliceId - the slice id considered + * \param [in] nbOfSlices - the number of slices (typically the number of cores on which the work is expected to be sliced) + * \param [out] startSlice - the start of the slice considered + * \param [out] stopSlice - the stop of the slice consided + * + * \throw If \a step == 0 + * \throw If \a nbOfSlices not > 0 + * \throw If \a sliceId not in [0,nbOfSlices) + */ +void DataArray::GetSlice(int start, int stop, int step, int sliceId, int nbOfSlices, int& startSlice, int& stopSlice) throw(INTERP_KERNEL::Exception) +{ + if(nbOfSlices<=0) + { + std::ostringstream oss; oss << "DataArray::GetSlice : nbOfSlices (" << nbOfSlices << ") must be > 0 !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + if(sliceId<0 || sliceId>=nbOfSlices) + { + std::ostringstream oss; oss << "DataArray::GetSlice : sliceId (" << nbOfSlices << ") must be in [0 , nbOfSlices (" << nbOfSlices << ") ) !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + int nbElems=GetNumberOfItemGivenBESRelative(start,stop,step,"DataArray::GetSlice"); + int minNbOfElemsPerSlice=nbElems/nbOfSlices; + startSlice=start+minNbOfElemsPerSlice*step*sliceId; + if(sliceIdgetNumberOfComponents() != \a info.size() && \a this->isAllocated() - */ -void DataArrayDouble::setInfoAndChangeNbOfCompo(const std::vector& info) throw(INTERP_KERNEL::Exception) -{ - if(getNumberOfComponents()!=(int)info.size()) - { - if(!isAllocated()) - _info_on_compo=info; - else - { - std::ostringstream oss; oss << "DataArrayDouble::setInfoAndChangeNbOfCompo : input is of size " << info.size() << " whereas number of components is equal to " << getNumberOfComponents() << " and this is already allocated !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - } - else - _info_on_compo=info; -} - /*! * Returns the only one value in \a this, if and only if number of elements * (nb of tuples * nb of components) is equal to 1, and that \a this is allocated. @@ -1211,7 +1250,7 @@ DataArrayDouble *DataArrayDouble::fromNoInterlace() const throw(INTERP_KERNEL::E throw INTERP_KERNEL::Exception("DataArrayDouble::fromNoInterlace : Not defined array !"); double *tab=_mem.fromNoInterlace(getNumberOfComponents()); DataArrayDouble *ret=DataArrayDouble::New(); - ret->useArray(tab,true,CPP_DEALLOC,getNumberOfTuples(),getNumberOfComponents()); + ret->useArray(tab,true,C_DEALLOC,getNumberOfTuples(),getNumberOfComponents()); return ret; } @@ -1231,7 +1270,7 @@ DataArrayDouble *DataArrayDouble::toNoInterlace() const throw(INTERP_KERNEL::Exc throw INTERP_KERNEL::Exception("DataArrayDouble::toNoInterlace : Not defined array !"); double *tab=_mem.toNoInterlace(getNumberOfComponents()); DataArrayDouble *ret=DataArrayDouble::New(); - ret->useArray(tab,true,CPP_DEALLOC,getNumberOfTuples(),getNumberOfComponents()); + ret->useArray(tab,true,C_DEALLOC,getNumberOfTuples(),getNumberOfComponents()); return ret; } @@ -1482,7 +1521,7 @@ DataArrayDouble *DataArrayDouble::selectByTupleId2(int bg, int end2, int step) c * \throw If \a end > \a this->getNumberOfTuples(). * \throw If \a this is not allocated. */ -DataArrayDouble *DataArrayDouble::selectByTupleRanges(const std::vector >& ranges) const throw(INTERP_KERNEL::Exception) +DataArray *DataArrayDouble::selectByTupleRanges(const std::vector >& ranges) const throw(INTERP_KERNEL::Exception) { checkAllocated(); int nbOfComp=getNumberOfComponents(); @@ -1669,7 +1708,7 @@ void DataArrayDouble::transpose() throw(INTERP_KERNEL::Exception) * * \ref py_mcdataarraydouble_KeepSelectedComponents "Here is a Python example". */ -DataArrayDouble *DataArrayDouble::keepSelectedComponents(const std::vector& compoIds) const throw(INTERP_KERNEL::Exception) +DataArray *DataArrayDouble::keepSelectedComponents(const std::vector& compoIds) const throw(INTERP_KERNEL::Exception) { checkAllocated(); MEDCouplingAutoRefCountObjectPtr ret(DataArrayDouble::New()); @@ -1713,7 +1752,7 @@ void DataArrayDouble::meldWith(const DataArrayDouble *other) throw(INTERP_KERNEL throw INTERP_KERNEL::Exception("DataArrayDouble::meldWith : mismatch of number of tuples !"); int nbOfComp1=getNumberOfComponents(); int nbOfComp2=other->getNumberOfComponents(); - double *newArr=new double[nbOfTuples*(nbOfComp1+nbOfComp2)]; + double *newArr=(double *)malloc((nbOfTuples*(nbOfComp1+nbOfComp2))*sizeof(double)); double *w=newArr; const double *inp1=getConstPointer(); const double *inp2=other->getConstPointer(); @@ -1722,7 +1761,7 @@ void DataArrayDouble::meldWith(const DataArrayDouble *other) throw(INTERP_KERNEL w=std::copy(inp1,inp1+nbOfComp1,w); w=std::copy(inp2,inp2+nbOfComp2,w); } - useArray(newArr,true,CPP_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2); + useArray(newArr,true,C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2); std::vector compIds(nbOfComp2); for(int i=0;i(aBase); + if(!a) + throw INTERP_KERNEL::Exception("DataArrayDouble::setContigPartOfSelectedValues : input DataArray aBase is not a DataArrayDouble !"); checkAllocated(); a->checkAllocated(); tuplesSelec->checkAllocated(); @@ -2567,10 +2609,13 @@ void DataArrayDouble::setContigPartOfSelectedValues(int tupleIdStart, const Data * non-empty range of increasing indices or indices are out of a valid range * for the array \a a. */ -void DataArrayDouble::setContigPartOfSelectedValues2(int tupleIdStart, const DataArrayDouble *a, int bg, int end2, int step) throw(INTERP_KERNEL::Exception) +void DataArrayDouble::setContigPartOfSelectedValues2(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step) throw(INTERP_KERNEL::Exception) { + if(!aBase) + throw INTERP_KERNEL::Exception("DataArrayDouble::setContigPartOfSelectedValues2 : input DataArray is NULL !"); + const DataArrayDouble *a=dynamic_cast(aBase); if(!a) - throw INTERP_KERNEL::Exception("DataArrayDouble::setContigPartOfSelectedValues2 : input DataArrayDouble is NULL !"); + throw INTERP_KERNEL::Exception("DataArrayDouble::setContigPartOfSelectedValues2 : input DataArray aBase is not a DataArrayDouble !"); checkAllocated(); a->checkAllocated(); int nbOfComp=getNumberOfComponents(); @@ -2941,6 +2986,29 @@ double DataArrayDouble::getMinValue2(DataArrayInt*& tupleIds) const throw(INTERP return ret; } +/*! + * This method returns the number of values in \a this that are equals ( within an absolute precision of \a eps ) to input parameter \a value. + * This method only works for single component array. + * + * \return a value in [ 0, \c this->getNumberOfTuples() ) + * + * \throw If \a this is not allocated + * + */ +int DataArrayDouble::count(double value, double eps) const throw(INTERP_KERNEL::Exception) +{ + int ret=0; + checkAllocated(); + if(getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayDouble::count : must be applied on DataArrayDouble with only one component, you can call 'rearrange' method before !"); + const double *vals=begin(); + int nbOfTuples=getNumberOfTuples(); + for(int i=0;igetNumberOfTuples). + * This method is quite useful for users that need to put a field on cells to field on nodes on the same mesh without a need of conservation. + * + * \param [in] bgOfIndex - begin (included) of the input index array. + * \param [in] endOfIndex - end (excluded) of the input index array. + * \return DataArrayDouble * - the new instance having the same number of components than \a this. + * + * \throw If bgOfIndex or end is NULL. + * \throw If input index array is not ascendingly sorted. + * \throw If there is an id in [ \a bgOfIndex, \a endOfIndex ) not in [0, \c this->getNumberOfTuples). + * \throw If std::distance(bgOfIndex,endOfIndex)==0. + */ +DataArrayDouble *DataArrayDouble::accumulatePerChunck(const int *bgOfIndex, const int *endOfIndex) const throw(INTERP_KERNEL::Exception) +{ + if(!bgOfIndex || !endOfIndex) + throw INTERP_KERNEL::Exception("DataArrayDouble::accumulatePerChunck : input pointer NULL !"); + checkAllocated(); + int nbCompo=getNumberOfComponents(); + int nbOfTuples=getNumberOfTuples(); + int sz=(int)std::distance(bgOfIndex,endOfIndex); + if(sz<1) + throw INTERP_KERNEL::Exception("DataArrayDouble::accumulatePerChunck : invalid size of input index array !"); + sz--; + MEDCouplingAutoRefCountObjectPtr ret=DataArrayDouble::New(); ret->alloc(sz,nbCompo); + const int *w=bgOfIndex; + if(*w<0 || *w>=nbOfTuples) + throw INTERP_KERNEL::Exception("DataArrayDouble::accumulatePerChunck : The first element of the input index not in [0,nbOfTuples) !"); + const double *srcPt=begin()+(*w)*nbCompo; + double *tmp=ret->getPointer(); + for(int i=0;i=w[0]) + { + for(int j=w[0];j=0 && j()); + else + { + std::ostringstream oss; oss << "DataArrayDouble::accumulatePerChunck : At rank #" << i << " the input index array points to id " << j << " should be in [0," << nbOfTuples << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + } + else + { + std::ostringstream oss; oss << "DataArrayDouble::accumulatePerChunck : At rank #" << i << " the input index array is not in ascendingly sorted."; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + ret->copyStringInfoFrom(*this); + return ret.retn(); +} + /*! * Converts each 2D point defined by the tuple of \a this array from the Polar to the * Cartesian coordinate system. The two components of the tuple of \a this array are @@ -3449,19 +3577,53 @@ DataArrayDouble *DataArrayDouble::magnitude() const throw(INTERP_KERNEL::Excepti * The caller is to delete this result array using decrRef() as it is no more * needed. * \throw If \a this is not allocated. + * \sa DataArrayDouble::maxPerTupleWithCompoId */ DataArrayDouble *DataArrayDouble::maxPerTuple() const throw(INTERP_KERNEL::Exception) { checkAllocated(); int nbOfComp=getNumberOfComponents(); - DataArrayDouble *ret=DataArrayDouble::New(); + MEDCouplingAutoRefCountObjectPtr ret=DataArrayDouble::New(); int nbOfTuple=getNumberOfTuples(); ret->alloc(nbOfTuple,1); const double *src=getConstPointer(); double *dest=ret->getPointer(); for(int i=0;i ret0=DataArrayDouble::New(); + MEDCouplingAutoRefCountObjectPtr ret1=DataArrayInt::New(); + int nbOfTuple=getNumberOfTuples(); + ret0->alloc(nbOfTuple,1); ret1->alloc(nbOfTuple,1); + const double *src=getConstPointer(); + double *dest=ret0->getPointer(); int *dest1=ret1->getPointer(); + for(int i=0;igetNumberOfComponents() != \a info.size() && \a this->isAllocated() - */ -void DataArrayInt::setInfoAndChangeNbOfCompo(const std::vector& info) throw(INTERP_KERNEL::Exception) -{ - if(getNumberOfComponents()!=(int)info.size()) - { - if(!isAllocated()) - _info_on_compo=info; - else - { - std::ostringstream oss; oss << "DataArrayInt::setInfoAndChangeNbOfCompo : input is of size " << info.size() << " whereas number of components is equal to " << getNumberOfComponents() << " and this is already allocated !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - } - else - _info_on_compo=info; -} - /*! * Returns the only one value in \a this, if and only if number of elements * (nb of tuples * nb of components) is equal to 1, and that \a this is allocated. @@ -6168,7 +6304,7 @@ DataArrayInt *DataArrayInt::fromNoInterlace() const throw(INTERP_KERNEL::Excepti throw INTERP_KERNEL::Exception("DataArrayInt::fromNoInterlace : Not defined array !"); int *tab=_mem.fromNoInterlace(getNumberOfComponents()); DataArrayInt *ret=DataArrayInt::New(); - ret->useArray(tab,true,CPP_DEALLOC,getNumberOfTuples(),getNumberOfComponents()); + ret->useArray(tab,true,C_DEALLOC,getNumberOfTuples(),getNumberOfComponents()); return ret; } @@ -6189,7 +6325,7 @@ DataArrayInt *DataArrayInt::toNoInterlace() const throw(INTERP_KERNEL::Exception throw INTERP_KERNEL::Exception("DataArrayInt::toNoInterlace : Not defined array !"); int *tab=_mem.toNoInterlace(getNumberOfComponents()); DataArrayInt *ret=DataArrayInt::New(); - ret->useArray(tab,true,CPP_DEALLOC,getNumberOfTuples(),getNumberOfComponents()); + ret->useArray(tab,true,C_DEALLOC,getNumberOfTuples(),getNumberOfComponents()); return ret; } @@ -6440,7 +6576,7 @@ DataArrayInt *DataArrayInt::selectByTupleId2(int bg, int end2, int step) const t * \throw If \a end > \a this->getNumberOfTuples(). * \throw If \a this is not allocated. */ -DataArrayInt *DataArrayInt::selectByTupleRanges(const std::vector >& ranges) const throw(INTERP_KERNEL::Exception) +DataArray *DataArrayInt::selectByTupleRanges(const std::vector >& ranges) const throw(INTERP_KERNEL::Exception) { checkAllocated(); int nbOfComp=getNumberOfComponents(); @@ -6515,7 +6651,7 @@ DataArrayInt *DataArrayInt::checkAndPreparePermutation() const throw(INTERP_KERN const int *pt=getConstPointer(); int *pt2=CheckAndPreparePermutation(pt,pt+nbTuples); DataArrayInt *ret=DataArrayInt::New(); - ret->useArray(pt2,true,CPP_DEALLOC,nbTuples,1); + ret->useArray(pt2,true,C_DEALLOC,nbTuples,1); return ret; } @@ -6918,7 +7054,7 @@ void DataArrayInt::reAlloc(int nbOfTuples) throw(INTERP_KERNEL::Exception) * * \ref py_mcdataarrayint_keepselectedcomponents "Here is a Python example". */ -DataArrayInt *DataArrayInt::keepSelectedComponents(const std::vector& compoIds) const throw(INTERP_KERNEL::Exception) +DataArray *DataArrayInt::keepSelectedComponents(const std::vector& compoIds) const throw(INTERP_KERNEL::Exception) { checkAllocated(); MEDCouplingAutoRefCountObjectPtr ret(DataArrayInt::New()); @@ -6960,7 +7096,7 @@ void DataArrayInt::meldWith(const DataArrayInt *other) throw(INTERP_KERNEL::Exce throw INTERP_KERNEL::Exception("DataArrayInt::meldWith : mismatch of number of tuples !"); int nbOfComp1=getNumberOfComponents(); int nbOfComp2=other->getNumberOfComponents(); - int *newArr=new int[nbOfTuples*(nbOfComp1+nbOfComp2)]; + int *newArr=(int *)malloc(nbOfTuples*(nbOfComp1+nbOfComp2)*sizeof(int)); int *w=newArr; const int *inp1=getConstPointer(); const int *inp2=other->getConstPointer(); @@ -6969,7 +7105,7 @@ void DataArrayInt::meldWith(const DataArrayInt *other) throw(INTERP_KERNEL::Exce w=std::copy(inp1,inp1+nbOfComp1,w); w=std::copy(inp2,inp2+nbOfComp2,w); } - useArray(newArr,true,CPP_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2); + useArray(newArr,true,C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2); std::vector compIds(nbOfComp2); for(int i=0;i(aBase); + if(!a) + throw INTERP_KERNEL::Exception("DataArrayInt::setContigPartOfSelectedValues : input DataArray aBase is not a DataArrayInt !"); checkAllocated(); a->checkAllocated(); tuplesSelec->checkAllocated(); @@ -7578,8 +7719,13 @@ void DataArrayInt::setContigPartOfSelectedValues(int tupleIdStart, const DataArr * non-empty range of increasing indices or indices are out of a valid range * for the array \a a. */ -void DataArrayInt::setContigPartOfSelectedValues2(int tupleIdStart, const DataArrayInt *a, int bg, int end2, int step) throw(INTERP_KERNEL::Exception) +void DataArrayInt::setContigPartOfSelectedValues2(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step) throw(INTERP_KERNEL::Exception) { + if(!aBase) + throw INTERP_KERNEL::Exception("DataArrayInt::setContigPartOfSelectedValues2 : input DataArray is NULL !"); + const DataArrayInt *a=dynamic_cast(aBase); + if(!a) + throw INTERP_KERNEL::Exception("DataArrayInt::setContigPartOfSelectedValues2 : input DataArray aBase is not a DataArrayInt !"); checkAllocated(); a->checkAllocated(); int nbOfComp=getNumberOfComponents(); @@ -7893,6 +8039,29 @@ int DataArrayInt::locateValue(const std::vector& vals) const throw(INTERP_K return -1; } +/*! + * This method returns the number of values in \a this that are equals to input parameter \a value. + * This method only works for single component array. + * + * \return a value in [ 0, \c this->getNumberOfTuples() ) + * + * \throw If \a this is not allocated + * + */ +int DataArrayInt::count(int value) const throw(INTERP_KERNEL::Exception) +{ + int ret=0; + checkAllocated(); + if(getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayInt::count : must be applied on DataArrayInt with only one component, you can call 'rearrange' method before !"); + const int *vals=begin(); + int nbOfTuples=getNumberOfTuples(); + for(int i=0;igetNumberOfTuples). + * + * \param [in] bgOfIndex - begin (included) of the input index array. + * \param [in] endOfIndex - end (excluded) of the input index array. + * \return DataArrayInt * - the new instance having the same number of components than \a this. + * + * \throw If bgOfIndex or end is NULL. + * \throw If input index array is not ascendingly sorted. + * \throw If there is an id in [ \a bgOfIndex, \a endOfIndex ) not in [0, \c this->getNumberOfTuples). + * \throw If std::distance(bgOfIndex,endOfIndex)==0. + */ +DataArrayInt *DataArrayInt::accumulatePerChunck(const int *bgOfIndex, const int *endOfIndex) const throw(INTERP_KERNEL::Exception) +{ + if(!bgOfIndex || !endOfIndex) + throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : input pointer NULL !"); + checkAllocated(); + int nbCompo=getNumberOfComponents(); + int nbOfTuples=getNumberOfTuples(); + int sz=(int)std::distance(bgOfIndex,endOfIndex); + if(sz<1) + throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : invalid size of input index array !"); + sz--; + MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); ret->alloc(sz,nbCompo); + const int *w=bgOfIndex; + if(*w<0 || *w>=nbOfTuples) + throw INTERP_KERNEL::Exception("DataArrayInt::accumulatePerChunck : The first element of the input index not in [0,nbOfTuples) !"); + const int *srcPt=begin()+(*w)*nbCompo; + int *tmp=ret->getPointer(); + for(int i=0;i=w[0]) + { + for(int j=w[0];j=0 && j()); + else + { + std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array points to id " << j << " should be in [0," << nbOfTuples << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + } + else + { + std::ostringstream oss; oss << "DataArrayInt::accumulatePerChunck : At rank #" << i << " the input index array is not in ascendingly sorted."; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + ret->copyStringInfoFrom(*this); + return ret.retn(); +} + /*! * Returns a new DataArrayInt by concatenating two given arrays, so that (1) the number * of tuples in the result array is a1->getNumberOfTuples() + a2->getNumberOfTuples() - @@ -8039,7 +8267,7 @@ DataArrayInt *DataArrayInt::Aggregate(const std::vector& a /*! * Returns the maximal value and its location within \a this one-dimensional array. * \param [out] tupleId - index of the tuple holding the maximal value. - * \return double - the maximal value among all values of \a this array. + * \return int - the maximal value among all values of \a this array. * \throw If \a this->getNumberOfComponents() != 1 * \throw If \a this->getNumberOfTuples() < 1 */ @@ -8246,8 +8474,8 @@ void DataArrayInt::applyModulus(int val) throw(INTERP_KERNEL::Exception) * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that * this[*id] in [\b vmin,\b vmax) * - * \param [in] vmin begin of range. This value is included in range. - * \param [out] vmax end of range. This value is \b not included in range. + * \param [in] vmin begin of range. This value is included in range (included). + * \param [out] vmax end of range. This value is \b not included in range (excluded). * \return a newly allocated data array that the caller should deal with. */ DataArrayInt *DataArrayInt::getIdsInRange(int vmin, int vmax) const throw(INTERP_KERNEL::Exception) @@ -8518,14 +8746,13 @@ DataArrayInt *DataArrayInt::MakePartition(const std::vectorgetNumberOfComponents() != 1. - * \throw If any value of \a arr[i] is negative. */ DataArrayInt *DataArrayInt::BuildUnion(const std::vector& arr) throw(INTERP_KERNEL::Exception) { @@ -8533,17 +8760,12 @@ DataArrayInt *DataArrayInt::BuildUnion(const std::vector& for(std::vector::const_iterator it4=arr.begin();it4!=arr.end();it4++) if(*it4) a.push_back(*it4); - int valm=std::numeric_limits::max(); for(std::vector::const_iterator it=a.begin();it!=a.end();it++) { (*it)->checkAllocated(); if((*it)->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception("DataArrayInt::BuildUnion : only single component allowed !"); - int tmp1; - valm=std::min((*it)->getMinValue(tmp1),valm); } - if(valm<0) - throw INTERP_KERNEL::Exception("DataArrayInt::BuildUnion : a negative value has been detected !"); // std::set r; for(std::vector::const_iterator it=a.begin();it!=a.end();it++) @@ -8560,14 +8782,13 @@ DataArrayInt *DataArrayInt::BuildUnion(const std::vector& /*! * Returns a new DataArrayInt which contains elements present in each of given one-dimensional - * not negative arrays. The result array does not contain any duplicates and its values + * arrays. The result array does not contain any duplicates and its values * are sorted in ascending order. * \param [in] arr - sequence of DataArrayInt's to intersect. * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this * array using decrRef() as it is no more needed. * \throw If any \a arr[i] is not allocated. * \throw If \a arr[i]->getNumberOfComponents() != 1. - * \throw If any value of \a arr[i] < 0. */ DataArrayInt *DataArrayInt::BuildIntersection(const std::vector& arr) throw(INTERP_KERNEL::Exception) { @@ -8575,17 +8796,12 @@ DataArrayInt *DataArrayInt::BuildIntersection(const std::vector::const_iterator it4=arr.begin();it4!=arr.end();it4++) if(*it4) a.push_back(*it4); - int valm=std::numeric_limits::max(); for(std::vector::const_iterator it=a.begin();it!=a.end();it++) { (*it)->checkAllocated(); if((*it)->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception("DataArrayInt::BuildIntersection : only single component allowed !"); - int tmp1; - valm=std::min((*it)->getMinValue(tmp1),valm); } - if(valm<0) - throw INTERP_KERNEL::Exception("DataArrayInt::BuildIntersection : a negative value has been detected !"); // std::set r; for(std::vector::const_iterator it=a.begin();it!=a.end();it++) @@ -8711,7 +8927,7 @@ DataArrayInt *DataArrayInt::buildSubstractionOptimized(const DataArrayInt *other /*! * Returns a new DataArrayInt which contains all elements of \a this and a given - * one-dimensional not negative arrays. The result array does not contain any duplicates + * one-dimensional arrays. The result array does not contain any duplicates * and its values are sorted in ascending order. * \param [in] other - an array to unite with \a this one. * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this @@ -8719,7 +8935,6 @@ DataArrayInt *DataArrayInt::buildSubstractionOptimized(const DataArrayInt *other * \throw If \a this or \a other is not allocated. * \throw If \a this->getNumberOfComponents() != 1. * \throw If \a other->getNumberOfComponents() != 1. - * \throw If any value of \a this or \a other is negative. */ DataArrayInt *DataArrayInt::buildUnion(const DataArrayInt *other) const throw(INTERP_KERNEL::Exception) { @@ -8731,7 +8946,7 @@ DataArrayInt *DataArrayInt::buildUnion(const DataArrayInt *other) const throw(IN /*! * Returns a new DataArrayInt which contains elements present in both \a this and a given - * one-dimensional not negative arrays. The result array does not contain any duplicates + * one-dimensional arrays. The result array does not contain any duplicates * and its values are sorted in ascending order. * \param [in] other - an array to intersect with \a this one. * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete this @@ -8739,7 +8954,6 @@ DataArrayInt *DataArrayInt::buildUnion(const DataArrayInt *other) const throw(IN * \throw If \a this or \a other is not allocated. * \throw If \a this->getNumberOfComponents() != 1. * \throw If \a other->getNumberOfComponents() != 1. - * \throw If any value of \a this or \a other is negative. */ DataArrayInt *DataArrayInt::buildIntersection(const DataArrayInt *other) const throw(INTERP_KERNEL::Exception) { @@ -8864,14 +9078,14 @@ void DataArrayInt::computeOffsets2() throw(INTERP_KERNEL::Exception) if(getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsets2 : only single component allowed !"); int nbOfTuples=getNumberOfTuples(); - int *ret=new int[nbOfTuples+1]; + int *ret=(int *)malloc((nbOfTuples+1)*sizeof(int)); if(nbOfTuples==0) return ; const int *work=getConstPointer(); ret[0]=0; for(int i=0;i m; + for(int *workPt=work;workPt!=work+sz;workPt++) + m[*workPt]=(int)std::distance(work,workPt); int *iter2=ret; for(const int *iter=start;iter!=end;iter++,iter2++) - *iter2=(int)std::distance(work,std::find(work,work+sz,*iter)); + *iter2=m[*iter]; delete [] work; return ret; } diff --git a/src/MEDCoupling/MEDCouplingMemArray.hxx b/src/MEDCoupling/MEDCouplingMemArray.hxx index f42d1a32d..64727c30c 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.hxx +++ b/src/MEDCoupling/MEDCouplingMemArray.hxx @@ -91,6 +91,7 @@ namespace ParaMEDMEM Deallocator getDeallocator() const { return _dealloc; } void setSpecificDeallocator(Deallocator dealloc) { _dealloc=dealloc; } void setParameterForDeallocator(void *param) { _param_for_deallocator=param; } + void *getParameterForDeallocator() const { return _param_for_deallocator; } void destroy(); ~MemArray() { destroy(); } public: @@ -108,6 +109,8 @@ namespace ParaMEDMEM void *_param_for_deallocator; }; + class DataArrayInt; + class DataArray : public RefCountObject, public TimeLabel { public: @@ -123,6 +126,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT const std::vector &getInfoOnComponents() const { return _info_on_compo; } MEDCOUPLING_EXPORT std::vector &getInfoOnComponents() { return _info_on_compo; } MEDCOUPLING_EXPORT void setInfoOnComponents(const std::vector& info) throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT void setInfoAndChangeNbOfCompo(const std::vector& info) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT std::vector getVarsOnComponent() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT std::vector getUnitsOnComponent() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT std::string getInfoOnComponent(int i) const throw(INTERP_KERNEL::Exception); @@ -130,14 +134,24 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT std::string getUnitOnComponent(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 (int)_info_on_compo.size(); } + MEDCOUPLING_EXPORT virtual bool isAllocated() const throw(INTERP_KERNEL::Exception) = 0; + MEDCOUPLING_EXPORT virtual void checkAllocated() const throw(INTERP_KERNEL::Exception) = 0; MEDCOUPLING_EXPORT virtual int getNumberOfTuples() const throw(INTERP_KERNEL::Exception) = 0; MEDCOUPLING_EXPORT virtual std::size_t getNbOfElems() const throw(INTERP_KERNEL::Exception) = 0; MEDCOUPLING_EXPORT virtual std::size_t getNbOfElemAllocated() const throw(INTERP_KERNEL::Exception) = 0; + MEDCOUPLING_EXPORT virtual void alloc(int nbOfTuple, int nbOfCompo=1) throw(INTERP_KERNEL::Exception) = 0; + MEDCOUPLING_EXPORT virtual void renumberInPlace(const int *old2New) throw(INTERP_KERNEL::Exception) = 0; + MEDCOUPLING_EXPORT virtual void renumberInPlaceR(const int *new2Old) throw(INTERP_KERNEL::Exception) = 0; + MEDCOUPLING_EXPORT virtual void setContigPartOfSelectedValues(int tupleIdStart, const DataArray *aBase, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception) = 0; + MEDCOUPLING_EXPORT virtual void setContigPartOfSelectedValues2(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step) throw(INTERP_KERNEL::Exception) = 0; + MEDCOUPLING_EXPORT virtual DataArray *selectByTupleRanges(const std::vector >& ranges) const throw(INTERP_KERNEL::Exception) = 0; + MEDCOUPLING_EXPORT virtual DataArray *keepSelectedComponents(const std::vector& compoIds) const throw(INTERP_KERNEL::Exception) = 0; MEDCOUPLING_EXPORT void checkNbOfTuples(int nbOfTuples, const char *msg) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void checkNbOfComps(int nbOfCompo, const char *msg) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void checkNbOfTuplesAndComp(const DataArray& other, const char *msg) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void checkNbOfTuplesAndComp(int nbOfTuples, int nbOfCompo, const char *msg) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void checkNbOfElems(std::size_t nbOfElems, const char *msg) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT static void GetSlice(int start, int stop, int step, int sliceId, int nbOfSlices, int& startSlice, int& stopSlice) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT static int GetNumberOfItemGivenBES(int begin, int end, int step, const char *msg) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT static int GetNumberOfItemGivenBESRelative(int begin, int end, int step, const char *msg) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT static int GetPosOfItemGivenBESRelativeNoThrow(int value, int begin, int end, int step) throw(INTERP_KERNEL::Exception); @@ -178,7 +192,6 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT int getNumberOfTuples() const throw(INTERP_KERNEL::Exception) { return _info_on_compo.empty()?0:_mem.getNbOfElem()/getNumberOfComponents(); } MEDCOUPLING_EXPORT std::size_t getNbOfElems() const throw(INTERP_KERNEL::Exception) { return _mem.getNbOfElem(); } MEDCOUPLING_EXPORT std::size_t getHeapMemorySize() const; - MEDCOUPLING_EXPORT void setInfoAndChangeNbOfCompo(const std::vector& info) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT double doubleValue() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT bool empty() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayDouble *deepCpy() const throw(INTERP_KERNEL::Exception); @@ -225,12 +238,12 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT DataArrayDouble *selectByTupleId(const int *new2OldBg, const int *new2OldEnd) const; MEDCOUPLING_EXPORT DataArrayDouble *selectByTupleIdSafe(const int *new2OldBg, const int *new2OldEnd) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayDouble *selectByTupleId2(int bg, int end2, int step) const throw(INTERP_KERNEL::Exception); - MEDCOUPLING_EXPORT DataArrayDouble *selectByTupleRanges(const std::vector >& ranges) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT DataArray *selectByTupleRanges(const std::vector >& ranges) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayDouble *substr(int tupleIdBg, int tupleIdEnd=-1) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void rearrange(int newNbOfCompo) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void transpose() throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayDouble *changeNbOfComponents(int newNbOfComp, double dftValue) const throw(INTERP_KERNEL::Exception); - MEDCOUPLING_EXPORT DataArrayDouble *keepSelectedComponents(const std::vector& compoIds) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT DataArray *keepSelectedComponents(const std::vector& compoIds) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void meldWith(const DataArrayDouble *other) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void findCommonTuples(double prec, int limitTupleId, DataArrayInt *&comm, DataArrayInt *&commIndex) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT double minimalDistanceTo(const DataArrayDouble *other, int& thisTupleId, int& otherTupleId) const throw(INTERP_KERNEL::Exception); @@ -247,8 +260,8 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT void setPartOfValues4(const DataArrayDouble *a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp, bool strictCompoCompare=true) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void setPartOfValuesSimple4(double a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void setPartOfValuesAdv(const DataArrayDouble *a, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception); - MEDCOUPLING_EXPORT void setContigPartOfSelectedValues(int tupleIdStart, const DataArrayDouble *a, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception); - MEDCOUPLING_EXPORT void setContigPartOfSelectedValues2(int tupleIdStart, const DataArrayDouble *a, int bg, int end2, int step) throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT void setContigPartOfSelectedValues(int tupleIdStart, const DataArray *aBase, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT void setContigPartOfSelectedValues2(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void getTuple(int tupleId, double *res) const throw(INTERP_KERNEL::Exception) { 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 double back() const throw(INTERP_KERNEL::Exception); @@ -277,11 +290,13 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT double getMinValueInArray() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT double getMaxValue2(DataArrayInt*& tupleIds) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT double getMinValue2(DataArrayInt*& tupleIds) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT int count(double value, double eps) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT double getAverageValue() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT double norm2() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT double normMax() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void accumulate(double *res) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT double accumulate(int compId) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT DataArrayDouble *accumulatePerChunck(const int *bgOfIndex, const int *endOfIndex) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT double distanceToTuple(const double *tupleBg, const double *tupleEnd, int& tupleId) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayDouble *fromPolarToCart() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayDouble *fromCylToCart() const throw(INTERP_KERNEL::Exception); @@ -295,6 +310,7 @@ namespace ParaMEDMEM 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 DataArrayDouble *maxPerTupleWithCompoId(DataArrayInt* &compoIdOfMaxPerTuple) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayDouble *buildEuclidianDistanceDenseMatrix() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayDouble *buildEuclidianDistanceDenseMatrixWith(const DataArrayDouble *other) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void sortPerTuple(bool asc) throw(INTERP_KERNEL::Exception); @@ -396,7 +412,6 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT int getNumberOfTuples() const throw(INTERP_KERNEL::Exception) { return _info_on_compo.empty()?0:_mem.getNbOfElem()/getNumberOfComponents(); } MEDCOUPLING_EXPORT std::size_t getNbOfElems() const throw(INTERP_KERNEL::Exception) { return _mem.getNbOfElem(); } MEDCOUPLING_EXPORT std::size_t getHeapMemorySize() const; - MEDCOUPLING_EXPORT void setInfoAndChangeNbOfCompo(const std::vector& info) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT int intValue() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT int getHashCode() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT bool empty() const throw(INTERP_KERNEL::Exception); @@ -454,7 +469,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT DataArrayInt *selectByTupleId(const int *new2OldBg, const int *new2OldEnd) const; MEDCOUPLING_EXPORT DataArrayInt *selectByTupleIdSafe(const int *new2OldBg, const int *new2OldEnd) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayInt *selectByTupleId2(int bg, int end, int step) const throw(INTERP_KERNEL::Exception); - MEDCOUPLING_EXPORT DataArrayInt *selectByTupleRanges(const std::vector >& ranges) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT DataArray *selectByTupleRanges(const std::vector >& ranges) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayInt *checkAndPreparePermutation() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void changeSurjectiveFormat(int targetNb, DataArrayInt *&arr, DataArrayInt *&arrI) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT static DataArrayInt *BuildOld2NewArrayFromSurjectiveFormat2(int nbOfOldTuples, const int *arr, const int *arrIBg, const int *arrIEnd, int &newNbOfTuples) throw(INTERP_KERNEL::Exception); @@ -465,7 +480,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT void rearrange(int newNbOfCompo) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void transpose() throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayInt *changeNbOfComponents(int newNbOfComp, int dftValue) const throw(INTERP_KERNEL::Exception); - MEDCOUPLING_EXPORT DataArrayInt *keepSelectedComponents(const std::vector& compoIds) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT DataArray *keepSelectedComponents(const std::vector& compoIds) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void meldWith(const DataArrayInt *other) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void setSelectedComponents(const DataArrayInt *a, const std::vector& compoIds) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void setPartOfValues1(const DataArrayInt *a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare=true) throw(INTERP_KERNEL::Exception); @@ -477,8 +492,8 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT void setPartOfValues4(const DataArrayInt *a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp, bool strictCompoCompare=true) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void setPartOfValuesSimple4(int a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void setPartOfValuesAdv(const DataArrayInt *a, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception); - MEDCOUPLING_EXPORT void setContigPartOfSelectedValues(int tupleIdStart, const DataArrayInt*a, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception); - MEDCOUPLING_EXPORT void setContigPartOfSelectedValues2(int tupleIdStart, const DataArrayInt *a, int bg, int end2, int step) throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT void setContigPartOfSelectedValues(int tupleIdStart, const DataArray *aBase, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT void setContigPartOfSelectedValues2(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void getTuple(int tupleId, int *res) const throw(INTERP_KERNEL::Exception) { 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 throw(INTERP_KERNEL::Exception) { return _mem[tupleId*_info_on_compo.size()+compoId]; } MEDCOUPLING_EXPORT int getIJSafe(int tupleId, int compoId) const throw(INTERP_KERNEL::Exception); @@ -503,8 +518,10 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT bool presenceOfTuple(const std::vector& tupl) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT bool presenceOfValue(int value) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT bool presenceOfValue(const std::vector& vals) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT int count(int value) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void accumulate(int *res) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT int accumulate(int compId) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT DataArrayInt *accumulatePerChunck(const int *bgOfIndex, const int *endOfIndex) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT int getMaxValue(int& tupleId) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT int getMaxValueInArray() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT int getMinValue(int& tupleId) const throw(INTERP_KERNEL::Exception); @@ -613,12 +630,12 @@ namespace ParaMEDMEM { public: MEDCOUPLING_EXPORT virtual DataArrayChar *buildEmptySpecializedDAChar() const throw(INTERP_KERNEL::Exception) = 0; + MEDCOUPLING_EXPORT virtual DataArrayChar *deepCpy() const = 0; MEDCOUPLING_EXPORT bool isAllocated() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void checkAllocated() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT int getNumberOfTuples() const throw(INTERP_KERNEL::Exception) { return _info_on_compo.empty()?0:_mem.getNbOfElem()/getNumberOfComponents(); } MEDCOUPLING_EXPORT std::size_t getNbOfElems() const throw(INTERP_KERNEL::Exception) { return _mem.getNbOfElem(); } MEDCOUPLING_EXPORT std::size_t getHeapMemorySize() const; - MEDCOUPLING_EXPORT void setInfoAndChangeNbOfCompo(const std::vector& info) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT int getHashCode() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT bool empty() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void cpyFrom(const DataArrayChar& other) throw(INTERP_KERNEL::Exception); @@ -651,7 +668,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT void rearrange(int newNbOfCompo) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayChar *substr(int tupleIdBg, int tupleIdEnd=-1) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayChar *changeNbOfComponents(int newNbOfComp, char dftValue) const throw(INTERP_KERNEL::Exception); - MEDCOUPLING_EXPORT DataArrayChar *keepSelectedComponents(const std::vector& compoIds) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT DataArray *keepSelectedComponents(const std::vector& compoIds) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void meldWith(const DataArrayChar *other) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void setPartOfValues1(const DataArrayChar *a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare=true) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void setPartOfValuesSimple1(char a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp) throw(INTERP_KERNEL::Exception); @@ -662,6 +679,9 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT void setPartOfValues4(const DataArrayChar *a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp, bool strictCompoCompare=true) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void setPartOfValuesSimple4(char a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void setPartOfValuesAdv(const DataArrayChar *a, const DataArrayChar *tuplesSelec) throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT void setContigPartOfSelectedValues(int tupleIdStart, const DataArray *aBase, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT void setContigPartOfSelectedValues2(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step) throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT DataArray *selectByTupleRanges(const std::vector >& ranges) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void getTuple(int tupleId, char *res) const { std::copy(_mem.getConstPointerLoc(tupleId*_info_on_compo.size()),_mem.getConstPointerLoc((tupleId+1)*_info_on_compo.size()),res); } MEDCOUPLING_EXPORT char getIJ(int tupleId, int compoId) const { return _mem[tupleId*_info_on_compo.size()+compoId]; } MEDCOUPLING_EXPORT char getIJSafe(int tupleId, int compoId) const throw(INTERP_KERNEL::Exception); diff --git a/src/MEDCoupling/MEDCouplingMemArray.txx b/src/MEDCoupling/MEDCouplingMemArray.txx index 1cb03da77..39030643d 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.txx +++ b/src/MEDCoupling/MEDCouplingMemArray.txx @@ -27,6 +27,7 @@ #include "InterpolationUtils.hxx" #include +#include #include namespace ParaMEDMEM @@ -51,9 +52,9 @@ namespace ParaMEDMEM if(!other._pointer.isNull()) { _nb_of_elem_alloc=other._nb_of_elem; - T *pointer=new T[_nb_of_elem_alloc]; + T *pointer=(T*)malloc(_nb_of_elem_alloc*sizeof(T)); std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+other._nb_of_elem,pointer); - useArray(pointer,true,CPP_DEALLOC,other._nb_of_elem); + useArray(pointer,true,C_DEALLOC,other._nb_of_elem); } } @@ -272,7 +273,7 @@ namespace ParaMEDMEM throw INTERP_KERNEL::Exception("MemArray::fromNoInterlace : number of components must be > 0 !"); const T *pt=_pointer.getConstPointer(); std::size_t nbOfTuples=_nb_of_elem/nbOfComp; - T *ret=new T[_nb_of_elem]; + T *ret=(T*)malloc(_nb_of_elem*sizeof(T)); T *w=ret; for(std::size_t i=0;i::toNoInterlace : number of components must be > 0 !"); const T *pt=_pointer.getConstPointer(); std::size_t nbOfTuples=_nb_of_elem/nbOfComp; - T *ret=new T[_nb_of_elem]; + T *ret=(T*)malloc(_nb_of_elem*sizeof(T)); T *w=ret; for(int i=0;i(_nb_of_elem,newNbOfElements),pointer); if(_ownership) destroyPointer(const_cast(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external @@ -369,7 +370,7 @@ namespace ParaMEDMEM _nb_of_elem=std::min(_nb_of_elem,newNbOfElements); _nb_of_elem_alloc=newNbOfElements; _ownership=true; - _dealloc=CPPDeallocator; + _dealloc=CDeallocator; _param_for_deallocator=0; } @@ -387,7 +388,7 @@ namespace ParaMEDMEM throw INTERP_KERNEL::Exception("MemArray::reAlloc : request for negative length of data !"); if(_nb_of_elem==newNbOfElements) return ; - T *pointer=new T[newNbOfElements]; + T *pointer=(T*)malloc(newNbOfElements*sizeof(T)); std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min(_nb_of_elem,newNbOfElements),pointer); if(_ownership) destroyPointer(const_cast(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external @@ -395,7 +396,7 @@ namespace ParaMEDMEM _nb_of_elem=newNbOfElements; _nb_of_elem_alloc=newNbOfElements; _ownership=true; - _dealloc=CPPDeallocator; + _dealloc=CDeallocator; _param_for_deallocator=0; } diff --git a/src/MEDCoupling/MEDCouplingMemArrayChar.cxx b/src/MEDCoupling/MEDCouplingMemArrayChar.cxx index 2cb71a8bc..ea09de283 100644 --- a/src/MEDCoupling/MEDCouplingMemArrayChar.cxx +++ b/src/MEDCoupling/MEDCouplingMemArrayChar.cxx @@ -56,32 +56,6 @@ std::size_t DataArrayChar::getHeapMemorySize() const return DataArray::getHeapMemorySize()+sz; } -/*! - * Sets information on all components. This method can change number of components - * at certain conditions; if the conditions are not respected, an exception is thrown. - * The number of components can be changed provided that \a this is not allocated. - * - * To know more on format of the component information see - * \ref MEDCouplingArrayBasicsCompoName "DataArrays infos". - * \param [in] info - a vector of component infos. - * \throw If \a this->getNumberOfComponents() != \a info.size() && \a this->isAllocated() - */ -void DataArrayChar::setInfoAndChangeNbOfCompo(const std::vector& info) throw(INTERP_KERNEL::Exception) -{ - if(getNumberOfComponents()!=(int)info.size()) - { - if(!isAllocated()) - _info_on_compo=info; - else - { - std::ostringstream oss; oss << "DataArrayChar::setInfoAndChangeNbOfCompo : input is of size " << info.size() << " whereas number of components is equal to " << getNumberOfComponents() << " and this is already allocated !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - } - else - _info_on_compo=info; -} - /*! * Returns an integer value characterizing \a this array, which is useful for a quick * comparison of many instances of DataArrayInt. @@ -728,7 +702,7 @@ DataArrayChar *DataArrayChar::changeNbOfComponents(int newNbOfComp, char dftValu * * \ref py_mcdataarrayint_keepselectedcomponents "Here is a Python example". */ -DataArrayChar *DataArrayChar::keepSelectedComponents(const std::vector& compoIds) const throw(INTERP_KERNEL::Exception) +DataArray *DataArrayChar::keepSelectedComponents(const std::vector& compoIds) const throw(INTERP_KERNEL::Exception) { checkAllocated(); MEDCouplingAutoRefCountObjectPtr ret(buildEmptySpecializedDAChar()); @@ -770,7 +744,7 @@ void DataArrayChar::meldWith(const DataArrayChar *other) throw(INTERP_KERNEL::Ex throw INTERP_KERNEL::Exception("DataArrayChar::meldWith : mismatch of number of tuples !"); int nbOfComp1=getNumberOfComponents(); int nbOfComp2=other->getNumberOfComponents(); - char *newArr=new char[nbOfTuples*(nbOfComp1+nbOfComp2)]; + char *newArr=(char *)malloc(nbOfTuples*(nbOfComp1+nbOfComp2)*sizeof(char)); char *w=newArr; const char *inp1=getConstPointer(); const char *inp2=other->getConstPointer(); @@ -779,7 +753,7 @@ void DataArrayChar::meldWith(const DataArrayChar *other) throw(INTERP_KERNEL::Ex w=std::copy(inp1,inp1+nbOfComp1,w); w=std::copy(inp2,inp2+nbOfComp2,w); } - useArray(newArr,true,CPP_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2); + useArray(newArr,true,C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2); std::vector compIds(nbOfComp2); for(int i=0;igetNumberOfTuples(). + * The tuples to copy are defined by values of a DataArrayChar. + * All components of selected tuples are copied. + * \param [in] tupleIdStart - index of the first tuple of \a this array to assign + * values to. + * \param [in] a - the array to copy values from. + * \param [in] tuplesSelec - the array specifying tuples of \a a to copy. + * \throw If \a this is not allocated. + * \throw If \a a is NULL. + * \throw If \a a is not allocated. + * \throw If \a tuplesSelec is NULL. + * \throw If \a tuplesSelec is not allocated. + * \throw If this->getNumberOfComponents() != a->getNumberOfComponents(). + * \throw If \a tuplesSelec->getNumberOfComponents() != 1. + * \throw If tupleIdStart + tuplesSelec->getNumberOfTuples() > this->getNumberOfTuples(). + * \throw If any tuple index given by \a tuplesSelec is out of a valid range for + * \a a array. + */ +void DataArrayChar::setContigPartOfSelectedValues(int tupleIdStart, const DataArray *aBase, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception) +{ + if(!aBase || !tuplesSelec) + throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : input DataArray is NULL !"); + const DataArrayChar *a=dynamic_cast(aBase); + if(!a) + throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : input DataArray aBase is not a DataArrayChar !"); + checkAllocated(); + a->checkAllocated(); + tuplesSelec->checkAllocated(); + int nbOfComp=getNumberOfComponents(); + if(nbOfComp!=a->getNumberOfComponents()) + throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : This and a do not have the same number of components !"); + if(tuplesSelec->getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : Expecting to have a tuple selector DataArrayChar instance with exactly 1 component !"); + int thisNt=getNumberOfTuples(); + int aNt=a->getNumberOfTuples(); + int nbOfTupleToWrite=tuplesSelec->getNumberOfTuples(); + char *valsToSet=getPointer()+tupleIdStart*nbOfComp; + if(tupleIdStart+nbOfTupleToWrite>thisNt) + throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : invalid number range of values to write !"); + const char *valsSrc=a->getConstPointer(); + for(const int *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple++,valsToSet+=nbOfComp) + { + if(*tuple>=0 && *tuplebegin(),tuple); + oss << " of 'tuplesSelec' request of tuple id #" << *tuple << " in 'a' ! It should be in [0," << aNt << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } +} + +/*! + * Copy some tuples from another DataArrayChar (\a a) into contiguous tuples + * of \a this array. Textual data is not copied. Both arrays must have equal number of + * components. + * The tuples to copy are defined by three values similar to parameters of + * the Python function \c range(\c start,\c stop,\c step). + * The tuples to assign to are defined by index of the first tuple, and + * their number is defined by number of tuples to copy. + * All components of selected tuples are copied. + * \param [in] tupleIdStart - index of the first tuple of \a this array to assign + * values to. + * \param [in] a - the array to copy values from. + * \param [in] bg - index of the first tuple to copy of the array \a a. + * \param [in] end2 - index of the tuple of \a a before which the tuples to copy + * are located. + * \param [in] step - index increment to get index of the next tuple to copy. + * \throw If \a this is not allocated. + * \throw If \a a is NULL. + * \throw If \a a is not allocated. + * \throw If this->getNumberOfComponents() != a->getNumberOfComponents(). + * \throw If tupleIdStart + len(range(bg,end2,step)) > this->getNumberOfTuples(). + * \throw If parameters specifying tuples to copy, do not give a + * non-empty range of increasing indices or indices are out of a valid range + * for the array \a a. + */ +void DataArrayChar::setContigPartOfSelectedValues2(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step) throw(INTERP_KERNEL::Exception) +{ + if(!aBase) + throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues2 : input DataArray is NULL !"); + const DataArrayChar *a=dynamic_cast(aBase); + if(!a) + throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues2 : input DataArray aBase is not a DataArrayChar !"); + checkAllocated(); + a->checkAllocated(); + int nbOfComp=getNumberOfComponents(); + const char msg[]="DataArrayChar::setContigPartOfSelectedValues2"; + int nbOfTupleToWrite=DataArray::GetNumberOfItemGivenBES(bg,end2,step,msg); + if(nbOfComp!=a->getNumberOfComponents()) + throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues2 : This and a do not have the same number of components !"); + int thisNt=getNumberOfTuples(); + int aNt=a->getNumberOfTuples(); + char *valsToSet=getPointer()+tupleIdStart*nbOfComp; + if(tupleIdStart+nbOfTupleToWrite>thisNt) + throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues2 : invalid number range of values to write !"); + if(end2>aNt) + throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues2 : invalid range of values to read !"); + const char *valsSrc=a->getConstPointer()+bg*nbOfComp; + for(int i=0;i \a this->getNumberOfTuples(). + * \throw If \a this is not allocated. + */ +DataArray *DataArrayChar::selectByTupleRanges(const std::vector >& ranges) const throw(INTERP_KERNEL::Exception) +{ + checkAllocated(); + int nbOfComp=getNumberOfComponents(); + int nbOfTuplesThis=getNumberOfTuples(); + if(ranges.empty()) + { + MEDCouplingAutoRefCountObjectPtr ret=buildEmptySpecializedDAChar(); + ret->alloc(0,nbOfComp); + ret->copyStringInfoFrom(*this); + return ret.retn(); + } + int ref=ranges.front().first; + int nbOfTuples=0; + bool isIncreasing=true; + for(std::vector >::const_iterator it=ranges.begin();it!=ranges.end();it++) + { + if((*it).first<=(*it).second) + { + if((*it).first>=0 && (*it).second<=nbOfTuplesThis) + { + nbOfTuples+=(*it).second-(*it).first; + if(isIncreasing) + isIncreasing=ref<=(*it).first; + ref=(*it).second; + } + else + { + std::ostringstream oss; oss << "DataArrayChar::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it); + oss << " (" << (*it).first << "," << (*it).second << ") is greater than number of tuples of this :" << nbOfTuples << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + else + { + std::ostringstream oss; oss << "DataArrayChar::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it); + oss << " (" << (*it).first << "," << (*it).second << ") end is before begin !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + if(isIncreasing && nbOfTuplesThis==nbOfTuples) + return deepCpy(); + MEDCouplingAutoRefCountObjectPtr ret=buildEmptySpecializedDAChar(); + ret->alloc(nbOfTuples,nbOfComp); + ret->copyStringInfoFrom(*this); + const char *src=getConstPointer(); + char *work=ret->getPointer(); + for(std::vector >::const_iterator it=ranges.begin();it!=ranges.end();it++) + work=std::copy(src+(*it).first*nbOfComp,src+(*it).second*nbOfComp,work); + return ret.retn(); +} + /*! * Returns a value located at specified tuple and component. * This method is equivalent to DataArrayChar::getIJ() except that validity of diff --git a/src/MEDCoupling/MEDCouplingMesh.cxx b/src/MEDCoupling/MEDCouplingMesh.cxx index 48489218f..95d450a9c 100644 --- a/src/MEDCoupling/MEDCouplingMesh.cxx +++ b/src/MEDCoupling/MEDCouplingMesh.cxx @@ -113,22 +113,37 @@ bool MEDCouplingMesh::isEqual(const MEDCouplingMesh *other, double prec) const t } /*! - * 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. - * So in case of success cell \c other[i] is equal to cell \c this[cellCor[i]]. If \a cellCor is null it means that for all i cell \c other[i] is equal to cell \c this[i]. + * This method checks geo equivalence between two meshes : \a this and \a other. + * If no exception is thrown \a this and \a other are geometrically equivalent regarding \a levOfCheck level. + * This method is typically used to change the mesh of a field "safely" depending the \a 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'. + * In case of success cell \c other[i] is equal to the cell \c this[cellCor[i]]. + * In case of success node \c other->getCoords()[i] is equal to the node \c this->getCoords()[nodeCor[i]]. + * + * If \a cellCor is null (or Py_None) it means that for all #i cell in \a other is equal to cell # i in \a this. + * + * If \a nodeCor is null (or Py_None) it means that for all #i node in \a other is equal to node # i in \a this. + * + * So null (or Py_None) returned in \a cellCor and/or \a nodeCor means identity array. This is for optimization reason to avoid to build useless arrays + * for some \a levOfCheck (for example 0). + * + * **Warning a not null output does not mean that it is not identity !** + * + * \param [in] other - the mesh to be compared with \a this. + * \param [in] levOfCheck - input that specifies the level of check specified. The possible values are listed below. + * \param [in] prec - input that specifies precision for double float data used for comparison in meshes. + * \param [out] cellCor - output array not always informed (depending \a levOfCheck param) that gives the corresponding array for cells from \a other to \a this. + * \param [out] nodeCor - output array not always informed (depending \a levOfCheck param) that gives the corresponding array for nodes from \a other to \a 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) + * - 0 for strict equality. This is the strongest level. \a cellCor and \a nodeCor params are never informed. + * - 10,11,12 (10+x) for less strict equality. Two meshes are compared geometrically. In case of success \a cellCor and \a 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 (20+x), 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 \a 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. + * + * So the most strict level of check is 0 (equality). The least strict is 12. If the level of check 12 throws, the 2 meshes \a this and \a other are not similar enough + * to be compared. An interpolation using MEDCouplingRemapper class should be then used. */ void MEDCouplingMesh::checkGeoEquivalWith(const MEDCouplingMesh *other, int levOfCheck, double prec, DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception) @@ -207,7 +222,7 @@ DataArrayInt *MEDCouplingMesh::getCellIdsFullyIncludedInNodeIds(const int *partB } /*! - * This method checks fastly that 'this' and 'other' are equal. All common checks are done here. + * This method checks fastly that \a this and \a other are equal. All common checks are done here. */ void MEDCouplingMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception) { @@ -220,7 +235,7 @@ void MEDCouplingMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double } /*! - * This method is very poor and looks only if 'this' and 'other' are candidate for merge of fields lying repectively on them. + * This method is very poor and looks only if \a this and \a other are candidate for merge of fields lying repectively on them. */ bool MEDCouplingMesh::areCompatibleForMerge(const MEDCouplingMesh *other) const { @@ -254,7 +269,7 @@ MEDCouplingMesh *MEDCouplingMesh::buildPartRangeAndReduceNodes(int beginCellIds, } /*! - * This method builds a field lying on 'this' with 'nbOfComp' components. + * This method builds a field lying on \a this with 'nbOfComp' components. * 'func' is a pointer that points to a function that takes 2 arrays in parameter and returns a boolean. * The first array is a in-param of size this->getSpaceDimension and the second an out param of size 'nbOfComp'. * The return field will have type specified by 't'. 't' is also used to determine where values of field will be @@ -263,10 +278,11 @@ MEDCouplingMesh *MEDCouplingMesh::buildPartRangeAndReduceNodes(int beginCellIds, * The 'func' is a callback that takes as first parameter an input array of size 'this->getSpaceDimension()', * the second parameter is a pointer on a valid zone of size at least equal to 'nbOfComp' values. And too finish * the returned value is a boolean that is equal to False in case of invalid evaluation (log(0) for example...) - * @param t type of field returned and specifies where the evaluation of func will be done. - * @param nbOfComp number of components of returned field. - * @param func pointer to a function that should return false if the evaluation failed. (division by 0. for example) - * @return field with counter = 1. + * + * \param t type of field returned and specifies where the evaluation of func will be done. + * \param nbOfComp number of components of returned field. + * \param func pointer to a function that should return false if the evaluation failed. (division by 0. for example) + * \return field with counter = 1. */ MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic(TypeOfField t, int nbOfComp, FunctionToEvaluate func) const { @@ -290,7 +306,7 @@ void MEDCouplingMesh::copyTinyStringsFrom(const MEDCouplingMesh *other) throw(IN /*! * This method copies all attributes that are \b NOT arrays in this. - * All tiny attributes not usefully for state of 'this' are ignored. + * All tiny attributes not usefully for state of \a this are ignored. */ void MEDCouplingMesh::copyTinyInfoFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception) { @@ -509,6 +525,54 @@ MEDCouplingMesh *MEDCouplingMesh::MergeMeshes(std::vector getAllGeoTypes() const = 0; @@ -124,6 +125,10 @@ namespace ParaMEDMEM virtual bool areCompatibleForMerge(const MEDCouplingMesh *other) const; static MEDCouplingMesh *MergeMeshes(const MEDCouplingMesh *mesh1, const MEDCouplingMesh *mesh2) throw(INTERP_KERNEL::Exception); static MEDCouplingMesh *MergeMeshes(std::vector& meshes) throw(INTERP_KERNEL::Exception); + static bool IsStaticGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception); + static bool IsLinearGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception); + static INTERP_KERNEL::NormalizedCellType GetCorrespondingPolyType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception); + static int GetNumberOfNodesOfGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception); static int GetDimensionOfGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception); static const char *GetReprOfGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception); //serialisation-unserialization diff --git a/src/MEDCoupling/MEDCouplingStructuredMesh.cxx b/src/MEDCoupling/MEDCouplingStructuredMesh.cxx index 77f8ca03e..407f956dc 100644 --- a/src/MEDCoupling/MEDCouplingStructuredMesh.cxx +++ b/src/MEDCoupling/MEDCouplingStructuredMesh.cxx @@ -109,6 +109,16 @@ DataArrayInt *MEDCouplingStructuredMesh::computeNbOfNodesPerCell() const throw(I return ret.retn(); } +DataArrayInt *MEDCouplingStructuredMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception) +{ + int nbCells=getNumberOfCells(); + MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); + ret->alloc(nbCells,1); + const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(getTypeOfCell(0)); + ret->fillWithValue((int)cm.getNumberOfSons()); + return ret.retn(); +} + void MEDCouplingStructuredMesh::getNodeIdsOfCell(int cellId, std::vector& conn) const { int meshDim=getMeshDimension(); diff --git a/src/MEDCoupling/MEDCouplingStructuredMesh.hxx b/src/MEDCoupling/MEDCouplingStructuredMesh.hxx index 1e79a9f46..b04db7add 100644 --- a/src/MEDCoupling/MEDCouplingStructuredMesh.hxx +++ b/src/MEDCoupling/MEDCouplingStructuredMesh.hxx @@ -34,6 +34,7 @@ namespace ParaMEDMEM int getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const; DataArrayInt *giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception); DataArrayInt *computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception); + DataArrayInt *computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception); static void GetPosFromId(int nodeId, int meshDim, const int *split, int *res); void getNodeIdsOfCell(int cellId, std::vector& conn) const; std::size_t getHeapMemorySize() const; diff --git a/src/MEDCoupling/MEDCouplingTimeDiscretization.cxx b/src/MEDCoupling/MEDCouplingTimeDiscretization.cxx index b75dbd2ab..818f4eb71 100644 --- a/src/MEDCoupling/MEDCouplingTimeDiscretization.cxx +++ b/src/MEDCoupling/MEDCouplingTimeDiscretization.cxx @@ -49,7 +49,7 @@ 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) +MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::New(TypeOfTimeDiscretization type) throw(INTERP_KERNEL::Exception) { switch(type) { @@ -72,7 +72,7 @@ void MEDCouplingTimeDiscretization::copyTinyAttrFrom(const MEDCouplingTimeDiscre _time_unit=other._time_unit; } -void MEDCouplingTimeDiscretization::copyTinyStringsFrom(const MEDCouplingTimeDiscretization& other) +void MEDCouplingTimeDiscretization::copyTinyStringsFrom(const MEDCouplingTimeDiscretization& other) throw(INTERP_KERNEL::Exception) { _time_unit=other._time_unit; if(_array && other._array) @@ -101,7 +101,7 @@ std::size_t MEDCouplingTimeDiscretization::getHeapMemorySize() const return ret; } -bool MEDCouplingTimeDiscretization::areCompatible(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingTimeDiscretization::areCompatible(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(std::fabs(_time_tolerance-other->_time_tolerance)>1.e-16) return false; @@ -114,7 +114,7 @@ bool MEDCouplingTimeDiscretization::areCompatible(const MEDCouplingTimeDiscretiz return true; } -bool MEDCouplingTimeDiscretization::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const +bool MEDCouplingTimeDiscretization::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const throw(INTERP_KERNEL::Exception) { std::ostringstream oss; oss.precision(15); if(_time_unit!=other->_time_unit) @@ -143,7 +143,7 @@ bool MEDCouplingTimeDiscretization::areStrictlyCompatible(const MEDCouplingTimeD return true; } -bool MEDCouplingTimeDiscretization::areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingTimeDiscretization::areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(std::fabs(_time_tolerance-other->_time_tolerance)>1.e-16) return false; @@ -156,7 +156,7 @@ bool MEDCouplingTimeDiscretization::areCompatibleForMeld(const MEDCouplingTimeDi return true; } -bool MEDCouplingTimeDiscretization::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingTimeDiscretization::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(std::fabs(_time_tolerance-other->_time_tolerance)>1.e-16) return false; @@ -172,7 +172,7 @@ bool MEDCouplingTimeDiscretization::areStrictlyCompatibleForMul(const MEDCouplin return true; } -bool MEDCouplingTimeDiscretization::areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingTimeDiscretization::areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(std::fabs(_time_tolerance-other->_time_tolerance)>1.e-16) return false; @@ -187,7 +187,7 @@ bool MEDCouplingTimeDiscretization::areStrictlyCompatibleForDiv(const MEDCouplin return true; } -bool MEDCouplingTimeDiscretization::isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const +bool MEDCouplingTimeDiscretization::isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception) { if(!areStrictlyCompatible(other,reason)) return false; @@ -196,13 +196,13 @@ bool MEDCouplingTimeDiscretization::isEqualIfNotWhy(const MEDCouplingTimeDiscret return _array->isEqualIfNotWhy(*other->_array,prec,reason); } -bool MEDCouplingTimeDiscretization::isEqual(const MEDCouplingTimeDiscretization *other, double prec) const +bool MEDCouplingTimeDiscretization::isEqual(const MEDCouplingTimeDiscretization *other, double prec) const throw(INTERP_KERNEL::Exception) { std::string reason; return isEqualIfNotWhy(other,prec,reason); } -bool MEDCouplingTimeDiscretization::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const +bool MEDCouplingTimeDiscretization::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const throw(INTERP_KERNEL::Exception) { std::string tmp; if(!areStrictlyCompatible(other,tmp)) @@ -212,7 +212,7 @@ bool MEDCouplingTimeDiscretization::isEqualWithoutConsideringStr(const MEDCoupli return _array->isEqualWithoutConsideringStr(*other->_array,prec); } -MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::buildNewTimeReprFromThis(TypeOfTimeDiscretization type, bool deepCpy) const +MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::buildNewTimeReprFromThis(TypeOfTimeDiscretization type, bool deepCpy) const throw(INTERP_KERNEL::Exception) { MEDCouplingTimeDiscretization *ret=MEDCouplingTimeDiscretization::New(type); ret->setTimeUnit(getTimeUnit()); @@ -224,7 +224,7 @@ MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::buildNewTimeReprFr return ret; } -void MEDCouplingTimeDiscretization::getTinySerializationIntInformation(std::vector& tinyInfo) const +void MEDCouplingTimeDiscretization::getTinySerializationIntInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { if(_array) { @@ -238,7 +238,7 @@ void MEDCouplingTimeDiscretization::getTinySerializationIntInformation(std::vect } } -void MEDCouplingTimeDiscretization::resizeForUnserialization(const std::vector& tinyInfoI, std::vector& arrays) +void MEDCouplingTimeDiscretization::resizeForUnserialization(const std::vector& tinyInfoI, std::vector& arrays) throw(INTERP_KERNEL::Exception) { arrays.resize(1); if(_array!=0) @@ -253,7 +253,7 @@ void MEDCouplingTimeDiscretization::resizeForUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS) +void MEDCouplingTimeDiscretization::finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS) throw(INTERP_KERNEL::Exception) { _time_tolerance=tinyInfoD[0]; int nbOfCompo=_array->getNumberOfComponents(); @@ -261,12 +261,12 @@ void MEDCouplingTimeDiscretization::finishUnserialization(const std::vector _array->setInfoOnComponent(i,tinyInfoS[i].c_str()); } -void MEDCouplingTimeDiscretization::getTinySerializationDbleInformation(std::vector& tinyInfo) const +void MEDCouplingTimeDiscretization::getTinySerializationDbleInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { tinyInfo.push_back(_time_tolerance); } -void MEDCouplingTimeDiscretization::getTinySerializationStrInformation(std::vector& tinyInfo) const +void MEDCouplingTimeDiscretization::getTinySerializationStrInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { int nbOfCompo=_array->getNumberOfComponents(); for(int i=0;idecrRef(); } -void MEDCouplingTimeDiscretization::setArray(DataArrayDouble *array, TimeLabel *owner) +void MEDCouplingTimeDiscretization::setArray(DataArrayDouble *array, TimeLabel *owner) throw(INTERP_KERNEL::Exception) { if(array!=_array) { @@ -305,17 +305,17 @@ void MEDCouplingTimeDiscretization::setArray(DataArrayDouble *array, TimeLabel * } } -const DataArrayDouble *MEDCouplingTimeDiscretization::getEndArray() const +const DataArrayDouble *MEDCouplingTimeDiscretization::getEndArray() const throw(INTERP_KERNEL::Exception) { throw INTERP_KERNEL::Exception("getEndArray not available for this type of time discretization !"); } -DataArrayDouble *MEDCouplingTimeDiscretization::getEndArray() +DataArrayDouble *MEDCouplingTimeDiscretization::getEndArray() throw(INTERP_KERNEL::Exception) { throw INTERP_KERNEL::Exception("getEndArray not available for this type of time discretization !"); } -void MEDCouplingTimeDiscretization::setEndArray(DataArrayDouble *array, TimeLabel *owner) +void MEDCouplingTimeDiscretization::setEndArray(DataArrayDouble *array, TimeLabel *owner) throw(INTERP_KERNEL::Exception) { throw INTERP_KERNEL::Exception("setEndArray not available for this type of time discretization !"); } @@ -327,7 +327,7 @@ void MEDCouplingTimeDiscretization::setArrays(const std::vector& arrays) const +void MEDCouplingTimeDiscretization::getArrays(std::vector& arrays) const throw(INTERP_KERNEL::Exception) { arrays.resize(1); arrays[0]=_array; @@ -567,7 +567,7 @@ MEDCouplingTimeDiscretization *MEDCouplingTimeDiscretization::keepSelectedCompon for(std::size_t j=0;jkeepSelectedComponents(compoIds); + arrays2[j]=static_cast(arrays[j]->keepSelectedComponents(compoIds)); else arrays2[j]=0; } @@ -625,7 +625,7 @@ void MEDCouplingTimeDiscretization::sortPerTuple(bool asc) throw(INTERP_KERNEL:: } } -void MEDCouplingTimeDiscretization::setUniformValue(int nbOfTuple, int nbOfCompo, double value) +void MEDCouplingTimeDiscretization::setUniformValue(int nbOfTuple, int nbOfCompo, double value) throw(INTERP_KERNEL::Exception) { std::vector arrays; getArrays(arrays); @@ -650,7 +650,7 @@ void MEDCouplingTimeDiscretization::setUniformValue(int nbOfTuple, int nbOfCompo setArrays(arrays3,0); } -void MEDCouplingTimeDiscretization::setOrCreateUniformValueOnAllComponents(int nbOfTuple, double value) +void MEDCouplingTimeDiscretization::setOrCreateUniformValueOnAllComponents(int nbOfTuple, double value) throw(INTERP_KERNEL::Exception) { std::vector arrays; getArrays(arrays); @@ -680,7 +680,7 @@ void MEDCouplingTimeDiscretization::setOrCreateUniformValueOnAllComponents(int n } } -void MEDCouplingTimeDiscretization::applyLin(double a, double b, int compoId) +void MEDCouplingTimeDiscretization::applyLin(double a, double b, int compoId) throw(INTERP_KERNEL::Exception) { std::vector arrays; getArrays(arrays); @@ -691,7 +691,7 @@ void MEDCouplingTimeDiscretization::applyLin(double a, double b, int compoId) } } -void MEDCouplingTimeDiscretization::applyFunc(int nbOfComp, FunctionToEvaluate func) +void MEDCouplingTimeDiscretization::applyFunc(int nbOfComp, FunctionToEvaluate func) throw(INTERP_KERNEL::Exception) { std::vector arrays; getArrays(arrays); @@ -709,7 +709,7 @@ void MEDCouplingTimeDiscretization::applyFunc(int nbOfComp, FunctionToEvaluate f setArrays(arrays3,0); } -void MEDCouplingTimeDiscretization::applyFunc(int nbOfComp, const char *func) +void MEDCouplingTimeDiscretization::applyFunc(int nbOfComp, const char *func) throw(INTERP_KERNEL::Exception) { std::vector arrays; getArrays(arrays); @@ -727,7 +727,7 @@ void MEDCouplingTimeDiscretization::applyFunc(int nbOfComp, const char *func) setArrays(arrays3,0); } -void MEDCouplingTimeDiscretization::applyFunc2(int nbOfComp, const char *func) +void MEDCouplingTimeDiscretization::applyFunc2(int nbOfComp, const char *func) throw(INTERP_KERNEL::Exception) { std::vector arrays; getArrays(arrays); @@ -745,7 +745,7 @@ void MEDCouplingTimeDiscretization::applyFunc2(int nbOfComp, const char *func) setArrays(arrays3,0); } -void MEDCouplingTimeDiscretization::applyFunc3(int nbOfComp, const std::vector& varsOrder, const char *func) +void MEDCouplingTimeDiscretization::applyFunc3(int nbOfComp, const std::vector& varsOrder, const char *func) throw(INTERP_KERNEL::Exception) { std::vector arrays; getArrays(arrays); @@ -763,7 +763,7 @@ void MEDCouplingTimeDiscretization::applyFunc3(int nbOfComp, const std::vector arrays; getArrays(arrays); @@ -781,7 +781,7 @@ void MEDCouplingTimeDiscretization::applyFunc(const char *func) setArrays(arrays3,0); } -void MEDCouplingTimeDiscretization::applyFuncFast32(const char *func) +void MEDCouplingTimeDiscretization::applyFuncFast32(const char *func) throw(INTERP_KERNEL::Exception) { std::vector arrays; getArrays(arrays); @@ -792,7 +792,7 @@ void MEDCouplingTimeDiscretization::applyFuncFast32(const char *func) } } -void MEDCouplingTimeDiscretization::applyFuncFast64(const char *func) +void MEDCouplingTimeDiscretization::applyFuncFast64(const char *func) throw(INTERP_KERNEL::Exception) { std::vector arrays; getArrays(arrays); @@ -863,7 +863,7 @@ MEDCouplingNoTimeLabel::MEDCouplingNoTimeLabel(const MEDCouplingTimeDiscretizati { } -std::string MEDCouplingNoTimeLabel::getStringRepr() const +std::string MEDCouplingNoTimeLabel::getStringRepr() const throw(INTERP_KERNEL::Exception) { std::ostringstream stream; stream << REPR; @@ -876,7 +876,7 @@ void MEDCouplingNoTimeLabel::synchronizeTimeWith(const MEDCouplingMesh *mesh) th throw INTERP_KERNEL::Exception("MEDCouplingNoTimeLabel::synchronizeTimeWith : impossible to synchronize time with a MEDCouplingMesh because the time discretization is incompatible with it !"); } -bool MEDCouplingNoTimeLabel::areCompatible(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingNoTimeLabel::areCompatible(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areCompatible(other)) return false; @@ -884,7 +884,7 @@ bool MEDCouplingNoTimeLabel::areCompatible(const MEDCouplingTimeDiscretization * return otherC!=0; } -bool MEDCouplingNoTimeLabel::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const +bool MEDCouplingNoTimeLabel::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areStrictlyCompatible(other,reason)) return false; @@ -895,7 +895,7 @@ bool MEDCouplingNoTimeLabel::areStrictlyCompatible(const MEDCouplingTimeDiscreti return ret; } -bool MEDCouplingNoTimeLabel::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingNoTimeLabel::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areStrictlyCompatibleForMul(other)) return false; @@ -903,7 +903,7 @@ bool MEDCouplingNoTimeLabel::areStrictlyCompatibleForMul(const MEDCouplingTimeDi return otherC!=0; } -bool MEDCouplingNoTimeLabel::areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingNoTimeLabel::areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areStrictlyCompatibleForDiv(other)) return false; @@ -911,7 +911,7 @@ bool MEDCouplingNoTimeLabel::areStrictlyCompatibleForDiv(const MEDCouplingTimeDi return otherC!=0; } -bool MEDCouplingNoTimeLabel::areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingNoTimeLabel::areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areCompatibleForMeld(other)) return false; @@ -919,7 +919,7 @@ bool MEDCouplingNoTimeLabel::areCompatibleForMeld(const MEDCouplingTimeDiscretiz return otherC!=0; } -bool MEDCouplingNoTimeLabel::isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const +bool MEDCouplingNoTimeLabel::isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -930,7 +930,7 @@ bool MEDCouplingNoTimeLabel::isEqualIfNotWhy(const MEDCouplingTimeDiscretization return MEDCouplingTimeDiscretization::isEqualIfNotWhy(other,prec,reason); } -bool MEDCouplingNoTimeLabel::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const +bool MEDCouplingNoTimeLabel::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -938,7 +938,7 @@ bool MEDCouplingNoTimeLabel::isEqualWithoutConsideringStr(const MEDCouplingTimeD return MEDCouplingTimeDiscretization::isEqualWithoutConsideringStr(other,prec); } -MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::aggregate(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::aggregate(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -949,7 +949,7 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::aggregate(const MEDCoupli return ret; } -MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::aggregate(const std::vector& other) const +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::aggregate(const std::vector& other) const throw(INTERP_KERNEL::Exception) { std::vector a(other.size()); int i=0; @@ -966,7 +966,7 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::aggregate(const std::vect return ret; } -MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::meld(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::meld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -978,7 +978,7 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::meld(const MEDCouplingTim return ret; } -MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::dot(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::dot(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -989,7 +989,7 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::dot(const MEDCouplingTime return ret; } -MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::crossProduct(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::crossProduct(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -1000,7 +1000,7 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::crossProduct(const MEDCou return ret; } -MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::max(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::max(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -1011,7 +1011,7 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::max(const MEDCouplingTime return ret; } -MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::min(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::min(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -1022,7 +1022,7 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::min(const MEDCouplingTime return ret; } -MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::add(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::add(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -1033,7 +1033,7 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::add(const MEDCouplingTime return ret; } -void MEDCouplingNoTimeLabel::addEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingNoTimeLabel::addEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -1043,7 +1043,7 @@ void MEDCouplingNoTimeLabel::addEqual(const MEDCouplingTimeDiscretization *other getArray()->addEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::substract(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::substract(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -1056,7 +1056,7 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::substract(const MEDCoupli return ret; } -void MEDCouplingNoTimeLabel::substractEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingNoTimeLabel::substractEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -1066,7 +1066,7 @@ void MEDCouplingNoTimeLabel::substractEqual(const MEDCouplingTimeDiscretization getArray()->substractEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::multiply(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::multiply(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -1077,7 +1077,7 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::multiply(const MEDCouplin return ret; } -void MEDCouplingNoTimeLabel::multiplyEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingNoTimeLabel::multiplyEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -1087,7 +1087,7 @@ void MEDCouplingNoTimeLabel::multiplyEqual(const MEDCouplingTimeDiscretization * getArray()->multiplyEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::divide(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::divide(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -1098,7 +1098,7 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::divide(const MEDCouplingT return ret; } -void MEDCouplingNoTimeLabel::divideEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingNoTimeLabel::divideEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -1108,7 +1108,7 @@ void MEDCouplingNoTimeLabel::divideEqual(const MEDCouplingTimeDiscretization *ot getArray()->divideEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::pow(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::pow(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -1119,7 +1119,7 @@ MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::pow(const MEDCouplingTime return ret; } -void MEDCouplingNoTimeLabel::powEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingNoTimeLabel::powEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingNoTimeLabel *otherC=dynamic_cast(other); if(!otherC) @@ -1129,7 +1129,7 @@ void MEDCouplingNoTimeLabel::powEqual(const MEDCouplingTimeDiscretization *other getArray()->powEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::performCpy(bool deepCpy) const +MEDCouplingTimeDiscretization *MEDCouplingNoTimeLabel::performCpy(bool deepCpy) const throw(INTERP_KERNEL::Exception) { return new MEDCouplingNoTimeLabel(*this,deepCpy); } @@ -1144,7 +1144,7 @@ std::vector< const DataArrayDouble *> MEDCouplingNoTimeLabel::getArraysForTime(d throw INTERP_KERNEL::Exception(EXCEPTION_MSG); } -void MEDCouplingNoTimeLabel::getValueForTime(double time, const std::vector& vals, double *res) const +void MEDCouplingNoTimeLabel::getValueForTime(double time, const std::vector& vals, double *res) const throw(INTERP_KERNEL::Exception) { throw INTERP_KERNEL::Exception(EXCEPTION_MSG); } @@ -1222,7 +1222,7 @@ void MEDCouplingNoTimeLabel::getValueOnDiscTime(int eltId, int iteration, int or /*! * idem getTinySerializationIntInformation except that it is for multi field fetch */ -void MEDCouplingNoTimeLabel::getTinySerializationIntInformation2(std::vector& tinyInfo) const +void MEDCouplingNoTimeLabel::getTinySerializationIntInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { tinyInfo.clear(); } @@ -1230,7 +1230,7 @@ void MEDCouplingNoTimeLabel::getTinySerializationIntInformation2(std::vector& tinyInfo) const +void MEDCouplingNoTimeLabel::getTinySerializationDbleInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { tinyInfo.resize(1); tinyInfo[0]=_time_tolerance; @@ -1239,7 +1239,7 @@ void MEDCouplingNoTimeLabel::getTinySerializationDbleInformation2(std::vector& tinyInfoI, const std::vector& tinyInfoD) +void MEDCouplingNoTimeLabel::finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD) throw(INTERP_KERNEL::Exception) { _time_tolerance=tinyInfoD[0]; } @@ -1253,7 +1253,7 @@ MEDCouplingWithTimeStep::MEDCouplingWithTimeStep():_time(0.),_iteration(-1),_ord { } -std::string MEDCouplingWithTimeStep::getStringRepr() const +std::string MEDCouplingWithTimeStep::getStringRepr() const throw(INTERP_KERNEL::Exception) { std::ostringstream stream; stream << REPR << " Time is defined by iteration=" << _iteration << " order=" << _order << " and time=" << _time << "."; @@ -1272,20 +1272,20 @@ void MEDCouplingWithTimeStep::synchronizeTimeWith(const MEDCouplingMesh *mesh) t _time_unit=tUnit; } -void MEDCouplingWithTimeStep::getTinySerializationIntInformation(std::vector& tinyInfo) const +void MEDCouplingWithTimeStep::getTinySerializationIntInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { MEDCouplingTimeDiscretization::getTinySerializationIntInformation(tinyInfo); tinyInfo.push_back(_iteration); tinyInfo.push_back(_order); } -void MEDCouplingWithTimeStep::getTinySerializationDbleInformation(std::vector& tinyInfo) const +void MEDCouplingWithTimeStep::getTinySerializationDbleInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { MEDCouplingTimeDiscretization::getTinySerializationDbleInformation(tinyInfo); tinyInfo.push_back(_time); } -void MEDCouplingWithTimeStep::finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS) +void MEDCouplingWithTimeStep::finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS) throw(INTERP_KERNEL::Exception) { MEDCouplingTimeDiscretization::finishUnserialization(tinyInfoI,tinyInfoD,tinyInfoS); _time=tinyInfoD[1]; @@ -1296,7 +1296,7 @@ void MEDCouplingWithTimeStep::finishUnserialization(const std::vector& tiny /*! * idem getTinySerializationIntInformation except that it is for multi field fetch */ -void MEDCouplingWithTimeStep::getTinySerializationIntInformation2(std::vector& tinyInfo) const +void MEDCouplingWithTimeStep::getTinySerializationIntInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { tinyInfo.resize(2); tinyInfo[0]=_iteration; @@ -1306,7 +1306,7 @@ void MEDCouplingWithTimeStep::getTinySerializationIntInformation2(std::vector& tinyInfo) const +void MEDCouplingWithTimeStep::getTinySerializationDbleInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { tinyInfo.resize(2); tinyInfo[0]=_time_tolerance; @@ -1316,7 +1316,7 @@ void MEDCouplingWithTimeStep::getTinySerializationDbleInformation2(std::vector& tinyInfoI, const std::vector& tinyInfoD) +void MEDCouplingWithTimeStep::finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD) throw(INTERP_KERNEL::Exception) { _iteration=tinyInfoI[0]; _order=tinyInfoI[1]; @@ -1324,7 +1324,7 @@ void MEDCouplingWithTimeStep::finishUnserialization2(const std::vector& tin _time=tinyInfoD[1]; } -bool MEDCouplingWithTimeStep::areCompatible(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingWithTimeStep::areCompatible(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areCompatible(other)) return false; @@ -1332,7 +1332,7 @@ bool MEDCouplingWithTimeStep::areCompatible(const MEDCouplingTimeDiscretization return otherC!=0; } -bool MEDCouplingWithTimeStep::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const +bool MEDCouplingWithTimeStep::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areStrictlyCompatible(other,reason)) return false; @@ -1343,7 +1343,7 @@ bool MEDCouplingWithTimeStep::areStrictlyCompatible(const MEDCouplingTimeDiscret return ret; } -bool MEDCouplingWithTimeStep::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingWithTimeStep::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areStrictlyCompatibleForMul(other)) return false; @@ -1351,7 +1351,7 @@ bool MEDCouplingWithTimeStep::areStrictlyCompatibleForMul(const MEDCouplingTimeD return otherC!=0; } -bool MEDCouplingWithTimeStep::areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingWithTimeStep::areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areStrictlyCompatibleForDiv(other)) return false; @@ -1359,7 +1359,7 @@ bool MEDCouplingWithTimeStep::areStrictlyCompatibleForDiv(const MEDCouplingTimeD return otherC!=0; } -bool MEDCouplingWithTimeStep::areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingWithTimeStep::areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areCompatibleForMeld(other)) return false; @@ -1367,7 +1367,7 @@ bool MEDCouplingWithTimeStep::areCompatibleForMeld(const MEDCouplingTimeDiscreti return otherC!=0; } -bool MEDCouplingWithTimeStep::isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const +bool MEDCouplingWithTimeStep::isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); std::ostringstream oss; oss.precision(15); @@ -1397,7 +1397,7 @@ bool MEDCouplingWithTimeStep::isEqualIfNotWhy(const MEDCouplingTimeDiscretizatio return MEDCouplingTimeDiscretization::isEqualIfNotWhy(other,prec,reason); } -bool MEDCouplingWithTimeStep::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const +bool MEDCouplingWithTimeStep::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1422,7 +1422,7 @@ void MEDCouplingWithTimeStep::copyTinyAttrFrom(const MEDCouplingTimeDiscretizati _order=otherC->_order; } -MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::aggregate(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::aggregate(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1433,7 +1433,7 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::aggregate(const MEDCoupl return ret; } -MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::aggregate(const std::vector& other) const +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::aggregate(const std::vector& other) const throw(INTERP_KERNEL::Exception) { std::vector a(other.size()); int i=0; @@ -1450,7 +1450,7 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::aggregate(const std::vec return ret; } -MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::meld(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::meld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1461,7 +1461,7 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::meld(const MEDCouplingTi return ret; } -MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::dot(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::dot(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1472,7 +1472,7 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::dot(const MEDCouplingTim return ret; } -MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::crossProduct(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::crossProduct(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1483,7 +1483,7 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::crossProduct(const MEDCo return ret; } -MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::max(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::max(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1494,7 +1494,7 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::max(const MEDCouplingTim return ret; } -MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::min(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::min(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1505,7 +1505,7 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::min(const MEDCouplingTim return ret; } -MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::add(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::add(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1519,7 +1519,7 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::add(const MEDCouplingTim return ret; } -void MEDCouplingWithTimeStep::addEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingWithTimeStep::addEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1529,7 +1529,7 @@ void MEDCouplingWithTimeStep::addEqual(const MEDCouplingTimeDiscretization *othe getArray()->addEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::substract(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::substract(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1543,7 +1543,7 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::substract(const MEDCoupl return ret; } -void MEDCouplingWithTimeStep::substractEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingWithTimeStep::substractEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1553,7 +1553,7 @@ void MEDCouplingWithTimeStep::substractEqual(const MEDCouplingTimeDiscretization getArray()->substractEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::multiply(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::multiply(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1567,7 +1567,7 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::multiply(const MEDCoupli return ret; } -void MEDCouplingWithTimeStep::multiplyEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingWithTimeStep::multiplyEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1577,7 +1577,7 @@ void MEDCouplingWithTimeStep::multiplyEqual(const MEDCouplingTimeDiscretization getArray()->multiplyEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::divide(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::divide(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1591,7 +1591,7 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::divide(const MEDCoupling return ret; } -void MEDCouplingWithTimeStep::divideEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingWithTimeStep::divideEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1601,7 +1601,7 @@ void MEDCouplingWithTimeStep::divideEqual(const MEDCouplingTimeDiscretization *o getArray()->divideEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::pow(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::pow(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1615,7 +1615,7 @@ MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::pow(const MEDCouplingTim return ret; } -void MEDCouplingWithTimeStep::powEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingWithTimeStep::powEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingWithTimeStep *otherC=dynamic_cast(other); if(!otherC) @@ -1625,7 +1625,7 @@ void MEDCouplingWithTimeStep::powEqual(const MEDCouplingTimeDiscretization *othe getArray()->powEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::performCpy(bool deepCpy) const +MEDCouplingTimeDiscretization *MEDCouplingWithTimeStep::performCpy(bool deepCpy) const throw(INTERP_KERNEL::Exception) { return new MEDCouplingWithTimeStep(*this,deepCpy); } @@ -1657,7 +1657,7 @@ std::vector< const DataArrayDouble *> MEDCouplingWithTimeStep::getArraysForTime( throw INTERP_KERNEL::Exception(EXCEPTION_MSG); } -void MEDCouplingWithTimeStep::getValueForTime(double time, const std::vector& vals, double *res) const +void MEDCouplingWithTimeStep::getValueForTime(double time, const std::vector& vals, double *res) const throw(INTERP_KERNEL::Exception) { std::copy(vals.begin(),vals.end(),res); } @@ -1702,7 +1702,7 @@ void MEDCouplingConstOnTimeInterval::copyTinyAttrFrom(const MEDCouplingTimeDiscr _end_order=otherC->_end_order; } -void MEDCouplingConstOnTimeInterval::getTinySerializationIntInformation(std::vector& tinyInfo) const +void MEDCouplingConstOnTimeInterval::getTinySerializationIntInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { MEDCouplingTimeDiscretization::getTinySerializationIntInformation(tinyInfo); tinyInfo.push_back(_start_iteration); @@ -1711,14 +1711,14 @@ void MEDCouplingConstOnTimeInterval::getTinySerializationIntInformation(std::vec tinyInfo.push_back(_end_order); } -void MEDCouplingConstOnTimeInterval::getTinySerializationDbleInformation(std::vector& tinyInfo) const +void MEDCouplingConstOnTimeInterval::getTinySerializationDbleInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { MEDCouplingTimeDiscretization::getTinySerializationDbleInformation(tinyInfo); tinyInfo.push_back(_start_time); tinyInfo.push_back(_end_time); } -void MEDCouplingConstOnTimeInterval::finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS) +void MEDCouplingConstOnTimeInterval::finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS) throw(INTERP_KERNEL::Exception) { MEDCouplingTimeDiscretization::finishUnserialization(tinyInfoI,tinyInfoD,tinyInfoS); _start_time=tinyInfoD[1]; @@ -1732,7 +1732,7 @@ void MEDCouplingConstOnTimeInterval::finishUnserialization(const std::vector& tinyInfo) const +void MEDCouplingConstOnTimeInterval::getTinySerializationIntInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { tinyInfo.resize(4); tinyInfo[0]=_start_iteration; @@ -1744,7 +1744,7 @@ void MEDCouplingConstOnTimeInterval::getTinySerializationIntInformation2(std::ve /*! * idem getTinySerializationDbleInformation except that it is for multi field fetch */ -void MEDCouplingConstOnTimeInterval::getTinySerializationDbleInformation2(std::vector& tinyInfo) const +void MEDCouplingConstOnTimeInterval::getTinySerializationDbleInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { tinyInfo.resize(3); tinyInfo[0]=_time_tolerance; @@ -1755,7 +1755,7 @@ void MEDCouplingConstOnTimeInterval::getTinySerializationDbleInformation2(std::v /*! * idem finishUnserialization except that it is for multi field fetch */ -void MEDCouplingConstOnTimeInterval::finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD) +void MEDCouplingConstOnTimeInterval::finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD) throw(INTERP_KERNEL::Exception) { _start_iteration=tinyInfoI[0]; _start_order=tinyInfoI[1]; @@ -1772,7 +1772,7 @@ MEDCouplingConstOnTimeInterval::MEDCouplingConstOnTimeInterval(const MEDCoupling { } -std::string MEDCouplingConstOnTimeInterval::getStringRepr() const +std::string MEDCouplingConstOnTimeInterval::getStringRepr() const throw(INTERP_KERNEL::Exception) { std::ostringstream stream; stream << REPR << " Time interval is defined by :\niteration_start=" << _start_iteration << " order_start=" << _start_order << " and time_start=" << _start_time << "\n"; @@ -1793,7 +1793,7 @@ void MEDCouplingConstOnTimeInterval::synchronizeTimeWith(const MEDCouplingMesh * _time_unit=tUnit; } -MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::performCpy(bool deepCpy) const +MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::performCpy(bool deepCpy) const throw(INTERP_KERNEL::Exception) { return new MEDCouplingConstOnTimeInterval(*this,deepCpy); } @@ -1810,12 +1810,12 @@ std::vector< const DataArrayDouble *> MEDCouplingConstOnTimeInterval::getArraysF throw INTERP_KERNEL::Exception(EXCEPTION_MSG); } -void MEDCouplingConstOnTimeInterval::getValueForTime(double time, const std::vector& vals, double *res) const +void MEDCouplingConstOnTimeInterval::getValueForTime(double time, const std::vector& vals, double *res) const throw(INTERP_KERNEL::Exception) { std::copy(vals.begin(),vals.end(),res); } -bool MEDCouplingConstOnTimeInterval::areCompatible(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingConstOnTimeInterval::areCompatible(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areCompatible(other)) return false; @@ -1823,7 +1823,7 @@ bool MEDCouplingConstOnTimeInterval::areCompatible(const MEDCouplingTimeDiscreti return otherC!=0; } -bool MEDCouplingConstOnTimeInterval::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const +bool MEDCouplingConstOnTimeInterval::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areStrictlyCompatible(other,reason)) return false; @@ -1834,7 +1834,7 @@ bool MEDCouplingConstOnTimeInterval::areStrictlyCompatible(const MEDCouplingTime return ret; } -bool MEDCouplingConstOnTimeInterval::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingConstOnTimeInterval::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areStrictlyCompatibleForMul(other)) return false; @@ -1842,7 +1842,7 @@ bool MEDCouplingConstOnTimeInterval::areStrictlyCompatibleForMul(const MEDCoupli return otherC!=0; } -bool MEDCouplingConstOnTimeInterval::areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingConstOnTimeInterval::areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areStrictlyCompatibleForDiv(other)) return false; @@ -1850,7 +1850,7 @@ bool MEDCouplingConstOnTimeInterval::areStrictlyCompatibleForDiv(const MEDCoupli return otherC!=0; } -bool MEDCouplingConstOnTimeInterval::areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingConstOnTimeInterval::areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areCompatibleForMeld(other)) return false; @@ -1858,7 +1858,7 @@ bool MEDCouplingConstOnTimeInterval::areCompatibleForMeld(const MEDCouplingTimeD return otherC!=0; } -bool MEDCouplingConstOnTimeInterval::isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const +bool MEDCouplingConstOnTimeInterval::isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); std::ostringstream oss; oss.precision(15); @@ -1906,7 +1906,7 @@ bool MEDCouplingConstOnTimeInterval::isEqualIfNotWhy(const MEDCouplingTimeDiscre return MEDCouplingTimeDiscretization::isEqualIfNotWhy(other,prec,reason); } -bool MEDCouplingConstOnTimeInterval::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const +bool MEDCouplingConstOnTimeInterval::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -1964,7 +1964,7 @@ void MEDCouplingConstOnTimeInterval::checkTimePresence(double time) const throw( } } -MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::aggregate(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::aggregate(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -1975,7 +1975,7 @@ MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::aggregate(const M return ret; } -MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::aggregate(const std::vector& other) const +MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::aggregate(const std::vector& other) const throw(INTERP_KERNEL::Exception) { std::vector a(other.size()); int i=0; @@ -1992,7 +1992,7 @@ MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::aggregate(const s return ret; } -MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::meld(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::meld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2004,7 +2004,7 @@ MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::meld(const MEDCou return ret; } -MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::dot(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::dot(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2015,7 +2015,7 @@ MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::dot(const MEDCoup return ret; } -MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::crossProduct(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::crossProduct(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2026,7 +2026,7 @@ MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::crossProduct(cons return ret; } -MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::max(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::max(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2037,7 +2037,7 @@ MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::max(const MEDCoup return ret; } -MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::min(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::min(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2048,7 +2048,7 @@ MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::min(const MEDCoup return ret; } -MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::add(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::add(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2064,7 +2064,7 @@ MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::add(const MEDCoup return ret; } -void MEDCouplingConstOnTimeInterval::addEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingConstOnTimeInterval::addEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2074,7 +2074,7 @@ void MEDCouplingConstOnTimeInterval::addEqual(const MEDCouplingTimeDiscretizatio getArray()->addEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::substract(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::substract(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2090,7 +2090,7 @@ MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::substract(const M return ret; } -void MEDCouplingConstOnTimeInterval::substractEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingConstOnTimeInterval::substractEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2100,7 +2100,7 @@ void MEDCouplingConstOnTimeInterval::substractEqual(const MEDCouplingTimeDiscret getArray()->substractEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::multiply(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::multiply(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2116,7 +2116,7 @@ MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::multiply(const ME return ret; } -void MEDCouplingConstOnTimeInterval::multiplyEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingConstOnTimeInterval::multiplyEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2126,7 +2126,7 @@ void MEDCouplingConstOnTimeInterval::multiplyEqual(const MEDCouplingTimeDiscreti getArray()->multiplyEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::divide(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::divide(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2142,7 +2142,7 @@ MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::divide(const MEDC return ret; } -void MEDCouplingConstOnTimeInterval::divideEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingConstOnTimeInterval::divideEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2152,7 +2152,7 @@ void MEDCouplingConstOnTimeInterval::divideEqual(const MEDCouplingTimeDiscretiza getArray()->divideEqual(other->getArray()); } -MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::pow(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::pow(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2168,7 +2168,7 @@ MEDCouplingTimeDiscretization *MEDCouplingConstOnTimeInterval::pow(const MEDCoup return ret; } -void MEDCouplingConstOnTimeInterval::powEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingConstOnTimeInterval::powEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingConstOnTimeInterval *otherC=dynamic_cast(other); if(!otherC) @@ -2230,7 +2230,7 @@ void MEDCouplingTwoTimeSteps::copyTinyAttrFrom(const MEDCouplingTimeDiscretizati _end_order=otherC->_end_order; } -void MEDCouplingTwoTimeSteps::copyTinyStringsFrom(const MEDCouplingTimeDiscretization& other) +void MEDCouplingTwoTimeSteps::copyTinyStringsFrom(const MEDCouplingTimeDiscretization& other) throw(INTERP_KERNEL::Exception) { MEDCouplingTimeDiscretization::copyTinyStringsFrom(other); const MEDCouplingTwoTimeSteps *otherC=dynamic_cast(&other); @@ -2240,12 +2240,12 @@ void MEDCouplingTwoTimeSteps::copyTinyStringsFrom(const MEDCouplingTimeDiscretiz _end_array->copyStringInfoFrom(*otherC->_end_array); } -const DataArrayDouble *MEDCouplingTwoTimeSteps::getEndArray() const +const DataArrayDouble *MEDCouplingTwoTimeSteps::getEndArray() const throw(INTERP_KERNEL::Exception) { return _end_array; } -DataArrayDouble *MEDCouplingTwoTimeSteps::getEndArray() +DataArrayDouble *MEDCouplingTwoTimeSteps::getEndArray() throw(INTERP_KERNEL::Exception) { return _end_array; } @@ -2261,7 +2261,7 @@ void MEDCouplingTwoTimeSteps::checkCoherency() const throw(INTERP_KERNEL::Except throw INTERP_KERNEL::Exception("The number of tuples mismatch between the start and the end arrays !"); } -bool MEDCouplingTwoTimeSteps::isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const +bool MEDCouplingTwoTimeSteps::isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception) { std::ostringstream oss; const MEDCouplingTwoTimeSteps *otherC=dynamic_cast(other); @@ -2315,7 +2315,7 @@ bool MEDCouplingTwoTimeSteps::isEqualIfNotWhy(const MEDCouplingTimeDiscretizatio return MEDCouplingTimeDiscretization::isEqualIfNotWhy(other,prec,reason); } -bool MEDCouplingTwoTimeSteps::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const +bool MEDCouplingTwoTimeSteps::isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const throw(INTERP_KERNEL::Exception) { const MEDCouplingTwoTimeSteps *otherC=dynamic_cast(other); if(!otherC) @@ -2364,14 +2364,14 @@ void MEDCouplingTwoTimeSteps::checkTimePresence(double time) const throw(INTERP_ } } -void MEDCouplingTwoTimeSteps::getArrays(std::vector& arrays) const +void MEDCouplingTwoTimeSteps::getArrays(std::vector& arrays) const throw(INTERP_KERNEL::Exception) { arrays.resize(2); arrays[0]=_array; arrays[1]=_end_array; } -void MEDCouplingTwoTimeSteps::setEndArray(DataArrayDouble *array, TimeLabel *owner) +void MEDCouplingTwoTimeSteps::setEndArray(DataArrayDouble *array, TimeLabel *owner) throw(INTERP_KERNEL::Exception) { if(array!=_end_array) { @@ -2385,7 +2385,7 @@ void MEDCouplingTwoTimeSteps::setEndArray(DataArrayDouble *array, TimeLabel *own } } -void MEDCouplingTwoTimeSteps::getTinySerializationIntInformation(std::vector& tinyInfo) const +void MEDCouplingTwoTimeSteps::getTinySerializationIntInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { MEDCouplingTimeDiscretization::getTinySerializationIntInformation(tinyInfo); tinyInfo.push_back(_start_iteration); @@ -2404,14 +2404,14 @@ void MEDCouplingTwoTimeSteps::getTinySerializationIntInformation(std::vector& tinyInfo) const +void MEDCouplingTwoTimeSteps::getTinySerializationDbleInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { MEDCouplingTimeDiscretization::getTinySerializationDbleInformation(tinyInfo); tinyInfo.push_back(_start_time); tinyInfo.push_back(_end_time); } -void MEDCouplingTwoTimeSteps::getTinySerializationStrInformation(std::vector& tinyInfo) const +void MEDCouplingTwoTimeSteps::getTinySerializationStrInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { int nbOfCompo=_array->getNumberOfComponents(); for(int i=0;igetInfoOnComponent(i)); } -void MEDCouplingTwoTimeSteps::resizeForUnserialization(const std::vector& tinyInfoI, std::vector& arrays) +void MEDCouplingTwoTimeSteps::resizeForUnserialization(const std::vector& tinyInfoI, std::vector& arrays) throw(INTERP_KERNEL::Exception) { arrays.resize(2); if(_array!=0) @@ -2445,7 +2445,7 @@ void MEDCouplingTwoTimeSteps::resizeForUnserialization(const std::vector& t arrays[1]=arr; } -void MEDCouplingTwoTimeSteps::finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS) +void MEDCouplingTwoTimeSteps::finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS) throw(INTERP_KERNEL::Exception) { MEDCouplingTimeDiscretization::finishUnserialization(tinyInfoI,tinyInfoD,tinyInfoS); _start_time=tinyInfoD[1]; @@ -2459,7 +2459,7 @@ void MEDCouplingTwoTimeSteps::finishUnserialization(const std::vector& tiny /*! * idem getTinySerializationIntInformation except that it is for multi field fetch */ -void MEDCouplingTwoTimeSteps::getTinySerializationIntInformation2(std::vector& tinyInfo) const +void MEDCouplingTwoTimeSteps::getTinySerializationIntInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { tinyInfo.resize(4); tinyInfo[0]=_start_iteration; @@ -2471,7 +2471,7 @@ void MEDCouplingTwoTimeSteps::getTinySerializationIntInformation2(std::vector& tinyInfo) const +void MEDCouplingTwoTimeSteps::getTinySerializationDbleInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) { tinyInfo.resize(3); tinyInfo[0]=_time_tolerance; @@ -2482,7 +2482,7 @@ void MEDCouplingTwoTimeSteps::getTinySerializationDbleInformation2(std::vector& tinyInfoI, const std::vector& tinyInfoD) +void MEDCouplingTwoTimeSteps::finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD) throw(INTERP_KERNEL::Exception) { _start_iteration=tinyInfoI[0]; _start_order=tinyInfoI[1]; @@ -2522,7 +2522,7 @@ MEDCouplingLinearTime::MEDCouplingLinearTime() { } -std::string MEDCouplingLinearTime::getStringRepr() const +std::string MEDCouplingLinearTime::getStringRepr() const throw(INTERP_KERNEL::Exception) { std::ostringstream stream; stream << REPR << " Time interval is defined by :\niteration_start=" << _start_iteration << " order_start=" << _start_order << " and time_start=" << _start_time << "\n"; @@ -2538,12 +2538,12 @@ void MEDCouplingLinearTime::checkCoherency() const throw(INTERP_KERNEL::Exceptio throw INTERP_KERNEL::Exception("Start time and end time are equals regarding time tolerance."); } -MEDCouplingTimeDiscretization *MEDCouplingLinearTime::performCpy(bool deepCpy) const +MEDCouplingTimeDiscretization *MEDCouplingLinearTime::performCpy(bool deepCpy) const throw(INTERP_KERNEL::Exception) { return new MEDCouplingLinearTime(*this,deepCpy); } -bool MEDCouplingLinearTime::areCompatible(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingLinearTime::areCompatible(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areCompatible(other)) return false; @@ -2559,7 +2559,7 @@ bool MEDCouplingLinearTime::areCompatible(const MEDCouplingTimeDiscretization *o return true; } -bool MEDCouplingLinearTime::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const +bool MEDCouplingLinearTime::areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areStrictlyCompatible(other,reason)) return false; @@ -2570,7 +2570,7 @@ bool MEDCouplingLinearTime::areStrictlyCompatible(const MEDCouplingTimeDiscretiz return ret; } -bool MEDCouplingLinearTime::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingLinearTime::areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areStrictlyCompatibleForMul(other)) return false; @@ -2578,7 +2578,7 @@ bool MEDCouplingLinearTime::areStrictlyCompatibleForMul(const MEDCouplingTimeDis return otherC!=0; } -bool MEDCouplingLinearTime::areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingLinearTime::areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areStrictlyCompatibleForDiv(other)) return false; @@ -2596,7 +2596,7 @@ bool MEDCouplingLinearTime::areStrictlyCompatibleForDiv(const MEDCouplingTimeDis return true; } -bool MEDCouplingLinearTime::areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const +bool MEDCouplingLinearTime::areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { if(!MEDCouplingTimeDiscretization::areCompatibleForMeld(other)) return false; @@ -2607,7 +2607,7 @@ bool MEDCouplingLinearTime::areCompatibleForMeld(const MEDCouplingTimeDiscretiza /*! * 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 +void MEDCouplingLinearTime::getValueForTime(double time, const std::vector& vals, double *res) const throw(INTERP_KERNEL::Exception) { double alpha=(_end_time-time)/(_end_time-_start_time); std::size_t nbComp=vals.size()/2; @@ -2656,7 +2656,7 @@ void MEDCouplingLinearTime::getValueOnDiscTime(int eltId, int iteration, int ord throw INTERP_KERNEL::Exception(EXCEPTION_MSG); } -MEDCouplingTimeDiscretization *MEDCouplingLinearTime::aggregate(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingLinearTime::aggregate(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2669,7 +2669,7 @@ MEDCouplingTimeDiscretization *MEDCouplingLinearTime::aggregate(const MEDCouplin return ret; } -MEDCouplingTimeDiscretization *MEDCouplingLinearTime::aggregate(const std::vector& other) const +MEDCouplingTimeDiscretization *MEDCouplingLinearTime::aggregate(const std::vector& other) const throw(INTERP_KERNEL::Exception) { std::vector a(other.size()); std::vector b(other.size()); @@ -2690,7 +2690,7 @@ MEDCouplingTimeDiscretization *MEDCouplingLinearTime::aggregate(const std::vecto return ret; } -MEDCouplingTimeDiscretization *MEDCouplingLinearTime::meld(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingLinearTime::meld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2704,7 +2704,7 @@ MEDCouplingTimeDiscretization *MEDCouplingLinearTime::meld(const MEDCouplingTime return ret; } -MEDCouplingTimeDiscretization *MEDCouplingLinearTime::dot(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingLinearTime::dot(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2717,7 +2717,7 @@ MEDCouplingTimeDiscretization *MEDCouplingLinearTime::dot(const MEDCouplingTimeD return ret; } -MEDCouplingTimeDiscretization *MEDCouplingLinearTime::crossProduct(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingLinearTime::crossProduct(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2730,7 +2730,7 @@ MEDCouplingTimeDiscretization *MEDCouplingLinearTime::crossProduct(const MEDCoup return ret; } -MEDCouplingTimeDiscretization *MEDCouplingLinearTime::max(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingLinearTime::max(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2743,7 +2743,7 @@ MEDCouplingTimeDiscretization *MEDCouplingLinearTime::max(const MEDCouplingTimeD return ret; } -MEDCouplingTimeDiscretization *MEDCouplingLinearTime::min(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingLinearTime::min(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2756,7 +2756,7 @@ MEDCouplingTimeDiscretization *MEDCouplingLinearTime::min(const MEDCouplingTimeD return ret; } -MEDCouplingTimeDiscretization *MEDCouplingLinearTime::add(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingLinearTime::add(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2769,7 +2769,7 @@ MEDCouplingTimeDiscretization *MEDCouplingLinearTime::add(const MEDCouplingTimeD return ret; } -void MEDCouplingLinearTime::addEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingLinearTime::addEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2782,7 +2782,7 @@ void MEDCouplingLinearTime::addEqual(const MEDCouplingTimeDiscretization *other) getEndArray()->addEqual(other->getEndArray()); } -MEDCouplingTimeDiscretization *MEDCouplingLinearTime::substract(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingLinearTime::substract(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2795,7 +2795,7 @@ MEDCouplingTimeDiscretization *MEDCouplingLinearTime::substract(const MEDCouplin return ret; } -void MEDCouplingLinearTime::substractEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingLinearTime::substractEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2808,7 +2808,7 @@ void MEDCouplingLinearTime::substractEqual(const MEDCouplingTimeDiscretization * getEndArray()->substractEqual(other->getEndArray()); } -MEDCouplingTimeDiscretization *MEDCouplingLinearTime::multiply(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingLinearTime::multiply(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2821,7 +2821,7 @@ MEDCouplingTimeDiscretization *MEDCouplingLinearTime::multiply(const MEDCoupling return ret; } -void MEDCouplingLinearTime::multiplyEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingLinearTime::multiplyEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2834,7 +2834,7 @@ void MEDCouplingLinearTime::multiplyEqual(const MEDCouplingTimeDiscretization *o getEndArray()->multiplyEqual(other->getEndArray()); } -MEDCouplingTimeDiscretization *MEDCouplingLinearTime::divide(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingLinearTime::divide(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2847,7 +2847,7 @@ MEDCouplingTimeDiscretization *MEDCouplingLinearTime::divide(const MEDCouplingTi return ret; } -void MEDCouplingLinearTime::divideEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingLinearTime::divideEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2860,7 +2860,7 @@ void MEDCouplingLinearTime::divideEqual(const MEDCouplingTimeDiscretization *oth getEndArray()->divideEqual(other->getEndArray()); } -MEDCouplingTimeDiscretization *MEDCouplingLinearTime::pow(const MEDCouplingTimeDiscretization *other) const +MEDCouplingTimeDiscretization *MEDCouplingLinearTime::pow(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) @@ -2873,7 +2873,7 @@ MEDCouplingTimeDiscretization *MEDCouplingLinearTime::pow(const MEDCouplingTimeD return ret; } -void MEDCouplingLinearTime::powEqual(const MEDCouplingTimeDiscretization *other) +void MEDCouplingLinearTime::powEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) { const MEDCouplingLinearTime *otherC=dynamic_cast(other); if(!otherC) diff --git a/src/MEDCoupling/MEDCouplingTimeDiscretization.hxx b/src/MEDCoupling/MEDCouplingTimeDiscretization.hxx index b252ef5e1..8cdbbe957 100644 --- a/src/MEDCoupling/MEDCouplingTimeDiscretization.hxx +++ b/src/MEDCoupling/MEDCouplingTimeDiscretization.hxx @@ -42,64 +42,64 @@ namespace ParaMEDMEM public: void updateTime() const; virtual std::size_t getHeapMemorySize() const; - static MEDCouplingTimeDiscretization *New(TypeOfTimeDiscretization type); + static MEDCouplingTimeDiscretization *New(TypeOfTimeDiscretization type) throw(INTERP_KERNEL::Exception); void setTimeUnit(const char *unit) { _time_unit=unit; } const char *getTimeUnit() const { return _time_unit.c_str(); } virtual void copyTinyAttrFrom(const MEDCouplingTimeDiscretization& other) throw(INTERP_KERNEL::Exception); - virtual void copyTinyStringsFrom(const MEDCouplingTimeDiscretization& other); + virtual void copyTinyStringsFrom(const MEDCouplingTimeDiscretization& other) throw(INTERP_KERNEL::Exception); virtual void checkCoherency() const throw(INTERP_KERNEL::Exception); - virtual bool areCompatible(const MEDCouplingTimeDiscretization *other) const; - virtual bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const; - virtual bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const; - virtual bool areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const; - virtual bool areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const; - virtual bool isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const; - virtual bool isEqual(const MEDCouplingTimeDiscretization *other, double prec) const; - virtual bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const; - virtual MEDCouplingTimeDiscretization *buildNewTimeReprFromThis(TypeOfTimeDiscretization type, bool deepCpy) const; - virtual std::string getStringRepr() const = 0; - virtual TypeOfTimeDiscretization getEnum() const = 0; + virtual bool areCompatible(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + virtual bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const throw(INTERP_KERNEL::Exception); + virtual bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + virtual bool areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + virtual bool areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + virtual bool isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception); + virtual bool isEqual(const MEDCouplingTimeDiscretization *other, double prec) const throw(INTERP_KERNEL::Exception); + virtual bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const throw(INTERP_KERNEL::Exception); + virtual MEDCouplingTimeDiscretization *buildNewTimeReprFromThis(TypeOfTimeDiscretization type, bool deepCpy) const throw(INTERP_KERNEL::Exception); + virtual std::string getStringRepr() const throw(INTERP_KERNEL::Exception) = 0; + virtual TypeOfTimeDiscretization getEnum() const throw(INTERP_KERNEL::Exception) = 0; virtual void synchronizeTimeWith(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception) = 0; - virtual MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const = 0; - virtual MEDCouplingTimeDiscretization *aggregate(const std::vector& other) const = 0; - virtual MEDCouplingTimeDiscretization *meld(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; - virtual void substractEqual(const MEDCouplingTimeDiscretization *other) = 0; - virtual MEDCouplingTimeDiscretization *multiply(const MEDCouplingTimeDiscretization *other) const = 0; - virtual void multiplyEqual(const MEDCouplingTimeDiscretization *other) = 0; - virtual MEDCouplingTimeDiscretization *divide(const MEDCouplingTimeDiscretization *other) const = 0; - virtual void divideEqual(const MEDCouplingTimeDiscretization *other) = 0; - virtual MEDCouplingTimeDiscretization *pow(const MEDCouplingTimeDiscretization *other) const = 0; - virtual void powEqual(const MEDCouplingTimeDiscretization *other) = 0; - virtual void getTinySerializationIntInformation(std::vector& tinyInfo) const; - virtual void getTinySerializationDbleInformation(std::vector& tinyInfo) const; - virtual void getTinySerializationStrInformation(std::vector& tinyInfo) const; - virtual void resizeForUnserialization(const std::vector& tinyInfoI, std::vector& arrays); - virtual void finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS); - virtual void getTinySerializationIntInformation2(std::vector& tinyInfo) const = 0; - virtual void getTinySerializationDbleInformation2(std::vector& tinyInfo) const = 0; - virtual void finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD) = 0; - virtual MEDCouplingTimeDiscretization *performCpy(bool deepCpy) const = 0; + virtual MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual MEDCouplingTimeDiscretization *aggregate(const std::vector& other) const throw(INTERP_KERNEL::Exception) = 0; + virtual MEDCouplingTimeDiscretization *meld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual MEDCouplingTimeDiscretization *dot(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual MEDCouplingTimeDiscretization *crossProduct(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual MEDCouplingTimeDiscretization *max(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual MEDCouplingTimeDiscretization *min(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual MEDCouplingTimeDiscretization *add(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual void addEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) = 0; + virtual MEDCouplingTimeDiscretization *substract(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual void substractEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) = 0; + virtual MEDCouplingTimeDiscretization *multiply(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual void multiplyEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) = 0; + virtual MEDCouplingTimeDiscretization *divide(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual void divideEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) = 0; + virtual MEDCouplingTimeDiscretization *pow(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual void powEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception) = 0; + virtual void getTinySerializationIntInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + virtual void getTinySerializationDbleInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + virtual void getTinySerializationStrInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + virtual void resizeForUnserialization(const std::vector& tinyInfoI, std::vector& arrays) throw(INTERP_KERNEL::Exception); + virtual void finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS) throw(INTERP_KERNEL::Exception); + virtual void getTinySerializationIntInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) = 0; + virtual void getTinySerializationDbleInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception) = 0; + virtual void finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD) throw(INTERP_KERNEL::Exception) = 0; + virtual MEDCouplingTimeDiscretization *performCpy(bool deepCpy) const throw(INTERP_KERNEL::Exception) = 0; void setTimeTolerance(double val) { _time_tolerance=val; } double getTimeTolerance() const { return _time_tolerance; } 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 setArray(DataArrayDouble *array, TimeLabel *owner) throw(INTERP_KERNEL::Exception); + virtual void setEndArray(DataArrayDouble *array, TimeLabel *owner) throw(INTERP_KERNEL::Exception); virtual void setArrays(const std::vector& arrays, TimeLabel *owner) throw(INTERP_KERNEL::Exception); - DataArrayDouble *getArray() { return _array; } - const DataArrayDouble *getArray() const { return _array; } - virtual const DataArrayDouble *getEndArray() const; - virtual DataArrayDouble *getEndArray(); + DataArrayDouble *getArray() throw(INTERP_KERNEL::Exception) { return _array; } + const DataArrayDouble *getArray() const throw(INTERP_KERNEL::Exception) { return _array; } + virtual const DataArrayDouble *getEndArray() const throw(INTERP_KERNEL::Exception); + virtual DataArrayDouble *getEndArray() throw(INTERP_KERNEL::Exception); 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 void getValueForTime(double time, const std::vector& vals, double *res) const throw(INTERP_KERNEL::Exception) = 0; + virtual void getArrays(std::vector& arrays) const throw(INTERP_KERNEL::Exception); 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& iteration, int& order) const throw(INTERP_KERNEL::Exception) { return getStartTime(iteration,order); } @@ -134,16 +134,16 @@ namespace ParaMEDMEM virtual void setSelectedComponents(const MEDCouplingTimeDiscretization *other, const std::vector& compoIds) 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 setUniformValue(int nbOfTuple, int nbOfCompo, double value); - virtual void setOrCreateUniformValueOnAllComponents(int nbOfTuple, double value); - 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 applyFunc2(int nbOfComp, const char *func); - virtual void applyFunc3(int nbOfComp, const std::vector& varsOrder, const char *func); - virtual void applyFunc(const char *func); - virtual void applyFuncFast32(const char *func); - virtual void applyFuncFast64(const char *func); + virtual void setUniformValue(int nbOfTuple, int nbOfCompo, double value) throw(INTERP_KERNEL::Exception); + virtual void setOrCreateUniformValueOnAllComponents(int nbOfTuple, double value) throw(INTERP_KERNEL::Exception); + virtual void applyLin(double a, double b, int compoId) throw(INTERP_KERNEL::Exception); + virtual void applyFunc(int nbOfComp, FunctionToEvaluate func) throw(INTERP_KERNEL::Exception); + virtual void applyFunc(int nbOfComp, const char *func) throw(INTERP_KERNEL::Exception); + virtual void applyFunc2(int nbOfComp, const char *func) throw(INTERP_KERNEL::Exception); + virtual void applyFunc3(int nbOfComp, const std::vector& varsOrder, const char *func) throw(INTERP_KERNEL::Exception); + virtual void applyFunc(const char *func) throw(INTERP_KERNEL::Exception); + virtual void applyFuncFast32(const char *func) throw(INTERP_KERNEL::Exception); + virtual void applyFuncFast64(const char *func) throw(INTERP_KERNEL::Exception); virtual void fillFromAnalytic(const DataArrayDouble *loc, int nbOfComp, FunctionToEvaluate func) throw(INTERP_KERNEL::Exception); virtual void fillFromAnalytic(const DataArrayDouble *loc, int nbOfComp, const char *func) throw(INTERP_KERNEL::Exception); virtual void fillFromAnalytic2(const DataArrayDouble *loc, int nbOfComp, const char *func) throw(INTERP_KERNEL::Exception); @@ -163,38 +163,38 @@ namespace ParaMEDMEM public: MEDCouplingNoTimeLabel(); MEDCouplingNoTimeLabel(const MEDCouplingTimeDiscretization& other, bool deepCpy); - std::string getStringRepr() const; - TypeOfTimeDiscretization getEnum() const { return DISCRETIZATION; } + std::string getStringRepr() const throw(INTERP_KERNEL::Exception); + TypeOfTimeDiscretization getEnum() const throw(INTERP_KERNEL::Exception) { return DISCRETIZATION; } void synchronizeTimeWith(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception); - MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const; - MEDCouplingTimeDiscretization *aggregate(const std::vector& other) const; - MEDCouplingTimeDiscretization *meld(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); - MEDCouplingTimeDiscretization *pow(const MEDCouplingTimeDiscretization *other) const; - void powEqual(const MEDCouplingTimeDiscretization *other); - bool isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const; - bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const; - bool areCompatible(const MEDCouplingTimeDiscretization *other) const; - bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const; - bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const; - bool areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const; - bool areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const; - MEDCouplingTimeDiscretization *performCpy(bool deepCpy) const; + MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *aggregate(const std::vector& other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *meld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *dot(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *crossProduct(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *max(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *min(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *add(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void addEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *substract(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void substractEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *multiply(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void multiplyEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *divide(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void divideEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *pow(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void powEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + bool isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception); + bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const throw(INTERP_KERNEL::Exception); + bool areCompatible(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const throw(INTERP_KERNEL::Exception); + bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + bool areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + bool areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *performCpy(bool deepCpy) const throw(INTERP_KERNEL::Exception); void checkNoTimePresence() const throw(INTERP_KERNEL::Exception) { } void checkTimePresence(double time) const throw(INTERP_KERNEL::Exception); std::vector< const DataArrayDouble *> getArraysForTime(double time) const throw(INTERP_KERNEL::Exception); - void getValueForTime(double time, const std::vector& vals, double *res) const; + void getValueForTime(double time, const std::vector& vals, double *res) const throw(INTERP_KERNEL::Exception); bool isBefore(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); bool isStrictlyBefore(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); double getStartTime(int& iteration, int& order) const throw(INTERP_KERNEL::Exception); @@ -209,9 +209,9 @@ namespace ParaMEDMEM 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 iteration, int order, double *value) const throw(INTERP_KERNEL::Exception); - void getTinySerializationIntInformation2(std::vector& tinyInfo) const; - void getTinySerializationDbleInformation2(std::vector& tinyInfo) const; - void finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD); + void getTinySerializationIntInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void getTinySerializationDbleInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD) throw(INTERP_KERNEL::Exception); public: static const TypeOfTimeDiscretization DISCRETIZATION=NO_TIME; static const char REPR[]; @@ -225,41 +225,41 @@ namespace ParaMEDMEM MEDCouplingWithTimeStep(const MEDCouplingWithTimeStep& other, bool deepCpy); public: MEDCouplingWithTimeStep(); - std::string getStringRepr() const; + std::string getStringRepr() const throw(INTERP_KERNEL::Exception); void copyTinyAttrFrom(const MEDCouplingTimeDiscretization& other) throw(INTERP_KERNEL::Exception); - TypeOfTimeDiscretization getEnum() const { return DISCRETIZATION; } + TypeOfTimeDiscretization getEnum() const throw(INTERP_KERNEL::Exception) { return DISCRETIZATION; } void synchronizeTimeWith(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception); - MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const; - MEDCouplingTimeDiscretization *aggregate(const std::vector& other) const; - MEDCouplingTimeDiscretization *meld(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); - MEDCouplingTimeDiscretization *pow(const MEDCouplingTimeDiscretization *other) const; - void powEqual(const MEDCouplingTimeDiscretization *other); - bool isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const; - bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const; - bool areCompatible(const MEDCouplingTimeDiscretization *other) const; - bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const; - bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const; - bool areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const; - bool areCompatibleForMeld(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); - void getTinySerializationIntInformation2(std::vector& tinyInfo) const; - void getTinySerializationDbleInformation2(std::vector& tinyInfo) const; - void finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD); - MEDCouplingTimeDiscretization *performCpy(bool deepCpy) const; + MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *aggregate(const std::vector& other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *meld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *dot(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *crossProduct(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *max(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *min(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *add(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void addEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *substract(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void substractEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *multiply(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void multiplyEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *divide(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void divideEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *pow(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void powEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + bool isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception); + bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const throw(INTERP_KERNEL::Exception); + bool areCompatible(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const throw(INTERP_KERNEL::Exception); + bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + bool areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + bool areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void getTinySerializationIntInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void getTinySerializationDbleInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS) throw(INTERP_KERNEL::Exception); + void getTinySerializationIntInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void getTinySerializationDbleInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *performCpy(bool deepCpy) const throw(INTERP_KERNEL::Exception); void checkNoTimePresence() const throw(INTERP_KERNEL::Exception); void checkTimePresence(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; } @@ -273,7 +273,7 @@ namespace ParaMEDMEM void setStartTimeValue(double time) throw(INTERP_KERNEL::Exception) { _time=time; } void setEndTimeValue(double time) throw(INTERP_KERNEL::Exception) { _time=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 getValueForTime(double time, const std::vector& vals, double *res) const throw(INTERP_KERNEL::Exception); 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); public: @@ -294,44 +294,44 @@ namespace ParaMEDMEM public: MEDCouplingConstOnTimeInterval(); void copyTinyAttrFrom(const MEDCouplingTimeDiscretization& other) throw(INTERP_KERNEL::Exception); - 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); - void getTinySerializationIntInformation2(std::vector& tinyInfo) const; - void getTinySerializationDbleInformation2(std::vector& tinyInfo) const; - void finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD); - MEDCouplingTimeDiscretization *performCpy(bool deepCpy) const; - bool areCompatible(const MEDCouplingTimeDiscretization *other) const; - bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const; - bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const; - bool areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const; - bool areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const; - bool isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const; - bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const; + void getTinySerializationIntInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void getTinySerializationDbleInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS) throw(INTERP_KERNEL::Exception); + void getTinySerializationIntInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void getTinySerializationDbleInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *performCpy(bool deepCpy) const throw(INTERP_KERNEL::Exception); + bool areCompatible(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const throw(INTERP_KERNEL::Exception); + bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + bool areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + bool areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + bool isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception); + bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const throw(INTERP_KERNEL::Exception); std::vector< const DataArrayDouble *> getArraysForTime(double time) const throw(INTERP_KERNEL::Exception); - void getValueForTime(double time, const std::vector& vals, double *res) const; + void getValueForTime(double time, const std::vector& vals, double *res) const throw(INTERP_KERNEL::Exception); 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); - TypeOfTimeDiscretization getEnum() const { return DISCRETIZATION; } + TypeOfTimeDiscretization getEnum() const throw(INTERP_KERNEL::Exception) { return DISCRETIZATION; } void synchronizeTimeWith(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception); - std::string getStringRepr() const; - MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const; - MEDCouplingTimeDiscretization *aggregate(const std::vector& other) const; - MEDCouplingTimeDiscretization *meld(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); - MEDCouplingTimeDiscretization *pow(const MEDCouplingTimeDiscretization *other) const; - void powEqual(const MEDCouplingTimeDiscretization *other); + std::string getStringRepr() const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *aggregate(const std::vector& other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *meld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *dot(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *crossProduct(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *max(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *min(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *add(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void addEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *substract(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void substractEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *multiply(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void multiplyEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *divide(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void divideEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *pow(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void powEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); 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; } @@ -369,16 +369,16 @@ namespace ParaMEDMEM void synchronizeTimeWith(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception); std::size_t getHeapMemorySize() const; void copyTinyAttrFrom(const MEDCouplingTimeDiscretization& other) throw(INTERP_KERNEL::Exception); - void copyTinyStringsFrom(const MEDCouplingTimeDiscretization& other); - const DataArrayDouble *getEndArray() const; - DataArrayDouble *getEndArray(); + void copyTinyStringsFrom(const MEDCouplingTimeDiscretization& other) throw(INTERP_KERNEL::Exception); + const DataArrayDouble *getEndArray() const throw(INTERP_KERNEL::Exception); + DataArrayDouble *getEndArray() throw(INTERP_KERNEL::Exception); void checkCoherency() const throw(INTERP_KERNEL::Exception); - bool isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const; - bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const; + bool isEqualIfNotWhy(const MEDCouplingTimeDiscretization *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception); + bool isEqualWithoutConsideringStr(const MEDCouplingTimeDiscretization *other, double prec) const throw(INTERP_KERNEL::Exception); void checkNoTimePresence() const throw(INTERP_KERNEL::Exception); void checkTimePresence(double time) const throw(INTERP_KERNEL::Exception); - void getArrays(std::vector& arrays) const; - void setEndArray(DataArrayDouble *array, TimeLabel *owner); + void getArrays(std::vector& arrays) const throw(INTERP_KERNEL::Exception); + void setEndArray(DataArrayDouble *array, TimeLabel *owner) throw(INTERP_KERNEL::Exception); 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; } @@ -389,14 +389,14 @@ namespace ParaMEDMEM void setEndOrder(int order) throw(INTERP_KERNEL::Exception) { _end_order=order; } void setStartTimeValue(double time) throw(INTERP_KERNEL::Exception) { _start_time=time; } void setEndTimeValue(double time) throw(INTERP_KERNEL::Exception) { _end_time=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); - void getTinySerializationIntInformation2(std::vector& tinyInfo) const; - void getTinySerializationDbleInformation2(std::vector& tinyInfo) const; - void finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD); + void getTinySerializationIntInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void getTinySerializationDbleInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void getTinySerializationStrInformation(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void resizeForUnserialization(const std::vector& tinyInfoI, std::vector& arrays) throw(INTERP_KERNEL::Exception); + void finishUnserialization(const std::vector& tinyInfoI, const std::vector& tinyInfoD, const std::vector& tinyInfoS) throw(INTERP_KERNEL::Exception); + void getTinySerializationIntInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void getTinySerializationDbleInformation2(std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); + void finishUnserialization2(const std::vector& tinyInfoI, const std::vector& tinyInfoD) throw(INTERP_KERNEL::Exception); 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: @@ -417,35 +417,35 @@ namespace ParaMEDMEM MEDCouplingLinearTime(const MEDCouplingLinearTime& other, bool deepCpy); public: MEDCouplingLinearTime(); - std::string getStringRepr() const; - TypeOfTimeDiscretization getEnum() const { return DISCRETIZATION; } + std::string getStringRepr() const throw(INTERP_KERNEL::Exception); + TypeOfTimeDiscretization getEnum() const throw(INTERP_KERNEL::Exception) { 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, std::string& reason) const; - bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const; - bool areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const; - bool areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const; - void getValueForTime(double time, const std::vector& vals, double *res) const; + MEDCouplingTimeDiscretization *performCpy(bool deepCpy) const throw(INTERP_KERNEL::Exception); + bool areCompatible(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + bool areStrictlyCompatible(const MEDCouplingTimeDiscretization *other, std::string& reason) const throw(INTERP_KERNEL::Exception); + bool areStrictlyCompatibleForMul(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + bool areStrictlyCompatibleForDiv(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + bool areCompatibleForMeld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void getValueForTime(double time, const std::vector& vals, double *res) const throw(INTERP_KERNEL::Exception); 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 *aggregate(const std::vector& other) const; - MEDCouplingTimeDiscretization *meld(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); - MEDCouplingTimeDiscretization *pow(const MEDCouplingTimeDiscretization *other) const; - void powEqual(const MEDCouplingTimeDiscretization *other); + MEDCouplingTimeDiscretization *aggregate(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *aggregate(const std::vector& other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *meld(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *dot(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *crossProduct(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *max(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *min(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *add(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void addEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *substract(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void substractEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *multiply(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void multiplyEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *divide(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void divideEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); + MEDCouplingTimeDiscretization *pow(const MEDCouplingTimeDiscretization *other) const throw(INTERP_KERNEL::Exception); + void powEqual(const MEDCouplingTimeDiscretization *other) throw(INTERP_KERNEL::Exception); public: static const TypeOfTimeDiscretization DISCRETIZATION=LINEAR_TIME; static const char REPR[]; diff --git a/src/MEDCoupling/MEDCouplingUMesh.cxx b/src/MEDCoupling/MEDCouplingUMesh.cxx index b155c5ee9..6772aafaf 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.cxx +++ b/src/MEDCoupling/MEDCouplingUMesh.cxx @@ -26,6 +26,7 @@ #include "InterpolationUtils.hxx" #include "PointLocatorAlgos.txx" #include "BBTree.txx" +#include "BBTreeDst.txx" #include "SplitterTetra.hxx" #include "DirectedBoundingBox.hxx" #include "InterpKernelMeshQuality.hxx" @@ -627,8 +628,8 @@ void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataA { checkFullyDefined(); int nbOfNodes=getNumberOfNodes(); - int *revNodalIndxPtr=new int[nbOfNodes+1]; - revNodalIndx->useArray(revNodalIndxPtr,true,CPP_DEALLOC,nbOfNodes+1,1); + int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int)); + revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1); std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0); const int *conn=_nodal_connec->getConstPointer(); const int *connIndex=_nodal_connec_index->getConstPointer(); @@ -646,8 +647,8 @@ void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataA } } std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus()); - int *revNodalPtr=new int[nbOfEltsInRevNodal]; - revNodal->useArray(revNodalPtr,true,CPP_DEALLOC,nbOfEltsInRevNodal,1); + int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int)); + revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1); std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1); for(int eltId=0;eltId=0 && *itergetNumberOfCells() tuples and 1 component. * For each cell in \b this the number of nodes constituting cell is computed. - * Excepted for poyhedrons, the result can be deduced by performing a deltaShiftIndex on the nodal connectivity index in \b this minus 1. - * For polyhedrons, the face separation (-1) are excluded from the couting. + * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned. + * So for pohyhedrons some nodes can be counted several times in the returned result. * * \return a newly allocated array */ @@ -1481,6 +1482,29 @@ DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KER return ret.retn(); } +/*! + * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component. + * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed. + * + * \return a newly allocated array + */ +DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception) +{ + checkConnectivityFullyDefined(); + int nbOfCells=getNumberOfCells(); + MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); + ret->alloc(nbOfCells,1); + int *retPtr=ret->getPointer(); + const int *conn=getNodalConnectivity()->getConstPointer(); + const int *connI=getNodalConnectivityIndex()->getConstPointer(); + for(int i=0;igetConstPointer(); const int *connI=_nodal_connec_index->getConstPointer(); + MEDCouplingAutoRefCountObjectPtr o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1); + MEDCouplingAutoRefCountObjectPtr n2o=o2n->invertArrayO2N2N2O(nbCells); + const int *n2oPtr=n2o->begin(); MEDCouplingAutoRefCountObjectPtr newConn=DataArrayInt::New(); newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents()); newConn->copyStringInfoFrom(*_nodal_connec); @@ -2823,7 +2850,7 @@ void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INT newCI[0]=loc; for(int i=0;i(array); + free(const_cast(array)); } /*! @@ -3467,7 +3494,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin ret->_mesh_dim=_mesh_dim; ret->setCoords(_coords); std::size_t nbOfElemsRet=std::distance(begin,end); - int *connIndexRet=new int[nbOfElemsRet+1]; + int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int)); connIndexRet[0]=0; const int *conn=_nodal_connec->getConstPointer(); const int *connIndex=_nodal_connec_index->getConstPointer(); @@ -3478,12 +3505,12 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work]; else { - delete [] connIndexRet; + free(connIndexRet); std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } } - int *connRet=new int[connIndexRet[nbOfElemsRet]]; + int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int)); int *connRetWork=connRet; std::set types; for(const int *work=begin;work!=end;work++) @@ -3492,9 +3519,9 @@ MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork); } MEDCouplingAutoRefCountObjectPtr connRetArr=DataArrayInt::New(); - connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1); + connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1); MEDCouplingAutoRefCountObjectPtr connIndexRetArr=DataArrayInt::New(); - connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1); + connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1); ret->setConnectivity(connRetArr,connIndexRetArr,false); ret->_types=types; ret->copyTinyInfoFrom(this); @@ -4095,14 +4122,14 @@ void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, } /*! - * This method computes the distance from a point \a pt to \a this and the first \a cellId and \a nodeId in \a this corresponding to the returned distance. + * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance. * \a this is expected to be a mesh so that its space dimension is equal to its * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment. * Distance from \a ptBg to \a ptEnd is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates). - * - * This method firstly find the closer node in \a this to the requested point whose coordinates are defined by [ \a ptBg, \a ptEnd ). Then for this node found - * the cells sharing this node (if any) are considered to find if the distance to these cell are smaller than the result found previously. If no cells are linked - * to the node that minimizes distance with the input point then -1 is returned in cellId. + + * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken + * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance). + * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this. * * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this. * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this. @@ -4113,9 +4140,9 @@ void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, * \return the positive value of the distance. * \throw if distance from \a ptBg to \a ptEnd is not equal to the space dimension. An exception is also thrown if mesh dimension of \a this is not equal to space * dimension - 1. - * \sa DataArrayDouble::distanceToTuple + * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints */ -double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId, int& nodeId) const throw(INTERP_KERNEL::Exception) +double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception) { int meshDim=getMeshDimension(),spaceDim=getSpaceDimension(); if(meshDim!=spaceDim-1) @@ -4125,53 +4152,117 @@ double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd checkFullyDefined(); if((int)std::distance(ptBg,ptEnd)!=spaceDim) { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } - nodeId=-1; - double ret0=_coords->distanceToTuple(ptBg,ptEnd,nodeId); - if(nodeId==-1) - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : something wrong with nodes in this !"); - MEDCouplingAutoRefCountObjectPtr cellIds=getCellIdsLyingOnNodes(&nodeId,&nodeId+1,false); - switch(meshDim) + DataArrayInt *ret1=0; + MEDCouplingAutoRefCountObjectPtr pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim); + MEDCouplingAutoRefCountObjectPtr ret0=distanceToPoints(pts,ret1); + MEDCouplingAutoRefCountObjectPtr ret1Safe(ret1); + cellId=*ret1Safe->begin(); + return *ret0->begin(); +} + +/*! + * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point) + * to \a this and the first \a cellId in \a this corresponding to the returned distance. + * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken + * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance). + * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this. + * + * \a this is expected to be a mesh so that its space dimension is equal to its + * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment. + * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates). + * + * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this. + * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this. + * + * \param [in] pts the list of points in which each tuple represents a point + * \param [out] cellIds a newly allocated object that tells for each point in \a pts the first cell id in \a this that minimizes the distance. + * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this. + * \throw if number of components of \a pts is not equal to the space dimension. + * \throw if mesh dimension of \a this is not equal to space dimension - 1. + * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint + */ +DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception) +{ + if(!pts) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !"); + pts->checkAllocated(); + int meshDim=getMeshDimension(),spaceDim=getSpaceDimension(); + if(meshDim!=spaceDim-1) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !"); + if(meshDim!=2 && meshDim!=1) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !"); + if(pts->getNumberOfComponents()!=spaceDim) { - case 2: + std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + checkFullyDefined(); + int nbCells=getNumberOfCells(); + if(nbCells==0) + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !"); + int nbOfPts=pts->getNumberOfTuples(); + MEDCouplingAutoRefCountObjectPtr ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1); + MEDCouplingAutoRefCountObjectPtr ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1); + const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin(); + double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin(); + std::vector bbox; + getBoundingBoxForBBTree(bbox); + switch(spaceDim) + { + case 3: { - distanceToPoint3DSurfAlg(ptBg,cellIds,ret0,cellId); - return ret0; + BBTreeDst<3> myTree(&bbox[0],0,0,nbCells); + for(int i=0;i::max(); + std::vector elems; + myTree.getMinDistanceOfMax(ptsPtr,x); + myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems); + DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr); + } + break; } - case 1: + case 2: { - distanceToPoint2DCurveAlg(ptBg,cellIds,ret0,cellId); - return ret0; + BBTreeDst<2> myTree(&bbox[0],0,0,nbCells); + for(int i=0;i::max(); + std::vector elems; + myTree.getMinDistanceOfMax(ptsPtr,x); + myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems); + DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr); + } + break; } default: - throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !"); + throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !"); } - - return ret0; + cellIds=ret1.retn(); + return ret0.retn(); } - /*! * \param [in] pt the start pointer (included) of the coordinates of the point - * \param [in] cellIds + * \param [in] cellIdsBg the start pointer (included) of cellIds + * \param [in] cellIdsEnd the end pointer (excluded) of cellIds + * \param [in] nc nodal connectivity + * \param [in] ncI nodal connectivity index * \param [in,out] ret0 the min distance between \a this and the external input point * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned. - * \sa MEDCouplingUMesh::distanceToPoint + * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints */ -void MEDCouplingUMesh::distanceToPoint3DSurfAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception) +void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception) { - const double *coords=_coords->getConstPointer(); - cellId=-1; - if(cellIds->empty()) - return; - const int *ptr=_nodal_connec->getConstPointer(); - const int *ptrI=_nodal_connec_index->getConstPointer(); - for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++) + cellId=-1; + ret0=std::numeric_limits::max(); + for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++) { - switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]]) + switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]]) { case INTERP_KERNEL::NORM_TRI3: { - double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*ptr[ptrI[*zeCell]+1],coords+3*ptr[ptrI[*zeCell]+2],coords+3*ptr[ptrI[*zeCell]+3]); + double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]); if(tmpgetConstPointer(); - if(cellIds->empty()) - { cellId=-1; return; } - const int *ptr=_nodal_connec->getConstPointer(); - const int *ptrI=_nodal_connec_index->getConstPointer(); - for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++) + cellId=-1; + ret0=std::numeric_limits::max(); + for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++) { - switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]]) + switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]]) { case INTERP_KERNEL::NORM_SEG2: { - double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*ptr[ptrI[*zeCell]+1],coords+2*ptr[ptrI[*zeCell]+2]); - if(tmp!=std::numeric_limits::max()) tmp=sqrt(tmp); + std::size_t uselessEntry=0; + double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry); + tmp=sqrt(tmp); if(tmpgetConstPointer(); for(int i=0;i newConn=DataArrayInt::New(); MEDCouplingAutoRefCountObjectPtr newConnI=DataArrayInt::New(); + const int *icptr=_nodal_connec->getConstPointer(); 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; @@ -5007,6 +5102,8 @@ void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exce _types.insert(typel); const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel); int newNbOfNodes=cml.getNumberOfNodes(); + if(cml.isDynamic()) + newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2; *ocptr++=(int)typel; ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr); ociptr[1]=ociptr[0]+newNbOfNodes+1; @@ -6710,7 +6807,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception) { checkConnectivityFullyDefined(); - MEDCouplingAutoRefCountObjectPtr ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER); + MEDCouplingAutoRefCountObjectPtr ret=getRenumArrForMEDFileFrmt(); renumberCells(ret->getConstPointer(),false); return ret.retn(); } @@ -6829,6 +6926,18 @@ DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::Norma return tmpa.retn(); } +/*! + * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec. + * + * \return a new object containing the old to new correspondance. + * + * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt. + */ +DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception) +{ + return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER); +} + /*! * 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 in 'this'. * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells. @@ -7920,7 +8029,7 @@ void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, c std::size_t nbPoints=std::distance(begin,end); if(nbPoints<3) throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !"); - double vec[3]; + double vec[3]={0.,0.,0.}; std::size_t j=0; bool refFound=false; for(;j& nodeIdsInUse) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayInt *computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT DataArrayInt *computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayInt *zipCoordsTraducer() throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayInt *zipConnectivityTraducer(int compType, int startCellId=0) throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception); @@ -161,7 +162,8 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT DataArrayInt *getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT bool isContiguous1D() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void project1D(const double *pt, const double *v, double eps, double *res) const; - MEDCOUPLING_EXPORT double distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId, int& nodeId) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT double distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT DataArrayDouble *distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT int getCellContainingPoint(const double *pos, double eps) const; MEDCOUPLING_EXPORT void getCellsContainingPoint(const double *pos, double eps, std::vector& elts) const; MEDCOUPLING_EXPORT void getCellsContainingPoints(const double *pos, int nbOfPoints, double eps, std::vector& elts, std::vector& eltsIndex) const; @@ -200,6 +202,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT bool checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT bool checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const; MEDCOUPLING_EXPORT DataArrayInt *getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT DataArrayInt *getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayInt *getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayInt *rearrange2ConsecutiveCellTypes(); MEDCOUPLING_EXPORT std::vector splitByType() const; @@ -290,8 +293,8 @@ namespace ParaMEDMEM MEDCouplingUMesh *buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception); DataArrayInt *buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception); DataArrayInt *buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception); - void distanceToPoint3DSurfAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception); - void distanceToPoint2DCurveAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception); + static void DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception); + static void DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception); static DataArrayInt *ComputeSpreadZoneGraduallyFromSeedAlg(std::vector& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception); static void FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception); static void AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector& ret); diff --git a/src/MEDCoupling/MEDCouplingUMeshDesc.cxx b/src/MEDCoupling/MEDCouplingUMeshDesc.cxx index 4c6ef588f..df9d89271 100644 --- a/src/MEDCoupling/MEDCouplingUMeshDesc.cxx +++ b/src/MEDCoupling/MEDCouplingUMeshDesc.cxx @@ -168,6 +168,11 @@ DataArrayInt *MEDCouplingUMeshDesc::computeNbOfNodesPerCell() const throw(INTERP throw INTERP_KERNEL::Exception("MEDCouplingUMeshDesc::computeNbOfNodesPerCell : not implemented yet !"); } +DataArrayInt *MEDCouplingUMeshDesc::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception) +{ + throw INTERP_KERNEL::Exception("MEDCouplingUMeshDesc::computeNbOfFacesPerCell : not implemented yet !"); +} + int MEDCouplingUMeshDesc::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const { const int *desc_connec=_desc_connec->getConstPointer(); diff --git a/src/MEDCoupling/MEDCouplingUMeshDesc.hxx b/src/MEDCoupling/MEDCouplingUMeshDesc.hxx index c959bdc7b..e6a25b09b 100644 --- a/src/MEDCoupling/MEDCouplingUMeshDesc.hxx +++ b/src/MEDCoupling/MEDCouplingUMeshDesc.hxx @@ -53,6 +53,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT std::set getAllGeoTypes() const; MEDCOUPLING_EXPORT DataArrayInt *giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayInt *computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT DataArrayInt *computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT int getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const; MEDCOUPLING_EXPORT void getNodeIdsOfCell(int cellId, std::vector& conn) const; MEDCOUPLING_EXPORT std::string simpleRepr() const; diff --git a/src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx b/src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx index 2832db0c0..5d2b0c0f9 100644 --- a/src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx +++ b/src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx @@ -139,7 +139,21 @@ void MEDCouplingBasicsTest1::testMesh() int tab4[4*nbOfCells]={ 1, 2, 8, 7, 2, 3, 9, 8, 3, 4, 10, 9, 4, 5, 11, 10, 5, 0, 6, 11, 0, 1, 7, 6, }; - + CPPUNIT_ASSERT_EQUAL(MEDCouplingMesh::GetNumberOfNodesOfGeometricType(INTERP_KERNEL::NORM_TRI3),3); + CPPUNIT_ASSERT(MEDCouplingMesh::IsStaticGeometricType(INTERP_KERNEL::NORM_TRI3)); + CPPUNIT_ASSERT(MEDCouplingMesh::IsLinearGeometricType(INTERP_KERNEL::NORM_TRI3)); + CPPUNIT_ASSERT_EQUAL(MEDCouplingMesh::GetDimensionOfGeometricType(INTERP_KERNEL::NORM_TRI3),2); + CPPUNIT_ASSERT_EQUAL(std::string(MEDCouplingMesh::GetReprOfGeometricType(INTERP_KERNEL::NORM_TRI3)),std::string("NORM_TRI3")); + CPPUNIT_ASSERT_THROW(MEDCouplingMesh::GetNumberOfNodesOfGeometricType(INTERP_KERNEL::NORM_POLYGON),INTERP_KERNEL::Exception); + CPPUNIT_ASSERT(not MEDCouplingMesh::IsStaticGeometricType(INTERP_KERNEL::NORM_POLYGON)); + CPPUNIT_ASSERT(MEDCouplingMesh::IsLinearGeometricType(INTERP_KERNEL::NORM_POLYGON)); + CPPUNIT_ASSERT_EQUAL(MEDCouplingMesh::GetDimensionOfGeometricType(INTERP_KERNEL::NORM_POLYGON),2); + CPPUNIT_ASSERT_EQUAL(std::string(MEDCouplingMesh::GetReprOfGeometricType(INTERP_KERNEL::NORM_POLYGON)),std::string("NORM_POLYGON")); + CPPUNIT_ASSERT_EQUAL(MEDCouplingMesh::GetNumberOfNodesOfGeometricType(INTERP_KERNEL::NORM_TRI6),6); + CPPUNIT_ASSERT(MEDCouplingMesh::IsStaticGeometricType(INTERP_KERNEL::NORM_TRI6)); + CPPUNIT_ASSERT(!MEDCouplingMesh::IsLinearGeometricType(INTERP_KERNEL::NORM_TRI6)); + CPPUNIT_ASSERT_EQUAL(MEDCouplingMesh::GetDimensionOfGeometricType(INTERP_KERNEL::NORM_TRI6),2); + CPPUNIT_ASSERT_EQUAL(std::string(MEDCouplingMesh::GetReprOfGeometricType(INTERP_KERNEL::NORM_TRI6)),std::string("NORM_TRI6")); MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(); mesh->setMeshDimension(2); mesh->allocateCells(8); diff --git a/src/MEDCoupling/Test/MEDCouplingBasicsTest2.cxx b/src/MEDCoupling/Test/MEDCouplingBasicsTest2.cxx index 4be6abb37..d1482a268 100644 --- a/src/MEDCoupling/Test/MEDCouplingBasicsTest2.cxx +++ b/src/MEDCoupling/Test/MEDCouplingBasicsTest2.cxx @@ -1816,6 +1816,18 @@ void MEDCouplingBasicsTest2::testMaxPerTuple1() CPPUNIT_ASSERT_DOUBLES_EQUAL(5.6,f2->getIJ(i,0),1e-13); f2->decrRef(); // + DataArrayInt *d2I=0; + DataArrayDouble *d2=array->maxPerTupleWithCompoId(d2I); + CPPUNIT_ASSERT_EQUAL(1,d2->getNumberOfComponents()); + CPPUNIT_ASSERT_EQUAL(5,d2->getNumberOfTuples()); + const int expected2[5]={4,3,2,0,1}; + for(int i=0;i<5;i++) + { + CPPUNIT_ASSERT_DOUBLES_EQUAL(5.6,d2->getIJ(i,0),1e-13); + CPPUNIT_ASSERT_EQUAL(expected2[i],d2I->getIJ(i,0)); + } + d2->decrRef(); d2I->decrRef(); + // mesh1->decrRef(); f1->decrRef(); } diff --git a/src/MEDCoupling/Test/MEDCouplingBasicsTest3.cxx b/src/MEDCoupling/Test/MEDCouplingBasicsTest3.cxx index cea76482a..bda6db201 100644 --- a/src/MEDCoupling/Test/MEDCouplingBasicsTest3.cxx +++ b/src/MEDCoupling/Test/MEDCouplingBasicsTest3.cxx @@ -669,7 +669,7 @@ void MEDCouplingBasicsTest3::testKeepSetSelectedComponent1() a1->setInfoOnComponent(3,"dddd"); const int arr2[6]={1,2,1,2,0,0}; std::vector arr2V(arr2,arr2+6); - DataArrayDouble *a2=a1->keepSelectedComponents(arr2V); + DataArrayDouble *a2=static_cast(a1->keepSelectedComponents(arr2V)); CPPUNIT_ASSERT_EQUAL(6,a2->getNumberOfComponents()); CPPUNIT_ASSERT_EQUAL(5,a2->getNumberOfTuples()); CPPUNIT_ASSERT(std::string(a2->getInfoOnComponent(0))=="bbbb"); @@ -682,7 +682,7 @@ void MEDCouplingBasicsTest3::testKeepSetSelectedComponent1() for(int i=0;i<30;i++) CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i],a2->getIJ(0,i),1e-14); DataArrayInt *a3=a1->convertToIntArr(); - DataArrayInt *a4=a3->keepSelectedComponents(arr2V); + DataArrayInt *a4=static_cast(a3->keepSelectedComponents(arr2V)); CPPUNIT_ASSERT_EQUAL(6,a4->getNumberOfComponents()); CPPUNIT_ASSERT_EQUAL(5,a4->getNumberOfTuples()); CPPUNIT_ASSERT(std::string(a4->getInfoOnComponent(0))=="bbbb"); @@ -696,7 +696,7 @@ void MEDCouplingBasicsTest3::testKeepSetSelectedComponent1() // setSelectedComponents const int arr3[2]={3,2}; std::vector arr3V(arr3,arr3+2); - DataArrayDouble *a5=a1->keepSelectedComponents(arr3V); + DataArrayDouble *a5=static_cast(a1->keepSelectedComponents(arr3V)); a5->setInfoOnComponent(0,"eeee"); a5->setInfoOnComponent(1,"ffff"); const int arr4[2]={1,2}; diff --git a/src/MEDCoupling/Test/MEDCouplingBasicsTest5.cxx b/src/MEDCoupling/Test/MEDCouplingBasicsTest5.cxx index 51d08c599..a4d9b168b 100644 --- a/src/MEDCoupling/Test/MEDCouplingBasicsTest5.cxx +++ b/src/MEDCoupling/Test/MEDCouplingBasicsTest5.cxx @@ -323,11 +323,11 @@ void MEDCouplingBasicsTest5::testDataArrayDoubleAdvSetting1() // std::vector > p(3); p[0].first=0; p[0].second=3; p[1].first=3; p[1].second=5; p[2].first=5; p[2].second=7; - tmp=da->selectByTupleRanges(p); + tmp=dynamic_cast(da->selectByTupleRanges(p)); CPPUNIT_ASSERT(tmp->isEqual(*da,1e-14)); tmp->decrRef(); p[0].first=0; p[0].second=2; p[1].first=3; p[1].second=4; p[2].first=5; p[2].second=7; - tmp=da->selectByTupleRanges(p); + tmp=dynamic_cast(da->selectByTupleRanges(p)); const double expected1[10]={1.,11.,2.,12.,4.,14.,6.,16.,7.,17.}; CPPUNIT_ASSERT_EQUAL(5,tmp->getNumberOfTuples()); CPPUNIT_ASSERT_EQUAL(2,tmp->getNumberOfComponents()); @@ -335,7 +335,7 @@ void MEDCouplingBasicsTest5::testDataArrayDoubleAdvSetting1() CPPUNIT_ASSERT_DOUBLES_EQUAL(expected1[i],tmp->getIJ(0,i),1e-14); tmp->decrRef(); p[0].first=0; p[0].second=2; p[1].first=0; p[1].second=2; p[2].first=5; p[2].second=6; - tmp=da->selectByTupleRanges(p); + tmp=dynamic_cast(da->selectByTupleRanges(p)); const double expected2[10]={1.,11.,2.,12.,1.,11.,2.,12.,6.,16.}; CPPUNIT_ASSERT_EQUAL(5,tmp->getNumberOfTuples()); CPPUNIT_ASSERT_EQUAL(2,tmp->getNumberOfComponents()); @@ -417,11 +417,11 @@ void MEDCouplingBasicsTest5::testDataArrayIntAdvSetting1() // std::vector > p(3); p[0].first=0; p[0].second=3; p[1].first=3; p[1].second=5; p[2].first=5; p[2].second=7; - tmp=da->selectByTupleRanges(p); + tmp=dynamic_cast(da->selectByTupleRanges(p)); CPPUNIT_ASSERT(tmp->isEqual(*da)); tmp->decrRef(); p[0].first=0; p[0].second=2; p[1].first=3; p[1].second=4; p[2].first=5; p[2].second=7; - tmp=da->selectByTupleRanges(p); + tmp=dynamic_cast(da->selectByTupleRanges(p)); const int expected1[10]={1,11,2,12,4,14,6,16,7,17}; CPPUNIT_ASSERT_EQUAL(5,tmp->getNumberOfTuples()); CPPUNIT_ASSERT_EQUAL(2,tmp->getNumberOfComponents()); @@ -429,7 +429,7 @@ void MEDCouplingBasicsTest5::testDataArrayIntAdvSetting1() CPPUNIT_ASSERT_EQUAL(expected1[i],tmp->getIJ(0,i)); tmp->decrRef(); p[0].first=0; p[0].second=2; p[1].first=0; p[1].second=2; p[2].first=5; p[2].second=6; - tmp=da->selectByTupleRanges(p); + tmp=dynamic_cast(da->selectByTupleRanges(p)); const int expected2[10]={1,11,2,12,1,11,2,12,6,16}; CPPUNIT_ASSERT_EQUAL(5,tmp->getNumberOfTuples()); CPPUNIT_ASSERT_EQUAL(2,tmp->getNumberOfComponents()); diff --git a/src/MEDCoupling/Test/MEDCouplingExamplesTest.cxx b/src/MEDCoupling/Test/MEDCouplingExamplesTest.cxx index 365d6dd58..be1e0bf73 100644 --- a/src/MEDCoupling/Test/MEDCouplingExamplesTest.cxx +++ b/src/MEDCoupling/Test/MEDCouplingExamplesTest.cxx @@ -104,7 +104,7 @@ void CppExample_MEDCouplingFieldDouble_MergeFields() MEDCouplingAutoRefCountObjectPtr field2 = field1->cloneWithMesh( true ); double vec[1] = { 5. }; - ((ParaMEDMEM::MEDCouplingMesh *)field2->getMesh())->translate(vec); // translate mesh2 + (const_cast(field2->getMesh()))->translate(vec); // translate mesh2 field2->applyFunc("x + 5"); // "translate" field2 // concatenate field1 and field2 @@ -596,7 +596,7 @@ void CppExample_MEDCouplingFieldDouble_renumberNodes() field->renumberNodes(renumber,false); const MEDCouplingMesh* mesh2 = field->getMesh(); // field now refers to another mesh values = field->getArray(); - nodeCoords = ((MEDCouplingUMesh*)mesh2)->getCoords(); + nodeCoords = (static_cast(mesh2))->getCoords(); CPPUNIT_ASSERT( values->isEqualWithoutConsideringStr( *nodeCoords, 1e-13 )); //! [CppSnippet_MEDCouplingFieldDouble_renumberNodes_3] } diff --git a/src/MEDCoupling_Swig/CMakeLists.txt b/src/MEDCoupling_Swig/CMakeLists.txt index 4890ae86b..9d7e5e352 100644 --- a/src/MEDCoupling_Swig/CMakeLists.txt +++ b/src/MEDCoupling_Swig/CMakeLists.txt @@ -82,11 +82,11 @@ SET(PYFILES_TO_INSTALL ${CMAKE_CURRENT_BINARY_DIR}/MEDCoupling.py ${CMAKE_CURREN INSTALL_AND_COMPILE_PYTHON_FILE("${PYFILES_TO_INSTALL}" ${MED_salomescript_PYTHON}) INSTALL(FILES MEDCoupling.i MEDCouplingCommon.i MEDCouplingMemArray.i MEDCouplingFinalize.i MEDCouplingRemapper.i MEDCouplingTypemaps.i DESTINATION ${MED_salomeinclude_HEADERS}) -INSTALL(FILES MEDCouplingBasicsTest.py MEDCouplingRemapperTest.py MEDCouplingDataForTest.py MEDCouplingNumpyTest.py DESTINATION ${MED_salomescript_PYTHON}) +INSTALL(FILES MEDCouplingBasicsTest.py MEDCouplingRemapperTest.py MEDCouplingDataForTest.py MEDCouplingNumPyTest.py DESTINATION ${MED_salomescript_PYTHON}) ADD_TEST(MEDCouplingBasicsTest ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/MEDCouplingBasicsTest.py) ADD_TEST(MEDCouplingExamplesTest ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/MEDCouplingExamplesTest.py) ADD_TEST(MEDCouplingRemapperTest ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/MEDCouplingRemapperTest.py) IF(NUMPY_STATUS) - ADD_TEST(MEDCouplingNumpyTest ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/MEDCouplingNumpyTest.py) + ADD_TEST(MEDCouplingNumPyTest ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/MEDCouplingNumPyTest.py) ENDIF(NUMPY_STATUS) diff --git a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py index b0523db87..6fe9040bc 100644 --- a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py +++ b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py @@ -21,7 +21,9 @@ from MEDCoupling import * import unittest from math import pi,e,sqrt,cos,sin +from datetime import datetime from MEDCouplingDataForTest import MEDCouplingDataForTest +import rlcompleter,readline # this line has to be here, ot ensure a usability of MEDCoupling/MEDLoader. B4 removing it please notify to anthony.geay@cea.fr class MEDCouplingBasicsTest(unittest.TestCase): def testArray2(self): @@ -89,6 +91,21 @@ class MEDCouplingBasicsTest(unittest.TestCase): -0.305, 0.024155, 0.04183768725682622, -0.2863, 0.04831000000000001, -1.015761910347357e-17, -0.2863, 0.09662000000000001, -1.832979297858306e-18, -0.2863, 0.120775, 0.04183768725682623, -0.2863, 0.09662000000000001, 0.08367537451365245, -0.2863, 0.04831000000000001, 0.08367537451365246, -0.2863 ] + self.assertEqual(MEDCouplingMesh.GetNumberOfNodesOfGeometricType(NORM_TRI3),3) + self.assertTrue(MEDCouplingMesh.IsStaticGeometricType(NORM_TRI3)) + self.assertTrue(MEDCouplingMesh.IsLinearGeometricType(NORM_TRI3)) + self.assertEqual(MEDCouplingMesh.GetDimensionOfGeometricType(NORM_TRI3),2) + self.assertEqual(MEDCouplingMesh.GetReprOfGeometricType(NORM_TRI3),"NORM_TRI3") + self.assertRaises(InterpKernelException,MEDCouplingMesh.GetNumberOfNodesOfGeometricType,NORM_POLYGON) + self.assertTrue(not MEDCouplingMesh.IsStaticGeometricType(NORM_POLYGON)) + self.assertTrue(MEDCouplingMesh.IsLinearGeometricType(NORM_POLYGON)) + self.assertEqual(MEDCouplingMesh.GetDimensionOfGeometricType(NORM_POLYGON),2) + self.assertEqual(MEDCouplingMesh.GetReprOfGeometricType(NORM_POLYGON),"NORM_POLYGON") + self.assertEqual(MEDCouplingMesh.GetNumberOfNodesOfGeometricType(NORM_TRI6),6) + self.assertTrue(MEDCouplingMesh.IsStaticGeometricType(NORM_TRI6)) + self.assertTrue(not MEDCouplingMesh.IsLinearGeometricType(NORM_TRI6)) + self.assertEqual(MEDCouplingMesh.GetDimensionOfGeometricType(NORM_TRI6),2) + self.assertEqual(MEDCouplingMesh.GetReprOfGeometricType(NORM_TRI6),"NORM_TRI6") mesh=MEDCouplingUMesh.New() mesh.setMeshDimension(2) mesh.allocateCells(8); @@ -582,6 +599,7 @@ class MEDCouplingBasicsTest(unittest.TestCase): self.assertTrue(not fieldOnNodes1.isEqual(fieldOnCells1,1e-12,1e-15)); # fieldOnCells2=MEDCouplingFieldDouble.New(ON_CELLS,ONE_TIME); + self.assertEqual(fieldOnCells2.getMesh(),None) # to check that convertMesh wrapping do not raise but return Py_None self.assertTrue(not fieldOnCells1.isEqual(fieldOnCells2,1e-12,1e-15)); self.assertTrue(not fieldOnCells2.isEqual(fieldOnCells1,1e-12,1e-15)); fieldOnCells1=MEDCouplingFieldDouble.New(ON_CELLS,ONE_TIME); @@ -3505,6 +3523,13 @@ class MEDCouplingBasicsTest(unittest.TestCase): self.assertAlmostEqual(5.6,f2.getIJ(i,0),13); pass # + d2,d2I=array.maxPerTupleWithCompoId() + self.assertEqual(1,d2.getNumberOfComponents()); + self.assertEqual(5,d2.getNumberOfTuples()); + for i in xrange(5): + self.assertAlmostEqual(5.6,d2.getIJ(i,0),13); + pass + self.assertTrue(d2I.isEqual(DataArrayInt([4,3,2,0,1]))) pass def testChangeNbOfComponents(self): @@ -10890,11 +10915,11 @@ class MEDCouplingBasicsTest(unittest.TestCase): m.setCoords(coords) m.allocateCells(0) m.insertNextCell(NORM_TRI3,[0,1,2]) - a,b,c=m.distanceToPoint([-0.335,2.27,1.21]) - self.assertEqual(0,b) ; self.assertEqual(0,c) + a,b=m.distanceToPoint([-0.335,2.27,1.21]) + self.assertEqual(0,b) self.assertAlmostEqual(0.022360988100374124,a,14); - a,b,c=m.distanceToPoint(DataArrayDouble([-0.335,2.27,1.21],1,3)) - self.assertEqual(0,b) ; self.assertEqual(0,c) + a,b=m.distanceToPoint(DataArrayDouble([-0.335,2.27,1.21],1,3)) + self.assertEqual(0,b) self.assertAlmostEqual(0.022360988100374124,a,14); a,b=coords.distanceToTuple([-0.335,2.27,1.21]) self.assertAlmostEqual(5.243302871282566,a,14) @@ -10907,31 +10932,31 @@ class MEDCouplingBasicsTest(unittest.TestCase): m.insertNextCell(NORM_QUAD4,[0,1,2,3]) m.checkCoherency2() self.assertEqual([4,0,1,2,3],m.getNodalConnectivity().getValues()) - a,b,c=m.distanceToPoint([5.,2.,0.1]) - self.assertAlmostEqual(0.1,a,14) ; self.assertEqual(0,b) ; self.assertEqual(1,c) - a,b,c=m.distanceToPoint([5.,-2.,4.]) - self.assertAlmostEqual(sqrt(2*2+4*4),a,14) ; self.assertEqual(0,b) ; self.assertEqual(1,c) + a,b=m.distanceToPoint([5.,2.,0.1]) + self.assertAlmostEqual(0.1,a,14) ; self.assertEqual(0,b) + a,b=m.distanceToPoint([5.,-2.,4.]) + self.assertAlmostEqual(sqrt(2*2+4*4),a,14) ; self.assertEqual(0,b) m.allocateCells(0) m.insertNextCell(NORM_POLYGON,[0,1,2,3]) m.checkCoherency2() self.assertEqual([5,0,1,2,3],m.getNodalConnectivity().getValues()) - a,b,c=m.distanceToPoint([11.,3.,4.]) - self.assertAlmostEqual(sqrt(3*3+4*4),a,14) ; self.assertEqual(0,b) ; self.assertEqual(1,c) - a,b,c=m.distanceToPoint([4.,12.,5.]) - self.assertAlmostEqual(sqrt(4*4+5*5),a,14) ; self.assertEqual(0,b) ; self.assertEqual(2,c) + a,b=m.distanceToPoint([11.,3.,4.]) + self.assertAlmostEqual(sqrt(3*3+4*4),a,14) ; self.assertEqual(0,b) + a,b=m.distanceToPoint([4.,12.,5.]) + self.assertAlmostEqual(sqrt(4*4+5*5),a,14) ; self.assertEqual(0,b) d=DataArrayDouble([-1.2,3.,2.],1,3) for elt in d: - a,b,c=m.distanceToPoint(d) - self.assertAlmostEqual(sqrt(1.2*1.2+2*2),a,14) ; self.assertEqual(0,b) ; self.assertEqual(0,c) + a,b=m.distanceToPoint(d) + self.assertAlmostEqual(sqrt(1.2*1.2+2*2),a,14) ; self.assertEqual(0,b) pass # m=MEDCouplingUMesh("toto",1) coords=DataArrayDouble([0.,0.,4.,0.,0.,4.],3,2) ; m.setCoords(coords) m.allocateCells(0) ; m.insertNextCell(NORM_SEG2,[0,1]) ; m.insertNextCell(NORM_SEG2,[1,2]) - a,b,c=m.distanceToPoint([-0.1,4.1]) - self.assertAlmostEqual(0.14142135623730925,a,14) ; self.assertEqual(-1,b) ; self.assertEqual(2,c) - a,b,c=m.distanceToPoint([0.,3.9]) - self.assertAlmostEqual(0.07071067811865482,a,14) ; self.assertEqual(1,b) ; self.assertEqual(2,c) + a,b=m.distanceToPoint([-0.1,4.1]) + self.assertAlmostEqual(0.14142135623730925,a,14) # b==1 self.assertEqual(2,c) + a,b=m.distanceToPoint([0.,3.9]) + self.assertAlmostEqual(0.07071067811865482,a,14) ; self.assertEqual(1,b) # self.assertEqual(2,c) pass def testSwig2NonRegressionPartitionBySpreadZone1(self): @@ -12570,6 +12595,359 @@ class MEDCouplingBasicsTest(unittest.TestCase): self.assertTrue( field.getArray().getValues() == coords2 ) pass + def testSwig2UMeshDistanceToMesh2(self): + sz=5 + m=MEDCouplingCMesh() + arr=DataArrayDouble(sz+1) ; arr.iota() ; arr/=sz + m.setCoords(arr,arr,arr) + m=m.buildUnstructured() + m1=m.computeSkin() + m1.zipCoords() + c=m1.getCoords()[:] + d=2*(c-[0.5,0.5,0.5])+[0.5,0.5,0.5] + time_deb = datetime.now() + #print "go.." + a,b=m1.distanceToPoints(d) + #print 'time spent in distanceToPoints %s ' %str(datetime.now() - time_deb) + time_deb = datetime.now() + a1=DataArrayDouble(len(d)) + b1=DataArrayInt(len(d)) + m1s=[m1[i] for i in xrange(m1.getNumberOfCells())] + for j,pt in enumerate(d): + eter=1e308 + fter=-1 + for i,miter in enumerate(m1s): + e,f=miter.distanceToPoint(pt) + self.assertEqual(0,f) + if edecrRef();" %feature("unref") MEDCouplingCMesh "$this->decrRef();" %feature("unref") DataArrayInt "$this->decrRef();" +%feature("unref") DataArrayChar "$this->decrRef();" %feature("unref") DataArrayAsciiChar "$this->decrRef();" %feature("unref") DataArrayByte "$this->decrRef();" %feature("unref") MEDCouplingField "$this->decrRef();" @@ -488,7 +494,7 @@ namespace ParaMEDMEM %inline { - bool MEDCouplingHasNumpyBindings() + bool MEDCouplingHasNumPyBindings() { #ifdef WITH_NUMPY return true; @@ -496,6 +502,15 @@ namespace ParaMEDMEM return false; #endif } + + std::string MEDCouplingCompletionScript() throw(INTERP_KERNEL::Exception) + { + static const char script[]="import rlcompleter,readline\nreadline.parse_and_bind('tab:complete')"; + std::ostringstream oss; oss << "MEDCouplingCompletionScript : error when trying to activate completion ! readline not present ?\nScript is :\n" << script; + if(PyRun_SimpleString(script)!=0) + throw INTERP_KERNEL::Exception(oss.str().c_str()); + return std::string(script); + } } %include "MEDCouplingMemArray.i" @@ -569,6 +584,7 @@ namespace ParaMEDMEM virtual DataArrayDouble *computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception); virtual DataArrayInt *giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception); virtual DataArrayInt *computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception); + virtual DataArrayInt *computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception); virtual MEDCouplingMesh *buildPartRange(int beginCellIds, int endCellIds, int stepCellIds) const throw(INTERP_KERNEL::Exception); virtual int getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception); virtual INTERP_KERNEL::NormalizedCellType getTypeOfCell(int cellId) const throw(INTERP_KERNEL::Exception); @@ -587,6 +603,10 @@ namespace ParaMEDMEM virtual bool areCompatibleForMerge(const MEDCouplingMesh *other) const throw(INTERP_KERNEL::Exception); virtual DataArrayInt *simplexize(int policy) throw(INTERP_KERNEL::Exception); static MEDCouplingMesh *MergeMeshes(const MEDCouplingMesh *mesh1, const MEDCouplingMesh *mesh2) throw(INTERP_KERNEL::Exception); + static bool IsStaticGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception); + static bool IsLinearGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception); + static INTERP_KERNEL::NormalizedCellType GetCorrespondingPolyType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception); + static int GetNumberOfNodesOfGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception); static int GetDimensionOfGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception); static const char *GetReprOfGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception); %extend @@ -653,7 +673,7 @@ namespace ParaMEDMEM if (!SWIG_IsOK(res1)) { int size; - INTERP_KERNEL::AutoPtr tmp=convertPyToNewDblArr2(p,&size); + INTERP_KERNEL::AutoCPtr tmp=convertPyToNewDblArr2(p,&size); int nbOfPoints=size/spaceDim; if(size%spaceDim!=0) { @@ -950,14 +970,14 @@ namespace ParaMEDMEM void rotate(PyObject *center, PyObject *vector, double alpha) throw(INTERP_KERNEL::Exception) { const char msg[]="Python wrap of MEDCouplingPointSet::rotate : "; - double val; - DataArrayDouble *a; - DataArrayDoubleTuple *aa; - std::vector bb; + double val,val2; + DataArrayDouble *a,*a2; + DataArrayDoubleTuple *aa,*aa2; + std::vector bb,bb2; int sw; int spaceDim=self->getSpaceDimension(); const double *centerPtr=convertObjToPossibleCpp5_Safe(center,sw,val,a,aa,bb,msg,1,spaceDim,true); - const double *vectorPtr=convertObjToPossibleCpp5_Safe(vector,sw,val,a,aa,bb,msg,1,spaceDim,false); + const double *vectorPtr=convertObjToPossibleCpp5_Safe(vector,sw,val2,a2,aa2,bb2,msg,1,spaceDim,false);//vectorPtr can be null in case of space dim 2 self->rotate(centerPtr,vectorPtr,alpha); } @@ -1246,8 +1266,8 @@ namespace ParaMEDMEM static void Rotate2DAlg(PyObject *center, double angle, int nbNodes, PyObject *coords) throw(INTERP_KERNEL::Exception) { int sz; - INTERP_KERNEL::AutoPtr c=convertPyToNewDblArr2(center,&sz); - INTERP_KERNEL::AutoPtr coo=convertPyToNewDblArr2(coords,&sz); + INTERP_KERNEL::AutoCPtr c=convertPyToNewDblArr2(center,&sz); + INTERP_KERNEL::AutoCPtr coo=convertPyToNewDblArr2(coords,&sz); ParaMEDMEM::MEDCouplingPointSet::Rotate2DAlg(c,angle,nbNodes,coo); for(int i=0;i c=convertPyToNewDblArr2(center,&sz); + INTERP_KERNEL::AutoCPtr c=convertPyToNewDblArr2(center,&sz); int sw,nbNodes=0; double val0; ParaMEDMEM::DataArrayDouble *val1=0; ParaMEDMEM::DataArrayDoubleTuple *val2=0; std::vector val3; @@ -1270,9 +1290,9 @@ namespace ParaMEDMEM static void Rotate3DAlg(PyObject *center, PyObject *vect, double angle, int nbNodes, PyObject *coords) throw(INTERP_KERNEL::Exception) { int sz,sz2; - INTERP_KERNEL::AutoPtr c=convertPyToNewDblArr2(center,&sz); - INTERP_KERNEL::AutoPtr coo=convertPyToNewDblArr2(coords,&sz); - INTERP_KERNEL::AutoPtr v=convertPyToNewDblArr2(vect,&sz2); + INTERP_KERNEL::AutoCPtr c=convertPyToNewDblArr2(center,&sz); + INTERP_KERNEL::AutoCPtr coo=convertPyToNewDblArr2(coords,&sz); + INTERP_KERNEL::AutoCPtr v=convertPyToNewDblArr2(vect,&sz2); ParaMEDMEM::MEDCouplingPointSet::Rotate3DAlg(c,v,angle,nbNodes,coo); for(int i=0;i c=convertPyToNewDblArr2(center,&sz); + INTERP_KERNEL::AutoCPtr c=convertPyToNewDblArr2(center,&sz); int sw,nbNodes=0; double val0; ParaMEDMEM::DataArrayDouble *val1=0; ParaMEDMEM::DataArrayDoubleTuple *val2=0; std::vector val3; @@ -1289,7 +1309,7 @@ namespace ParaMEDMEM "Rotate3DAlg",3,true,nbNodes); if(sw!=2 && sw!=3) throw INTERP_KERNEL::Exception("Invalid call to MEDCouplingPointSet::Rotate3DAlg : try another overload method !"); - INTERP_KERNEL::AutoPtr v=convertPyToNewDblArr2(vect,&sz2); + INTERP_KERNEL::AutoCPtr v=convertPyToNewDblArr2(vect,&sz2); ParaMEDMEM::MEDCouplingPointSet::Rotate3DAlg(c,v,angle,nbNodes,const_cast(coo)); } } @@ -1413,6 +1433,7 @@ namespace ParaMEDMEM bool checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception); DataArrayInt *rearrange2ConsecutiveCellTypes() throw(INTERP_KERNEL::Exception); DataArrayInt *sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception); + DataArrayInt *getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception); DataArrayInt *convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception); DataArrayInt *computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception); DataArrayInt *zipConnectivityTraducer(int compType, int startCellId=0) throw(INTERP_KERNEL::Exception); @@ -1735,12 +1756,21 @@ namespace ParaMEDMEM int nbOfCompo=self->getSpaceDimension(); const double *pt=convertObjToPossibleCpp5_Safe(point,sw,val,a,aa,bb,"Python wrap of MEDCouplingUMesh::distanceToPoint",1,nbOfCompo,true); // - int cellId=-1,nodeId=-1; - double ret0=self->distanceToPoint(pt,pt+nbOfCompo,cellId,nodeId); - PyObject *ret=PyTuple_New(3); + int cellId=-1; + double ret0=self->distanceToPoint(pt,pt+nbOfCompo,cellId); + PyObject *ret=PyTuple_New(2); PyTuple_SetItem(ret,0,PyFloat_FromDouble(ret0)); PyTuple_SetItem(ret,1,PyInt_FromLong(cellId)); - PyTuple_SetItem(ret,2,PyInt_FromLong(nodeId)); + return ret; + } + + PyObject *distanceToPoints(const DataArrayDouble *pts) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + DataArrayDouble *ret0=self->distanceToPoints(pts,ret1); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__DataArrayDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); return ret; } @@ -3122,7 +3152,7 @@ namespace ParaMEDMEM if (!SWIG_IsOK(res1)) { int size; - INTERP_KERNEL::AutoPtr tmp=convertPyToNewDblArr2(li,&size); + INTERP_KERNEL::AutoCPtr tmp=convertPyToNewDblArr2(li,&size); const MEDCouplingMesh *mesh=self->getMesh(); if(!mesh) throw INTERP_KERNEL::Exception("Python wrap MEDCouplingFieldDouble::getValueOnMulti : lying on a null mesh !"); @@ -3174,18 +3204,16 @@ namespace ParaMEDMEM return convertDblArrToPyList(res,sz); } - void setValues(PyObject *li) throw(INTERP_KERNEL::Exception) + void setValues(PyObject *li, PyObject *nbOfTuples=0, PyObject *nbOfComp=0) throw(INTERP_KERNEL::Exception) { if(self->getArray()!=0) + ParaMEDMEM_DataArrayDouble_setValues__SWIG_0(self->getArray(),li,nbOfTuples,nbOfComp); + else { - int sz; - double *tmp=convertPyToNewDblArr2(li,&sz); - int nbTuples=self->getArray()->getNumberOfTuples(); - int nbOfCompo=self->getArray()->getNumberOfComponents(); - self->getArray()->useArray(tmp,true,CPP_DEALLOC,nbTuples,nbOfCompo); + MEDCouplingAutoRefCountObjectPtr arr=DataArrayDouble::New(); + ParaMEDMEM_DataArrayDouble_setValues__SWIG_0(arr,li,nbOfTuples,nbOfComp); + self->setArray(arr); } - else - throw INTERP_KERNEL::Exception("setValuesCpy : field must contain an array behind"); } PyObject *getTime() throw(INTERP_KERNEL::Exception) @@ -3382,13 +3410,13 @@ namespace ParaMEDMEM case 1: { std::vector v2(1,singleVal); - MEDCouplingAutoRefCountObjectPtr aarr=ret0Arr->keepSelectedComponents(v2); + MEDCouplingAutoRefCountObjectPtr aarr=static_cast(ret0Arr->keepSelectedComponents(v2)); ret0->setArray(aarr); return ret0.retn(); } case 2: { - MEDCouplingAutoRefCountObjectPtr aarr=ret0Arr->keepSelectedComponents(multiVal); + MEDCouplingAutoRefCountObjectPtr aarr=static_cast(ret0Arr->keepSelectedComponents(multiVal)); ret0->setArray(aarr); return ret0.retn(); } @@ -3398,7 +3426,7 @@ namespace ParaMEDMEM std::vector v2(nbOfComp); for(int i=0;i aarr=ret0Arr->keepSelectedComponents(v2); + MEDCouplingAutoRefCountObjectPtr aarr=static_cast(ret0Arr->keepSelectedComponents(v2)); ret0->setArray(aarr); return ret0.retn(); } diff --git a/src/MEDCoupling_Swig/MEDCouplingExamplesTest.py b/src/MEDCoupling_Swig/MEDCouplingExamplesTest.py index c4351bcc9..cf346fa47 100644 --- a/src/MEDCoupling_Swig/MEDCouplingExamplesTest.py +++ b/src/MEDCoupling_Swig/MEDCouplingExamplesTest.py @@ -371,7 +371,7 @@ class MEDCouplingBasicsTest(unittest.TestCase): #! [PySnippet_MEDCouplingFieldDouble_getValueOnMulti_1] #! [PySnippet_MEDCouplingFieldDouble_getValueOnMulti_2] bc = mesh.getBarycenterAndOwner() # field values are located at cell barycenters - valArray = field.getValueOnMulti( bc.getValues() ) + valArray = field.getValueOnMulti( bc ) self.assertTrue( valArray.isEqual( field.getArray(), 1e-13 )) #! [PySnippet_MEDCouplingFieldDouble_getValueOnMulti_2] return @@ -387,8 +387,8 @@ class MEDCouplingBasicsTest(unittest.TestCase): #! [PySnippet_MEDCouplingFieldDouble_getValueOn_2] bc = mesh.getBarycenterAndOwner() # field values are located at cell barycenters vals = [] # array to collect values returned by getValueOn() - for i in range( bc.getNumberOfTuples() ): - vals.extend( field.getValueOn( bc.getTuple( i ))) + for i,tupl in enumerate( bc ): + vals.extend( field.getValueOn( tupl ) ) self.assertTrue( vals == field.getArray().getValues() ) #! [PySnippet_MEDCouplingFieldDouble_getValueOn_2] return @@ -622,9 +622,9 @@ class MEDCouplingBasicsTest(unittest.TestCase): #! [PySnippet_MEDCouplingUMesh_findAndCorrectBadOriented3DExtrudedCells_1] #! [PySnippet_MEDCouplingUMesh_findAndCorrectBadOriented3DExtrudedCells_2] fixedCells = mesh.findAndCorrectBadOriented3DExtrudedCells() - assert len( fixedCells.getValues() ) == 2 # 2 cells fixed + assert len( fixedCells ) == 2 # 2 cells fixed fixedCells = mesh.findAndCorrectBadOriented3DExtrudedCells() - assert len( fixedCells.getValues() ) == 0 # no bad cells + assert len( fixedCells ) == 0 # no bad cells #! [PySnippet_MEDCouplingUMesh_findAndCorrectBadOriented3DExtrudedCells_2] return @@ -655,12 +655,12 @@ class MEDCouplingBasicsTest(unittest.TestCase): #! [PySnippet_MEDCouplingUMesh_arePolyhedronsNotCorrectlyOriented_1] #! [PySnippet_MEDCouplingUMesh_arePolyhedronsNotCorrectlyOriented_2] badCells = mesh.arePolyhedronsNotCorrectlyOriented() - assert len( badCells.getValues() ) == 1 # one polyhedron is KO + assert len( badCells ) == 1 # one polyhedron is KO # fix invalid rolyherdons mesh.orientCorrectlyPolyhedrons() # re-check the orientation badCells = mesh.arePolyhedronsNotCorrectlyOriented() - assert len( badCells.getValues() ) == 0 # connectivity is OK + assert len( badCells ) == 0 # connectivity is OK #! [PySnippet_MEDCouplingUMesh_arePolyhedronsNotCorrectlyOriented_2] return @@ -1405,9 +1405,9 @@ class MEDCouplingBasicsTest(unittest.TestCase): #! [PySnippet_MEDCouplingPointSet_rotate_3] #! [PySnippet_MEDCouplingPointSet_rotate_4] mesh.changeSpaceDimension(2) - coords2 = mesh.getCoords().getValues() + coords2 = mesh.getCoords() for i,c in enumerate( coords ): - self.assertAlmostEqual( c, coords2[i], 13 ) + self.assertAlmostEqual( c, coords2.getIJ(0,i), 13 ) #! [PySnippet_MEDCouplingPointSet_rotate_4] return @@ -2100,9 +2100,9 @@ class MEDCouplingBasicsTest(unittest.TestCase): for i in xrange(8):#8 is not an error self.assertAlmostEqual(expected2[i],m2C.getCoords().getIJ(0,i),12) pass - self.assertEqual(expected3[:4],list(m2C.getNodalConnectivity().getValues())[4:]) - self.assertEqual(expected3[4:8],list(m2C.getNodalConnectivity().getValues())[:4]) - self.assertEqual(expected4[:3],list(m2C.getNodalConnectivityIndex().getValues())) + self.assertEqual(expected3[:4],[int(i) for i in m2C.getNodalConnectivity()][4:]) + self.assertEqual(expected3[4:8],[int(i) for i in m2C.getNodalConnectivity()][:4]) + self.assertEqual(expected4[:3],[int(i) for i in m2C.getNodalConnectivityIndex()]) #idem previous because nodes of cell#4 are not fully present in part3 part3=[1,2] arrr=DataArrayInt.New() @@ -2122,9 +2122,9 @@ class MEDCouplingBasicsTest(unittest.TestCase): for i in xrange(8):#8 is not an error self.assertAlmostEqual(expected2[i],m2C.getCoords().getIJ(0,i),12) pass - self.assertEqual(expected3[:4],list(m2C.getNodalConnectivity().getValues())[4:8]) - self.assertEqual(expected3[4:8],list(m2C.getNodalConnectivity().getValues())[:4]) - self.assertEqual(expected4[:3],list(m2C.getNodalConnectivityIndex().getValues())) + self.assertEqual(expected3[:4],[int(i) for i in m2C.getNodalConnectivity()][4:8]) + self.assertEqual(expected3[4:8],[int(i) for i in m2C.getNodalConnectivity()][:4]) + self.assertEqual(expected4[:3],m2C.getNodalConnectivityIndex().getValues()) part4=[1,2,4] f2=f1.buildSubPart(part4) self.assertEqual(6,f2.getNumberOfTuples()) @@ -2142,10 +2142,12 @@ class MEDCouplingBasicsTest(unittest.TestCase): for i in xrange(12): self.assertAlmostEqual(expected2[i],m2C.getCoords().getIJ(0,i),12) pass - self.assertEqual(expected3[0:4],list(m2C.getNodalConnectivity().getValues())[4:8]) - self.assertEqual(expected3[4:8],list(m2C.getNodalConnectivity().getValues())[0:4]) - self.assertEqual(expected3[8:13],list(m2C.getNodalConnectivity().getValues())[8:13]) - self.assertEqual(expected4,list(m2C.getNodalConnectivityIndex().getValues())) + self.assertEqual(expected3[0:4],m2C.getNodalConnectivity().getValues()[4:8]) + self.assertEqual(expected3[4:8],m2C.getNodalConnectivity().getValues()[0:4]) + self.assertEqual(expected3[8:13],m2C.getNodalConnectivity().getValues()[8:13]) + self.assertEqual(expected4,m2C.getNodalConnectivityIndex().getValues()) + # previous line equivalent to + self.assertEqual(expected4,[int(i) for i in m2C.getNodalConnectivityIndex()]) return def testExampleUMeshStdBuild1(self): diff --git a/src/MEDCoupling_Swig/MEDCouplingMemArray.i b/src/MEDCoupling_Swig/MEDCouplingMemArray.i index 9b916b298..a687bf850 100644 --- a/src/MEDCoupling_Swig/MEDCouplingMemArray.i +++ b/src/MEDCoupling_Swig/MEDCouplingMemArray.i @@ -32,6 +32,7 @@ namespace ParaMEDMEM std::string cppRepr(const char *varName) const throw(INTERP_KERNEL::Exception); std::string getName() const; void setInfoOnComponents(const std::vector& info) throw(INTERP_KERNEL::Exception); + void setInfoAndChangeNbOfCompo(const std::vector& info) throw(INTERP_KERNEL::Exception); std::vector getVarsOnComponent() const throw(INTERP_KERNEL::Exception); std::vector getUnitsOnComponent() const throw(INTERP_KERNEL::Exception); std::string getInfoOnComponent(int i) const throw(INTERP_KERNEL::Exception); @@ -39,6 +40,9 @@ namespace ParaMEDMEM std::string getUnitOnComponent(int i) const throw(INTERP_KERNEL::Exception); void setInfoOnComponent(int i, const char *info) throw(INTERP_KERNEL::Exception); int getNumberOfComponents() const; + virtual void alloc(int nbOfTuple, int nbOfCompo=1) throw(INTERP_KERNEL::Exception); + virtual bool isAllocated() const throw(INTERP_KERNEL::Exception); + virtual void checkAllocated() const throw(INTERP_KERNEL::Exception); virtual int getNumberOfTuples() const throw(INTERP_KERNEL::Exception); virtual std::size_t getNbOfElems() const throw(INTERP_KERNEL::Exception); virtual std::size_t getNbOfElemAllocated() const throw(INTERP_KERNEL::Exception); @@ -77,6 +81,177 @@ namespace ParaMEDMEM convertPyToNewIntArr3(li,tmp); self->copyPartOfStringInfoFrom2(tmp,other); } + + virtual void renumberInPlace(PyObject *li) throw(INTERP_KERNEL::Exception) + { + void *da=0; + int res1=SWIG_ConvertPtr(li,&da,SWIGTYPE_p_ParaMEDMEM__DataArrayInt, 0 | 0 ); + if (!SWIG_IsOK(res1)) + { + int size; + INTERP_KERNEL::AutoPtr tmp=convertPyToNewIntArr2(li,&size); + if(size!=self->getNumberOfTuples()) + { + throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); + } + self->renumberInPlace(tmp); + } + else + { + DataArrayInt *da2=reinterpret_cast< DataArrayInt * >(da); + if(!da2) + throw INTERP_KERNEL::Exception("Not null DataArrayInt instance expected !"); + da2->checkAllocated(); + int size=self->getNumberOfTuples(); + if(size!=self->getNumberOfTuples()) + { + throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); + } + self->renumberInPlace(da2->getConstPointer()); + } + } + + virtual void renumberInPlaceR(PyObject *li) throw(INTERP_KERNEL::Exception) + { + void *da=0; + int res1=SWIG_ConvertPtr(li,&da,SWIGTYPE_p_ParaMEDMEM__DataArrayInt, 0 | 0 ); + if (!SWIG_IsOK(res1)) + { + int size; + INTERP_KERNEL::AutoPtr tmp=convertPyToNewIntArr2(li,&size); + if(size!=self->getNumberOfTuples()) + { + throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); + } + self->renumberInPlaceR(tmp); + } + else + { + DataArrayInt *da2=reinterpret_cast< DataArrayInt * >(da); + if(!da2) + throw INTERP_KERNEL::Exception("Not null DataArrayInt instance expected !"); + da2->checkAllocated(); + int size=self->getNumberOfTuples(); + if(size!=self->getNumberOfTuples()) + { + throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); + } + self->renumberInPlaceR(da2->getConstPointer()); + } + } + + //tuplesSelec in PyObject * because DataArrayInt is not already existing ! + virtual void setContigPartOfSelectedValues(int tupleIdStart, PyObject *aBase, PyObject *tuplesSelec) throw(INTERP_KERNEL::Exception) + { + static const char msg[]="DataArray::setContigPartOfSelectedValues2 : 4th parameter \"tuplesSelec\" should be of type DataArrayInt"; + DataArray *a=CheckAndRetrieveDataArrayInstance(aBase,"DataArray::setContigPartOfSelectedValues2 : 3rd parameter \"aBase\" should be of type DataArray"); + DataArray *tuplesSelecPtr=CheckAndRetrieveDataArrayInstance(tuplesSelec,msg); + DataArrayInt *tuplesSelecPtr2=0; + if(tuplesSelecPtr) + { + tuplesSelecPtr2=dynamic_cast(tuplesSelecPtr); + if(!tuplesSelecPtr2) + throw INTERP_KERNEL::Exception(msg); + } + self->setContigPartOfSelectedValues(tupleIdStart,a,tuplesSelecPtr2); + } + + virtual void setContigPartOfSelectedValues2(int tupleIdStart, PyObject *aBase, int bg, int end2, int step) throw(INTERP_KERNEL::Exception) + { + DataArray *a=CheckAndRetrieveDataArrayInstance(aBase,"DataArray::setContigPartOfSelectedValues2 : 2nd parameter \"aBase\" should be of type DataArray"); + self->setContigPartOfSelectedValues2(tupleIdStart,a,bg,end2,step); + } + + virtual DataArray *selectByTupleRanges(PyObject *li) const throw(INTERP_KERNEL::Exception) + { + std::vector > ranges; + convertPyToVectorPairInt(li,ranges); + return self->selectByTupleRanges(ranges); + } + + virtual PyObject *keepSelectedComponents(PyObject *li) const throw(INTERP_KERNEL::Exception) + { + std::vector tmp; + convertPyToNewIntArr3(li,tmp); + DataArray *ret=self->keepSelectedComponents(tmp); + return convertDataArray(ret,SWIG_POINTER_OWN | 0 ); + } + + static PyObject *GetSlice(PyObject *slic, int sliceId, int nbOfSlices) throw(INTERP_KERNEL::Exception) + { + if(!PySlice_Check(slic)) + throw INTERP_KERNEL::Exception("DataArray::GetSlice (wrap) : expecting a pyslice as second (first) parameter !"); + Py_ssize_t strt=2,stp=2,step=2; + PySliceObject *sly=reinterpret_cast(slic); + if(PySlice_GetIndices(sly,std::numeric_limits::max(),&strt,&stp,&step)!=0) + throw INTERP_KERNEL::Exception("DataArray::GetSlice (wrap) : the input slice is invalid !"); + if(strt==std::numeric_limits::max() || stp==std::numeric_limits::max()) + throw INTERP_KERNEL::Exception("DataArray::GetSlice (wrap) : the input slice contains some unknowns that can't be determined in static method ! Call DataArray::getSlice (non static) instead !"); + int a,b; + DataArray::GetSlice(strt,stp,step,sliceId,nbOfSlices,a,b); + return PySlice_New(PyInt_FromLong(a),PyInt_FromLong(b),PyInt_FromLong(step)); + } + + PyObject *getSlice(PyObject *slic, int sliceId, int nbOfSlices) const throw(INTERP_KERNEL::Exception) + { + if(!PySlice_Check(slic)) + throw INTERP_KERNEL::Exception("DataArray::getSlice (wrap) : expecting a pyslice as second (first) parameter !"); + Py_ssize_t strt=2,stp=2,step=2; + PySliceObject *sly=reinterpret_cast(slic); + if(PySlice_GetIndices(sly,self->getNumberOfTuples(),&strt,&stp,&step)!=0) + throw INTERP_KERNEL::Exception("DataArray::getSlice (wrap) : the input slice is invalid !"); + int a,b; + DataArray::GetSlice(strt,stp,step,sliceId,nbOfSlices,a,b); + return PySlice_New(PyInt_FromLong(a),PyInt_FromLong(b),PyInt_FromLong(step)); + } + + static int GetNumberOfItemGivenBES(PyObject *slic) throw(INTERP_KERNEL::Exception) + { + if(!PySlice_Check(slic)) + throw INTERP_KERNEL::Exception("DataArray::GetNumberOfItemGivenBES (wrap) : expecting a pyslice as second (first) parameter !"); + Py_ssize_t strt=2,stp=2,step=2; + PySliceObject *sly=reinterpret_cast(slic); + if(PySlice_GetIndices(sly,std::numeric_limits::max(),&strt,&stp,&step)!=0) + throw INTERP_KERNEL::Exception("DataArray::GetNumberOfItemGivenBES (wrap) : the input slice is invalid !"); + if(strt==std::numeric_limits::max() || stp==std::numeric_limits::max()) + throw INTERP_KERNEL::Exception("DataArray::GetNumberOfItemGivenBES (wrap) : the input slice contains some unknowns that can't be determined in static method !"); + return DataArray::GetNumberOfItemGivenBES(strt,stp,step,""); + } + + static int GetNumberOfItemGivenBESRelative(PyObject *slic) throw(INTERP_KERNEL::Exception) + { + if(!PySlice_Check(slic)) + throw INTERP_KERNEL::Exception("DataArray::GetNumberOfItemGivenBESRelative (wrap) : expecting a pyslice as second (first) parameter !"); + Py_ssize_t strt=2,stp=2,step=2; + PySliceObject *sly=reinterpret_cast(slic); + if(PySlice_GetIndices(sly,std::numeric_limits::max(),&strt,&stp,&step)!=0) + throw INTERP_KERNEL::Exception("DataArray::GetNumberOfItemGivenBESRelative (wrap) : the input slice is invalid !"); + if(strt==std::numeric_limits::max() || stp==std::numeric_limits::max()) + throw INTERP_KERNEL::Exception("DataArray::GetNumberOfItemGivenBESRelative (wrap) : the input slice contains some unknowns that can't be determined in static method !"); + return DataArray::GetNumberOfItemGivenBESRelative(strt,stp,step,""); + } + + int getNumberOfItemGivenBES(PyObject *slic) const throw(INTERP_KERNEL::Exception) + { + if(!PySlice_Check(slic)) + throw INTERP_KERNEL::Exception("DataArray::getNumberOfItemGivenBES (wrap) : expecting a pyslice as second (first) parameter !"); + Py_ssize_t strt=2,stp=2,step=2; + PySliceObject *sly=reinterpret_cast(slic); + if(PySlice_GetIndices(sly,self->getNumberOfTuples(),&strt,&stp,&step)!=0) + throw INTERP_KERNEL::Exception("DataArray::getNumberOfItemGivenBES (wrap) : the input slice is invalid !"); + return DataArray::GetNumberOfItemGivenBES(strt,stp,step,""); + } + + int getNumberOfItemGivenBESRelative(PyObject *slic) throw(INTERP_KERNEL::Exception) + { + if(!PySlice_Check(slic)) + throw INTERP_KERNEL::Exception("DataArray::getNumberOfItemGivenBESRelative (wrap) : expecting a pyslice as second (first) parameter !"); + Py_ssize_t strt=2,stp=2,step=2; + PySliceObject *sly=reinterpret_cast(slic); + if(PySlice_GetIndices(sly,self->getNumberOfTuples(),&strt,&stp,&step)!=0) + throw INTERP_KERNEL::Exception("DataArray::getNumberOfItemGivenBESRelative (wrap) : the input slice is invalid !"); + return DataArray::GetNumberOfItemGivenBESRelative(strt,stp,step,""); + } } }; @@ -87,9 +262,6 @@ namespace ParaMEDMEM { public: static DataArrayDouble *New(); - bool isAllocated() const throw(INTERP_KERNEL::Exception); - void checkAllocated() const throw(INTERP_KERNEL::Exception); - void setInfoAndChangeNbOfCompo(const std::vector& info) throw(INTERP_KERNEL::Exception); double doubleValue() const throw(INTERP_KERNEL::Exception); bool empty() const throw(INTERP_KERNEL::Exception); DataArrayDouble *deepCpy() const throw(INTERP_KERNEL::Exception); @@ -100,7 +272,6 @@ namespace ParaMEDMEM void pushBackValsSilent(const double *valsBg, const double *valsEnd) throw(INTERP_KERNEL::Exception); double popBackSilent() throw(INTERP_KERNEL::Exception); void pack() const throw(INTERP_KERNEL::Exception); - void alloc(int nbOfTuple, int nbOfCompo=1) throw(INTERP_KERNEL::Exception); void allocIfNecessary(int nbOfTuple, int nbOfCompo) throw(INTERP_KERNEL::Exception); void fillWithZero() throw(INTERP_KERNEL::Exception); void fillWithValue(double val) throw(INTERP_KERNEL::Exception); @@ -130,8 +301,6 @@ namespace ParaMEDMEM void setPartOfValues1(const DataArrayDouble *a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare=true) throw(INTERP_KERNEL::Exception); void setPartOfValuesSimple1(double a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp) throw(INTERP_KERNEL::Exception); void setPartOfValuesAdv(const DataArrayDouble *a, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception); - void setContigPartOfSelectedValues(int tupleIdStart, const DataArrayDouble *a, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception); - void setContigPartOfSelectedValues2(int tupleIdStart, const DataArrayDouble *a, int bg, int end2, int step) throw(INTERP_KERNEL::Exception); double getIJ(int tupleId, int compoId) const; double back() const throw(INTERP_KERNEL::Exception); double getIJSafe(int tupleId, int compoId) const throw(INTERP_KERNEL::Exception); @@ -145,10 +314,10 @@ namespace ParaMEDMEM double getMaxValueInArray() const throw(INTERP_KERNEL::Exception); double getMinValue(int& tupleId) const throw(INTERP_KERNEL::Exception); double getMinValueInArray() const throw(INTERP_KERNEL::Exception); + int count(double value, double eps) const throw(INTERP_KERNEL::Exception); double getAverageValue() const throw(INTERP_KERNEL::Exception); double norm2() const throw(INTERP_KERNEL::Exception); double normMax() const throw(INTERP_KERNEL::Exception); - void accumulate(double *res) const throw(INTERP_KERNEL::Exception); double accumulate(int compId) const throw(INTERP_KERNEL::Exception); DataArrayDouble *fromPolarToCart() const throw(INTERP_KERNEL::Exception); DataArrayDouble *fromCylToCart() const throw(INTERP_KERNEL::Exception); @@ -207,7 +376,12 @@ namespace ParaMEDMEM static DataArrayDouble *New(PyObject *elt0, PyObject *nbOfTuples=0, PyObject *elt2=0) throw(INTERP_KERNEL::Exception) { - const char *msg="ParaMEDMEM::DataArrayDouble::New : Available API are : \n-DataArrayDouble.New()\n-DataArrayDouble.New([1.,3.,4.])\n-DataArrayDouble.New([1.,3.,4.],3)\n-DataArrayDouble.New([1.,3.,4.,5.],2,2)\n-DataArrayDouble.New([1.,3.,4.,5.,7,8.],3,2)\n-DataArrayDouble.New(5)\n-DataArrayDouble.New(5,2) !"; + const char *msgBase="ParaMEDMEM::DataArrayDouble::New : Available API are : \n-DataArrayDouble.New()\n-DataArrayDouble.New([1.,3.,4.])\n-DataArrayDouble.New([1.,3.,4.],3)\n-DataArrayDouble.New([1.,3.,4.,5.],2,2)\n-DataArrayDouble.New([1.,3.,4.,5.,7,8.],3,2)\n-DataArrayDouble.New([(1.,3.),(4.,5.),(7,8.)])\n-DataArrayDouble.New(5)\n-DataArrayDouble.New(5,2)"; + std::string msg(msgBase); +#ifdef WITH_NUMPY + msg+="\n-DataArrayDouble.New(numpy array with dtype=float64)"; +#endif + msg+=" !"; if(PyList_Check(elt0) || PyTuple_Check(elt0)) { if(nbOfTuples) @@ -230,7 +404,7 @@ namespace ParaMEDMEM return ret.retn(); } else - throw INTERP_KERNEL::Exception(msg); + throw INTERP_KERNEL::Exception(msg.c_str()); } else {//DataArrayDouble.New([1.,3.,4.],3) @@ -242,7 +416,7 @@ namespace ParaMEDMEM } } else - throw INTERP_KERNEL::Exception(msg); + throw INTERP_KERNEL::Exception(msg.c_str()); } else {// DataArrayDouble.New([1.,3.,4.]) @@ -272,10 +446,10 @@ namespace ParaMEDMEM return ret.retn(); } else - throw INTERP_KERNEL::Exception(msg); + throw INTERP_KERNEL::Exception(msg.c_str()); } else - throw INTERP_KERNEL::Exception(msg); + throw INTERP_KERNEL::Exception(msg.c_str()); } else {//DataArrayDouble.New(5) @@ -285,13 +459,13 @@ namespace ParaMEDMEM } } #ifdef WITH_NUMPY - else if(PyArray_Check(elt0)) + else if(PyArray_Check(elt0) && nbOfTuples==NULL && elt2==NULL) {//DataArrayDouble.New(numpyArray) return BuildNewInstance(elt0,NPY_DOUBLE,&PyCallBackDataArrayDouble_RefType,"FLOAT64"); } #endif else - throw INTERP_KERNEL::Exception(msg); + throw INTERP_KERNEL::Exception(msg.c_str()); } DataArrayDouble(PyObject *elt0, PyObject *nbOfTuples=0, PyObject *elt2=0) throw(INTERP_KERNEL::Exception) @@ -509,64 +683,6 @@ namespace ParaMEDMEM } } - void renumberInPlace(PyObject *li) throw(INTERP_KERNEL::Exception) - { - void *da=0; - int res1=SWIG_ConvertPtr(li,&da,SWIGTYPE_p_ParaMEDMEM__DataArrayInt, 0 | 0 ); - if (!SWIG_IsOK(res1)) - { - int size; - INTERP_KERNEL::AutoPtr tmp=convertPyToNewIntArr2(li,&size); - if(size!=self->getNumberOfTuples()) - { - throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); - } - self->renumberInPlace(tmp); - } - else - { - DataArrayInt *da2=reinterpret_cast< DataArrayInt * >(da); - if(!da2) - throw INTERP_KERNEL::Exception("Not null DataArrayInt instance expected !"); - da2->checkAllocated(); - int size=self->getNumberOfTuples(); - if(size!=self->getNumberOfTuples()) - { - throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); - } - self->renumberInPlace(da2->getConstPointer()); - } - } - - void renumberInPlaceR(PyObject *li) throw(INTERP_KERNEL::Exception) - { - void *da=0; - int res1=SWIG_ConvertPtr(li,&da,SWIGTYPE_p_ParaMEDMEM__DataArrayInt, 0 | 0 ); - if (!SWIG_IsOK(res1)) - { - int size; - INTERP_KERNEL::AutoPtr tmp=convertPyToNewIntArr2(li,&size); - if(size!=self->getNumberOfTuples()) - { - throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); - } - self->renumberInPlaceR(tmp); - } - else - { - DataArrayInt *da2=reinterpret_cast< DataArrayInt * >(da); - if(!da2) - throw INTERP_KERNEL::Exception("Not null DataArrayInt instance expected !"); - da2->checkAllocated(); - int size=self->getNumberOfTuples(); - if(size!=self->getNumberOfTuples()) - { - throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); - } - self->renumberInPlaceR(da2->getConstPointer()); - } - } - DataArrayDouble *selectByTupleId(PyObject *li) const throw(INTERP_KERNEL::Exception) { void *da=0; @@ -674,12 +790,13 @@ namespace ParaMEDMEM self->accumulate(tmp); return convertDblArrToPyList(tmp,sz); } - - DataArrayDouble *keepSelectedComponents(PyObject *li) const throw(INTERP_KERNEL::Exception) + + DataArrayDouble *accumulatePerChunck(PyObject *indexArr) const throw(INTERP_KERNEL::Exception) { - std::vector tmp; - convertPyToNewIntArr3(li,tmp); - return self->keepSelectedComponents(tmp); + int sw,sz,val; + std::vector val2; + const int *bg=convertObjToPossibleCpp1_Safe(indexArr,sw,sz,val,val2); + return self->accumulatePerChunck(bg,bg+sz); } PyObject *findCommonTuples(double prec, int limitNodeId=-1) const throw(INTERP_KERNEL::Exception) @@ -738,13 +855,6 @@ namespace ParaMEDMEM return DataArrayDouble::Meld(tmp); } - DataArrayDouble *selectByTupleRanges(PyObject *li) const throw(INTERP_KERNEL::Exception) - { - std::vector > ranges; - convertPyToVectorPairInt(li,ranges); - return self->selectByTupleRanges(ranges); - } - PyObject *computeTupleIdsNearTuples(PyObject *pt, double eps) const throw(INTERP_KERNEL::Exception) { double val; @@ -1849,6 +1959,16 @@ namespace ParaMEDMEM PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(cI),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); return ret; } + + PyObject *maxPerTupleWithCompoId() const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + DataArrayDouble *ret0=self->maxPerTupleWithCompoId(ret1); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__DataArrayDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; + } } }; @@ -2154,9 +2274,6 @@ namespace ParaMEDMEM { public: static DataArrayInt *New(); - bool isAllocated() const throw(INTERP_KERNEL::Exception); - void checkAllocated() const throw(INTERP_KERNEL::Exception); - void setInfoAndChangeNbOfCompo(const std::vector& info) throw(INTERP_KERNEL::Exception); int intValue() const throw(INTERP_KERNEL::Exception); int getHashCode() const throw(INTERP_KERNEL::Exception); bool empty() const throw(INTERP_KERNEL::Exception); @@ -2167,7 +2284,6 @@ namespace ParaMEDMEM void pushBackSilent(int val) throw(INTERP_KERNEL::Exception); int popBackSilent() throw(INTERP_KERNEL::Exception); void pack() const throw(INTERP_KERNEL::Exception); - void alloc(int nbOfTuple, int nbOfCompo=1) throw(INTERP_KERNEL::Exception); void allocIfNecessary(int nbOfTuple, int nbOfCompo) throw(INTERP_KERNEL::Exception); bool isEqual(const DataArrayInt& other) const throw(INTERP_KERNEL::Exception); bool isEqualWithoutConsideringStr(const DataArrayInt& other) const throw(INTERP_KERNEL::Exception); @@ -2204,8 +2320,6 @@ namespace ParaMEDMEM void setPartOfValues1(const DataArrayInt *a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare=true) throw(INTERP_KERNEL::Exception); void setPartOfValuesSimple1(int a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp) throw(INTERP_KERNEL::Exception); void setPartOfValuesAdv(const DataArrayInt *a, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception); - void setContigPartOfSelectedValues(int tupleIdStart, const DataArrayInt*a, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception); - void setContigPartOfSelectedValues2(int tupleIdStart, const DataArrayInt *a, int bg, int end2, int step) throw(INTERP_KERNEL::Exception); void getTuple(int tupleId, int *res) const throw(INTERP_KERNEL::Exception); int getIJ(int tupleId, int compoId) const throw(INTERP_KERNEL::Exception); int getIJSafe(int tupleId, int compoId) const throw(INTERP_KERNEL::Exception); @@ -2227,7 +2341,7 @@ namespace ParaMEDMEM bool presenceOfTuple(const std::vector& tupl) const throw(INTERP_KERNEL::Exception); bool presenceOfValue(int value) const throw(INTERP_KERNEL::Exception); bool presenceOfValue(const std::vector& vals) const throw(INTERP_KERNEL::Exception); - void accumulate(int *res) const throw(INTERP_KERNEL::Exception); + int count(int value) const throw(INTERP_KERNEL::Exception); int accumulate(int compId) const throw(INTERP_KERNEL::Exception); int getMaxValue(int& tupleId) const throw(INTERP_KERNEL::Exception); int getMaxValueInArray() const throw(INTERP_KERNEL::Exception); @@ -2289,7 +2403,12 @@ namespace ParaMEDMEM static DataArrayInt *New(PyObject *elt0, PyObject *nbOfTuples=0, PyObject *nbOfComp=0) throw(INTERP_KERNEL::Exception) { - const char *msg="ParaMEDMEM::DataArrayInt::New : Available API are : \n-DataArrayInt.New()\n-DataArrayInt.New([1,3,4])\n-DataArrayInt.New([1,3,4],3)\n-DataArrayInt.New([1,3,4,5],2,2)\n-DataArrayInt.New([1,3,4,5,7,8],3,2)\n-DataArrayInt.New(5)\n-DataArrayInt.New(5,2) !"; + const char *msgBase="ParaMEDMEM::DataArrayInt::New : Available API are : \n-DataArrayInt.New()\n-DataArrayInt.New([1,3,4])\n-DataArrayInt.New([1,3,4],3)\n-DataArrayInt.New([1,3,4,5],2,2)\n-DataArrayInt.New([1,3,4,5,7,8],3,2)\n-DataArrayInt.New([(1,3),(4,5),(7,8)])\n-DataArrayInt.New(5)\n-DataArrayInt.New(5,2)"; + std::string msg(msgBase); +#ifdef WITH_NUMPY + msg+="\n-DataArrayInt.New(numpy array with dtype=int32)"; +#endif + msg+=" !"; if(PyList_Check(elt0) || PyTuple_Check(elt0)) { if(nbOfTuples) @@ -2312,7 +2431,7 @@ namespace ParaMEDMEM return ret.retn(); } else - throw INTERP_KERNEL::Exception(msg); + throw INTERP_KERNEL::Exception(msg.c_str()); } else {//DataArrayInt.New([1,3,4],3) @@ -2324,7 +2443,7 @@ namespace ParaMEDMEM } } else - throw INTERP_KERNEL::Exception(msg); + throw INTERP_KERNEL::Exception(msg.c_str()); } else {// DataArrayInt.New([1,3,4]) @@ -2354,10 +2473,10 @@ namespace ParaMEDMEM return ret.retn(); } else - throw INTERP_KERNEL::Exception(msg); + throw INTERP_KERNEL::Exception(msg.c_str()); } else - throw INTERP_KERNEL::Exception(msg); + throw INTERP_KERNEL::Exception(msg.c_str()); } else {//DataArrayInt.New(5) @@ -2367,13 +2486,13 @@ namespace ParaMEDMEM } } #ifdef WITH_NUMPY - else if(PyArray_Check(elt0)) + else if(PyArray_Check(elt0) && nbOfTuples==NULL && nbOfComp==NULL) {//DataArrayInt.New(numpyArray) return BuildNewInstance(elt0,NPY_INT,&PyCallBackDataArrayInt_RefType,"INT32"); } #endif else - throw INTERP_KERNEL::Exception(msg); + throw INTERP_KERNEL::Exception(msg.c_str()); } DataArrayInt(PyObject *elt0, PyObject *nbOfTuples=0, PyObject *nbOfComp=0) throw(INTERP_KERNEL::Exception) @@ -2415,6 +2534,14 @@ namespace ParaMEDMEM self->accumulate(tmp); return convertIntArrToPyList(tmp,sz); } + + DataArrayInt *accumulatePerChunck(PyObject *indexArr) const throw(INTERP_KERNEL::Exception) + { + int sw,sz,val; + std::vector val2; + const int *bg=convertObjToPossibleCpp1_Safe(indexArr,sw,sz,val,val2); + return self->accumulatePerChunck(bg,bg+sz); + } static PyObject *BuildOld2NewArrayFromSurjectiveFormat2(int nbOfOldTuples, PyObject *arr, PyObject *arrI) throw(INTERP_KERNEL::Exception) { @@ -2611,7 +2738,7 @@ namespace ParaMEDMEM return ret; } - DataArrayInt *transformWithIndArrR(PyObject *li) const + DataArrayInt *transformWithIndArrR(PyObject *li) const throw(INTERP_KERNEL::Exception) { void *da=0; int res1=SWIG_ConvertPtr(li,&da,SWIGTYPE_p_ParaMEDMEM__DataArrayInt, 0 | 0 ); @@ -2628,64 +2755,6 @@ namespace ParaMEDMEM } } - void renumberInPlace(PyObject *li) throw(INTERP_KERNEL::Exception) - { - void *da=0; - int res1=SWIG_ConvertPtr(li,&da,SWIGTYPE_p_ParaMEDMEM__DataArrayInt, 0 | 0 ); - if (!SWIG_IsOK(res1)) - { - int size; - INTERP_KERNEL::AutoPtr tmp=convertPyToNewIntArr2(li,&size); - if(size!=self->getNumberOfTuples()) - { - throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); - } - self->renumberInPlace(tmp); - } - else - { - DataArrayInt *da2=reinterpret_cast< DataArrayInt * >(da); - if(!da2) - throw INTERP_KERNEL::Exception("Not null DataArrayInt instance expected !"); - da2->checkAllocated(); - int size=self->getNumberOfTuples(); - if(size!=self->getNumberOfTuples()) - { - throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); - } - self->renumberInPlace(da2->getConstPointer()); - } - } - - void renumberInPlaceR(PyObject *li) throw(INTERP_KERNEL::Exception) - { - void *da=0; - int res1=SWIG_ConvertPtr(li,&da,SWIGTYPE_p_ParaMEDMEM__DataArrayInt, 0 | 0 ); - if (!SWIG_IsOK(res1)) - { - int size; - INTERP_KERNEL::AutoPtr tmp=convertPyToNewIntArr2(li,&size); - if(size!=self->getNumberOfTuples()) - { - throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); - } - self->renumberInPlaceR(tmp); - } - else - { - DataArrayInt *da2=reinterpret_cast< DataArrayInt * >(da); - if(!da2) - throw INTERP_KERNEL::Exception("Not null DataArrayInt instance expected !"); - da2->checkAllocated(); - int size=self->getNumberOfTuples(); - if(size!=self->getNumberOfTuples()) - { - throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); - } - self->renumberInPlaceR(da2->getConstPointer()); - } - } - DataArrayInt *renumberAndReduce(PyObject *li, int newNbOfTuple) throw(INTERP_KERNEL::Exception) { void *da=0; @@ -2813,13 +2882,6 @@ namespace ParaMEDMEM } } - DataArrayInt *keepSelectedComponents(PyObject *li) const throw(INTERP_KERNEL::Exception) - { - std::vector tmp; - convertPyToNewIntArr3(li,tmp); - return self->keepSelectedComponents(tmp); - } - void setSelectedComponents(const DataArrayInt *a, PyObject *li) throw(INTERP_KERNEL::Exception) { std::vector tmp; @@ -2846,13 +2908,6 @@ namespace ParaMEDMEM return res; } - DataArrayInt *selectByTupleRanges(PyObject *li) const throw(INTERP_KERNEL::Exception) - { - std::vector > ranges; - convertPyToVectorPairInt(li,ranges); - return self->selectByTupleRanges(ranges); - } - static DataArrayInt *Meld(PyObject *li) throw(INTERP_KERNEL::Exception) { std::vector tmp; @@ -4483,9 +4538,7 @@ namespace ParaMEDMEM { public: virtual DataArrayChar *buildEmptySpecializedDAChar() const throw(INTERP_KERNEL::Exception) = 0; - bool isAllocated() const throw(INTERP_KERNEL::Exception); - void checkAllocated() const throw(INTERP_KERNEL::Exception); - void setInfoAndChangeNbOfCompo(const std::vector& info) throw(INTERP_KERNEL::Exception); + virtual DataArrayChar *deepCpy() const throw(INTERP_KERNEL::Exception); int getHashCode() const throw(INTERP_KERNEL::Exception); bool empty() const throw(INTERP_KERNEL::Exception); void cpyFrom(const DataArrayChar& other) throw(INTERP_KERNEL::Exception); @@ -4494,7 +4547,6 @@ namespace ParaMEDMEM void pushBackValsSilent(const char *valsBg, const char *valsEnd) throw(INTERP_KERNEL::Exception); char popBackSilent() throw(INTERP_KERNEL::Exception); void pack() const throw(INTERP_KERNEL::Exception); - void alloc(int nbOfTuple, int nbOfCompo=1) throw(INTERP_KERNEL::Exception); void allocIfNecessary(int nbOfTuple, int nbOfCompo) throw(INTERP_KERNEL::Exception); bool isEqual(const DataArrayChar& other) const throw(INTERP_KERNEL::Exception); bool isEqualWithoutConsideringStr(const DataArrayChar& other) const throw(INTERP_KERNEL::Exception); @@ -4505,8 +4557,6 @@ namespace ParaMEDMEM std::string reprZip() const throw(INTERP_KERNEL::Exception); void reAlloc(int nbOfTuples) throw(INTERP_KERNEL::Exception); DataArrayInt *convertToIntArr() const throw(INTERP_KERNEL::Exception); - void renumberInPlace(const int *old2New) throw(INTERP_KERNEL::Exception); - void renumberInPlaceR(const int *new2Old) throw(INTERP_KERNEL::Exception); DataArrayChar *renumber(const int *old2New) const throw(INTERP_KERNEL::Exception); DataArrayChar *renumberR(const int *new2Old) const throw(INTERP_KERNEL::Exception); DataArrayChar *renumberAndReduce(const int *old2NewBg, int newNbOfTuple) const throw(INTERP_KERNEL::Exception); @@ -4561,64 +4611,6 @@ namespace ParaMEDMEM return ret; } - void renumberInPlace(PyObject *li) throw(INTERP_KERNEL::Exception) - { - void *da=0; - int res1=SWIG_ConvertPtr(li,&da,SWIGTYPE_p_ParaMEDMEM__DataArrayInt, 0 | 0 ); - if (!SWIG_IsOK(res1)) - { - int size; - INTERP_KERNEL::AutoPtr tmp=convertPyToNewIntArr2(li,&size); - if(size!=self->getNumberOfTuples()) - { - throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); - } - self->renumberInPlace(tmp); - } - else - { - DataArrayInt *da2=reinterpret_cast< DataArrayInt * >(da); - if(!da2) - throw INTERP_KERNEL::Exception("Not null DataArrayInt instance expected !"); - da2->checkAllocated(); - int size=self->getNumberOfTuples(); - if(size!=self->getNumberOfTuples()) - { - throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); - } - self->renumberInPlace(da2->getConstPointer()); - } - } - - void renumberInPlaceR(PyObject *li) throw(INTERP_KERNEL::Exception) - { - void *da=0; - int res1=SWIG_ConvertPtr(li,&da,SWIGTYPE_p_ParaMEDMEM__DataArrayInt, 0 | 0 ); - if (!SWIG_IsOK(res1)) - { - int size; - INTERP_KERNEL::AutoPtr tmp=convertPyToNewIntArr2(li,&size); - if(size!=self->getNumberOfTuples()) - { - throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); - } - self->renumberInPlaceR(tmp); - } - else - { - DataArrayInt *da2=reinterpret_cast< DataArrayInt * >(da); - if(!da2) - throw INTERP_KERNEL::Exception("Not null DataArrayInt instance expected !"); - da2->checkAllocated(); - int size=self->getNumberOfTuples(); - if(size!=self->getNumberOfTuples()) - { - throw INTERP_KERNEL::Exception("Invalid list length ! Must be equal to number of tuples !"); - } - self->renumberInPlaceR(da2->getConstPointer()); - } - } - DataArrayChar *renumber(PyObject *li) throw(INTERP_KERNEL::Exception) { void *da=0; @@ -4726,13 +4718,6 @@ namespace ParaMEDMEM } } - DataArrayChar *keepSelectedComponents(PyObject *li) const throw(INTERP_KERNEL::Exception) - { - std::vector tmp; - convertPyToNewIntArr3(li,tmp); - return self->keepSelectedComponents(tmp); - } - static DataArrayChar *Aggregate(PyObject *dachs) throw(INTERP_KERNEL::Exception) { std::vector tmp; @@ -4757,7 +4742,6 @@ namespace ParaMEDMEM static DataArrayByte *New(); DataArrayChar *buildEmptySpecializedDAChar() const throw(INTERP_KERNEL::Exception); DataArrayByteIterator *iterator(); - DataArrayByte *deepCpy() const; DataArrayByte *performCpy(bool deepCpy) const; char byteValue() const throw(INTERP_KERNEL::Exception); %extend @@ -5060,7 +5044,6 @@ namespace ParaMEDMEM static DataArrayAsciiChar *New(); DataArrayChar *buildEmptySpecializedDAChar() const throw(INTERP_KERNEL::Exception); DataArrayAsciiCharIterator *iterator(); - DataArrayAsciiChar *deepCpy() const; DataArrayAsciiChar *performCpy(bool deepCpy) const; char asciiCharValue() const throw(INTERP_KERNEL::Exception); %extend diff --git a/src/MEDCoupling_Swig/MEDCouplingNumPyTest.py b/src/MEDCoupling_Swig/MEDCouplingNumPyTest.py new file mode 100644 index 000000000..3af053fe1 --- /dev/null +++ b/src/MEDCoupling_Swig/MEDCouplingNumPyTest.py @@ -0,0 +1,663 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2007-2013 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 +# +# + +from MEDCoupling import * + +if MEDCouplingHasNumPyBindings(): + from numpy import * + pass + +from sys import getrefcount + +import os,gc,weakref,unittest + +class MEDCouplingNumPyTest(unittest.TestCase): + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test1(self): + sz=20 + a=array(0,dtype=int32) + a.resize(sz) + a[:]=4 + self.assertEqual(getrefcount(a),2) + a=a.cumsum(dtype=int32) + self.assertEqual(getrefcount(a),2) + d=DataArrayInt(a) + d[:]=2 + # + e=DataArrayInt(sz) ; e.fillWithValue(2) + self.assertTrue(d.isEqual(e)) + # + a[:]=4 ; e.fillWithValue(4) + self.assertTrue(d.isEqual(e)) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test2(self): + sz=20 + a=array(0,dtype=int32) + a.resize(sz,2) + self.assertEqual(getrefcount(a),2) + b=a.reshape(2*sz) + self.assertEqual(getrefcount(a),3) + self.assertEqual(getrefcount(b),2) + b[:]=5 + d=DataArrayInt(b) + # + e=DataArrayInt(sz*2) ; e.fillWithValue(5) + self.assertTrue(d.isEqual(e)) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test3(self): + sz=10 + a=array(0,dtype=int32) + a.resize(sz,2) + b=a.reshape(2*sz) + c=a.reshape(2,sz) + b[:]=6 + b[7:17]=7 + d=DataArrayInt(b) + self.assertTrue(d.isEqual(DataArrayInt([6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,6,6,6]))) + # + a=zeros((10,2),dtype=int32) + b=a.T + c=b.view() + a.shape=20 + a[3:]=10. + d=DataArrayInt(a) + self.assertTrue(d.isEqual(DataArrayInt([0,0,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]))) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test4(self): + a=zeros(20,dtype=int32) + b = a[::-1] + self.assertRaises(InterpKernelException,DataArrayInt.New,b) # b is not contiguous in memory + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test5(self): + a=arange(20,dtype=int32) + self.assertEqual(weakref.getweakrefcount(a),0) + d=DataArrayInt(a) + self.assertEqual(weakref.getweakrefcount(a),1) + self.assertTrue(not a.flags["OWNDATA"]) + self.assertTrue(d.isIdentity()) + self.assertEqual(len(d),20) + a[:]=2 # modifying a and d because a and d share the same chunk of data + self.assertTrue(d.isUniform(2)) + del d # d is destroyed, a retrieves its ownership of its initial chunk of data + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + import gc + gc.collect() + self.assertTrue(a.flags["OWNDATA"]) + a[:]=4 # a can be used has usual + self.assertTrue(DataArrayInt(a).isUniform(4)) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test6(self): + a=arange(20,dtype=int32) + d=DataArrayInt(a) # d owns data of a + e=DataArrayInt(a) # a not owned -> e only an access to chunk of a + self.assertTrue(d.isIdentity()) + self.assertTrue(e.isIdentity()) + a[:]=6 + self.assertTrue(d.isUniform(6)) + self.assertTrue(e.isUniform(6)) + del a # a destroyed -> d no change because owned and e array is has no more data set + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + import gc + gc.collect() + self.assertTrue(d.isUniform(6)) + self.assertTrue(not e.isAllocated()) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test7(self): + a=array(0,dtype=int32) ; a.resize(10,2) + b=a.reshape(20) + c=a.reshape(2,10) + d=DataArrayInt(b) # d owns data of a + e=DataArrayInt(b) # a not owned -> e only an access to chunk of a + f=DataArrayInt(b) # a not owned -> e only an access to chunk of a + del d # d removed -> a ownes again data + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + import gc + gc.collect() + self.assertTrue(e.isUniform(0)) + e[:]=6 + self.assertTrue(e.isUniform(6)) + self.assertTrue(f.isUniform(6)) + self.assertEqual(b.tolist(),[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6]) + self.assertEqual(a.tolist(),[[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6]]) + b[:]=arange(20) + del b # no impact on e and f because a is the base of a. + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + gc.collect() + self.assertTrue(f.isIdentity()) + self.assertTrue(e.isIdentity()) + del a # a destroyed, but as c has its base set to a, a exists -> e and f not allocated + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + gc.collect() + self.assertTrue(f.isIdentity()) + self.assertTrue(e.isIdentity()) + del c # c killed -> a killed -> e and d are put into not allocated state + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + gc.collect() + self.assertTrue(not e.isAllocated()) + self.assertTrue(not f.isAllocated()) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test8(self): + a=arange(20,dtype=int32) + self.assertTrue(a.flags["OWNDATA"]) + d=DataArrayInt(a) # d owns data of a + self.assertTrue(not a.flags["OWNDATA"]) + d.pushBackSilent(20)# d pushBack so release of chunk of data -> a becomes owner of its data again + self.assertTrue(a.flags["OWNDATA"]) + self.assertTrue(d.isEqual(DataArrayInt([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]))) + self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test9(self): + sz=20 + a=array(0,dtype=float64) + a.resize(sz) + a[:]=4 + self.assertEqual(getrefcount(a),2) + a=a.cumsum(dtype=float64) + self.assertEqual(getrefcount(a),2) + d=DataArrayDouble(a) + d[:]=2 + # + e=DataArrayDouble(sz) ; e.fillWithValue(2) + self.assertTrue(d.isEqual(e,1e-14)) + # + a[:]=4 ; e.fillWithValue(4) + self.assertTrue(d.isEqual(e,1e-14)) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test10(self): + sz=20 + a=array(0,dtype=float64) + a.resize(sz,2) + self.assertEqual(getrefcount(a),2) + b=a.reshape(2*sz) + self.assertEqual(getrefcount(a),3) + self.assertEqual(getrefcount(b),2) + b[:]=5 + d=DataArrayDouble(b) + # + e=DataArrayDouble(sz*2) ; e.fillWithValue(5) + self.assertTrue(d.isEqual(e,1e-14)) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test11(self): + sz=10 + a=array(0,dtype=float64) + a.resize(sz,2) + b=a.reshape(2*sz) + c=a.reshape(2,sz) + b[:]=6 + b[7:17]=7 + d=DataArrayDouble(b) + self.assertTrue(d.isEqual(DataArrayDouble([6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,6,6,6]),1e-14)) + # + a=zeros((10,2),dtype=float64) + b=a.T + c=b.view() + a.shape=20 + a[3:]=10. + d=DataArrayDouble(a) + self.assertTrue(d.isEqual(DataArrayDouble([0,0,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]),1e-14)) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test12(self): + a=zeros(20,dtype=float64) + b = a[::-1] + self.assertRaises(InterpKernelException,DataArrayDouble.New,b) # b is not contiguous in memory + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test13(self): + a=arange(20,dtype=float64) + self.assertEqual(weakref.getweakrefcount(a),0) + d=DataArrayDouble(a) + self.assertEqual(weakref.getweakrefcount(a),1) + self.assertTrue(not a.flags["OWNDATA"]) + self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) + self.assertEqual(len(d),20) + a[:]=2 # modifying a and d because a and d share the same chunk of data + self.assertTrue(d.isUniform(2,1e-14)) + del d # d is destroyed, a retrieves its ownership of its initial chunk of data + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + import gc + gc.collect() + self.assertTrue(a.flags["OWNDATA"]) + a[:]=4 # a can be used has usual + self.assertTrue(DataArrayDouble(a).isUniform(4,1e-14)) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test14(self): + a=arange(20,dtype=float64) + d=DataArrayDouble(a) # d owns data of a + e=DataArrayDouble(a) # a not owned -> e only an access to chunk of a + self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) + self.assertTrue(e.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) + a[:]=6 + self.assertTrue(d.isUniform(6,1e-14)) + self.assertTrue(e.isUniform(6,1e-14)) + del a # a destroyed -> d no change because owned and e array is has no more data set + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + import gc + gc.collect() + self.assertTrue(d.isUniform(6,1e-14)) + self.assertTrue(not e.isAllocated()) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test15(self): + a=array(0,dtype=float64) ; a.resize(10,2) + b=a.reshape(20) + c=a.reshape(2,10) + d=DataArrayDouble(b) # d owns data of a + e=DataArrayDouble(b) # a not owned -> e only an access to chunk of a + f=DataArrayDouble(b) # a not owned -> e only an access to chunk of a + del d # d removed -> a ownes again data + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + import gc + gc.collect() + self.assertTrue(e.isUniform(0,1e-14)) + e[:]=6 + self.assertTrue(e.isUniform(6,1e-14)) + self.assertTrue(f.isUniform(6,1e-14)) + self.assertEqual(b.tolist(),[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6]) + self.assertEqual(a.tolist(),[[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6]]) + b[:]=arange(20) + del b # no impact on e and f because a is the base of a. + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + gc.collect() + self.assertTrue(f.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) + self.assertTrue(e.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) + del a # a destroyed, but as c has its base set to a, a exists -> e and f not allocated + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + gc.collect() + self.assertTrue(f.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) + self.assertTrue(e.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) + del c # c killed -> a killed -> e and d are put into not allocated state + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + gc.collect() + self.assertTrue(not e.isAllocated()) + self.assertTrue(not f.isAllocated()) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test16(self): + a=arange(20,dtype=float64) + self.assertTrue(a.flags["OWNDATA"]) + d=DataArrayDouble(a) # d owns data of a + self.assertTrue(not a.flags["OWNDATA"]) + d.pushBackSilent(20)# d pushBack so release of chunk of data -> a becomes owner of its data again + self.assertTrue(a.flags["OWNDATA"]) + self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]),1e-14)) + self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test17(self): + d=DataArrayInt.Range(0,20,1) + a=d.toNumPyArray() + self.assertTrue(not a.flags["OWNDATA"]) + a[-2:]=100 + self.assertTrue(d.isEqual(DataArrayInt([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,100,100]))) + self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,100,100]) + del a + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + import gc + gc.collect() + self.assertTrue(d.isEqual(DataArrayInt([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,100,100]))) + # + d.rearrange(2) + a=d.toNumPyArray() + self.assertTrue(not a.flags["OWNDATA"]) + a[-2:]=200 + self.assertTrue(d.isEqual(DataArrayInt([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,200,200,200,200],10,2))) + self.assertEqual(a.tolist(),[[0,1],[2,3],[4,5],[6,7],[8,9],[10,11],[12,13],[14,15],[200,200],[200,200]]) + del a + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + gc.collect() + self.assertTrue(d.isEqual(DataArrayInt([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,200,200,200,200],10,2))) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test18(self): + d=DataArrayInt.Range(0,20,1) + d=d.convertToDblArr() + a=d.toNumPyArray() + self.assertTrue(not a.flags["OWNDATA"]) + a[-2:]=100 + self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,100,100]),1e-14)) + self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,100,100]) + del a + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + import gc + gc.collect() + self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,100,100]),1e-14)) + # + d.rearrange(2) + a=d.toNumPyArray() + self.assertTrue(not a.flags["OWNDATA"]) + a[-2:]=200 + self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,200,200,200,200],10,2),1e-14)) + self.assertEqual(a.tolist(),[[0,1],[2,3],[4,5],[6,7],[8,9],[10,11],[12,13],[14,15],[200,200],[200,200]]) + del a + ##@@ Ensure a pass of the garbage collector so that the de-allocator of d is called + gc.collect() + self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,200,200,200,200],10,2),1e-14)) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test19(self): + sz=20 + a=array(0,dtype=int32) + a.resize(sz/2,2) + a[:]=4 + self.assertEqual(getrefcount(a),2) + d=DataArrayInt(a) + self.assertEqual(10,d.getNumberOfTuples()) + self.assertEqual(2,d.getNumberOfComponents()) + self.assertEqual(sz,d.getNbOfElems()) + self.assertTrue(d.isEqual(DataArrayInt([(4,4),(4,4),(4,4),(4,4),(4,4),(4,4),(4,4),(4,4),(4,4),(4,4)]))) + a[:]=7 + self.assertTrue(d.isEqual(DataArrayInt([(7,7),(7,7),(7,7),(7,7),(7,7),(7,7),(7,7),(7,7),(7,7),(7,7)]))) + # + b=a.reshape((2,5,2)) + self.assertRaises(InterpKernelException,DataArrayInt.New,b) # b has not dimension in [0,1] ! + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test20(self): + sz=20 + a=array(0,dtype=float64) + a.resize(sz/2,2) + a[:]=4 + self.assertEqual(getrefcount(a),2) + d=DataArrayDouble(a) + self.assertEqual(10,d.getNumberOfTuples()) + self.assertEqual(2,d.getNumberOfComponents()) + self.assertEqual(sz,d.getNbOfElems()) + self.assertTrue(d.isEqual(DataArrayDouble([(4.,4.),(4.,4.),(4.,4.),(4.,4.),(4.,4.),(4.,4.),(4.,4.),(4.,4.),(4.,4.),(4.,4.)]),1e-14)) + a[:]=7 + self.assertTrue(d.isEqual(DataArrayDouble([(7.,7.),(7.,7.),(7.,7.),(7.,7.),(7.,7.),(7.,7.),(7.,7.),(7.,7.),(7.,7.),(7.,7.)]),1e-14)) + # + b=a.reshape((2,5,2)) + self.assertRaises(InterpKernelException,DataArrayDouble.New,b) # b has not dimension in [0,1] ! + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test21(self): + #tests that only DataArray*(npArray) contructor is available + a=array(0,dtype=int32) + a.resize(20) + DataArrayInt(a) + self.assertRaises(InterpKernelException,DataArrayInt.New,a,20) + self.assertRaises(InterpKernelException,DataArrayInt.New,a,20,1) + a=array(0,dtype=float64) + a.resize(20) + DataArrayDouble(a) + self.assertRaises(InterpKernelException,DataArrayDouble.New,a,20) + self.assertRaises(InterpKernelException,DataArrayDouble.New,a,20,1) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test22(self): + d=DataArrayDouble(10) + d.iota() + a=d.toNumPyArray() + self.assertTrue(not a.flags["OWNDATA"]) + del d + gc.collect() + self.assertTrue(a.flags["OWNDATA"]) + self.assertEqual(a.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + # + d=DataArrayInt(10) + d.iota() + a=d.toNumPyArray() + self.assertTrue(not a.flags["OWNDATA"]) + del d + gc.collect() + self.assertTrue(a.flags["OWNDATA"]) + self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9]) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test23(self): + d=DataArrayDouble(10) + d.iota() + a=d.toNumPyArray() + b=d.toNumPyArray() + c=d.toNumPyArray() + self.assertTrue(not a.flags["OWNDATA"]) + self.assertTrue(not b.flags["OWNDATA"]) + self.assertTrue(not c.flags["OWNDATA"]) + self.assertEqual(a.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + self.assertEqual(b.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + self.assertEqual(c.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + del d + gc.collect() + self.assertTrue(a.flags["OWNDATA"]) + self.assertTrue(not b.flags["OWNDATA"]) + self.assertTrue(not c.flags["OWNDATA"]) + self.assertEqual(a.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + self.assertEqual(b.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + self.assertEqual(c.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + # + d=DataArrayInt(10) + d.iota() + a=d.toNumPyArray() + b=d.toNumPyArray() + c=d.toNumPyArray() + self.assertTrue(not a.flags["OWNDATA"]) + self.assertTrue(not b.flags["OWNDATA"]) + self.assertTrue(not c.flags["OWNDATA"]) + self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9]) + self.assertEqual(b.tolist(),[0,1,2,3,4,5,6,7,8,9]) + self.assertEqual(c.tolist(),[0,1,2,3,4,5,6,7,8,9]) + del d + gc.collect() + self.assertTrue(a.flags["OWNDATA"]) + self.assertTrue(not b.flags["OWNDATA"]) + self.assertTrue(not c.flags["OWNDATA"]) + self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9]) + self.assertEqual(b.tolist(),[0,1,2,3,4,5,6,7,8,9]) + self.assertEqual(c.tolist(),[0,1,2,3,4,5,6,7,8,9]) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test24(self): + d=DataArrayDouble(10) + d.iota() + a=d.toNumPyArray() + self.assertEqual(a.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + self.assertTrue(not a.flags["OWNDATA"]) + self.assertTrue(a.base is None) + del a + gc.collect() + a=d.toNumPyArray() + self.assertEqual(a.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + self.assertTrue(not a.flags["OWNDATA"]) + self.assertTrue(a.base is None) + b=d.toNumPyArray() + self.assertEqual(a.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + self.assertEqual(b.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + self.assertTrue(not a.flags["OWNDATA"]) + self.assertTrue(not b.flags["OWNDATA"]) + self.assertTrue(b.base is a) + del a + gc.collect() + self.assertEqual(b.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + self.assertTrue(not b.flags["OWNDATA"]) + del d + gc.collect() + self.assertEqual(b.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + self.assertTrue(not b.flags["OWNDATA"]) + # + d=DataArrayInt(10) + d.iota() + a=d.toNumPyArray() + self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9]) + self.assertTrue(not a.flags["OWNDATA"]) + self.assertTrue(a.base is None) + del a + gc.collect() + a=d.toNumPyArray() + self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9]) + self.assertTrue(not a.flags["OWNDATA"]) + self.assertTrue(a.base is None) + b=d.toNumPyArray() + self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9]) + self.assertEqual(b.tolist(),[0,1,2,3,4,5,6,7,8,9]) + self.assertTrue(not a.flags["OWNDATA"]) + self.assertTrue(not b.flags["OWNDATA"]) + self.assertTrue(b.base is a) + del a + gc.collect() + self.assertEqual(b.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + self.assertTrue(not b.flags["OWNDATA"]) + del d + gc.collect() + self.assertEqual(b.tolist(),[0.,1.,2.,3.,4.,5.,6.,7.,8.,9.]) + self.assertTrue(not b.flags["OWNDATA"]) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test25(self): + a=arange(10,dtype=int32) + b=DataArrayInt(a) + c=DataArrayInt(a) + d=DataArrayInt(a) + self.assertTrue(b.isIdentity()) ; self.assertEqual(len(b),10) + self.assertTrue(c.isIdentity()) ; self.assertEqual(len(c),10) + self.assertTrue(d.isIdentity()) ; self.assertEqual(len(d),10) + c.pushBackSilent(10) # c and a,b are dissociated + self.assertTrue(b.isIdentity()) ; self.assertEqual(len(b),10) + self.assertTrue(c.isIdentity()) ; self.assertEqual(len(c),11) + self.assertTrue(d.isIdentity()) ; self.assertEqual(len(d),10) + del a + gc.collect() + self.assertTrue(b.isIdentity()) ; self.assertEqual(len(b),10) + self.assertTrue(c.isIdentity()) ; self.assertEqual(len(c),11) + self.assertTrue(not d.isAllocated()) + del b + gc.collect() + self.assertTrue(c.isIdentity()) ; self.assertEqual(len(c),11) + # + a=arange(10,dtype=int32) + b=DataArrayInt(a) + c=DataArrayInt(a) + self.assertTrue(b.isIdentity()) ; self.assertEqual(len(b),10) + self.assertTrue(c.isIdentity()) ; self.assertEqual(len(c),10) + b.pushBackSilent(10) # c and a,b are dissociated + self.assertTrue(b.isIdentity()) ; self.assertEqual(len(b),11) + self.assertTrue(c.isIdentity()) ; self.assertEqual(len(c),10) + del a + gc.collect() + self.assertTrue(b.isIdentity()) ; self.assertEqual(len(b),11) + self.assertTrue(not c.isAllocated()) + del b + gc.collect() + self.assertTrue(not c.isAllocated()) + # + a=float64(arange(5,dtype=int32)) + b=DataArrayDouble(a) + c=DataArrayDouble(a) + d=DataArrayDouble(a) + self.assertTrue(b.isEqual(DataArrayDouble([0.,1.,2.,3.,4.]),1e-12)) + self.assertTrue(c.isEqual(DataArrayDouble([0.,1.,2.,3.,4.]),1e-12)) + self.assertTrue(d.isEqual(DataArrayDouble([0.,1.,2.,3.,4.]),1e-12)) + c.pushBackSilent(10.) # c and a,b are dissociated + self.assertTrue(b.isEqual(DataArrayDouble([0.,1.,2.,3.,4.]),1e-12)) + self.assertTrue(c.isEqual(DataArrayDouble([0.,1.,2.,3.,4.,10.]),1e-12)) + self.assertTrue(d.isEqual(DataArrayDouble([0.,1.,2.,3.,4.]),1e-12)) + del a + gc.collect() + self.assertTrue(b.isEqual(DataArrayDouble([0.,1.,2.,3.,4.]),1e-12)) + self.assertTrue(c.isEqual(DataArrayDouble([0.,1.,2.,3.,4.,10.]),1e-12)) + self.assertTrue(not d.isAllocated()) + del b + gc.collect() + self.assertTrue(c.isEqual(DataArrayDouble([0.,1.,2.,3.,4.,10.]),1e-12)) + # + a=float64(arange(5,dtype=int32)) + b=DataArrayDouble(a) + c=DataArrayDouble(a) + self.assertTrue(b.isEqual(DataArrayDouble([0.,1.,2.,3.,4.]),1e-12)) + self.assertTrue(c.isEqual(DataArrayDouble([0.,1.,2.,3.,4.]),1e-12)) + b.pushBackSilent(10.) # c and a,b are dissociated + self.assertTrue(b.isEqual(DataArrayDouble([0.,1.,2.,3.,4.,10.]),1e-12)) + self.assertTrue(c.isEqual(DataArrayDouble([0.,1.,2.,3.,4.]),1e-12)) + del a + gc.collect() + self.assertTrue(b.isEqual(DataArrayDouble([0.,1.,2.,3.,4.,10.]),1e-12)) + self.assertTrue(not c.isAllocated()) + del b + gc.collect() + self.assertTrue(not c.isAllocated()) + pass + + # @unittest.skipUnless(MEDCouplingHasNumPyBindings(),"requires numpy") + def test26(self): + d=DataArrayInt(15) ; d.iota() + d.rearrange(3) + a=d.toNumPyArray() + self.assertEqual(a.ndim,2) + self.assertEqual(a.size,15) + self.assertEqual(a.shape,(5,3)) + self.assertEqual(a.strides,(12,4)) + self.assertEqual(a.nbytes,60) + self.assertEqual(a.itemsize,4) + self.assertEqual(a.tolist(),[[0,1,2],[3,4,5],[6,7,8],[9,10,11],[12,13,14]]) + # + d2=d.convertToDblArr() + a2=d2.toNumPyArray() + self.assertEqual(a2.ndim,2) + self.assertEqual(a2.size,15) + self.assertEqual(a2.shape,(5,3)) + self.assertEqual(a2.strides,(24,8)) + self.assertEqual(a2.nbytes,120) + self.assertEqual(a2.itemsize,8) + self.assertEqual(a2.tolist(),[[0.,1.,2.],[3.,4.,5.],[6.,7.,8.],[9.,10.,11.],[12.,13.,14.]]) + pass + + def setUp(self): + pass + pass + +#gc.set_debug(gc.DEBUG_LEAK) +unittest.main() diff --git a/src/MEDCoupling_Swig/MEDCouplingNumpyTest.py b/src/MEDCoupling_Swig/MEDCouplingNumpyTest.py deleted file mode 100644 index b6f54f119..000000000 --- a/src/MEDCoupling_Swig/MEDCouplingNumpyTest.py +++ /dev/null @@ -1,356 +0,0 @@ -# -*- coding: iso-8859-1 -*- -# Copyright (C) 2007-2013 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 -# -# - -from MEDCoupling import * - -if MEDCouplingHasNumpyBindings(): - from numpy import * - pass - -from sys import getrefcount - -import os,gc,weakref,unittest - -class MEDCouplingNumpyTest(unittest.TestCase): - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test1(self): - sz=20 - a=array(0,dtype=int32) - a.resize(sz) - a[:]=4 - self.assertEqual(getrefcount(a),2) - a=a.cumsum(dtype=int32) - self.assertEqual(getrefcount(a),2) - d=DataArrayInt(a) - d[:]=2 - # - e=DataArrayInt(sz) ; e.fillWithValue(2) - self.assertTrue(d.isEqual(e)) - # - a[:]=4 ; e.fillWithValue(4) - self.assertTrue(d.isEqual(e)) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test2(self): - sz=20 - a=array(0,dtype=int32) - a.resize(sz,2) - self.assertEqual(getrefcount(a),2) - b=a.reshape(2*sz) - self.assertEqual(getrefcount(a),3) - self.assertEqual(getrefcount(b),2) - b[:]=5 - d=DataArrayInt(b) - # - e=DataArrayInt(sz*2) ; e.fillWithValue(5) - self.assertTrue(d.isEqual(e)) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test3(self): - sz=10 - a=array(0,dtype=int32) - a.resize(sz,2) - b=a.reshape(2*sz) - c=a.reshape(2,sz) - b[:]=6 - b[7:17]=7 - d=DataArrayInt(b) - self.assertTrue(d.isEqual(DataArrayInt([6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,6,6,6]))) - # - a=zeros((10,2),dtype=int32) - b=a.T - c=b.view() - a.shape=20 - a[3:]=10. - d=DataArrayInt(a) - self.assertTrue(d.isEqual(DataArrayInt([0,0,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]))) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test4(self): - a=zeros(20,dtype=int32) - b = a[::-1] - self.assertRaises(InterpKernelException,DataArrayInt.New,b) # b is not contiguous in memory - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test5(self): - a=arange(20,dtype=int32) - self.assertEqual(weakref.getweakrefcount(a),0) - d=DataArrayInt(a) - self.assertEqual(weakref.getweakrefcount(a),1) - self.assertTrue(not a.flags["OWNDATA"]) - self.assertTrue(d.isIdentity()) - self.assertEqual(len(d),20) - a[:]=2 # modifying a and d because a and d share the same chunk of data - self.assertTrue(d.isUniform(2)) - del d # d is destroyed, a retrieves its ownership of its initial chunk of data - self.assertTrue(a.flags["OWNDATA"]) - a[:]=4 # a can be used has usual - self.assertTrue(DataArrayInt(a).isUniform(4)) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test6(self): - a=arange(20,dtype=int32) - d=DataArrayInt(a) # d owns data of a - e=DataArrayInt(a) # a not owned -> e only an access to chunk of a - self.assertTrue(d.isIdentity()) - self.assertTrue(e.isIdentity()) - a[:]=6 - self.assertTrue(d.isUniform(6)) - self.assertTrue(e.isUniform(6)) - del a # a destroyed -> d no change because owned and e array is has no more data set - self.assertTrue(d.isUniform(6)) - self.assertTrue(not e.isAllocated()) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test7(self): - a=array(0,dtype=int32) ; a.resize(10,2) - b=a.reshape(20) - c=a.reshape(2,10) - d=DataArrayInt(b) # d owns data of a - e=DataArrayInt(b) # a not owned -> e only an access to chunk of a - f=DataArrayInt(b) # a not owned -> e only an access to chunk of a - del d # d removed -> a ownes again data - self.assertTrue(e.isUniform(0)) - e[:]=6 - self.assertTrue(e.isUniform(6)) - self.assertTrue(f.isUniform(6)) - self.assertEqual(b.tolist(),[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6]) - self.assertEqual(a.tolist(),[[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6]]) - b[:]=arange(20) - del b # no impact on e and f because a is the base of a. - self.assertTrue(f.isIdentity()) - self.assertTrue(e.isIdentity()) - del a # a destroyed, but as c has its base set to a, a exists -> e and f not allocated - self.assertTrue(f.isIdentity()) - self.assertTrue(e.isIdentity()) - del c # c killed -> a killed -> e and d are put into not allocated state - self.assertTrue(not e.isAllocated()) - self.assertTrue(not f.isAllocated()) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test8(self): - a=arange(20,dtype=int32) - self.assertTrue(a.flags["OWNDATA"]) - d=DataArrayInt(a) # d owns data of a - self.assertTrue(not a.flags["OWNDATA"]) - d.pushBackSilent(20)# d pushBack so release of chunk of data -> a becomes owner of its data again - self.assertTrue(a.flags["OWNDATA"]) - self.assertTrue(d.isEqual(DataArrayInt([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]))) - self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test9(self): - sz=20 - a=array(0,dtype=float64) - a.resize(sz) - a[:]=4 - self.assertEqual(getrefcount(a),2) - a=a.cumsum(dtype=float64) - self.assertEqual(getrefcount(a),2) - d=DataArrayDouble(a) - d[:]=2 - # - e=DataArrayDouble(sz) ; e.fillWithValue(2) - self.assertTrue(d.isEqual(e,1e-14)) - # - a[:]=4 ; e.fillWithValue(4) - self.assertTrue(d.isEqual(e,1e-14)) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test10(self): - sz=20 - a=array(0,dtype=float64) - a.resize(sz,2) - self.assertEqual(getrefcount(a),2) - b=a.reshape(2*sz) - self.assertEqual(getrefcount(a),3) - self.assertEqual(getrefcount(b),2) - b[:]=5 - d=DataArrayDouble(b) - # - e=DataArrayDouble(sz*2) ; e.fillWithValue(5) - self.assertTrue(d.isEqual(e,1e-14)) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test11(self): - sz=10 - a=array(0,dtype=float64) - a.resize(sz,2) - b=a.reshape(2*sz) - c=a.reshape(2,sz) - b[:]=6 - b[7:17]=7 - d=DataArrayDouble(b) - self.assertTrue(d.isEqual(DataArrayDouble([6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,6,6,6]),1e-14)) - # - a=zeros((10,2),dtype=float64) - b=a.T - c=b.view() - a.shape=20 - a[3:]=10. - d=DataArrayDouble(a) - self.assertTrue(d.isEqual(DataArrayDouble([0,0,0,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]),1e-14)) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test12(self): - a=zeros(20,dtype=float64) - b = a[::-1] - self.assertRaises(InterpKernelException,DataArrayDouble.New,b) # b is not contiguous in memory - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test13(self): - a=arange(20,dtype=float64) - self.assertEqual(weakref.getweakrefcount(a),0) - d=DataArrayDouble(a) - self.assertEqual(weakref.getweakrefcount(a),1) - self.assertTrue(not a.flags["OWNDATA"]) - self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) - self.assertEqual(len(d),20) - a[:]=2 # modifying a and d because a and d share the same chunk of data - self.assertTrue(d.isUniform(2,1e-14)) - del d # d is destroyed, a retrieves its ownership of its initial chunk of data - self.assertTrue(a.flags["OWNDATA"]) - a[:]=4 # a can be used has usual - self.assertTrue(DataArrayDouble(a).isUniform(4,1e-14)) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test14(self): - a=arange(20,dtype=float64) - d=DataArrayDouble(a) # d owns data of a - e=DataArrayDouble(a) # a not owned -> e only an access to chunk of a - self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) - self.assertTrue(e.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) - a[:]=6 - self.assertTrue(d.isUniform(6,1e-14)) - self.assertTrue(e.isUniform(6,1e-14)) - del a # a destroyed -> d no change because owned and e array is has no more data set - self.assertTrue(d.isUniform(6,1e-14)) - self.assertTrue(not e.isAllocated()) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test15(self): - a=array(0,dtype=float64) ; a.resize(10,2) - b=a.reshape(20) - c=a.reshape(2,10) - d=DataArrayDouble(b) # d owns data of a - e=DataArrayDouble(b) # a not owned -> e only an access to chunk of a - f=DataArrayDouble(b) # a not owned -> e only an access to chunk of a - del d # d removed -> a ownes again data - self.assertTrue(e.isUniform(0,1e-14)) - e[:]=6 - self.assertTrue(e.isUniform(6,1e-14)) - self.assertTrue(f.isUniform(6,1e-14)) - self.assertEqual(b.tolist(),[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6]) - self.assertEqual(a.tolist(),[[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6],[6,6]]) - b[:]=arange(20) - del b # no impact on e and f because a is the base of a. - self.assertTrue(f.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) - self.assertTrue(e.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) - del a # a destroyed, but as c has its base set to a, a exists -> e and f not allocated - self.assertTrue(f.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) - self.assertTrue(e.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]),1e-14)) - del c # c killed -> a killed -> e and d are put into not allocated state - self.assertTrue(not e.isAllocated()) - self.assertTrue(not f.isAllocated()) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test16(self): - a=arange(20,dtype=float64) - self.assertTrue(a.flags["OWNDATA"]) - d=DataArrayDouble(a) # d owns data of a - self.assertTrue(not a.flags["OWNDATA"]) - d.pushBackSilent(20)# d pushBack so release of chunk of data -> a becomes owner of its data again - self.assertTrue(a.flags["OWNDATA"]) - self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]),1e-14)) - self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test17(self): - d=DataArrayInt.Range(0,20,1) - d.rearrange(10) - self.assertRaises(InterpKernelException,d.toNumPyArray)# forbidden one or two components of d is accepted - d.rearrange(1) - a=d.toNumPyArray() - self.assertTrue(not a.flags["OWNDATA"]) - a[-2:]=100 - self.assertTrue(d.isEqual(DataArrayInt([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,100,100]))) - self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,100,100]) - del a - self.assertTrue(d.isEqual(DataArrayInt([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,100,100]))) - # - d.rearrange(2) - a=d.toNumPyArray() - self.assertTrue(not a.flags["OWNDATA"]) - a[-2:]=200 - self.assertTrue(d.isEqual(DataArrayInt([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,200,200,200,200],10,2))) - self.assertEqual(a.tolist(),[[0,1],[2,3],[4,5],[6,7],[8,9],[10,11],[12,13],[14,15],[200,200],[200,200]]) - del a - self.assertTrue(d.isEqual(DataArrayInt([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,200,200,200,200],10,2))) - pass - - @unittest.skipUnless(MEDCouplingHasNumpyBindings(),"requires numpy") - def test18(self): - d=DataArrayInt.Range(0,20,1) - d=d.convertToDblArr() - d.rearrange(10) - self.assertRaises(InterpKernelException,d.toNumPyArray)# forbidden one or two components of d is accepted - d.rearrange(1) - a=d.toNumPyArray() - self.assertTrue(not a.flags["OWNDATA"]) - a[-2:]=100 - self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,100,100]),1e-14)) - self.assertEqual(a.tolist(),[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,100,100]) - del a - self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,100,100]),1e-14)) - # - d.rearrange(2) - a=d.toNumPyArray() - self.assertTrue(not a.flags["OWNDATA"]) - a[-2:]=200 - self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,200,200,200,200],10,2),1e-14)) - self.assertEqual(a.tolist(),[[0,1],[2,3],[4,5],[6,7],[8,9],[10,11],[12,13],[14,15],[200,200],[200,200]]) - del a - self.assertTrue(d.isEqual(DataArrayDouble([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,200,200,200,200],10,2),1e-14)) - pass - - def setUp(self): - pass - pass - -#gc.set_debug(gc.DEBUG_LEAK) -unittest.main() diff --git a/src/MEDCoupling_Swig/MEDCouplingTypemaps.i b/src/MEDCoupling_Swig/MEDCouplingTypemaps.i index fe655d9aa..60c3c86af 100644 --- a/src/MEDCoupling_Swig/MEDCouplingTypemaps.i +++ b/src/MEDCoupling_Swig/MEDCouplingTypemaps.i @@ -22,6 +22,9 @@ #ifdef WITH_NUMPY #include +// specific DataArray deallocator callback. This deallocator is used both in the constructor of DataArray and in the toNumPyArr +// method. This dellocator uses weakref to determine if the linked numArr is still alive or not. If alive the ownership is given to it. +// if no more alive the "standart" DataArray deallocator is called. void numarrdeal(void *pt, void *wron) { void **wronc=(void **)wron; @@ -40,6 +43,7 @@ void numarrdeal(void *pt, void *wron) typedef void (*MyDeallocator)(void *,void *); MyDeallocator deall=(MyDeallocator)wronc[1]; deall(pt,NULL); + Py_XDECREF(weakRefOnOwner); } delete [] wronc; } @@ -74,6 +78,8 @@ extern "C" Py_TYPE(self)->tp_free(self); } + // real callback called when a numpy arr having more than one DataArray instance client on it is destroyed. + // In this case, all the "weak" clients, except the first one, invoke this call back that desable the content of these "weak" clients. static PyObject *callbackmcdataarrayint_call(PyCallBackDataArrayInt *self, PyObject *args, PyObject *kw) { if(self->_pt_mc) @@ -84,7 +90,9 @@ extern "C" Py_XINCREF(Py_None); return Py_None; } - + + // real callback called when a numpy arr having more than one DataArray instance client on it is destroyed. + // In this case, all the "weak" clients, except the first one, invoke this call back that desable the content of these "weak" clients. static PyObject *callbackmcdataarraydouble_call(PyCallBackDataArrayDouble *self, PyObject *args, PyObject *kw) { if(self->_pt_mc) @@ -181,6 +189,8 @@ PyTypeObject PyCallBackDataArrayDouble_RefType = { PyObject_GC_Del, /*tp_free*/ }; +// this is the second type of specific deallocator, only valid for the constructor of DataArrays taking numpy array +// in input when an another DataArray is already client of this. template void numarrdeal2(void *pt, void *obj) { @@ -198,23 +208,33 @@ template MCData *BuildNewInstance(PyObject *elt0, int npyObjectType, PyTypeObject *pytype, const char *msg) { int ndim=PyArray_NDIM(elt0); - if(ndim!=1) - throw INTERP_KERNEL::Exception("Input numpy array has not 1 dimension !");//to do 1 or 2. + if(ndim!=1 && ndim!=2) + throw INTERP_KERNEL::Exception("Input numpy array should have dimension equal to 1 or 2 !"); if(PyArray_ObjectType(elt0,0)!=npyObjectType) { - std::ostringstream oss; oss << "Input numpy array has not of type " << msg << " !"; - throw INTERP_KERNEL::Exception(oss.str().c_str());//to do 1 or 2. + std::ostringstream oss; oss << "Input numpy array has not of type " << msg << " at component #0 !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); } - npy_intp stride=PyArray_STRIDE(elt0,0); + if(ndim==2) + if(PyArray_ObjectType(elt0,1)!=npyObjectType) + { + std::ostringstream oss; oss << "Input numpy array has not of type " << msg << " at component #1 !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + npy_intp sz0=PyArray_DIM(elt0,0); + npy_intp sz1=ndim==2?PyArray_DIM(elt0,1):1; + // int itemSize=PyArray_ITEMSIZE(elt0); - if(itemSize ret=MCData::New(); if(PyArray_ISBEHAVED(elt0))//aligned and writeable and in machine byte-order @@ -244,7 +264,7 @@ MCData *BuildNewInstance(PyObject *elt0, int npyObjectType, PyTypeObject *pytype { PyCallBackDataArraySt *cb=PyObject_GC_New(PyCallBackDataArraySt,pytype); cb->_pt_mc=ret; - ret->useArray(reinterpret_cast(data),true,ParaMEDMEM::C_DEALLOC,sz,1); + ret->useArray(reinterpret_cast(data),true,ParaMEDMEM::C_DEALLOC,sz0,sz1); PyObject *ref=PyWeakref_NewRef(deepestObj,(PyObject *)cb); void **objs=new void *[2]; objs[0]=cb; objs[1]=ref; mma.setParameterForDeallocator(objs); @@ -253,7 +273,7 @@ MCData *BuildNewInstance(PyObject *elt0, int npyObjectType, PyTypeObject *pytype } else { - ret->useArray(reinterpret_cast(data),true,ParaMEDMEM::C_DEALLOC,sz,1); + ret->useArray(reinterpret_cast(data),true,ParaMEDMEM::C_DEALLOC,sz0,sz1); PyObject *ref=PyWeakref_NewRef(reinterpret_cast(eltOwning),NULL); void **objs=new void *[2]; objs[0]=ref; objs[1]=(void*) ParaMEDMEM::MemArray::CDeallocator; mma.setParameterForDeallocator(objs); @@ -261,10 +281,79 @@ MCData *BuildNewInstance(PyObject *elt0, int npyObjectType, PyTypeObject *pytype } } else if(PyArray_ISBEHAVED_RO(elt0)) - ret->useArray(reinterpret_cast(data),false,ParaMEDMEM::CPP_DEALLOC,sz,1); + ret->useArray(reinterpret_cast(data),false,ParaMEDMEM::CPP_DEALLOC,sz0,sz1); return ret.retn(); } + +int NumpyArrSetBaseObjectExt(PyArrayObject *arr, PyObject *obj) +{ + if (obj == NULL) { + PyErr_SetString(PyExc_ValueError, + "Cannot set the NumPy array 'base' " + "dependency to NULL after initialization"); + return -1; + } + /* + * Allow the base to be set only once. Once the object which + * owns the data is set, it doesn't make sense to change it. + */ + if (PyArray_BASE(arr) != NULL) { + Py_DECREF(obj); + PyErr_SetString(PyExc_ValueError, + "Cannot set the NumPy array 'base' " + "dependency more than once"); + return -1; + } + + /* + * Don't allow infinite chains of views, always set the base + * to the first owner of the data. + * That is, either the first object which isn't an array, + * or the first object which owns its own data. + */ + + while (PyArray_Check(obj) && (PyObject *)arr != obj) { + PyArrayObject *obj_arr = (PyArrayObject *)obj; + PyObject *tmp; + + + /* If this array owns its own data, stop collapsing */ + if (PyArray_CHKFLAGS(obj_arr, NPY_OWNDATA)) { + break; + } + + tmp = PyArray_BASE(obj_arr); + /* If there's no base, stop collapsing */ + if (tmp == NULL) { + break; + } + /* Stop the collapse new base when the would not be of the same + * type (i.e. different subclass). + */ + if (Py_TYPE(tmp) != Py_TYPE(arr)) { + break; + } + + + Py_INCREF(tmp); + Py_DECREF(obj); + obj = tmp; + } + + /* Disallow circular references */ + if ((PyObject *)arr == obj) { + Py_DECREF(obj); + PyErr_SetString(PyExc_ValueError, + "Cannot create a circular NumPy array 'base' dependency"); + return -1; + } + + arr->base = obj; + + return 0; +} + template PyObject *ToNumPyArray(MCData *self, int npyObjectType, const char *MCDataStr) { @@ -275,32 +364,43 @@ PyObject *ToNumPyArray(MCData *self, int npyObjectType, const char *MCDataStr) } ParaMEDMEM::MemArray& mem=self->accessToMemArray(); int nbComp=self->getNumberOfComponents(); - if(nbComp!=1 && nbComp!=2) + if(nbComp==0) { - std::ostringstream oss; oss << MCDataStr << "::toNumPyArray : number of components of this is " << nbComp << " ! Should 1 or 2 !"; + std::ostringstream oss; oss << MCDataStr << "::toNumPyArray : number of components of this is 0 ! Should be > 0 !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } - std::size_t sz=self->getNbOfElems(); + int nbDims=nbComp==1?1:2; npy_intp dim[2]; - dim[0]=(npy_intp)self->getNumberOfTuples(); dim[1]=2; + dim[0]=(npy_intp)self->getNumberOfTuples(); dim[1]=nbComp; const T *bg=self->getConstPointer(); - PyObject *ret=PyArray_SimpleNewFromData(nbComp,dim,npyObjectType,const_cast(bg)); + PyObject *ret=PyArray_SimpleNewFromData(nbDims,dim,npyObjectType,const_cast(bg)); if(mem.isDeallocatorCalled()) { - if(mem.getDeallocator()!=ParaMEDMEM::MemArray::CDeallocator) - { - int mask=NPY_OWNDATA; mask=~mask; - (reinterpret_cast(ret))->flags&=mask; - return ret; - } - else - { + if(mem.getDeallocator()!=numarrdeal) + {// case for the first call of toNumPyArray PyObject *ref=PyWeakref_NewRef(ret,NULL); - void **objs=new void *[2]; objs[0]=ref; objs[1]=(void*) ParaMEDMEM::MemArray::CDeallocator; + void **objs=new void *[2]; objs[0]=ref; objs[1]=(void*) mem.getDeallocator(); mem.setParameterForDeallocator(objs); mem.setSpecificDeallocator(numarrdeal); return ret; } + else + {// case for the second and other call of toNumPyArray + void **objs=(void **)mem.getParameterForDeallocator(); + PyObject *weakRefOnOwner=(PyObject *)objs[0]; + PyObject *obj=PyWeakref_GetObject(weakRefOnOwner); + if(obj!=Py_None) + {//the previous numArray exists let numpy deals the numpy array each other by declaring the still alive instance as base + Py_XINCREF(obj); + NumpyArrSetBaseObjectExt((PyArrayObject*)ret,obj); + } + else + {//the previous numArray no more exists -> declare the newly created numpy array as the first one. + Py_XDECREF(weakRefOnOwner); + PyObject *ref=PyWeakref_NewRef(ret,NULL); + objs[0]=ref; + } + } } return ret; } @@ -310,6 +410,11 @@ PyObject *ToNumPyArray(MCData *self, int npyObjectType, const char *MCDataStr) static PyObject *convertMesh(ParaMEDMEM::MEDCouplingMesh *mesh, int owner) throw(INTERP_KERNEL::Exception) { PyObject *ret=0; + if(!mesh) + { + Py_XINCREF(Py_None); + return Py_None; + } if(dynamic_cast(mesh)) ret=SWIG_NewPointerObj((void*)mesh,SWIGTYPE_p_ParaMEDMEM__MEDCouplingUMesh,owner); if(dynamic_cast(mesh)) @@ -326,6 +431,11 @@ static PyObject *convertMesh(ParaMEDMEM::MEDCouplingMesh *mesh, int owner) throw static PyObject *convertFieldDiscretization(ParaMEDMEM::MEDCouplingFieldDiscretization *fd, int owner) throw(INTERP_KERNEL::Exception) { PyObject *ret=0; + if(!fd) + { + Py_XINCREF(Py_None); + return Py_None; + } if(dynamic_cast(fd)) ret=SWIG_NewPointerObj(reinterpret_cast(fd),SWIGTYPE_p_ParaMEDMEM__MEDCouplingFieldDiscretizationP0,owner); if(dynamic_cast(fd)) @@ -344,6 +454,11 @@ static PyObject *convertFieldDiscretization(ParaMEDMEM::MEDCouplingFieldDiscreti static PyObject *convertDataArrayChar(ParaMEDMEM::DataArrayChar *dac, int owner) throw(INTERP_KERNEL::Exception) { PyObject *ret=0; + if(!dac) + { + Py_XINCREF(Py_None); + return Py_None; + } if(dynamic_cast(dac)) ret=SWIG_NewPointerObj((void*)dac,SWIGTYPE_p_ParaMEDMEM__DataArrayByte,owner); if(dynamic_cast(dac)) @@ -353,9 +468,35 @@ static PyObject *convertDataArrayChar(ParaMEDMEM::DataArrayChar *dac, int owner) return ret; } +static PyObject *convertDataArray(ParaMEDMEM::DataArray *dac, int owner) throw(INTERP_KERNEL::Exception) +{ + PyObject *ret=0; + if(!dac) + { + Py_XINCREF(Py_None); + return Py_None; + } + if(dynamic_cast(dac)) + ret=SWIG_NewPointerObj((void*)dac,SWIGTYPE_p_ParaMEDMEM__DataArrayDouble,owner); + if(dynamic_cast(dac)) + ret=SWIG_NewPointerObj((void*)dac,SWIGTYPE_p_ParaMEDMEM__DataArrayInt,owner); + if(dynamic_cast(dac)) + ret=SWIG_NewPointerObj((void*)dac,SWIGTYPE_p_ParaMEDMEM__DataArrayByte,owner); + if(dynamic_cast(dac)) + ret=SWIG_NewPointerObj((void*)dac,SWIGTYPE_p_ParaMEDMEM__DataArrayAsciiChar,owner); + if(!ret) + throw INTERP_KERNEL::Exception("Not recognized type of DataArray on downcast !"); + return ret; +} + static PyObject* convertMultiFields(ParaMEDMEM::MEDCouplingMultiFields *mfs, int owner) throw(INTERP_KERNEL::Exception) { PyObject *ret=0; + if(!mfs) + { + Py_XINCREF(Py_None); + return Py_None; + } if(dynamic_cast(mfs)) ret=SWIG_NewPointerObj((void*)mfs,SWIGTYPE_p_ParaMEDMEM__MEDCouplingFieldOverTime,owner); else @@ -814,7 +955,7 @@ static double *convertPyToNewDblArr2(PyObject *pyLi, int *size) throw(INTERP_KER if(PyList_Check(pyLi)) { *size=PyList_Size(pyLi); - double *tmp=new double[*size]; + double *tmp=(double *)malloc((*size)*sizeof(double)); for(int i=0;i<*size;i++) { PyObject *o=PyList_GetItem(pyLi,i); @@ -831,7 +972,7 @@ static double *convertPyToNewDblArr2(PyObject *pyLi, int *size) throw(INTERP_KER } else { - delete [] tmp; + free(tmp); throw INTERP_KERNEL::Exception("convertPyToNewDblArr2 : list must contain floats/integers only"); } } @@ -840,7 +981,7 @@ static double *convertPyToNewDblArr2(PyObject *pyLi, int *size) throw(INTERP_KER else if(PyTuple_Check(pyLi)) { *size=PyTuple_Size(pyLi); - double *tmp=new double[*size]; + double *tmp=(double *)malloc((*size)*sizeof(double)); for(int i=0;i<*size;i++) { PyObject *o=PyTuple_GetItem(pyLi,i); @@ -857,7 +998,7 @@ static double *convertPyToNewDblArr2(PyObject *pyLi, int *size) throw(INTERP_KER } else { - delete [] tmp; + free(tmp); throw INTERP_KERNEL::Exception("convertPyToNewDblArr2 : tuple must contain floats/integers only"); } } @@ -2360,3 +2501,28 @@ ParaMEDMEM::MEDCouplingFieldDouble *ParaMEDMEM_MEDCouplingFieldDouble___rdiv__Im { throw INTERP_KERNEL::Exception(msg); } } } + +static ParaMEDMEM::DataArray *CheckAndRetrieveDataArrayInstance(PyObject *obj, const char *msg) +{ + void *aBasePtrVS=0; + int status=SWIG_ConvertPtr(obj,&aBasePtrVS,SWIGTYPE_p_ParaMEDMEM__DataArray,0|0); + if(!SWIG_IsOK(status)) + { + status=SWIG_ConvertPtr(obj,&aBasePtrVS,SWIGTYPE_p_ParaMEDMEM__DataArrayDouble,0|0); + if(!SWIG_IsOK(status)) + { + status=SWIG_ConvertPtr(obj,&aBasePtrVS,SWIGTYPE_p_ParaMEDMEM__DataArrayInt,0|0); + if(!SWIG_IsOK(status)) + { + status=SWIG_ConvertPtr(obj,&aBasePtrVS,SWIGTYPE_p_ParaMEDMEM__DataArrayAsciiChar,0|0); + if(!SWIG_IsOK(status)) + { + status=SWIG_ConvertPtr(obj,&aBasePtrVS,SWIGTYPE_p_ParaMEDMEM__DataArrayByte,0|0); + std::ostringstream oss; oss << msg << " ! Accepted instances are DataArrayDouble, DataArrayInt, DataArrayAsciiChar, DataArrayByte !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + } + } + return reinterpret_cast< ParaMEDMEM::DataArray * >(aBasePtrVS); +} diff --git a/src/MEDCoupling_Swig/Makefile.am b/src/MEDCoupling_Swig/Makefile.am index bc06eea25..32cb8eada 100644 --- a/src/MEDCoupling_Swig/Makefile.am +++ b/src/MEDCoupling_Swig/Makefile.am @@ -58,7 +58,7 @@ _MEDCouplingRemapper_la_LDFLAGS = -module $(PYTHON_LIBS) \ CLEANFILES = MEDCouplingWRAP.cxx MEDCoupling.py MEDCouplingRemapperWRAP.cxx MEDCouplingRemapper.py -dist_salomescript_DATA= MEDCouplingBasicsTest.py MEDCouplingRemapperTest.py MEDCoupling.py MEDCouplingRemapper.py MEDCouplingDataForTest.py MEDCouplingNumpyTest.py libMEDCoupling_Swig.py +dist_salomescript_DATA= MEDCouplingBasicsTest.py MEDCouplingRemapperTest.py MEDCoupling.py MEDCouplingRemapper.py MEDCouplingDataForTest.py MEDCouplingNumPyTest.py libMEDCoupling_Swig.py UNIT_TEST_PROG = MEDCouplingBasicsTest.py MEDCouplingRemapperTest.py diff --git a/src/MEDLoader/CMakeLists.txt b/src/MEDLoader/CMakeLists.txt index 7c9eaa4ea..8666e2b55 100644 --- a/src/MEDLoader/CMakeLists.txt +++ b/src/MEDLoader/CMakeLists.txt @@ -19,7 +19,9 @@ # Author : Anthony Geay (CEA/DEN) ADD_SUBDIRECTORY(Swig) -ADD_SUBDIRECTORY(Test) +IF(CPPUNIT_STATUS) + ADD_SUBDIRECTORY(Test) +ENDIF(CPPUNIT_STATUS) INCLUDE_DIRECTORIES( ${MED3_INCLUDE_DIRS} diff --git a/src/MEDLoader/MEDFileData.cxx b/src/MEDLoader/MEDFileData.cxx index c6919ac40..8dc033c54 100644 --- a/src/MEDLoader/MEDFileData.cxx +++ b/src/MEDLoader/MEDFileData.cxx @@ -147,7 +147,7 @@ std::string MEDFileData::simpleRepr() const tmp3->simpleReprWithoutHeader(oss); } else - oss << "params set !!!\n"; + oss << "No params set !!!\n"; return oss.str(); } diff --git a/src/MEDLoader/MEDFileField.cxx b/src/MEDLoader/MEDFileField.cxx index cc9e3fe60..590958004 100644 --- a/src/MEDLoader/MEDFileField.cxx +++ b/src/MEDLoader/MEDFileField.cxx @@ -39,6 +39,9 @@ extern med_geometry_type typmai3[32]; using namespace ParaMEDMEM; +const char MEDFileField1TSWithoutSDA::TYPE_STR[]="FLOAT64"; +const char MEDFileIntField1TSWithoutSDA::TYPE_STR[]="INT32"; + MEDFileFieldLoc *MEDFileFieldLoc::New(med_idt fid, const char *locName) { return new MEDFileFieldLoc(fid,locName); @@ -196,16 +199,15 @@ std::string MEDFileFieldLoc::repr() const return oss.str(); } -void MEDFileFieldPerMeshPerTypePerDisc::assignFieldNoProfile(int& start, int offset, int nbOfCells, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerTypePerDisc::assignFieldNoProfile(int& start, int offset, int nbOfCells, const MEDCouplingFieldDouble *field, const DataArray *arrr, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { _type=field->getTypeOfField(); - const DataArrayDouble *da=field->getArray(); _start=start; switch(_type) { case ON_CELLS: { - getArray()->setContigPartOfSelectedValues2(_start,da,offset,offset+nbOfCells,1); + getArray()->setContigPartOfSelectedValues2(_start,arrr,offset,offset+nbOfCells,1); _end=_start+nbOfCells; _nval=nbOfCells; break; @@ -214,7 +216,7 @@ void MEDFileFieldPerMeshPerTypePerDisc::assignFieldNoProfile(int& start, int off { MEDCouplingAutoRefCountObjectPtr arr=field->getDiscretization()->getOffsetArr(field->getMesh()); const int *arrPtr=arr->getConstPointer(); - getArray()->setContigPartOfSelectedValues2(_start,da,arrPtr[offset],arrPtr[offset+nbOfCells],1); + getArray()->setContigPartOfSelectedValues2(_start,arrr,arrPtr[offset],arrPtr[offset+nbOfCells],1); _end=_start+(arrPtr[offset+nbOfCells]-arrPtr[offset]); _nval=nbOfCells; break; @@ -235,7 +237,7 @@ void MEDFileFieldPerMeshPerTypePerDisc::assignFieldNoProfile(int& start, int off const int *da3Ptr=da3->getConstPointer(); if(da3->getNumberOfTuples()!=nbOfCells) {//profile : for gauss even in NoProfile !!! - std::ostringstream oss; oss << "Pfl_" << getName() << "_" << INTERP_KERNEL::CellModel::GetCellModel(getGeoType()).getRepr() << "_" << _loc_id; + std::ostringstream oss; oss << "Pfl_" << nasc.getName() << "_" << INTERP_KERNEL::CellModel::GetCellModel(getGeoType()).getRepr() << "_" << _loc_id; _profile=oss.str(); da3->setName(_profile.c_str()); glob.appendProfile(da3); @@ -250,9 +252,9 @@ void MEDFileFieldPerMeshPerTypePerDisc::assignFieldNoProfile(int& start, int off for(int j=0;jsetContigPartOfSelectedValues(_start,da,da4); + getArray()->setContigPartOfSelectedValues(_start,arrr,da4); _end=_start+_nval*nbi; glob.appendLoc(_localization.c_str(),getGeoType(),gsLoc.getRefCoords(),gsLoc.getGaussCoords(),gsLoc.getWeights()); break; @@ -272,7 +274,7 @@ void MEDFileFieldPerMeshPerTypePerDisc::assignFieldNoProfile(int& start, int off * \b WARNING if not null the MED file profile can be subdivided again in case of Gauss points. * \param [in] mesh is the mesh coming from the MEDFileMesh instance in correspondance with the MEDFileField. The mesh inside the \a field is simply ignored. */ -void MEDFileFieldPerMeshPerTypePerDisc::assignFieldProfile(int& start, const DataArrayInt *multiTypePfl, const DataArrayInt *idsInPfl, DataArrayInt *locIds, int nbOfEltsInWholeMesh, const MEDCouplingFieldDouble *field, const MEDCouplingMesh *mesh, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerTypePerDisc::assignFieldProfile(int& start, const DataArrayInt *multiTypePfl, const DataArrayInt *idsInPfl, DataArrayInt *locIds, int nbOfEltsInWholeMesh, const MEDCouplingFieldDouble *field, const DataArray *arrr, const MEDCouplingMesh *mesh, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { _profile.clear(); _type=field->getTypeOfField(); @@ -290,21 +292,20 @@ void MEDFileFieldPerMeshPerTypePerDisc::assignFieldProfile(int& start, const Dat _profile=oss.str(); } } - const DataArrayDouble *da=field->getArray(); _start=start; switch(_type) { case ON_NODES: { _nval=idsInPfl->getNumberOfTuples(); - getArray()->setContigPartOfSelectedValues2(_start,da,0,da->getNumberOfTuples(),1); + getArray()->setContigPartOfSelectedValues2(_start,arrr,0,arrr->getNumberOfTuples(),1); _end=_start+_nval; break; } case ON_CELLS: { _nval=idsInPfl->getNumberOfTuples(); - getArray()->setContigPartOfSelectedValues(_start,da,idsInPfl); + getArray()->setContigPartOfSelectedValues(_start,arrr,idsInPfl); _end=_start+_nval; break; } @@ -317,7 +318,7 @@ void MEDFileFieldPerMeshPerTypePerDisc::assignFieldProfile(int& start, const Dat MEDCouplingAutoRefCountObjectPtr tmp=idsInPfl->buildExplicitArrByRanges(arr3); int trueNval=tmp->getNumberOfTuples(); _nval=idsInPfl->getNumberOfTuples(); - getArray()->setContigPartOfSelectedValues(_start,da,tmp); + getArray()->setContigPartOfSelectedValues(_start,arrr,tmp); _end=_start+trueNval; break; } @@ -346,7 +347,7 @@ void MEDFileFieldPerMeshPerTypePerDisc::assignFieldProfile(int& start, const Dat *tmpPtr++=j; // _nval=da4->getNumberOfTuples(); - getArray()->setContigPartOfSelectedValues(_start,da,tmp); + getArray()->setContigPartOfSelectedValues(_start,arrr,tmp); _end=_start+trueNval; oss << "_loc_" << _loc_id; if(locIds) @@ -365,7 +366,7 @@ void MEDFileFieldPerMeshPerTypePerDisc::assignFieldProfile(int& start, const Dat _profile=oss.str(); } } - std::ostringstream oss2; oss2 << "Loc_" << getName() << "_" << INTERP_KERNEL::CellModel::GetCellModel(getGeoType()).getRepr() << "_" << _loc_id; + std::ostringstream oss2; oss2 << "Loc_" << nasc.getName() << "_" << INTERP_KERNEL::CellModel::GetCellModel(getGeoType()).getRepr() << "_" << _loc_id; _localization=oss2.str(); glob.appendLoc(_localization.c_str(),getGeoType(),gsLoc.getRefCoords(),gsLoc.getGaussCoords(),gsLoc.getWeights()); break; @@ -376,11 +377,11 @@ void MEDFileFieldPerMeshPerTypePerDisc::assignFieldProfile(int& start, const Dat start=_end; } -void MEDFileFieldPerMeshPerTypePerDisc::assignNodeFieldNoProfile(int& start, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerTypePerDisc::assignNodeFieldNoProfile(int& start, const MEDCouplingFieldDouble *field, const DataArray *arrr, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) { _start=start; - _nval=field->getArray()->getNumberOfTuples(); - getArray()->setContigPartOfSelectedValues2(_start,field->getArray(),0,_nval,1); + _nval=arrr->getNumberOfTuples(); + getArray()->setContigPartOfSelectedValues2(_start,arrr,0,_nval,1); _end=_start+_nval; start=_end; } @@ -439,11 +440,11 @@ const MEDFileFieldPerMeshPerType *MEDFileFieldPerMeshPerTypePerDisc::getFather() return _father; } -void MEDFileFieldPerMeshPerTypePerDisc::prepareLoading(med_idt fid, int profileIt, int& start) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerTypePerDisc::prepareLoading(med_idt fid, int profileIt, int& start, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { INTERP_KERNEL::AutoPtr locname=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); INTERP_KERNEL::AutoPtr pflname=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); - std::string fieldName=getName(); + std::string fieldName=nasc.getName(); std::string meshName=getMeshName(); int iteration=getIteration(); int order=getOrder(); @@ -471,9 +472,9 @@ void MEDFileFieldPerMeshPerTypePerDisc::prepareLoading(med_idt fid, int profileI } } -void MEDFileFieldPerMeshPerTypePerDisc::finishLoading(med_idt fid, int profileIt, int ft) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerTypePerDisc::finishLoading(med_idt fid, int profileIt, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { - std::string fieldName=getName(); + std::string fieldName=nasc.getName(); std::string meshName=getMeshName(); int iteration=getIteration(); int order=getOrder(); @@ -481,27 +482,24 @@ void MEDFileFieldPerMeshPerTypePerDisc::finishLoading(med_idt fid, int profileIt INTERP_KERNEL::NormalizedCellType geoType=getGeoType(); med_geometry_type mgeoti; med_entity_type menti=MEDFileFieldPerMeshPerType::ConvertIntoMEDFileType(type,geoType,mgeoti); - DataArrayDouble *arr=getArray(); - double *startFeeding=arr->getPointer()+_start*arr->getNumberOfComponents(); - switch(ft) + DataArray *arr=getArray(); + DataArrayDouble *arrD=dynamic_cast(arr); + if(arrD) { - case 0: - { - MEDfieldValueWithProfileRd(fid,fieldName.c_str(),iteration,order,menti,mgeoti,MED_COMPACT_PFLMODE, - _profile.c_str(),MED_FULL_INTERLACE,MED_ALL_CONSTITUENT,reinterpret_cast(startFeeding)); - break; - } - case 1: - { - INTERP_KERNEL::AutoPtr tmpp=new int[(_end-_start)*arr->getNumberOfComponents()]; - MEDfieldValueWithProfileRd(fid,fieldName.c_str(),iteration,order,menti,mgeoti,MED_COMPACT_PFLMODE, - _profile.c_str(),MED_FULL_INTERLACE,MED_ALL_CONSTITUENT,reinterpret_cast((int *)tmpp)); - std::copy((const int *)tmpp,(const int *)tmpp+(_end-_start)*arr->getNumberOfComponents(),startFeeding); - break; - } - default: - throw INTERP_KERNEL::Exception("Error on array reading ! Unrecognized type of field ! Should be in FLOAT64 or INT32 !"); + double *startFeeding=arrD->getPointer()+_start*arrD->getNumberOfComponents(); + MEDfieldValueWithProfileRd(fid,fieldName.c_str(),iteration,order,menti,mgeoti,MED_COMPACT_PFLMODE, + _profile.c_str(),MED_FULL_INTERLACE,MED_ALL_CONSTITUENT,reinterpret_cast(startFeeding)); + return ; + } + DataArrayInt *arrI=dynamic_cast(arr); + if(arrI) + { + int *startFeeding=arrI->getPointer()+_start*arrI->getNumberOfComponents(); + MEDfieldValueWithProfileRd(fid,fieldName.c_str(),iteration,order,menti,mgeoti,MED_COMPACT_PFLMODE, + _profile.c_str(),MED_FULL_INTERLACE,MED_ALL_CONSTITUENT,reinterpret_cast(startFeeding)); + return ; } + throw INTERP_KERNEL::Exception("Error on array reading ! Unrecognized type of field ! Should be in FLOAT64 or INT32 !"); } /*! @@ -529,11 +527,6 @@ double MEDFileFieldPerMeshPerTypePerDisc::getTime() const return _father->getTime(); } -std::string MEDFileFieldPerMeshPerTypePerDisc::getName() const -{ - return _father->getName(); -} - std::string MEDFileFieldPerMeshPerTypePerDisc::getMeshName() const { return _father->getMeshName(); @@ -583,17 +576,28 @@ int MEDFileFieldPerMeshPerTypePerDisc::getNumberOfTuples() const return _end-_start; } -DataArrayDouble *MEDFileFieldPerMeshPerTypePerDisc::getArray() +DataArray *MEDFileFieldPerMeshPerTypePerDisc::getArray() { return _father->getArray(); } -const DataArrayDouble *MEDFileFieldPerMeshPerTypePerDisc::getArray() const +const DataArray *MEDFileFieldPerMeshPerTypePerDisc::getArray() const { const MEDFileFieldPerMeshPerType *fath=_father; return fath->getArray(); } +DataArrayDouble *MEDFileFieldPerMeshPerTypePerDisc::getArrayDouble() +{ + return _father->getArrayDouble(); +} + +const DataArrayDouble *MEDFileFieldPerMeshPerTypePerDisc::getArrayDouble() const +{ + const MEDFileFieldPerMeshPerType *fath=_father; + return fath->getArrayDouble(); +} + const std::vector& MEDFileFieldPerMeshPerTypePerDisc::getInfo() const { return _father->getInfo(); @@ -669,17 +673,27 @@ void MEDFileFieldPerMeshPerTypePerDisc::fillValues(int discId, int& startEntryId startEntryId++; } -void MEDFileFieldPerMeshPerTypePerDisc::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerTypePerDisc::writeLL(med_idt fid, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { TypeOfField type=getType(); INTERP_KERNEL::NormalizedCellType geoType=getGeoType(); med_geometry_type mgeoti; med_entity_type menti=MEDFileFieldPerMeshPerType::ConvertIntoMEDFileType(type,geoType,mgeoti); - const DataArrayDouble *arr=getArray(); - const double *locToWrite=arr->getConstPointer()+_start*arr->getNumberOfComponents(); - MEDfieldValueWithProfileWr(fid,getName().c_str(),getIteration(),getOrder(),getTime(),menti,mgeoti, + const DataArray *arr=getArray(); + if(!arr) + throw INTERP_KERNEL::Exception("MEDFileFieldPerMeshPerTypePerDisc::writeLL : no array set !"); + const DataArrayDouble *arrD=dynamic_cast(arr); + const DataArrayInt *arrI=dynamic_cast(arr); + const unsigned char *locToWrite=0; + if(arrD) + locToWrite=reinterpret_cast(arrD->getConstPointer()+_start*arr->getNumberOfComponents()); + else if(arrI) + locToWrite=reinterpret_cast(arrI->getConstPointer()+_start*arr->getNumberOfComponents()); + else + throw INTERP_KERNEL::Exception("MEDFileFieldPerMeshPerTypePerDisc::writeLL : not recognized type of values ! Supported are FLOAT64 and INT32 !"); + MEDfieldValueWithProfileWr(fid,nasc.getName().c_str(),getIteration(),getOrder(),getTime(),menti,mgeoti, MED_COMPACT_PFLMODE,_profile.c_str(),_localization.c_str(),MED_FULL_INTERLACE,MED_ALL_CONSTITUENT,_nval, - reinterpret_cast(locToWrite)); + locToWrite); } void MEDFileFieldPerMeshPerTypePerDisc::getCoarseData(TypeOfField& type, std::pair& dad, std::string& pfl, std::string& loc) const throw(INTERP_KERNEL::Exception) @@ -931,9 +945,9 @@ MEDFileFieldPerMeshPerTypePerDisc *MEDFileFieldPerMeshPerTypePerDisc::NewObjectO } -MEDFileFieldPerMeshPerType *MEDFileFieldPerMeshPerType::NewOnRead(med_idt fid, MEDFileFieldPerMesh *fath, TypeOfField type, INTERP_KERNEL::NormalizedCellType geoType) throw(INTERP_KERNEL::Exception) +MEDFileFieldPerMeshPerType *MEDFileFieldPerMeshPerType::NewOnRead(med_idt fid, MEDFileFieldPerMesh *fath, TypeOfField type, INTERP_KERNEL::NormalizedCellType geoType, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { - return new MEDFileFieldPerMeshPerType(fid,fath,type,geoType); + return new MEDFileFieldPerMeshPerType(fid,fath,type,geoType,nasc); } MEDFileFieldPerMeshPerType *MEDFileFieldPerMeshPerType::New(MEDFileFieldPerMesh *fath, INTERP_KERNEL::NormalizedCellType geoType) throw(INTERP_KERNEL::Exception) @@ -962,11 +976,11 @@ MEDFileFieldPerMeshPerType *MEDFileFieldPerMeshPerType::deepCpy(MEDFileFieldPerM return ret.retn(); } -void MEDFileFieldPerMeshPerType::assignFieldNoProfile(int& start, int offset, int nbOfCells, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerType::assignFieldNoProfile(int& start, int offset, int nbOfCells, const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { std::vector pos=addNewEntryIfNecessary(field,offset,nbOfCells); for(std::vector::const_iterator it=pos.begin();it!=pos.end();it++) - _field_pm_pt_pd[*it]->assignFieldNoProfile(start,offset,nbOfCells,field,glob); + _field_pm_pt_pd[*it]->assignFieldNoProfile(start,offset,nbOfCells,field,arr,glob,nasc); } /*! @@ -978,27 +992,27 @@ void MEDFileFieldPerMeshPerType::assignFieldNoProfile(int& start, int offset, in * \param [in] nbOfEltsInWholeMesh nb of elts of type \a this->_geo_type in \b WHOLE mesh * \param [in] mesh is the mesh coming from the MEDFileMesh instance in correspondance with the MEDFileField. The mesh inside the \a field is simply ignored. */ -void MEDFileFieldPerMeshPerType::assignFieldProfile(int& start, const DataArrayInt *multiTypePfl, const DataArrayInt *idsInPfl, DataArrayInt *locIds, int nbOfEltsInWholeMesh, const MEDCouplingFieldDouble *field, const MEDCouplingMesh *mesh, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerType::assignFieldProfile(int& start, const DataArrayInt *multiTypePfl, const DataArrayInt *idsInPfl, DataArrayInt *locIds, int nbOfEltsInWholeMesh, const MEDCouplingFieldDouble *field, const DataArray *arr, const MEDCouplingMesh *mesh, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { std::vector pos=addNewEntryIfNecessary(field,idsInPfl); for(std::vector::const_iterator it=pos.begin();it!=pos.end();it++) - _field_pm_pt_pd[*it]->assignFieldProfile(start,multiTypePfl,idsInPfl,locIds,nbOfEltsInWholeMesh,field,mesh,glob); + _field_pm_pt_pd[*it]->assignFieldProfile(start,multiTypePfl,idsInPfl,locIds,nbOfEltsInWholeMesh,field,arr,mesh,glob,nasc); } -void MEDFileFieldPerMeshPerType::assignNodeFieldNoProfile(int& start, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerType::assignNodeFieldNoProfile(int& start, const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) { _field_pm_pt_pd.resize(1); _field_pm_pt_pd[0]=MEDFileFieldPerMeshPerTypePerDisc::New(this,ON_NODES,-3); - _field_pm_pt_pd[0]->assignNodeFieldNoProfile(start,field,glob); + _field_pm_pt_pd[0]->assignNodeFieldNoProfile(start,field,arr,glob); } -void MEDFileFieldPerMeshPerType::assignNodeFieldProfile(int& start, const DataArrayInt *pfl, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerType::assignNodeFieldProfile(int& start, const DataArrayInt *pfl, const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr pfl2=pfl->deepCpy(); // _field_pm_pt_pd.resize(1); _field_pm_pt_pd[0]=MEDFileFieldPerMeshPerTypePerDisc::New(this,ON_NODES,-3); - _field_pm_pt_pd[0]->assignFieldProfile(start,pfl,pfl2,pfl2,-1,field,0,glob);//mesh is not requested so 0 is send. + _field_pm_pt_pd[0]->assignFieldProfile(start,pfl,pfl2,pfl2,-1,field,arr,0,glob,nasc);//mesh is not requested so 0 is send. } std::vector MEDFileFieldPerMeshPerType::addNewEntryIfNecessary(const MEDCouplingFieldDouble *field, int offset, int nbOfCells) throw(INTERP_KERNEL::Exception) @@ -1190,11 +1204,6 @@ double MEDFileFieldPerMeshPerType::getTime() const return _father->getTime(); } -std::string MEDFileFieldPerMeshPerType::getName() const -{ - return _father->getName(); -} - std::string MEDFileFieldPerMeshPerType::getMeshName() const { return _father->getMeshName(); @@ -1247,17 +1256,28 @@ int MEDFileFieldPerMeshPerType::getNumberOfComponents() const return _father->getNumberOfComponents(); } -DataArrayDouble *MEDFileFieldPerMeshPerType::getArray() +DataArray *MEDFileFieldPerMeshPerType::getArray() { return _father->getArray(); } -const DataArrayDouble *MEDFileFieldPerMeshPerType::getArray() const +const DataArray *MEDFileFieldPerMeshPerType::getArray() const { const MEDFileFieldPerMesh *fath=_father; return fath->getArray(); } +DataArrayDouble *MEDFileFieldPerMeshPerType::getArrayDouble() +{ + return _father->getArrayDouble(); +} + +const DataArrayDouble *MEDFileFieldPerMeshPerType::getArrayDouble() const +{ + const MEDFileFieldPerMesh *fath=_father; + return fath->getArrayDouble(); +} + const std::vector& MEDFileFieldPerMeshPerType::getInfo() const { return _father->getInfo(); @@ -1400,13 +1420,13 @@ MEDFileFieldPerMeshPerType::MEDFileFieldPerMeshPerType(MEDFileFieldPerMesh *fath { } -MEDFileFieldPerMeshPerType::MEDFileFieldPerMeshPerType(med_idt fid, MEDFileFieldPerMesh *fath, TypeOfField type, INTERP_KERNEL::NormalizedCellType geoType) throw(INTERP_KERNEL::Exception):_father(fath),_geo_type(geoType) +MEDFileFieldPerMeshPerType::MEDFileFieldPerMeshPerType(med_idt fid, MEDFileFieldPerMesh *fath, TypeOfField type, INTERP_KERNEL::NormalizedCellType geoType, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception):_father(fath),_geo_type(geoType) { INTERP_KERNEL::AutoPtr pflName=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); INTERP_KERNEL::AutoPtr locName=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); med_geometry_type mgeoti; med_entity_type menti=ConvertIntoMEDFileType(type,geoType,mgeoti); - int nbProfiles=MEDfieldnProfile(fid,getName().c_str(),getIteration(),getOrder(),menti,mgeoti,pflName,locName); + int nbProfiles=MEDfieldnProfile(fid,nasc.getName().c_str(),getIteration(),getOrder(),menti,mgeoti,pflName,locName); _field_pm_pt_pd.resize(nbProfiles); for(int i=0;i >::iterator it=_field_pm_pt_pd.begin();it!=_field_pm_pt_pd.end();it++,pflId++) { - (*it)->prepareLoading(fid,pflId+1,start); + (*it)->prepareLoading(fid,pflId+1,start,nasc);//tony } } -void MEDFileFieldPerMeshPerType::finishLoading(med_idt fid, int ft) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerType::finishLoading(med_idt fid, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { int pflId=0; for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_field_pm_pt_pd.begin();it!=_field_pm_pt_pd.end();it++,pflId++) { - (*it)->finishLoading(fid,pflId+1,ft); + (*it)->finishLoading(fid,pflId+1,nasc);//tony } } -void MEDFileFieldPerMeshPerType::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMeshPerType::writeLL(med_idt fid, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_field_pm_pt_pd.begin();it!=_field_pm_pt_pd.end();it++) { (*it)->copyOptionsFrom(*this); - (*it)->writeLL(fid); + (*it)->writeLL(fid,nasc); } } @@ -1463,12 +1483,12 @@ med_entity_type MEDFileFieldPerMeshPerType::ConvertIntoMEDFileType(TypeOfField i return MED_UNDEF_ENTITY_TYPE; } -MEDFileFieldPerMesh *MEDFileFieldPerMesh::NewOnRead(med_idt fid, MEDFileField1TSWithoutSDA *fath, int meshCsit, int meshIteration, int meshOrder) throw(INTERP_KERNEL::Exception) +MEDFileFieldPerMesh *MEDFileFieldPerMesh::NewOnRead(med_idt fid, MEDFileAnyTypeField1TSWithoutSDA *fath, int meshCsit, int meshIteration, int meshOrder, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { - return new MEDFileFieldPerMesh(fid,fath,meshCsit,meshIteration,meshOrder); + return new MEDFileFieldPerMesh(fid,fath,meshCsit,meshIteration,meshOrder,nasc); } -MEDFileFieldPerMesh *MEDFileFieldPerMesh::New(MEDFileField1TSWithoutSDA *fath, const MEDCouplingMesh *mesh) +MEDFileFieldPerMesh *MEDFileFieldPerMesh::New(MEDFileAnyTypeField1TSWithoutSDA *fath, const MEDCouplingMesh *mesh) { return new MEDFileFieldPerMesh(fath,mesh); } @@ -1482,7 +1502,7 @@ std::size_t MEDFileFieldPerMesh::getHeapMemorySize() const return ret; } -MEDFileFieldPerMesh *MEDFileFieldPerMesh::deepCpy(MEDFileField1TSWithoutSDA *father) const throw(INTERP_KERNEL::Exception) +MEDFileFieldPerMesh *MEDFileFieldPerMesh::deepCpy(MEDFileAnyTypeField1TSWithoutSDA *father) const throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > ret=new MEDFileFieldPerMesh(*this); ret->_father=father; @@ -1519,7 +1539,7 @@ void MEDFileFieldPerMesh::copyTinyInfoFrom(const MEDCouplingMesh *mesh) throw(IN mesh->getTime(_mesh_iteration,_mesh_order); } -void MEDFileFieldPerMesh::assignFieldNoProfileNoRenum(int& start, const std::vector& code, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMesh::assignFieldNoProfileNoRenum(int& start, const std::vector& code, const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { int nbOfTypes=code.size()/3; int offset=0; @@ -1528,7 +1548,7 @@ void MEDFileFieldPerMesh::assignFieldNoProfileNoRenum(int& start, const std::vec INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)code[3*i]; int nbOfCells=code[3*i+1]; int pos=addNewEntryIfNecessary(type); - _field_pm_pt[pos]->assignFieldNoProfile(start,offset,nbOfCells,field,glob); + _field_pm_pt[pos]->assignFieldNoProfile(start,offset,nbOfCells,field,arr,glob,nasc); offset+=nbOfCells; } } @@ -1542,7 +1562,7 @@ void MEDFileFieldPerMesh::assignFieldNoProfileNoRenum(int& start, const std::vec * \param [in] idsPerType is a vector containing the profiles needed to be created for MED file format. \b WARNING these processed MED file profiles can be subdivided again in case of Gauss points. * \param [in] mesh is the mesh coming from the MEDFileMesh instance in correspondance with the MEDFileField. The mesh inside the \a field is simply ignored. */ -void MEDFileFieldPerMesh::assignFieldProfile(int& start, const DataArrayInt *multiTypePfl, const std::vector& code, const std::vector& code2, const std::vector& idsInPflPerType, const std::vector& idsPerType, const MEDCouplingFieldDouble *field, const MEDCouplingMesh *mesh, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMesh::assignFieldProfile(int& start, const DataArrayInt *multiTypePfl, const std::vector& code, const std::vector& code2, const std::vector& idsInPflPerType, const std::vector& idsPerType, const MEDCouplingFieldDouble *field, const DataArray *arr, const MEDCouplingMesh *mesh, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { int nbOfTypes=code.size()/3; for(int i=0;iassignFieldProfile(start,multiTypePfl,idsInPflPerType[i],pfl,code2[3*found+1],field,mesh,glob); + _field_pm_pt[pos]->assignFieldProfile(start,multiTypePfl,idsInPflPerType[i],pfl,code2[3*found+1],field,arr,mesh,glob,nasc); } } -void MEDFileFieldPerMesh::assignNodeFieldNoProfile(int& start, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMesh::assignNodeFieldNoProfile(int& start, const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) { int pos=addNewEntryIfNecessary(INTERP_KERNEL::NORM_ERROR); - _field_pm_pt[pos]->assignNodeFieldNoProfile(start,field,glob); + _field_pm_pt[pos]->assignNodeFieldNoProfile(start,field,arr,glob); } -void MEDFileFieldPerMesh::assignNodeFieldProfile(int& start, const DataArrayInt *pfl, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMesh::assignNodeFieldProfile(int& start, const DataArrayInt *pfl, const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { int pos=addNewEntryIfNecessary(INTERP_KERNEL::NORM_ERROR); - _field_pm_pt[pos]->assignNodeFieldProfile(start,pfl,field,glob); + _field_pm_pt[pos]->assignNodeFieldProfile(start,pfl,field,arr,glob,nasc); } -void MEDFileFieldPerMesh::prepareLoading(med_idt fid, int& start) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMesh::prepareLoading(med_idt fid, int& start, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMeshPerType > >::iterator it=_field_pm_pt.begin();it!=_field_pm_pt.end();it++) - (*it)->prepareLoading(fid,start); + (*it)->prepareLoading(fid,start,nasc); } -void MEDFileFieldPerMesh::finishLoading(med_idt fid, int ft) throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMesh::finishLoading(med_idt fid, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMeshPerType > >::iterator it=_field_pm_pt.begin();it!=_field_pm_pt.end();it++) - (*it)->finishLoading(fid,ft); + (*it)->finishLoading(fid,nasc); } -void MEDFileFieldPerMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMesh::writeLL(med_idt fid, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { int nbOfTypes=_field_pm_pt.size(); for(int i=0;icopyOptionsFrom(*this); - _field_pm_pt[i]->writeLL(fid); + _field_pm_pt[i]->writeLL(fid,nasc); } } @@ -1633,35 +1653,44 @@ int MEDFileFieldPerMesh::getIteration() const return _father->getIteration(); } -const std::string& MEDFileFieldPerMesh::getDtUnit() const -{ - return _father->getDtUnit(); -} - int MEDFileFieldPerMesh::getOrder() const { return _father->getOrder(); } -std::string MEDFileFieldPerMesh::getName() const +int MEDFileFieldPerMesh::getNumberOfComponents() const { - return _father->getName(); + return _father->getNumberOfComponents(); } -int MEDFileFieldPerMesh::getNumberOfComponents() const +DataArray *MEDFileFieldPerMesh::getArray() { - return _father->getNumberOfComponents(); + if(!_father) + throw INTERP_KERNEL::Exception("MEDFileFieldPerMesh::getArray : no father ! internal error !"); + return _father->getOrCreateAndGetArray(); } -DataArrayDouble *MEDFileFieldPerMesh::getArray() +const DataArray *MEDFileFieldPerMesh::getArray() const { + if(!_father) + throw INTERP_KERNEL::Exception("MEDFileFieldPerMesh::getArray : no father ! internal error !"); return _father->getOrCreateAndGetArray(); } -const DataArrayDouble *MEDFileFieldPerMesh::getArray() const +DataArrayDouble *MEDFileFieldPerMesh::getArrayDouble() +{ + MEDFileField1TSWithoutSDA *fatherC=dynamic_cast(_father); + if(!fatherC) + throw INTERP_KERNEL::Exception("MEDFileFieldPerMesh::getArrayDouble : Expected to be called on double array !"); + return fatherC->getOrCreateAndGetArrayDouble(); +} + +const DataArrayDouble *MEDFileFieldPerMesh::getArrayDouble() const { - const MEDFileField1TSWithoutSDA *fath=_father; - return fath->getOrCreateAndGetArray(); + const MEDFileField1TSWithoutSDA *fatherC=dynamic_cast(_father); + if(!fatherC) + throw INTERP_KERNEL::Exception("MEDFileFieldPerMesh::getArrayDouble : Expected to be called on double array !"); + return fatherC->getOrCreateAndGetArrayDouble(); } const std::vector& MEDFileFieldPerMesh::getInfo() const @@ -1829,7 +1858,8 @@ bool MEDFileFieldPerMesh::renumberEntitiesLyingOnMesh(const char *meshName, cons std::vector< std::pair,std::pair > > entries; std::vector< const MEDFileFieldPerMeshPerTypePerDisc *> entriesKept; std::vector< const MEDFileFieldPerMeshPerTypePerDisc *> otherEntries; - DataArrayDouble *arr=getUndergroundDataArrayExt(entries); + getUndergroundDataArrayExt(entries); + DataArrayDouble *arr=getArrayDouble(); int sz=0; if(!arr) throw INTERP_KERNEL::Exception("MEDFileFieldPerMesh::renumberEntitiesLyingOnMesh : DataArrayDouble storing values of field is null !"); @@ -1945,7 +1975,7 @@ void MEDFileFieldPerMesh::changeLocsRefsNamesGen(const std::vector< std::pair& arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { if(_field_pm_pt.empty()) throw INTERP_KERNEL::Exception("MEDFileFieldPerMesh::getFieldOnMeshAtLevel : no types field set !"); @@ -1961,7 +1991,7 @@ MEDCouplingFieldDouble *MEDFileFieldPerMesh::getFieldOnMeshAtLevel(TypeOfField t SortArraysPerType(glob,type,geoTypes,dads,pfls,locs,code,notNullPflsPerGeoType); if(code.empty()) { - std::ostringstream oss; oss << "MEDFileFieldPerMesh::getFieldOnMeshAtLevel : " << "The field \"" << getName() << "\" exists but not with such spatial discretization or such dimension specified !"; + std::ostringstream oss; oss << "MEDFileFieldPerMesh::getFieldOnMeshAtLevel : " << "The field \"" << nasc.getName() << "\" exists but not with such spatial discretization or such dimension specified !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } // @@ -1971,11 +2001,11 @@ MEDCouplingFieldDouble *MEDFileFieldPerMesh::getFieldOnMeshAtLevel(TypeOfField t { DataArrayInt *arr=mesh->checkTypeConsistencyAndContig(code,notNullPflsPerGeoType3); if(!arr) - return finishField(type,glob,dads,locs,mesh,isPfl); + return finishField(type,glob,dads,locs,mesh,isPfl,arrOut,nasc); else { MEDCouplingAutoRefCountObjectPtr arr2(arr); - return finishField2(type,glob,dads,locs,geoTypes,mesh,arr,isPfl); + return finishField2(type,glob,dads,locs,geoTypes,mesh,arr,isPfl,arrOut,nasc); } } else @@ -1991,14 +2021,14 @@ MEDCouplingFieldDouble *MEDFileFieldPerMesh::getFieldOnMeshAtLevel(TypeOfField t oss << " nodes in mesh !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } - return finishField(type,glob,dads,locs,mesh,isPfl); + return finishField(type,glob,dads,locs,mesh,isPfl,arrOut,nasc); } else - return finishFieldNode2(glob,dads,locs,mesh,notNullPflsPerGeoType3[0],isPfl); + return finishFieldNode2(glob,dads,locs,mesh,notNullPflsPerGeoType3[0],isPfl,arrOut,nasc); } } -DataArrayDouble *MEDFileFieldPerMesh::getFieldOnMeshAtLevelWithPfl(TypeOfField type, const MEDCouplingMesh *mesh, DataArrayInt *&pfl, const MEDFileFieldGlobsReal *glob) const throw(INTERP_KERNEL::Exception) +DataArray *MEDFileFieldPerMesh::getFieldOnMeshAtLevelWithPfl(TypeOfField type, const MEDCouplingMesh *mesh, DataArrayInt *&pfl, const MEDFileFieldGlobsReal *glob, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { if(_field_pm_pt.empty()) throw INTERP_KERNEL::Exception("MEDFileFieldPerMesh::getFieldOnMeshAtLevel : no types field set !"); @@ -2014,7 +2044,7 @@ DataArrayDouble *MEDFileFieldPerMesh::getFieldOnMeshAtLevelWithPfl(TypeOfField t SortArraysPerType(glob,type,geoTypes,dads,pfls,locs,code,notNullPflsPerGeoType); if(code.empty()) { - std::ostringstream oss; oss << "MEDFileFieldPerMesh::getFieldOnMeshAtLevelWithPfl : " << "The field \"" << getName() << "\" exists but not with such spatial discretization or such dimension specified !"; + std::ostringstream oss; oss << "MEDFileFieldPerMesh::getFieldOnMeshAtLevelWithPfl : " << "The field \"" << nasc.getName() << "\" exists but not with such spatial discretization or such dimension specified !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } std::vector< MEDCouplingAutoRefCountObjectPtr > notNullPflsPerGeoType2(notNullPflsPerGeoType.begin(),notNullPflsPerGeoType.end()); @@ -2044,7 +2074,7 @@ DataArrayDouble *MEDFileFieldPerMesh::getFieldOnMeshAtLevelWithPfl(TypeOfField t return 0; } -DataArrayDouble *MEDFileFieldPerMesh::getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) +void MEDFileFieldPerMesh::getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) { int globalSz=0; int nbOfEntries=0; @@ -2058,7 +2088,6 @@ DataArrayDouble *MEDFileFieldPerMesh::getUndergroundDataArrayExt(std::vector< st { (*it)->fillValues(nbOfEntries,entries); } - return _father->getUndergroundDataArray(); } MEDFileFieldPerMeshPerTypePerDisc *MEDFileFieldPerMesh::getLeafGivenTypeAndLocId(INTERP_KERNEL::NormalizedCellType typ, int locId) throw(INTERP_KERNEL::Exception) @@ -2125,16 +2154,15 @@ int MEDFileFieldPerMesh::addNewEntryIfNecessary(INTERP_KERNEL::NormalizedCellTyp */ MEDCouplingFieldDouble *MEDFileFieldPerMesh::finishField(TypeOfField type, const MEDFileFieldGlobsReal *glob, const std::vector< std::pair >& dads, const std::vector& locs, - const MEDCouplingMesh *mesh, bool& isPfl) const throw(INTERP_KERNEL::Exception) + const MEDCouplingMesh *mesh, bool& isPfl, MEDCouplingAutoRefCountObjectPtr& arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { isPfl=false; MEDCouplingAutoRefCountObjectPtr ret=MEDCouplingFieldDouble::New(type,ONE_TIME); - ret->setMesh(mesh); ret->setName(getName().c_str()); ret->setTime(getTime(),getIteration(),getOrder()); ret->setTimeUnit(getDtUnit().c_str()); - MEDCouplingAutoRefCountObjectPtr da=getArray()->selectByTupleRanges(dads); + ret->setMesh(mesh); ret->setName(nasc.getName().c_str()); ret->setTime(getTime(),getIteration(),getOrder()); ret->setTimeUnit(nasc.getDtUnit().c_str()); + MEDCouplingAutoRefCountObjectPtr da=getArray()->selectByTupleRanges(dads); const std::vector& infos=getInfo(); da->setInfoOnComponents(infos); da->setName(""); - ret->setArray(da); if(type==ON_GAUSS_PT) { int offset=0; @@ -2152,7 +2180,7 @@ MEDCouplingFieldDouble *MEDFileFieldPerMesh::finishField(TypeOfField type, const offset+=nbOfElems; } } - // + arrOut=da; return ret.retn(); } @@ -2166,17 +2194,17 @@ MEDCouplingFieldDouble *MEDFileFieldPerMesh::finishField(TypeOfField type, const MEDCouplingFieldDouble *MEDFileFieldPerMesh::finishField2(TypeOfField type, const MEDFileFieldGlobsReal *glob, const std::vector >& dads, const std::vector& locs, const std::vector& geoTypes, - const MEDCouplingMesh *mesh, const DataArrayInt *da, bool& isPfl) const throw(INTERP_KERNEL::Exception) + const MEDCouplingMesh *mesh, const DataArrayInt *da, bool& isPfl, MEDCouplingAutoRefCountObjectPtr& arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { if(da->isIdentity()) { int nbOfTuples=da->getNumberOfTuples(); if(nbOfTuples==mesh->getNumberOfCells()) - return finishField(type,glob,dads,locs,mesh,isPfl); + return finishField(type,glob,dads,locs,mesh,isPfl,arrOut,nasc); } MEDCouplingAutoRefCountObjectPtr m2=mesh->buildPart(da->getConstPointer(),da->getConstPointer()+da->getNbOfElems()); m2->setName(mesh->getName()); - MEDCouplingAutoRefCountObjectPtr ret=finishField(type,glob,dads,locs,m2,isPfl); + MEDCouplingAutoRefCountObjectPtr ret=finishField(type,glob,dads,locs,m2,isPfl,arrOut,nasc); isPfl=true; return ret.retn(); } @@ -2186,13 +2214,13 @@ MEDCouplingFieldDouble *MEDFileFieldPerMesh::finishField2(TypeOfField type, cons */ MEDCouplingFieldDouble *MEDFileFieldPerMesh::finishFieldNode2(const MEDFileFieldGlobsReal *glob, const std::vector >& dads, const std::vector& locs, - const MEDCouplingMesh *mesh, const DataArrayInt *da, bool& isPfl) const throw(INTERP_KERNEL::Exception) + const MEDCouplingMesh *mesh, const DataArrayInt *da, bool& isPfl, MEDCouplingAutoRefCountObjectPtr& arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { if(da->isIdentity()) { int nbOfTuples=da->getNumberOfTuples(); if(nbOfTuples==mesh->getNumberOfNodes())//No problem for NORM_ERROR because it is in context of node - return finishField(ON_NODES,glob,dads,locs,mesh,isPfl); + return finishField(ON_NODES,glob,dads,locs,mesh,isPfl,arrOut,nasc); } // Treatment of particular case where nodal field on pfl is requested with a meshDimRelToMax=1. const MEDCouplingUMesh *meshu=dynamic_cast(mesh); @@ -2200,7 +2228,7 @@ MEDCouplingFieldDouble *MEDFileFieldPerMesh::finishFieldNode2(const MEDFileField { if(meshu->getNodalConnectivity()==0) { - MEDCouplingAutoRefCountObjectPtr ret=finishField(ON_CELLS,glob,dads,locs,mesh,isPfl); + MEDCouplingAutoRefCountObjectPtr ret=finishField(ON_CELLS,glob,dads,locs,mesh,isPfl,arrOut,nasc); int nb=da->getNbOfElems(); const int *ptr=da->getConstPointer(); MEDCouplingUMesh *meshuc=const_cast(meshu); @@ -2209,12 +2237,14 @@ MEDCouplingFieldDouble *MEDFileFieldPerMesh::finishFieldNode2(const MEDFileField meshuc->insertNextCell(INTERP_KERNEL::NORM_POINT1,1,ptr+i); meshuc->finishInsertingCells(); ret->setMesh(meshuc); - ret->checkCoherency(); + const MEDCouplingFieldDiscretization *disc=ret->getDiscretization(); + if(!disc) throw INTERP_KERNEL::Exception("MEDFileFieldPerMesh::finishFieldNode2 : internal error, no discretization on field !"); + disc->checkCoherencyBetween(meshuc,arrOut); return ret.retn(); } } // - MEDCouplingAutoRefCountObjectPtr ret=finishField(ON_NODES,glob,dads,locs,mesh,isPfl); + MEDCouplingAutoRefCountObjectPtr ret=finishField(ON_NODES,glob,dads,locs,mesh,isPfl,arrOut,nasc); isPfl=true; DataArrayInt *arr2=0; MEDCouplingAutoRefCountObjectPtr cellIds=mesh->getCellIdsFullyIncludedInNodeIds(da->getConstPointer(),da->getConstPointer()+da->getNbOfElems()); @@ -2224,7 +2254,7 @@ MEDCouplingFieldDouble *MEDFileFieldPerMesh::finishFieldNode2(const MEDFileField if(nnodes==(int)da->getNbOfElems()) { MEDCouplingAutoRefCountObjectPtr da3=da->transformWithIndArrR(arr2->begin(),arr2->end()); - ret->getArray()->renumberInPlace(da3->getConstPointer()); + arrOut->renumberInPlace(da3->getConstPointer()); mesh2->setName(mesh->getName()); ret->setMesh(mesh2); return ret.retn(); @@ -2245,7 +2275,7 @@ MEDCouplingFieldDouble *MEDFileFieldPerMesh::finishFieldNode2(const MEDFileField /*! * This method is the most light method of field retrieving. */ -DataArrayDouble *MEDFileFieldPerMesh::finishField4(const std::vector >& dads, const DataArrayInt *pflIn, int nbOfElems, DataArrayInt *&pflOut) const throw(INTERP_KERNEL::Exception) +DataArray *MEDFileFieldPerMesh::finishField4(const std::vector >& dads, const DataArrayInt *pflIn, int nbOfElems, DataArrayInt *&pflOut) const throw(INTERP_KERNEL::Exception) { if(!pflIn) { @@ -2259,7 +2289,7 @@ DataArrayDouble *MEDFileFieldPerMesh::finishField4(const std::vectorincrRef(); } MEDCouplingAutoRefCountObjectPtr safePfl(pflOut); - MEDCouplingAutoRefCountObjectPtr da=getArray()->selectByTupleRanges(dads); + MEDCouplingAutoRefCountObjectPtr da=getArray()->selectByTupleRanges(dads); const std::vector& infos=getInfo(); int nbOfComp=infos.size(); for(int i=0;i meshName=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); INTERP_KERNEL::AutoPtr pflName=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); INTERP_KERNEL::AutoPtr locName=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); for(int i=0;i0) { - _field_pm_pt.push_back(MEDFileFieldPerMeshPerType::NewOnRead(fid,this,ON_CELLS,typmai2[i])); + _field_pm_pt.push_back(MEDFileFieldPerMeshPerType::NewOnRead(fid,this,ON_CELLS,typmai2[i],nasc)); _mesh_name=MEDLoaderBase::buildStringFromFortran(meshName,MED_NAME_SIZE+1); } - nbProfile=MEDfield23nProfile(fid,getName().c_str(),getIteration(),getOrder(),MED_NODE_ELEMENT,typmai[i],_mesh_csit,meshName,pflName,locName); + nbProfile=MEDfield23nProfile(fid,nasc.getName().c_str(),getIteration(),getOrder(),MED_NODE_ELEMENT,typmai[i],_mesh_csit,meshName,pflName,locName); if(nbProfile>0) { - _field_pm_pt.push_back(MEDFileFieldPerMeshPerType::NewOnRead(fid,this,ON_GAUSS_NE,typmai2[i])); + _field_pm_pt.push_back(MEDFileFieldPerMeshPerType::NewOnRead(fid,this,ON_GAUSS_NE,typmai2[i],nasc)); _mesh_name=MEDLoaderBase::buildStringFromFortran(meshName,MED_NAME_SIZE+1); } } - int nbProfile=MEDfield23nProfile(fid,getName().c_str(),getIteration(),getOrder(),MED_NODE,MED_NONE,_mesh_csit,meshName,pflName,locName); + int nbProfile=MEDfield23nProfile(fid,nasc.getName().c_str(),getIteration(),getOrder(),MED_NODE,MED_NONE,_mesh_csit,meshName,pflName,locName); if(nbProfile>0) { - _field_pm_pt.push_back(MEDFileFieldPerMeshPerType::NewOnRead(fid,this,ON_NODES,INTERP_KERNEL::NORM_ERROR)); + _field_pm_pt.push_back(MEDFileFieldPerMeshPerType::NewOnRead(fid,this,ON_NODES,INTERP_KERNEL::NORM_ERROR,nasc)); _mesh_name=MEDLoaderBase::buildStringFromFortran(meshName,MED_NAME_SIZE+1); } } -MEDFileFieldPerMesh::MEDFileFieldPerMesh(MEDFileField1TSWithoutSDA *fath, const MEDCouplingMesh *mesh):_father(fath) +MEDFileFieldPerMesh::MEDFileFieldPerMesh(MEDFileAnyTypeField1TSWithoutSDA *fath, const MEDCouplingMesh *mesh):_father(fath) { copyTinyInfoFrom(mesh); } @@ -2386,6 +2416,18 @@ void MEDFileFieldGlobs::appendGlobs(const MEDFileFieldGlobs& other, double eps) } } +void MEDFileFieldGlobs::checkGlobsPflsPartCoherency(const std::vector& pflsUsed) const throw(INTERP_KERNEL::Exception) +{ + for(std::vector::const_iterator it=pflsUsed.begin();it!=pflsUsed.end();it++) + getProfile((*it).c_str()); +} + +void MEDFileFieldGlobs::checkGlobsLocsPartCoherency(const std::vector& locsUsed) const throw(INTERP_KERNEL::Exception) +{ + for(std::vector::const_iterator it=locsUsed.begin();it!=locsUsed.end();it++) + getLocalization((*it).c_str()); +} + void MEDFileFieldGlobs::loadGlobals(med_idt fid, const MEDFileFieldGlobsReal& real) throw(INTERP_KERNEL::Exception) { std::vector profiles=real.getPflsReallyUsed(); @@ -2452,6 +2494,62 @@ MEDFileFieldGlobs *MEDFileFieldGlobs::deepCpy() const throw(INTERP_KERNEL::Excep return ret.retn(); } +/*! + * \throw if a profile in \a pfls in not in \a this. + * \throw if a localization in \a locs in not in \a this. + * \sa MEDFileFieldGlobs::deepCpyPart + */ +MEDFileFieldGlobs *MEDFileFieldGlobs::shallowCpyPart(const std::vector& pfls, const std::vector& locs) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=MEDFileFieldGlobs::New(); + for(std::vector::const_iterator it1=pfls.begin();it1!=pfls.end();it1++) + { + DataArrayInt *pfl=const_cast(getProfile((*it1).c_str())); + if(!pfl) + throw INTERP_KERNEL::Exception("MEDFileFieldGlobs::shallowCpyPart : internal error ! pfl null !"); + pfl->incrRef(); + MEDCouplingAutoRefCountObjectPtr pfl2(pfl); + ret->_pfls.push_back(pfl2); + } + for(std::vector::const_iterator it2=locs.begin();it2!=locs.end();it2++) + { + MEDFileFieldLoc *loc=const_cast(&getLocalization((*it2).c_str())); + if(!loc) + throw INTERP_KERNEL::Exception("MEDFileFieldGlobs::shallowCpyPart : internal error ! loc null !"); + loc->incrRef(); + MEDCouplingAutoRefCountObjectPtr loc2(loc); + ret->_locs.push_back(loc2); + } + ret->setFileName(getFileName()); + return ret.retn(); +} + +/*! + * \throw if a profile in \a pfls in not in \a this. + * \throw if a localization in \a locs in not in \a this. + * \sa MEDFileFieldGlobs::shallowCpyPart + */ +MEDFileFieldGlobs *MEDFileFieldGlobs::deepCpyPart(const std::vector& pfls, const std::vector& locs) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=MEDFileFieldGlobs::New(); + for(std::vector::const_iterator it1=pfls.begin();it1!=pfls.end();it1++) + { + DataArrayInt *pfl=const_cast(getProfile((*it1).c_str())); + if(!pfl) + throw INTERP_KERNEL::Exception("MEDFileFieldGlobs::deepCpyPart : internal error ! pfl null !"); + ret->_pfls.push_back(pfl->deepCpy()); + } + for(std::vector::const_iterator it2=locs.begin();it2!=locs.end();it2++) + { + MEDFileFieldLoc *loc=const_cast(&getLocalization((*it2).c_str())); + if(!loc) + throw INTERP_KERNEL::Exception("MEDFileFieldGlobs::deepCpyPart : internal error ! loc null !"); + ret->_locs.push_back(loc->deepCpy()); + } + ret->setFileName(getFileName()); + return ret.retn(); +} + MEDFileFieldGlobs::MEDFileFieldGlobs(const char *fname):_file_name(fname) { } @@ -2588,6 +2686,9 @@ int MEDFileFieldGlobs::getLocalizationId(const char *loc) const throw(INTERP_KER return std::distance(_locs.begin(),it); } +/*! + * The returned value is never null. + */ const DataArrayInt *MEDFileFieldGlobs::getProfile(const char *pflName) const throw(INTERP_KERNEL::Exception) { std::string pflNameCpp(pflName); @@ -2621,6 +2722,9 @@ MEDFileFieldLoc& MEDFileFieldGlobs::getLocalization(const char *locName) throw(I return getLocalizationFromId(getLocalizationId(locName)); } +/*! + * The returned value is never null. + */ DataArrayInt *MEDFileFieldGlobs::getProfile(const char *pflName) throw(INTERP_KERNEL::Exception) { std::string pflNameCpp(pflName); @@ -2830,16 +2934,23 @@ std::size_t MEDFileFieldGlobsReal::getHeapMemorySize() const * Returns a string describing profiles and Gauss points held in \a this. * \return std::string - the description string. */ -void MEDFileFieldGlobsReal::simpleRepr(std::ostream& oss) const +void MEDFileFieldGlobsReal::simpleReprGlobs(std::ostream& oss) const { - oss << "Globals information on fields :" << "\n*******************************\n\n"; const MEDFileFieldGlobs *glob=_globals; + std::ostringstream oss2; oss2 << glob; + std::string stars(oss2.str().length(),'*'); + oss << "Globals information on fields (at " << oss2.str() << "):" << "\n************************************" << stars << "\n\n"; if(glob) glob->simpleRepr(oss); else oss << "NO GLOBAL INFORMATION !\n"; } +void MEDFileFieldGlobsReal::resetContent() +{ + _globals=MEDFileFieldGlobs::New(); +} + MEDFileFieldGlobsReal::~MEDFileFieldGlobsReal() { } @@ -2853,6 +2964,30 @@ void MEDFileFieldGlobsReal::shallowCpyGlobs(const MEDFileFieldGlobsReal& other) _globals=other._globals; } +/*! + * Copies references to ** only used ** by \a this, profiles and Gauss points from another MEDFileFieldGlobsReal. + * \param [in] other - the other MEDFileFieldGlobsReal to copy data from. + */ +void MEDFileFieldGlobsReal::shallowCpyOnlyUsedGlobs(const MEDFileFieldGlobsReal& other) throw(INTERP_KERNEL::Exception) +{ + const MEDFileFieldGlobs *otherg(other._globals); + if(!otherg) + return ; + _globals=otherg->shallowCpyPart(getPflsReallyUsed(),getLocsReallyUsed()); +} + +/*! + * Copies deeply to ** only used ** by \a this, profiles and Gauss points from another MEDFileFieldGlobsReal. + * \param [in] other - the other MEDFileFieldGlobsReal to copy data from. + */ +void MEDFileFieldGlobsReal::deepCpyOnlyUsedGlobs(const MEDFileFieldGlobsReal& other) throw(INTERP_KERNEL::Exception) +{ + const MEDFileFieldGlobs *otherg(other._globals); + if(!otherg) + return ; + _globals=otherg->deepCpyPart(getPflsReallyUsed(),getLocsReallyUsed()); +} + void MEDFileFieldGlobsReal::deepCpyGlobs(const MEDFileFieldGlobsReal& other) { _globals=other._globals; @@ -2870,32 +3005,56 @@ void MEDFileFieldGlobsReal::deepCpyGlobs(const MEDFileFieldGlobsReal& other) */ void MEDFileFieldGlobsReal::appendGlobs(const MEDFileFieldGlobsReal& other, double eps) throw(INTERP_KERNEL::Exception) { + const MEDFileFieldGlobs *thisGlobals(_globals),*otherGlobals(other._globals); + if(thisGlobals==otherGlobals) + return ; + if(!thisGlobals) + { + _globals=other._globals; + return ; + } _globals->appendGlobs(*other._globals,eps); } +void MEDFileFieldGlobsReal::checkGlobsCoherency() const throw(INTERP_KERNEL::Exception) +{ + checkGlobsPflsPartCoherency(); + checkGlobsLocsPartCoherency(); +} + +void MEDFileFieldGlobsReal::checkGlobsPflsPartCoherency() const throw(INTERP_KERNEL::Exception) +{ + contentNotNull()->checkGlobsPflsPartCoherency(getPflsReallyUsed()); +} + +void MEDFileFieldGlobsReal::checkGlobsLocsPartCoherency() const throw(INTERP_KERNEL::Exception) +{ + contentNotNull()->checkGlobsLocsPartCoherency(getLocsReallyUsed()); +} + void MEDFileFieldGlobsReal::loadProfileInFile(med_idt fid, int id, const char *pflName) throw(INTERP_KERNEL::Exception) { - _globals->loadProfileInFile(fid,id,pflName); + contentNotNull()->loadProfileInFile(fid,id,pflName); } void MEDFileFieldGlobsReal::loadProfileInFile(med_idt fid, int id) { - _globals->loadProfileInFile(fid,id); + contentNotNull()->loadProfileInFile(fid,id); } void MEDFileFieldGlobsReal::loadGlobals(med_idt fid) throw(INTERP_KERNEL::Exception) { - _globals->loadGlobals(fid,*this); + contentNotNull()->loadGlobals(fid,*this); } void MEDFileFieldGlobsReal::loadAllGlobals(med_idt fid) throw(INTERP_KERNEL::Exception) { - _globals->loadAllGlobals(fid); + contentNotNull()->loadAllGlobals(fid); } void MEDFileFieldGlobsReal::writeGlobals(med_idt fid, const MEDFileWritable& opt) const throw(INTERP_KERNEL::Exception) { - _globals->writeGlobals(fid,opt); + contentNotNull()->writeGlobals(fid,opt); } /*! @@ -2905,7 +3064,7 @@ void MEDFileFieldGlobsReal::writeGlobals(med_idt fid, const MEDFileWritable& opt */ std::vector MEDFileFieldGlobsReal::getPfls() const { - return _globals->getPfls(); + return contentNotNull()->getPfls(); } /*! @@ -2915,7 +3074,7 @@ std::vector MEDFileFieldGlobsReal::getPfls() const */ std::vector MEDFileFieldGlobsReal::getLocs() const { - return _globals->getLocs(); + return contentNotNull()->getLocs(); } /*! @@ -2925,7 +3084,7 @@ std::vector MEDFileFieldGlobsReal::getLocs() const */ bool MEDFileFieldGlobsReal::existsPfl(const char *pflName) const { - return _globals->existsPfl(pflName); + return contentNotNull()->existsPfl(pflName); } /*! @@ -2935,17 +3094,17 @@ bool MEDFileFieldGlobsReal::existsPfl(const char *pflName) const */ bool MEDFileFieldGlobsReal::existsLoc(const char *locName) const { - return _globals->existsLoc(locName); + return contentNotNull()->existsLoc(locName); } std::string MEDFileFieldGlobsReal::createNewNameOfPfl() const throw(INTERP_KERNEL::Exception) { - return _globals->createNewNameOfPfl(); + return contentNotNull()->createNewNameOfPfl(); } std::string MEDFileFieldGlobsReal::createNewNameOfLoc() const throw(INTERP_KERNEL::Exception) { - return _globals->createNewNameOfLoc(); + return contentNotNull()->createNewNameOfLoc(); } /*! @@ -2954,7 +3113,7 @@ std::string MEDFileFieldGlobsReal::createNewNameOfLoc() const throw(INTERP_KERNE */ void MEDFileFieldGlobsReal::setFileName(const char *fileName) { - _globals->setFileName(fileName); + contentNotNull()->setFileName(fileName); } /*! @@ -2965,7 +3124,7 @@ void MEDFileFieldGlobsReal::setFileName(const char *fileName) */ std::vector< std::vector > MEDFileFieldGlobsReal::whichAreEqualProfiles() const { - return _globals->whichAreEqualProfiles(); + return contentNotNull()->whichAreEqualProfiles(); } /*! @@ -2976,7 +3135,7 @@ std::vector< std::vector > MEDFileFieldGlobsReal::whichAreEqualProfiles() c */ std::vector< std::vector > MEDFileFieldGlobsReal::whichAreEqualLocs(double eps) const { - return _globals->whichAreEqualLocs(eps); + return contentNotNull()->whichAreEqualLocs(eps); } /*! @@ -2988,7 +3147,7 @@ std::vector< std::vector > MEDFileFieldGlobsReal::whichAreEqualLocs(double */ void MEDFileFieldGlobsReal::changePflsNamesInStruct(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) { - _globals->changePflsNamesInStruct(mapOfModif); + contentNotNull()->changePflsNamesInStruct(mapOfModif); } /*! @@ -3000,7 +3159,7 @@ void MEDFileFieldGlobsReal::changePflsNamesInStruct(const std::vector< std::pair */ void MEDFileFieldGlobsReal::changeLocsNamesInStruct(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) { - _globals->changeLocsNamesInStruct(mapOfModif); + contentNotNull()->changeLocsNamesInStruct(mapOfModif); } /*! @@ -3135,7 +3294,7 @@ std::vector< std::pair, std::string > > MEDFileFieldGlo */ int MEDFileFieldGlobsReal::getNbOfGaussPtPerCell(int locId) const throw(INTERP_KERNEL::Exception) { - return _globals->getNbOfGaussPtPerCell(locId); + return contentNotNull()->getNbOfGaussPtPerCell(locId); } /*! @@ -3146,7 +3305,7 @@ int MEDFileFieldGlobsReal::getNbOfGaussPtPerCell(int locId) const throw(INTERP_K */ int MEDFileFieldGlobsReal::getLocalizationId(const char *loc) const throw(INTERP_KERNEL::Exception) { - return _globals->getLocalizationId(loc); + return contentNotNull()->getLocalizationId(loc); } /*! @@ -3155,12 +3314,12 @@ int MEDFileFieldGlobsReal::getLocalizationId(const char *loc) const throw(INTERP */ const char *MEDFileFieldGlobsReal::getFileName() const { - return _globals->getFileName(); + return contentNotNull()->getFileName(); } std::string MEDFileFieldGlobsReal::getFileName2() const { - return _globals->getFileName2(); + return contentNotNull()->getFileName2(); } /*! @@ -3171,7 +3330,7 @@ std::string MEDFileFieldGlobsReal::getFileName2() const */ const MEDFileFieldLoc& MEDFileFieldGlobsReal::getLocalization(const char *locName) const throw(INTERP_KERNEL::Exception) { - return _globals->getLocalization(locName); + return contentNotNull()->getLocalization(locName); } /*! @@ -3182,7 +3341,7 @@ const MEDFileFieldLoc& MEDFileFieldGlobsReal::getLocalization(const char *locNam */ const MEDFileFieldLoc& MEDFileFieldGlobsReal::getLocalizationFromId(int locId) const throw(INTERP_KERNEL::Exception) { - return _globals->getLocalizationFromId(locId); + return contentNotNull()->getLocalizationFromId(locId); } /*! @@ -3193,7 +3352,7 @@ const MEDFileFieldLoc& MEDFileFieldGlobsReal::getLocalizationFromId(int locId) c */ const DataArrayInt *MEDFileFieldGlobsReal::getProfile(const char *pflName) const throw(INTERP_KERNEL::Exception) { - return _globals->getProfile(pflName); + return contentNotNull()->getProfile(pflName); } /*! @@ -3204,7 +3363,7 @@ const DataArrayInt *MEDFileFieldGlobsReal::getProfile(const char *pflName) const */ const DataArrayInt *MEDFileFieldGlobsReal::getProfileFromId(int pflId) const throw(INTERP_KERNEL::Exception) { - return _globals->getProfileFromId(pflId); + return contentNotNull()->getProfileFromId(pflId); } /*! @@ -3216,7 +3375,7 @@ const DataArrayInt *MEDFileFieldGlobsReal::getProfileFromId(int pflId) const thr */ MEDFileFieldLoc& MEDFileFieldGlobsReal::getLocalizationFromId(int locId) throw(INTERP_KERNEL::Exception) { - return _globals->getLocalizationFromId(locId); + return contentNotNull()->getLocalizationFromId(locId); } /*! @@ -3228,7 +3387,7 @@ MEDFileFieldLoc& MEDFileFieldGlobsReal::getLocalizationFromId(int locId) throw(I */ MEDFileFieldLoc& MEDFileFieldGlobsReal::getLocalization(const char *locName) throw(INTERP_KERNEL::Exception) { - return _globals->getLocalization(locName); + return contentNotNull()->getLocalization(locName); } /*! @@ -3239,7 +3398,7 @@ MEDFileFieldLoc& MEDFileFieldGlobsReal::getLocalization(const char *locName) thr */ DataArrayInt *MEDFileFieldGlobsReal::getProfile(const char *pflName) throw(INTERP_KERNEL::Exception) { - return _globals->getProfile(pflName); + return contentNotNull()->getProfile(pflName); } /*! @@ -3250,7 +3409,7 @@ DataArrayInt *MEDFileFieldGlobsReal::getProfile(const char *pflName) throw(INTER */ DataArrayInt *MEDFileFieldGlobsReal::getProfileFromId(int pflId) throw(INTERP_KERNEL::Exception) { - return _globals->getProfileFromId(pflId); + return contentNotNull()->getProfileFromId(pflId); } /*! @@ -3259,7 +3418,7 @@ DataArrayInt *MEDFileFieldGlobsReal::getProfileFromId(int pflId) throw(INTERP_KE */ void MEDFileFieldGlobsReal::killProfileIds(const std::vector& pflIds) throw(INTERP_KERNEL::Exception) { - _globals->killProfileIds(pflIds); + contentNotNull()->killProfileIds(pflIds); } /*! @@ -3268,7 +3427,7 @@ void MEDFileFieldGlobsReal::killProfileIds(const std::vector& pflIds) throw */ void MEDFileFieldGlobsReal::killLocalizationIds(const std::vector& locIds) throw(INTERP_KERNEL::Exception) { - _globals->killLocalizationIds(locIds); + contentNotNull()->killLocalizationIds(locIds); } /*! @@ -3280,7 +3439,7 @@ void MEDFileFieldGlobsReal::killLocalizationIds(const std::vector& locIds) */ void MEDFileFieldGlobsReal::appendProfile(DataArrayInt *pfl) throw(INTERP_KERNEL::Exception) { - _globals->appendProfile(pfl); + contentNotNull()->appendProfile(pfl); } /*! @@ -3298,143 +3457,71 @@ void MEDFileFieldGlobsReal::appendProfile(DataArrayInt *pfl) throw(INTERP_KERNEL */ void MEDFileFieldGlobsReal::appendLoc(const char *locName, INTERP_KERNEL::NormalizedCellType geoType, const std::vector& refCoo, const std::vector& gsCoo, const std::vector& w) throw(INTERP_KERNEL::Exception) { - _globals->appendLoc(locName,geoType,refCoo,gsCoo,w); + contentNotNull()->appendLoc(locName,geoType,refCoo,gsCoo,w); } -/*! - * Returns the maximal dimension of supporting elements. Returns -2 if \a this is - * empty. Returns -1 if this in on nodes. - * \return int - the dimension of \a this. - */ -int MEDFileField1TSWithoutSDA::getDimension() const +MEDFileFieldGlobs *MEDFileFieldGlobsReal::contentNotNull() throw(INTERP_KERNEL::Exception) { - int ret=-2; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) - (*it)->getDimension(ret); - return ret; + MEDFileFieldGlobs *g(_globals); + if(!g) + throw INTERP_KERNEL::Exception("MEDFileFieldGlobsReal::contentNotNull : no content in not const !"); + return g; } -/*! - * Throws if a given value is not a valid (non-extended) relative dimension. - * \param [in] meshDimRelToMax - the relative dimension value. - * \throw If \a meshDimRelToMax > 0. - */ -void MEDFileField1TSWithoutSDA::CheckMeshDimRel(int meshDimRelToMax) throw(INTERP_KERNEL::Exception) +const MEDFileFieldGlobs *MEDFileFieldGlobsReal::contentNotNull() const throw(INTERP_KERNEL::Exception) { - if(meshDimRelToMax>0) - throw INTERP_KERNEL::Exception("CheckMeshDimRel : This is a meshDimRel not a meshDimRelExt ! So value should be <=0 !"); + const MEDFileFieldGlobs *g(_globals); + if(!g) + throw INTERP_KERNEL::Exception("MEDFileFieldGlobsReal::contentNotNull : no content in const !"); + return g; } -/*! - * Checks if elements of a given mesh are in the order suitable for writing - * to the MED file. If this is not so, an exception is thrown. In a case of success, returns a - * vector describing types of elements and their number. - * \param [in] mesh - the mesh to check. - * \return std::vector - a vector holding for each element type (1) item of - * INTERP_KERNEL::NormalizedCellType, (2) number of elements, (3) -1. - * These values are in full-interlace mode. - * \throw If elements in \a mesh are not in the order suitable for writing to the MED file. - */ -std::vector MEDFileField1TSWithoutSDA::CheckSBTMesh(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception) -{ - // - std::set geoTypes=mesh->getAllGeoTypes(); - int nbOfTypes=geoTypes.size(); - std::vector code(3*nbOfTypes); - MEDCouplingAutoRefCountObjectPtr arr1=DataArrayInt::New(); - arr1->alloc(nbOfTypes,1); - int *arrPtr=arr1->getPointer(); - std::set::const_iterator it=geoTypes.begin(); - for(int i=0;i arr2=arr1->checkAndPreparePermutation(); - const int *arrPtr2=arr2->getConstPointer(); - int i=0; - for(it=geoTypes.begin();it!=geoTypes.end();it++,i++) - { - int pos=arrPtr2[i]; - int nbCells=mesh->getNumberOfCellsWithType(*it); - code[3*pos]=(int)(*it); - code[3*pos+1]=nbCells; - code[3*pos+2]=-1;//no profiles - } - std::vector idsPerType;//no profiles - DataArrayInt *da=mesh->checkTypeConsistencyAndContig(code,idsPerType); - if(da) - { - da->decrRef(); - throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::CheckSBTMesh : underlying mesh is not sorted by type as MED file expects !"); - } - return code; -} +//= MEDFileFieldNameScope -MEDFileField1TSWithoutSDA *MEDFileField1TSWithoutSDA::New(const char *fieldName, int csit, int fieldtype, int iteration, int order, const std::vector& infos) +MEDFileFieldNameScope::MEDFileFieldNameScope() { - return new MEDFileField1TSWithoutSDA(fieldName,csit,fieldtype,iteration,order,infos); } -/*! - * Copies tiny info and allocates \a this->_arr instance of DataArrayDouble to - * append data of a given MEDCouplingFieldDouble. So that the size of \a this->_arr becomes - * larger by the size of \a field. Returns an id of the first not filled - * tuple of \a this->_arr. - * \param [in] field - the field to copy the info on components and the name from. - * \return int - the id of first not initialized tuple of \a this->_arr. - * \throw If the name of \a field is empty. - * \throw If the data array of \a field is not set. - * \throw If \a this->_arr is already allocated but has different number of components - * than \a field. - */ -int MEDFileField1TSWithoutSDA::copyTinyInfoFrom(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception) +MEDFileFieldNameScope::MEDFileFieldNameScope(const char *fieldName):_name(fieldName) { - std::string name(field->getName()); - getOrCreateAndGetArray()->setName(name.c_str()); - if(name.empty()) - throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::copyTinyInfoFrom : unsupported fields with no name in MED file !"); - const DataArrayDouble *arr=field->getArray(); - if(!arr) - throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::copyTinyInfoFrom : no array set !"); - _dt=field->getTime(_iteration,_order); - int nbOfComponents=arr->getNumberOfComponents(); - getOrCreateAndGetArray()->setInfoAndChangeNbOfCompo(arr->getInfoOnComponents()); - if(!getOrCreateAndGetArray()->isAllocated()) - { - _arr->alloc(arr->getNumberOfTuples(),arr->getNumberOfComponents()); - return 0; - } - else - { - int oldNbOfTuples=getOrCreateAndGetArray()->getNumberOfTuples(); - int newNbOfTuples=oldNbOfTuples+arr->getNumberOfTuples(); - MEDCouplingAutoRefCountObjectPtr tmp=DataArrayDouble::New(); - tmp->alloc(newNbOfTuples,nbOfComponents); - tmp->copyStringInfoFrom(*_arr); - std::copy(_arr->begin(),_arr->end(),tmp->getPointer()); - _arr=tmp; - return oldNbOfTuples; - } } /*! * Returns the name of \a this field. * \return std::string - a string containing the field name. */ -std::string MEDFileField1TSWithoutSDA::getName() const +std::string MEDFileFieldNameScope::getName() const throw(INTERP_KERNEL::Exception) { - const DataArrayDouble *arr=getOrCreateAndGetArray(); - return arr->getName(); + return _name; } /*! * Sets name of \a this field * \param [in] name - the new field name. */ -void MEDFileField1TSWithoutSDA::setName(const char *name) +void MEDFileFieldNameScope::setName(const char *fieldName) throw(INTERP_KERNEL::Exception) +{ + _name=fieldName; +} + +std::string MEDFileFieldNameScope::getDtUnit() const throw(INTERP_KERNEL::Exception) +{ + return _dt_unit; +} + +void MEDFileFieldNameScope::setDtUnit(const char *dtUnit) throw(INTERP_KERNEL::Exception) +{ + _dt_unit=dtUnit; +} + +void MEDFileFieldNameScope::copyNameScope(const MEDFileFieldNameScope& other) { - DataArrayDouble *arr=getOrCreateAndGetArray(); - arr->setName(name); + _name=other._name; + _dt_unit=other._dt_unit; } +//= MEDFileAnyTypeField1TSWithoutSDA + /*! * Prints a string describing \a this field into a stream. This string is outputted * by \c print Python command. @@ -3443,15 +3530,18 @@ void MEDFileField1TSWithoutSDA::setName(const char *name) * \param [in] f1tsId - the field index within a MED file. If \a f1tsId < 0, the tiny * info id printed, else, not. */ -void MEDFileField1TSWithoutSDA::simpleRepr(int bkOffset, std::ostream& oss, int f1tsId) const +void MEDFileAnyTypeField1TSWithoutSDA::simpleRepr(int bkOffset, std::ostream& oss, int f1tsId) const { std::string startOfLine(bkOffset,' '); - oss << startOfLine << "Field on One time Step "; + oss << startOfLine << "Field "; + if(bkOffset==0) + oss << "[Type=" << getTypeStr() << "] "; + oss << "on One time Step "; if(f1tsId>=0) oss << "(" << f1tsId << ") "; oss << "on iteration=" << _iteration << " order=" << _order << "." << std::endl; oss << startOfLine << "Time attached is : " << _dt << " [" << _dt_unit << "]." << std::endl; - const DataArrayDouble *arr=_arr; + const DataArray *arr=getUndergroundDataArray(); if(arr) { const std::vector &comps=arr->getInfoOnComponents(); @@ -3493,19 +3583,57 @@ void MEDFileField1TSWithoutSDA::simpleRepr(int bkOffset, std::ostream& oss, int oss << startOfLine << "----------------------" << std::endl; } +std::vector< MEDCouplingAutoRefCountObjectPtr > MEDFileAnyTypeField1TSWithoutSDA::splitComponents() const throw(INTERP_KERNEL::Exception) +{ + const DataArray *arr(getUndergroundDataArray()); + if(!arr) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::splitComponents : no array defined !"); + int nbOfCompo=arr->getNumberOfComponents(); + std::vector< MEDCouplingAutoRefCountObjectPtr > ret(nbOfCompo); + for(int i=0;i v(1,i); + MEDCouplingAutoRefCountObjectPtr arr2=arr->keepSelectedComponents(v); + ret[i]->setArray(arr2); + } + return ret; +} + +MEDFileAnyTypeField1TSWithoutSDA::MEDFileAnyTypeField1TSWithoutSDA(const char *fieldName, int csit, int iteration, int order):MEDFileFieldNameScope(fieldName),_iteration(iteration),_order(order),_csit(csit) +{ +} + +MEDFileAnyTypeField1TSWithoutSDA::MEDFileAnyTypeField1TSWithoutSDA():_iteration(-1),_order(-1),_dt(0.),_csit(-1) +{ +} + +/*! + * Returns the maximal dimension of supporting elements. Returns -2 if \a this is + * empty. Returns -1 if this in on nodes. + * \return int - the dimension of \a this. + */ +int MEDFileAnyTypeField1TSWithoutSDA::getDimension() const +{ + int ret=-2; + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) + (*it)->getDimension(ret); + return ret; +} + /*! * Returns the mesh name. * \return std::string - a string holding the mesh name. * \throw If \c _field_per_mesh.empty() */ -std::string MEDFileField1TSWithoutSDA::getMeshName() const throw(INTERP_KERNEL::Exception) +std::string MEDFileAnyTypeField1TSWithoutSDA::getMeshName() const throw(INTERP_KERNEL::Exception) { if(_field_per_mesh.empty()) throw INTERP_KERNEL::Exception("MEDFileFieldPerMeshPerTypePerDisc::getMeshName : No field set !"); return _field_per_mesh[0]->getMeshName(); } -void MEDFileField1TSWithoutSDA::setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception) +void MEDFileAnyTypeField1TSWithoutSDA::setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception) { std::string oldName(getMeshName()); std::vector< std::pair > v(1); @@ -3513,7 +3641,7 @@ void MEDFileField1TSWithoutSDA::setMeshName(const char *newMeshName) throw(INTER changeMeshNames(v); } -bool MEDFileField1TSWithoutSDA::changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception) +bool MEDFileAnyTypeField1TSWithoutSDA::changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception) { bool ret=false; for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) @@ -3525,25 +3653,12 @@ bool MEDFileField1TSWithoutSDA::changeMeshNames(const std::vector< std::pair& oldCode, const std::vector& newCode, const DataArrayInt *renumO2N, - MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) -{ - bool ret=false; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) - { - MEDFileFieldPerMesh *fpm(*it); - if(fpm) - ret=fpm->renumberEntitiesLyingOnMesh(meshName,oldCode,newCode,renumO2N,glob) || ret; - } - return ret; -} - /*! * Returns the number of iteration of the state of underlying mesh. * \return int - the iteration number. * \throw If \c _field_per_mesh.empty() */ -int MEDFileField1TSWithoutSDA::getMeshIteration() const throw(INTERP_KERNEL::Exception) +int MEDFileAnyTypeField1TSWithoutSDA::getMeshIteration() const throw(INTERP_KERNEL::Exception) { if(_field_per_mesh.empty()) throw INTERP_KERNEL::Exception("MEDFileFieldPerMeshPerTypePerDisc::getMeshIteration : No field set !"); @@ -3555,22 +3670,13 @@ int MEDFileField1TSWithoutSDA::getMeshIteration() const throw(INTERP_KERNEL::Exc * \return int - the order number. * \throw If \c _field_per_mesh.empty() */ -int MEDFileField1TSWithoutSDA::getMeshOrder() const throw(INTERP_KERNEL::Exception) +int MEDFileAnyTypeField1TSWithoutSDA::getMeshOrder() const throw(INTERP_KERNEL::Exception) { if(_field_per_mesh.empty()) throw INTERP_KERNEL::Exception("MEDFileFieldPerMeshPerTypePerDisc::getMeshOrder : No field set !"); return _field_per_mesh[0]->getMeshOrder(); } -/*! - * Returns number of components in \a this field - * \return int - the number of components. - */ -int MEDFileField1TSWithoutSDA::getNumberOfComponents() const -{ - return getOrCreateAndGetArray()->getNumberOfComponents(); -} - /*! * Checks if \a this field is tagged by a given iteration number and a given * iteration order number. @@ -3579,7 +3685,7 @@ int MEDFileField1TSWithoutSDA::getNumberOfComponents() const * \return bool - \c true if \a this->getIteration() == \a iteration && * \a this->getOrder() == \a order. */ -bool MEDFileField1TSWithoutSDA::isDealingTS(int iteration, int order) const +bool MEDFileAnyTypeField1TSWithoutSDA::isDealingTS(int iteration, int order) const { return iteration==_iteration && order==_order; } @@ -3590,7 +3696,7 @@ bool MEDFileField1TSWithoutSDA::isDealingTS(int iteration, int order) const * \return std::pair - a pair of the iteration number and the iteration * order number. */ -std::pair MEDFileField1TSWithoutSDA::getDtIt() const +std::pair MEDFileAnyTypeField1TSWithoutSDA::getDtIt() const { std::pair p; fillIteration(p); @@ -3603,7 +3709,7 @@ std::pair MEDFileField1TSWithoutSDA::getDtIt() const * \param [in,out] p - a pair returning the iteration number and the iteration * order number. */ -void MEDFileField1TSWithoutSDA::fillIteration(std::pair& p) const +void MEDFileAnyTypeField1TSWithoutSDA::fillIteration(std::pair& p) const { p.first=_iteration; p.second=_order; @@ -3613,7 +3719,7 @@ void MEDFileField1TSWithoutSDA::fillIteration(std::pair& p) const * Returns all types of spatial discretization of \a this field. * \param [in,out] types - a sequence of types of \a this field. */ -void MEDFileField1TSWithoutSDA::fillTypesOfFieldAvailable(std::vector& types) const throw(INTERP_KERNEL::Exception) +void MEDFileAnyTypeField1TSWithoutSDA::fillTypesOfFieldAvailable(std::vector& types) const throw(INTERP_KERNEL::Exception) { std::set types2; for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) @@ -3625,25 +3731,125 @@ void MEDFileField1TSWithoutSDA::fillTypesOfFieldAvailable(std::vector& - a sequence of strings each being an - * information on _i_-th component. - */ -const std::vector& MEDFileField1TSWithoutSDA::getInfo() const -{ - const DataArrayDouble *arr=getOrCreateAndGetArray(); - return arr->getInfoOnComponents(); + * Returns all types of spatial discretization of \a this field. + * \return std::vector - a sequence of types of spatial discretization + * of \a this field. + */ +std::vector MEDFileAnyTypeField1TSWithoutSDA::getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception) +{ + std::vector ret; + fillTypesOfFieldAvailable(ret); + return ret; +} + +std::vector MEDFileAnyTypeField1TSWithoutSDA::getPflsReallyUsed2() const +{ + std::vector ret; + std::set ret2; + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) + { + std::vector tmp=(*it)->getPflsReallyUsed(); + for(std::vector::const_iterator it2=tmp.begin();it2!=tmp.end();it2++) + if(ret2.find(*it2)==ret2.end()) + { + ret.push_back(*it2); + ret2.insert(*it2); + } + } + return ret; +} + +std::vector MEDFileAnyTypeField1TSWithoutSDA::getLocsReallyUsed2() const +{ + std::vector ret; + std::set ret2; + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) + { + std::vector tmp=(*it)->getLocsReallyUsed(); + for(std::vector::const_iterator it2=tmp.begin();it2!=tmp.end();it2++) + if(ret2.find(*it2)==ret2.end()) + { + ret.push_back(*it2); + ret2.insert(*it2); + } + } + return ret; +} + +std::vector MEDFileAnyTypeField1TSWithoutSDA::getPflsReallyUsedMulti2() const +{ + std::vector ret; + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) + { + std::vector tmp=(*it)->getPflsReallyUsedMulti(); + ret.insert(ret.end(),tmp.begin(),tmp.end()); + } + return ret; +} + +std::vector MEDFileAnyTypeField1TSWithoutSDA::getLocsReallyUsedMulti2() const +{ + std::vector ret; + std::set ret2; + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) + { + std::vector tmp=(*it)->getLocsReallyUsedMulti(); + ret.insert(ret.end(),tmp.begin(),tmp.end()); + } + return ret; +} + +void MEDFileAnyTypeField1TSWithoutSDA::changePflsRefsNamesGen2(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) +{ + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) + (*it)->changePflsRefsNamesGen(mapOfModif); +} + +void MEDFileAnyTypeField1TSWithoutSDA::changeLocsRefsNamesGen2(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) +{ + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) + (*it)->changeLocsRefsNamesGen(mapOfModif); } /*! - * Returns a mutable info on components of \a this field. - * \return std::vector& - a sequence of strings each being an - * information on _i_-th component. + * Returns all attributes of parts of \a this field lying on a given mesh. + * Each part differs from other ones by a type of supporting mesh entity. The _i_-th + * item of every of returned sequences refers to the _i_-th part of \a this field. + * Thus all sequences returned by this method are of the same length equal to number + * of different types of supporting entities.
+ * A field part can include sub-parts with several different spatial discretizations, + * \ref ParaMEDMEM::ON_CELLS "ON_CELLS" and \ref ParaMEDMEM::ON_GAUSS_PT "ON_GAUSS_PT" + * for example. Hence, some of the returned sequences contains nested sequences, and an item + * of a nested sequence corresponds to a type of spatial discretization.
+ * This method allows for iteration over MEDFile DataStructure without any overhead. + * \param [in] mname - a name of a mesh of interest. It can be \c NULL, which is valid + * for the case with only one underlying mesh. (Actually, the number of meshes is + * not checked if \a mname == \c NULL). + * \param [in,out] types - a sequence of types of underlying mesh entities. A type per + * a field part is returned. + * \param [in,out] typesF - a sequence of sequences of types of spatial discretizations. + * This sequence is of the same length as \a types. + * \param [in,out] pfls - a sequence returning a profile name per each type of spatial + * discretization. A profile name can be empty. + * Length of this and of nested sequences is the same as that of \a typesF. + * \param [in,out] locs - a sequence returning a localization name per each type of spatial + * discretization. A localization name can be empty. + * Length of this and of nested sequences is the same as that of \a typesF. + * \return std::vector< std::vector< std::pair > > - a sequence holding a range + * of ids of tuples within the data array, per each type of spatial + * discretization within one mesh entity type. + * Length of this and of nested sequences is the same as that of \a typesF. + * \throw If no field is lying on \a mname. */ -std::vector& MEDFileField1TSWithoutSDA::getInfo() +std::vector< std::vector< std::pair > > MEDFileAnyTypeField1TSWithoutSDA::getFieldSplitedByType(const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) { - DataArrayDouble *arr=getOrCreateAndGetArray(); - return arr->getInfoOnComponents(); + int meshId=0; + if(mname) + meshId=getMeshIdFromMeshName(mname); + else + if(_field_per_mesh.empty()) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::getFieldSplitedByType : This is empty !"); + return _field_per_mesh[meshId]->getFieldSplitedByType(types,typesF,pfls,locs); } /*! @@ -3687,7 +3893,7 @@ std::vector& MEDFileField1TSWithoutSDA::getInfo() * \return int - the maximal absolute dimension of elements \a this fields lies on. * \throw If no field is lying on \a mname. */ -int MEDFileField1TSWithoutSDA::getNonEmptyLevels(const char *mname, std::vector& levs) const throw(INTERP_KERNEL::Exception) +int MEDFileAnyTypeField1TSWithoutSDA::getNonEmptyLevels(const char *mname, std::vector& levs) const throw(INTERP_KERNEL::Exception) { levs.clear(); int meshId=getMeshIdFromMeshName(mname); @@ -3714,228 +3920,139 @@ int MEDFileField1TSWithoutSDA::getNonEmptyLevels(const char *mname, std::vector< } /*! - * Returns all types of spatial discretization of \a this field. - * \return std::vector - a sequence of types of spatial discretization - * of \a this field. + * \param [in] mName specifies the underlying mesh name. This value can be pointer 0 for users that do not deal with fields on multi mesh. + * \param [in] typ is for the geometric cell type (or INTERP_KERNEL::NORM_ERROR for node field) entry to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. + * \param [in] locId is the localization id to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. It corresponds to the position of + * \c pfls[std::distance(types.begin(),std::find(types.begin(),typ)] vector in MEDFileField1TSWithoutSDA::getFieldSplitedByType. For non gausspoints field users, the value is 0. */ -std::vector MEDFileField1TSWithoutSDA::getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception) +MEDFileFieldPerMeshPerTypePerDisc *MEDFileAnyTypeField1TSWithoutSDA::getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) throw(INTERP_KERNEL::Exception) { - std::vector ret; - fillTypesOfFieldAvailable(ret); - return ret; + int mid=getMeshIdFromMeshName(mName); + return _field_per_mesh[mid]->getLeafGivenTypeAndLocId(typ,locId); } /*! - * Returns all attributes of parts of \a this field lying on a given mesh. - * Each part differs from other ones by a type of supporting mesh entity. The _i_-th - * item of every of returned sequences refers to the _i_-th part of \a this field. - * Thus all sequences returned by this method are of the same length equal to number - * of different types of supporting entities.
- * A field part can include sub-parts with several different spatial discretizations, - * \ref ParaMEDMEM::ON_CELLS "ON_CELLS" and \ref ParaMEDMEM::ON_GAUSS_PT "ON_GAUSS_PT" - * for example. Hence, some of the returned sequences contains nested sequences, and an item - * of a nested sequence corresponds to a type of spatial discretization.
- * This method allows for iteration over MEDFile DataStructure without any overhead. - * \param [in] mname - a name of a mesh of interest. It can be \c NULL, which is valid - * for the case with only one underlying mesh. (Actually, the number of meshes is - * not checked if \a mname == \c NULL). - * \param [in,out] types - a sequence of types of underlying mesh entities. A type per - * a field part is returned. - * \param [in,out] typesF - a sequence of sequences of types of spatial discretizations. - * This sequence is of the same length as \a types. - * \param [in,out] pfls - a sequence returning a profile name per each type of spatial - * discretization. A profile name can be empty. - * Length of this and of nested sequences is the same as that of \a typesF. - * \param [in,out] locs - a sequence returning a localization name per each type of spatial - * discretization. A localization name can be empty. - * Length of this and of nested sequences is the same as that of \a typesF. - * \return std::vector< std::vector< std::pair > > - a sequence holding a range - * of ids of tuples within the data array, per each type of spatial - * discretization within one mesh entity type. - * Length of this and of nested sequences is the same as that of \a typesF. - * \throw If no field is lying on \a mname. + * \param [in] mName specifies the underlying mesh name. This value can be pointer 0 for users that do not deal with fields on multi mesh. + * \param [in] typ is for the geometric cell type (or INTERP_KERNEL::NORM_ERROR for node field) entry to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. + * \param [in] locId is the localization id to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. It corresponds to the position of + * \c pfls[std::distance(types.begin(),std::find(types.begin(),typ)] vector in MEDFileField1TSWithoutSDA::getFieldSplitedByType. For non gausspoints field users, the value is 0. */ -std::vector< std::vector< std::pair > > MEDFileField1TSWithoutSDA::getFieldSplitedByType(const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) +const MEDFileFieldPerMeshPerTypePerDisc *MEDFileAnyTypeField1TSWithoutSDA::getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) const throw(INTERP_KERNEL::Exception) { - int meshId=0; - if(mname) - meshId=getMeshIdFromMeshName(mname); - else - if(_field_per_mesh.empty()) - throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::getFieldSplitedByType : This is empty !"); - return _field_per_mesh[meshId]->getFieldSplitedByType(types,typesF,pfls,locs); + int mid=getMeshIdFromMeshName(mName); + return _field_per_mesh[mid]->getLeafGivenTypeAndLocId(typ,locId); } /*! - * Returns all attributes and values of parts of \a this field lying on a given mesh. - * Each part differs from other ones by a type of supporting mesh entity. The _i_-th - * item of every of returned sequences refers to the _i_-th part of \a this field. - * Thus all sequences returned by this method are of the same length equal to number - * of different types of supporting entities.
- * A field part can include sub-parts with several different spatial discretizations, - * \ref ParaMEDMEM::ON_CELLS "ON_CELLS" and \ref ParaMEDMEM::ON_GAUSS_PT "ON_GAUSS_PT" - * for example. Hence, some of the returned sequences contains nested sequences, and an item - * of a nested sequence corresponds to a type of spatial discretization.
- * This method allows for iteration over MEDFile DataStructure with a reduced overhead. - * The overhead is due to selecting values into new instances of DataArrayDouble. - * \param [in] mname - a name of a mesh of interest. It can be \c NULL, which is valid - * for the case with only one underlying mesh. (Actually, the number of meshes is - * not checked if \a mname == \c NULL). - * \param [in,out] types - a sequence of types of underlying mesh entities. A type per - * a field part is returned. - * \param [in,out] typesF - a sequence of sequences of types of spatial discretizations. - * A field part can include sub-parts with several different spatial discretizations, - * \ref ParaMEDMEM::ON_CELLS "ON_CELLS" and - * \ref ParaMEDMEM::ON_GAUSS_PT "ON_GAUSS_PT" for example. - * This sequence is of the same length as \a types. - * \param [in,out] pfls - a sequence returning a profile name per each type of spatial - * discretization. A profile name can be empty. - * Length of this and of nested sequences is the same as that of \a typesF. - * \param [in,out] locs - a sequence returning a localization name per each type of spatial - * discretization. A localization name can be empty. - * Length of this and of nested sequences is the same as that of \a typesF. - * \return std::vector< std::vector > - a sequence holding arrays of values - * per each type of spatial discretization within one mesh entity type. - * The caller is to delete each DataArrayDouble using decrRef() as it is no more needed. - * Length of this and of nested sequences is the same as that of \a typesF. - * \throw If no field is lying on \a mname. + * \param [in] mName specifies the underlying mesh name. This value can be pointer 0 for users that do not deal with fields on multi mesh. */ -std::vector< std::vector > MEDFileField1TSWithoutSDA::getFieldSplitedByType2(const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) +int MEDFileAnyTypeField1TSWithoutSDA::getMeshIdFromMeshName(const char *mName) const throw(INTERP_KERNEL::Exception) { - int meshId=0; - if(mname) - meshId=getMeshIdFromMeshName(mname); - else - if(_field_per_mesh.empty()) - throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::getFieldSplitedByType : This is empty !"); - std::vector< std::vector< std::pair > > ret0=_field_per_mesh[meshId]->getFieldSplitedByType(types,typesF,pfls,locs); - int nbOfRet=ret0.size(); - std::vector< std::vector > ret(nbOfRet); - for(int i=0;i >& p=ret0[i]; - int nbOfRet1=p.size(); - ret[i].resize(nbOfRet1); - for(int j=0;jselectByTupleId2(p[j].first,p[j].second,1); - ret[i][j]=tmp; - } - } - return ret; + if(_field_per_mesh.empty()) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::getMeshIdFromMeshName : No field set !"); + if(mName==0) + return 0; + std::string mName2(mName); + int ret=0; + std::vector msg; + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++,ret++) + if(mName2==(*it)->getMeshName()) + return ret; + else + msg.push_back((*it)->getMeshName()); + std::ostringstream oss; oss << "MEDFileField1TSWithoutSDA::getMeshIdFromMeshName : No such mesh \"" << mName2 << "\" as underlying mesh of field \"" << getName() << "\" !\n"; + oss << "Possible meshes are : "; + for(std::vector::const_iterator it2=msg.begin();it2!=msg.end();it2++) + oss << "\"" << (*it2) << "\" "; + throw INTERP_KERNEL::Exception(oss.str().c_str()); } -void MEDFileField1TSWithoutSDA::finishLoading(med_idt fid) throw(INTERP_KERNEL::Exception) +int MEDFileAnyTypeField1TSWithoutSDA::addNewEntryIfNecessary(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception) { - med_int numdt,numit; - med_float dt; - med_int nmesh; - med_bool localMesh; - med_int meshnumdt,meshnumit; - INTERP_KERNEL::AutoPtr meshName=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); - MEDfieldComputingStepInfo(fid,getName().c_str(),_csit,&numdt,&numit,&_dt); - MEDfield23ComputingStepMeshInfo(fid,getName().c_str(),_csit,&numdt,&numit,&dt,&nmesh,meshName,&localMesh,&meshnumdt,&meshnumit); - if(_iteration!=numdt || _order!=numit) - throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::finishLoading : unexpected exception internal error !"); - _field_per_mesh.resize(nmesh); - for(int i=0;igetName()); + if(tmp.empty()) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::addNewEntryIfNecessary : empty mesh name ! unsupported by MED file !"); + std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin(); + int i=0; + for(;it!=_field_per_mesh.end();it++,i++) { - _field_per_mesh[i]->prepareLoading(fid,start); - } - getOrCreateAndGetArray()->alloc(start,getNumberOfComponents()); - for(int i=0;ifinishLoading(fid,_field_type); + if((*it)->getMeshName()==tmp) + return i; } + int sz=_field_per_mesh.size(); + _field_per_mesh.resize(sz+1); + _field_per_mesh[sz]=MEDFileFieldPerMesh::New(this,mesh); + return sz; } -std::vector MEDFileField1TSWithoutSDA::getPflsReallyUsed2() const +bool MEDFileAnyTypeField1TSWithoutSDA::renumberEntitiesLyingOnMesh(const char *meshName, const std::vector& oldCode, const std::vector& newCode, const DataArrayInt *renumO2N, + MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) { - std::vector ret; - std::set ret2; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) + bool ret=false; + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) { - std::vector tmp=(*it)->getPflsReallyUsed(); - for(std::vector::const_iterator it2=tmp.begin();it2!=tmp.end();it2++) - if(ret2.find(*it2)==ret2.end()) - { - ret.push_back(*it2); - ret2.insert(*it2); - } + MEDFileFieldPerMesh *fpm(*it); + if(fpm) + ret=fpm->renumberEntitiesLyingOnMesh(meshName,oldCode,newCode,renumO2N,glob) || ret; } return ret; } -std::vector MEDFileField1TSWithoutSDA::getLocsReallyUsed2() const +void MEDFileAnyTypeField1TSWithoutSDA::writeLL(med_idt fid, const MEDFileWritable& opts, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { - std::vector ret; - std::set ret2; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) - { - std::vector tmp=(*it)->getLocsReallyUsed(); - for(std::vector::const_iterator it2=tmp.begin();it2!=tmp.end();it2++) - if(ret2.find(*it2)==ret2.end()) - { - ret.push_back(*it2); - ret2.insert(*it2); - } - } - return ret; + if(_field_per_mesh.empty()) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::writeLL : empty field !"); + if(_field_per_mesh.size()>1) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::writeLL : In MED3.0 mode in writting mode only ONE underlying mesh supported !"); + _field_per_mesh[0]->copyOptionsFrom(opts); + _field_per_mesh[0]->writeLL(fid,nasc); } -std::vector MEDFileField1TSWithoutSDA::getPflsReallyUsedMulti2() const +void MEDFileAnyTypeField1TSWithoutSDA::finishLoading(med_idt fid, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { - std::vector ret; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) + med_int numdt,numit; + med_float dt; + med_int nmesh; + med_bool localMesh; + med_int meshnumdt,meshnumit; + INTERP_KERNEL::AutoPtr meshName=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); + MEDfieldComputingStepInfo(fid,nasc.getName().c_str(),_csit,&numdt,&numit,&_dt); + MEDfield23ComputingStepMeshInfo(fid,nasc.getName().c_str(),_csit,&numdt,&numit,&dt,&nmesh,meshName,&localMesh,&meshnumdt,&meshnumit); + if(_iteration!=numdt || _order!=numit) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::finishLoading : unexpected exception internal error !"); + _field_per_mesh.resize(nmesh); + for(int i=0;i tmp=(*it)->getPflsReallyUsedMulti(); - ret.insert(ret.end(),tmp.begin(),tmp.end()); + _field_per_mesh[i]->prepareLoading(fid,start,nasc); } - return ret; -} - -std::vector MEDFileField1TSWithoutSDA::getLocsReallyUsedMulti2() const -{ - std::vector ret; - std::set ret2; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) + getOrCreateAndGetArray()->alloc(start,getNumberOfComponents()); + for(int i=0;i tmp=(*it)->getLocsReallyUsedMulti(); - ret.insert(ret.end(),tmp.begin(),tmp.end()); + _field_per_mesh[i]->finishLoading(fid,nasc); } - return ret; -} - -void MEDFileField1TSWithoutSDA::changePflsRefsNamesGen2(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) -{ - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) - (*it)->changePflsRefsNamesGen(mapOfModif); -} - -void MEDFileField1TSWithoutSDA::changeLocsRefsNamesGen2(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) -{ - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) - (*it)->changeLocsRefsNamesGen(mapOfModif); } -void MEDFileField1TSWithoutSDA::writeLL(med_idt fid, const MEDFileWritable& opts) const throw(INTERP_KERNEL::Exception) +std::size_t MEDFileAnyTypeField1TSWithoutSDA::getHeapMemorySize() const { - if(_field_per_mesh.empty()) - throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::writeLL : empty field !"); - if(_field_per_mesh.size()>1) - throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::writeLL : In MED3.0 mode in writting mode only ONE underlying mesh supported !"); - _field_per_mesh[0]->copyOptionsFrom(opts); - _field_per_mesh[0]->writeLL(fid); + std::size_t ret=_dt_unit.capacity()+_field_per_mesh.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh >); + if(getUndergroundDataArray()) + ret+=getUndergroundDataArray()->getHeapMemorySize(); + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) + ret+=(*it)->getHeapMemorySize(); + return ret; } /*! * Adds a MEDCouplingFieldDouble to \a this. The underlying mesh of the given field is * checked if its elements are sorted suitable for writing to MED file ("STB" stands for * "Sort By Type"), if not, an exception is thrown. - * \param [in] field - the field to add to \a this. + * \param [in] field - the field to add to \a this. The array of field \a field is ignored + * \param [in] arr - the array of values. * \param [in,out] glob - the global data where profiles and localization present in * \a field, if any, are added. * \throw If the name of \a field is empty. @@ -3945,21 +4062,21 @@ void MEDFileField1TSWithoutSDA::writeLL(med_idt fid, const MEDFileWritable& opts * \throw If the underlying mesh of \a field has no name. * \throw If elements in the mesh are not in the order suitable for writing to the MED file. */ -void MEDFileField1TSWithoutSDA::setFieldNoProfileSBT(const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileAnyTypeField1TSWithoutSDA::setFieldNoProfileSBT(const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { const MEDCouplingMesh *mesh=field->getMesh(); // TypeOfField type=field->getTypeOfField(); std::vector dummy; - int start=copyTinyInfoFrom(field); + int start=copyTinyInfoFrom(field,arr); int pos=addNewEntryIfNecessary(mesh); if(type!=ON_NODES) { std::vector code=MEDFileField1TSWithoutSDA::CheckSBTMesh(mesh); - _field_per_mesh[pos]->assignFieldNoProfileNoRenum(start,code,field,glob); + _field_per_mesh[pos]->assignFieldNoProfileNoRenum(start,code,field,arr,glob,nasc); } else - _field_per_mesh[pos]->assignNodeFieldNoProfile(start,field,glob); + _field_per_mesh[pos]->assignNodeFieldNoProfile(start,field,arr,glob); } /*! @@ -3970,7 +4087,8 @@ void MEDFileField1TSWithoutSDA::setFieldNoProfileSBT(const MEDCouplingFieldDoubl * is not prescribed; this method permutes field values to have them sorted by element * type as required for writing to MED file. A new profile is added only if no equal * profile is missing. - * \param [in] field - the field to add to \a this. + * \param [in] field - the field to add to \a this. The field double values are ignored. + * \param [in] arrOfVals - the values of the field \a field used. * \param [in] mesh - the supporting mesh of \a field. * \param [in] meshDimRelToMax - a relative dimension of mesh entities \a field lies on. * \param [in] profile - ids of mesh entities on which corresponding field values lie. @@ -3984,10 +4102,10 @@ void MEDFileField1TSWithoutSDA::setFieldNoProfileSBT(const MEDCouplingFieldDoubl * \throw If elements in \a mesh are not in the order suitable for writing to the MED file. * \sa setFieldNoProfileSBT() */ -void MEDFileField1TSWithoutSDA::setFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileAnyTypeField1TSWithoutSDA::setFieldProfile(const MEDCouplingFieldDouble *field, const DataArray *arrOfVals, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception) { TypeOfField type=field->getTypeOfField(); - int start=copyTinyInfoFrom(field); + int start=copyTinyInfoFrom(field,arrOfVals); std::vector idsInPflPerType; std::vector idsPerType; std::vector code,code2; @@ -4005,15 +4123,101 @@ void MEDFileField1TSWithoutSDA::setFieldProfile(const MEDCouplingFieldDouble *fi idsPerType2[i]=idsPerType[i]; // int pos=addNewEntryIfNecessary(m); - _field_per_mesh[pos]->assignFieldProfile(start,profile,code,code2,idsInPflPerType,idsPerType,field,m,glob); + _field_per_mesh[pos]->assignFieldProfile(start,profile,code,code2,idsInPflPerType,idsPerType,field,arrOfVals,m,glob,nasc); } else { int pos=addNewEntryIfNecessary(m); - _field_per_mesh[pos]->assignNodeFieldProfile(start,profile,field,glob); + _field_per_mesh[pos]->assignNodeFieldProfile(start,profile,field,arrOfVals,glob,nasc); + } +} + +/*! + * Copies tiny info and allocates \a this->_arr instance of DataArrayDouble to + * append data of a given MEDCouplingFieldDouble. So that the size of \a this->_arr becomes + * larger by the size of \a field. Returns an id of the first not filled + * tuple of \a this->_arr. + * \param [in] field - the field to copy the info on components and the name from. + * \return int - the id of first not initialized tuple of \a this->_arr. + * \throw If the name of \a field is empty. + * \throw If the data array of \a field is not set. + * \throw If \a this->_arr is already allocated but has different number of components + * than \a field. + */ +int MEDFileAnyTypeField1TSWithoutSDA::copyTinyInfoFrom(const MEDCouplingFieldDouble *field, const DataArray *arr) throw(INTERP_KERNEL::Exception) +{ + if(!field) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::copyTinyInfoFrom : input field is NULL !"); + std::string name(field->getName()); + setName(name.c_str()); + setDtUnit(field->getTimeUnit()); + if(name.empty()) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::copyTinyInfoFrom : unsupported fields with no name in MED file !"); + if(!arr) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::copyTinyInfoFrom : no array set !"); + _dt=field->getTime(_iteration,_order); + int nbOfComponents=arr->getNumberOfComponents(); + getOrCreateAndGetArray()->setInfoAndChangeNbOfCompo(arr->getInfoOnComponents()); + if(!getOrCreateAndGetArray()->isAllocated()) + { + getOrCreateAndGetArray()->alloc(arr->getNumberOfTuples(),arr->getNumberOfComponents()); + return 0; + } + else + { + int oldNbOfTuples=getOrCreateAndGetArray()->getNumberOfTuples(); + int newNbOfTuples=oldNbOfTuples+arr->getNumberOfTuples(); + MEDCouplingAutoRefCountObjectPtr tmp=createNewEmptyDataArrayInstance(); + tmp->alloc(newNbOfTuples,nbOfComponents); + tmp->copyStringInfoFrom(*getOrCreateAndGetArray()); + DataArray *arrr=getOrCreateAndGetArray(); + tmp->setContigPartOfSelectedValues2(0,arrr,0,oldNbOfTuples,1); + setArray(tmp); + return oldNbOfTuples; } } +/*! + * Returns number of components in \a this field + * \return int - the number of components. + */ +int MEDFileAnyTypeField1TSWithoutSDA::getNumberOfComponents() const +{ + return getOrCreateAndGetArray()->getNumberOfComponents(); +} + +/*! + * Change info on components in \a this. + * \throw If size of \a infos is not equal to the number of components already in \a this. + */ +void MEDFileAnyTypeField1TSWithoutSDA::setInfo(const std::vector& infos) throw(INTERP_KERNEL::Exception) +{ + DataArray *arr=getOrCreateAndGetArray(); + arr->setInfoOnComponents(infos);//will throw an exception if number of components mimatches +} + +/*! + * Returns info on components of \a this field. + * \return const std::vector& - a sequence of strings each being an + * information on _i_-th component. + */ +const std::vector& MEDFileAnyTypeField1TSWithoutSDA::getInfo() const +{ + const DataArray *arr=getOrCreateAndGetArray(); + return arr->getInfoOnComponents(); +} + +/*! + * Returns a mutable info on components of \a this field. + * \return std::vector& - a sequence of strings each being an + * information on _i_-th component. + */ +std::vector& MEDFileAnyTypeField1TSWithoutSDA::getInfo() +{ + DataArray *arr=getOrCreateAndGetArray(); + return arr->getInfoOnComponents(); +} + /*! * Returns a new MEDCouplingFieldDouble of given type lying on a given support. * \param [in] type - a spatial discretization of the new field. @@ -4035,14 +4239,14 @@ void MEDFileField1TSWithoutSDA::setFieldProfile(const MEDCouplingFieldDouble *fi * \throw If no field of \a this is lying on the mesh \a mName. * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. */ -MEDCouplingFieldDouble *MEDFileField1TSWithoutSDA::getFieldAtLevel(TypeOfField type, int meshDimRelToMax, const char *mName, int renumPol, const MEDFileFieldGlobsReal *glob) const throw(INTERP_KERNEL::Exception) +MEDCouplingFieldDouble *MEDFileAnyTypeField1TSWithoutSDA::getFieldAtLevel(TypeOfField type, int meshDimRelToMax, const char *mName, int renumPol, const MEDFileFieldGlobsReal *glob, MEDCouplingAutoRefCountObjectPtr& arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr mm; if(mName==0) mm=MEDFileMesh::New(glob->getFileName(),getMeshName().c_str(),getMeshIteration(),getMeshOrder()); else mm=MEDFileMesh::New(glob->getFileName(),mName,getMeshIteration(),getMeshOrder()); - return MEDFileField1TSWithoutSDA::getFieldOnMeshAtLevel(type,meshDimRelToMax,renumPol,glob,mm); + return MEDFileAnyTypeField1TSWithoutSDA::getFieldOnMeshAtLevel(type,meshDimRelToMax,renumPol,glob,mm,arrOut,nasc); } /*! @@ -4065,14 +4269,14 @@ MEDCouplingFieldDouble *MEDFileField1TSWithoutSDA::getFieldAtLevel(TypeOfField t * \throw If there are no mesh entities of \a meshDimRelToMax dimension in the mesh. * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. */ -MEDCouplingFieldDouble *MEDFileField1TSWithoutSDA::getFieldOnMeshAtLevel(TypeOfField type, int meshDimRelToMax, int renumPol, const MEDFileFieldGlobsReal *glob, const MEDFileMesh *mesh) const throw(INTERP_KERNEL::Exception) +MEDCouplingFieldDouble *MEDFileAnyTypeField1TSWithoutSDA::getFieldOnMeshAtLevel(TypeOfField type, int meshDimRelToMax, int renumPol, const MEDFileFieldGlobsReal *glob, const MEDFileMesh *mesh, MEDCouplingAutoRefCountObjectPtr& arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr m=mesh->getGenMeshAtLevel(meshDimRelToMax,false); const DataArrayInt *d=mesh->getNumberFieldAtLevel(meshDimRelToMax); const DataArrayInt *e=mesh->getNumberFieldAtLevel(1); if(meshDimRelToMax==1) (static_cast((MEDCouplingMesh *)m))->setMeshDimension(0); - return MEDFileField1TSWithoutSDA::getFieldOnMeshAtLevel(type,renumPol,glob,m,d,e); + return MEDFileAnyTypeField1TSWithoutSDA::getFieldOnMeshAtLevel(type,renumPol,glob,m,d,e,arrOut,nasc); } /*! @@ -4095,7 +4299,7 @@ MEDCouplingFieldDouble *MEDFileField1TSWithoutSDA::getFieldOnMeshAtLevel(TypeOfF * \throw If there are no mesh entities in the mesh. * \throw If no field values of the given \a type are available. */ -MEDCouplingFieldDouble *MEDFileField1TSWithoutSDA::getFieldAtTopLevel(TypeOfField type, const char *mName, int renumPol, const MEDFileFieldGlobsReal *glob) const throw(INTERP_KERNEL::Exception) +MEDCouplingFieldDouble *MEDFileAnyTypeField1TSWithoutSDA::getFieldAtTopLevel(TypeOfField type, const char *mName, int renumPol, const MEDFileFieldGlobsReal *glob, MEDCouplingAutoRefCountObjectPtr& arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr mm; if(mName==0) @@ -4104,7 +4308,7 @@ MEDCouplingFieldDouble *MEDFileField1TSWithoutSDA::getFieldAtTopLevel(TypeOfFiel mm=MEDFileMesh::New(glob->getFileName(),mName,getMeshIteration(),getMeshOrder()); int absDim=getDimension(); int meshDimRelToMax=absDim-mm->getMeshDimension(); - return MEDFileField1TSWithoutSDA::getFieldOnMeshAtLevel(type,meshDimRelToMax,renumPol,glob,mm); + return MEDFileAnyTypeField1TSWithoutSDA::getFieldOnMeshAtLevel(type,meshDimRelToMax,renumPol,glob,mm,arrOut,nasc); } /*! @@ -4129,12 +4333,12 @@ MEDCouplingFieldDouble *MEDFileField1TSWithoutSDA::getFieldAtTopLevel(TypeOfFiel * \throw If no field of \a this is lying on \a mesh. * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. */ -MEDCouplingFieldDouble *MEDFileField1TSWithoutSDA::getFieldOnMeshAtLevel(TypeOfField type, int renumPol, const MEDFileFieldGlobsReal *glob, const MEDCouplingMesh *mesh, const DataArrayInt *cellRenum, const DataArrayInt *nodeRenum) const throw(INTERP_KERNEL::Exception) +MEDCouplingFieldDouble *MEDFileAnyTypeField1TSWithoutSDA::getFieldOnMeshAtLevel(TypeOfField type, int renumPol, const MEDFileFieldGlobsReal *glob, const MEDCouplingMesh *mesh, const DataArrayInt *cellRenum, const DataArrayInt *nodeRenum, MEDCouplingAutoRefCountObjectPtr& arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { static const char msg1[]="MEDFileField1TSWithoutSDA::getFieldOnMeshAtLevel : request for a renumbered field following mesh numbering whereas it is a profile field !"; int meshId=getMeshIdFromMeshName(mesh->getName()); bool isPfl=false; - MEDCouplingAutoRefCountObjectPtr ret=_field_per_mesh[meshId]->getFieldOnMeshAtLevel(type,glob,mesh,isPfl); + MEDCouplingAutoRefCountObjectPtr ret=_field_per_mesh[meshId]->getFieldOnMeshAtLevel(type,glob,mesh,isPfl,arrOut,nasc); switch(renumPol) { case 0: @@ -4156,7 +4360,12 @@ MEDCouplingFieldDouble *MEDFileField1TSWithoutSDA::getFieldOnMeshAtLevel(TypeOfF oss << "\"" << getName() << "\" has partial renumbering (some geotype has no renumber) !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } - ret->renumberCells(cellRenum->getConstPointer(),true); + MEDCouplingFieldDiscretization *disc=ret->getDiscretization(); + if(!disc) throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::getFieldOnMeshAtLevel : internal error, no discretization on field !"); + std::vector arrOut2(1,arrOut); + // 2 following lines replace ret->renumberCells(cellRenum->getConstPointer()) if not DataArrayDouble + disc->renumberArraysForCell(ret->getMesh(),arrOut2,cellRenum->getConstPointer(),true); + (const_cast(ret->getMesh()))->renumberCells(cellRenum->getConstPointer(),true); } if(renumPol==1) return ret.retn(); @@ -4171,10 +4380,12 @@ MEDCouplingFieldDouble *MEDFileField1TSWithoutSDA::getFieldOnMeshAtLevel(TypeOfF if((int)nodeRenum->getNbOfElems()!=mesh->getNumberOfNodes()) { std::ostringstream oss; oss << "MEDFileField1TSWithoutSDA::getFieldOnMeshAtLevel : Request of simple renumbering but it seems that underlying mesh \"" << mesh->getName() << "\" of requested field "; - oss << "\"" << getName() << "\" not defined on all nodes !"; + oss << "\"" << nasc.getName() << "\" not defined on all nodes !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } MEDCouplingAutoRefCountObjectPtr nodeRenumSafe=nodeRenum->checkAndPreparePermutation(); + if(!dynamic_cast((DataArray *)arrOut)) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::getFieldOnMeshAtLevel : node renumbering not implemented for not double DataArrays !"); ret->renumberNodes(nodeRenumSafe->getConstPointer()); } return ret.retn(); @@ -4200,145 +4411,235 @@ MEDCouplingFieldDouble *MEDFileField1TSWithoutSDA::getFieldOnMeshAtLevel(TypeOfF * \throw If no field of \a this is lying on \a mesh. * \throw If no field values of the given \a type are available. */ -DataArrayDouble *MEDFileField1TSWithoutSDA::getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl, const MEDFileFieldGlobsReal *glob) const throw(INTERP_KERNEL::Exception) +DataArray *MEDFileAnyTypeField1TSWithoutSDA::getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl, const MEDFileFieldGlobsReal *glob, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr m=mesh->getGenMeshAtLevel(meshDimRelToMax); int meshId=getMeshIdFromMeshName(mesh->getName()); - return _field_per_mesh[meshId]->getFieldOnMeshAtLevelWithPfl(type,m,pfl,glob); + MEDCouplingAutoRefCountObjectPtr ret=_field_per_mesh[meshId]->getFieldOnMeshAtLevelWithPfl(type,m,pfl,glob,nasc); + ret->setName(nasc.getName().c_str()); + return ret.retn(); } +//= MEDFileField1TSWithoutSDA + /*! - * Returns a pointer to the underground DataArrayDouble instance. So the - * caller should not decrRef() it. This method allows for a direct access to the field - * values. This method is quite unusable if there is more than a nodal field or a cell - * field on single geometric cell type. - * \return DataArrayDouble * - the pointer to the field values array. + * Throws if a given value is not a valid (non-extended) relative dimension. + * \param [in] meshDimRelToMax - the relative dimension value. + * \throw If \a meshDimRelToMax > 0. */ -DataArrayDouble *MEDFileField1TSWithoutSDA::getUndergroundDataArray() const throw(INTERP_KERNEL::Exception) +void MEDFileField1TSWithoutSDA::CheckMeshDimRel(int meshDimRelToMax) throw(INTERP_KERNEL::Exception) { - const DataArrayDouble *ret=_arr; - if(ret) - return const_cast(ret); - else - return 0; + if(meshDimRelToMax>0) + throw INTERP_KERNEL::Exception("CheckMeshDimRel : This is a meshDimRel not a meshDimRelExt ! So value should be <=0 !"); } /*! - * Returns a pointer to the underground DataArrayDouble instance and a - * sequence describing parameters of a support of each part of \a this field. The - * caller should not decrRef() the returned DataArrayDouble. This method allows for a - * direct access to the field values. This method is intended for the field lying on one - * mesh only. - * \param [in,out] entries - the sequence describing parameters of a support of each - * part of \a this field. Each item of this sequence consists of two parts. The - * first part describes a type of mesh entity and an id of discretization of a - * current field part. The second part describes a range of values [begin,end) - * within the returned array relating to the current field part. - * \return DataArrayDouble * - the pointer to the field values array. - * \throw If the number of underlying meshes is not equal to 1. - * \throw If no field values are available. - * \sa getUndergroundDataArray() + * Checks if elements of a given mesh are in the order suitable for writing + * to the MED file. If this is not so, an exception is thrown. In a case of success, returns a + * vector describing types of elements and their number. + * \param [in] mesh - the mesh to check. + * \return std::vector - a vector holding for each element type (1) item of + * INTERP_KERNEL::NormalizedCellType, (2) number of elements, (3) -1. + * These values are in full-interlace mode. + * \throw If elements in \a mesh are not in the order suitable for writing to the MED file. */ -DataArrayDouble *MEDFileField1TSWithoutSDA::getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) -{ - if(_field_per_mesh.size()!=1) - throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::getUndergroundDataArrayExt : field lies on several meshes, this method has no sense !"); - if(_field_per_mesh[0]==0) - throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::getUndergroundDataArrayExt : no field specified !"); - return _field_per_mesh[0]->getUndergroundDataArrayExt(entries); -} - -MEDFileField1TSWithoutSDA::MEDFileField1TSWithoutSDA(const char *fieldName, int csit, int fieldtype, int iteration, int order, - const std::vector& infos):_iteration(iteration),_order(order),_csit(csit),_field_type(fieldtype) -{ - DataArrayDouble *arr=getOrCreateAndGetArray(); - arr->setName(fieldName); - arr->setInfoAndChangeNbOfCompo(infos); -} - -MEDFileField1TSWithoutSDA::MEDFileField1TSWithoutSDA():_csit(-1),_field_type(-1) -{ -} - -int MEDFileField1TSWithoutSDA::addNewEntryIfNecessary(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception) +std::vector MEDFileField1TSWithoutSDA::CheckSBTMesh(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception) { - std::string tmp(mesh->getName()); - if(tmp.empty()) - throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::addNewEntryIfNecessary : empty mesh name ! unsupported by MED file !"); - std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin(); + if(!mesh) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::CheckSBTMesh : input mesh is NULL !"); + std::set geoTypes=mesh->getAllGeoTypes(); + int nbOfTypes=geoTypes.size(); + std::vector code(3*nbOfTypes); + MEDCouplingAutoRefCountObjectPtr arr1=DataArrayInt::New(); + arr1->alloc(nbOfTypes,1); + int *arrPtr=arr1->getPointer(); + std::set::const_iterator it=geoTypes.begin(); + for(int i=0;i arr2=arr1->checkAndPreparePermutation(); + const int *arrPtr2=arr2->getConstPointer(); int i=0; - for(;it!=_field_per_mesh.end();it++,i++) + for(it=geoTypes.begin();it!=geoTypes.end();it++,i++) { - if((*it)->getMeshName()==tmp) - return i; + int pos=arrPtr2[i]; + int nbCells=mesh->getNumberOfCellsWithType(*it); + code[3*pos]=(int)(*it); + code[3*pos+1]=nbCells; + code[3*pos+2]=-1;//no profiles } - int sz=_field_per_mesh.size(); - _field_per_mesh.resize(sz+1); - _field_per_mesh[sz]=MEDFileFieldPerMesh::New(this,mesh); - return sz; + std::vector idsPerType;//no profiles + DataArrayInt *da=mesh->checkTypeConsistencyAndContig(code,idsPerType); + if(da) + { + da->decrRef(); + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::CheckSBTMesh : underlying mesh is not sorted by type as MED file expects !"); + } + return code; } -/*! - * \param [in] mName specifies the underlying mesh name. This value can be pointer 0 for users that do not deal with fields on multi mesh. - */ -int MEDFileField1TSWithoutSDA::getMeshIdFromMeshName(const char *mName) const throw(INTERP_KERNEL::Exception) +MEDFileField1TSWithoutSDA *MEDFileField1TSWithoutSDA::New(const char *fieldName, int csit, int iteration, int order, const std::vector& infos) { - if(_field_per_mesh.empty()) - throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::getMeshIdFromMeshName : No field set !"); - if(mName==0) - return 0; - std::string mName2(mName); - int ret=0; - std::vector msg; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++,ret++) - if(mName2==(*it)->getMeshName()) - return ret; - else - msg.push_back((*it)->getMeshName()); - std::ostringstream oss; oss << "MEDFileField1TSWithoutSDA::getMeshIdFromMeshName : No such mesh \"" << mName2 << "\" as underlying mesh of field \"" << getName() << "\" !\n"; - oss << "Possible meshes are : "; - for(std::vector::const_iterator it2=msg.begin();it2!=msg.end();it2++) - oss << "\"" << (*it2) << "\" "; - throw INTERP_KERNEL::Exception(oss.str().c_str()); + return new MEDFileField1TSWithoutSDA(fieldName,csit,iteration,order,infos); } /*! - * \param [in] mName specifies the underlying mesh name. This value can be pointer 0 for users that do not deal with fields on multi mesh. - * \param [in] typ is for the geometric cell type (or INTERP_KERNEL::NORM_ERROR for node field) entry to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. - * \param [in] locId is the localization id to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. It corresponds to the position of - * \c pfls[std::distance(types.begin(),std::find(types.begin(),typ)] vector in MEDFileField1TSWithoutSDA::getFieldSplitedByType. For non gausspoints field users, the value is 0. + * Returns all attributes and values of parts of \a this field lying on a given mesh. + * Each part differs from other ones by a type of supporting mesh entity. The _i_-th + * item of every of returned sequences refers to the _i_-th part of \a this field. + * Thus all sequences returned by this method are of the same length equal to number + * of different types of supporting entities.
+ * A field part can include sub-parts with several different spatial discretizations, + * \ref ParaMEDMEM::ON_CELLS "ON_CELLS" and \ref ParaMEDMEM::ON_GAUSS_PT "ON_GAUSS_PT" + * for example. Hence, some of the returned sequences contains nested sequences, and an item + * of a nested sequence corresponds to a type of spatial discretization.
+ * This method allows for iteration over MEDFile DataStructure with a reduced overhead. + * The overhead is due to selecting values into new instances of DataArrayDouble. + * \param [in] mname - a name of a mesh of interest. It can be \c NULL, which is valid + * for the case with only one underlying mesh. (Actually, the number of meshes is + * not checked if \a mname == \c NULL). + * \param [in,out] types - a sequence of types of underlying mesh entities. A type per + * a field part is returned. + * \param [in,out] typesF - a sequence of sequences of types of spatial discretizations. + * A field part can include sub-parts with several different spatial discretizations, + * \ref ParaMEDMEM::ON_CELLS "ON_CELLS" and + * \ref ParaMEDMEM::ON_GAUSS_PT "ON_GAUSS_PT" for example. + * This sequence is of the same length as \a types. + * \param [in,out] pfls - a sequence returning a profile name per each type of spatial + * discretization. A profile name can be empty. + * Length of this and of nested sequences is the same as that of \a typesF. + * \param [in,out] locs - a sequence returning a localization name per each type of spatial + * discretization. A localization name can be empty. + * Length of this and of nested sequences is the same as that of \a typesF. + * \return std::vector< std::vector > - a sequence holding arrays of values + * per each type of spatial discretization within one mesh entity type. + * The caller is to delete each DataArrayDouble using decrRef() as it is no more needed. + * Length of this and of nested sequences is the same as that of \a typesF. + * \throw If no field is lying on \a mname. */ -MEDFileFieldPerMeshPerTypePerDisc *MEDFileField1TSWithoutSDA::getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) throw(INTERP_KERNEL::Exception) +std::vector< std::vector > MEDFileField1TSWithoutSDA::getFieldSplitedByType2(const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) { - int mid=getMeshIdFromMeshName(mName); - return _field_per_mesh[mid]->getLeafGivenTypeAndLocId(typ,locId); + int meshId=0; + if(mname) + meshId=getMeshIdFromMeshName(mname); + else + if(_field_per_mesh.empty()) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::getFieldSplitedByType : This is empty !"); + std::vector< std::vector< std::pair > > ret0=_field_per_mesh[meshId]->getFieldSplitedByType(types,typesF,pfls,locs); + int nbOfRet=ret0.size(); + std::vector< std::vector > ret(nbOfRet); + for(int i=0;i >& p=ret0[i]; + int nbOfRet1=p.size(); + ret[i].resize(nbOfRet1); + for(int j=0;jselectByTupleId2(p[j].first,p[j].second,1); + ret[i][j]=tmp; + } + } + return ret; } /*! - * \param [in] mName specifies the underlying mesh name. This value can be pointer 0 for users that do not deal with fields on multi mesh. - * \param [in] typ is for the geometric cell type (or INTERP_KERNEL::NORM_ERROR for node field) entry to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. - * \param [in] locId is the localization id to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. It corresponds to the position of - * \c pfls[std::distance(types.begin(),std::find(types.begin(),typ)] vector in MEDFileField1TSWithoutSDA::getFieldSplitedByType. For non gausspoints field users, the value is 0. + * Returns a pointer to the underground DataArrayDouble instance. So the + * caller should not decrRef() it. This method allows for a direct access to the field + * values. This method is quite unusable if there is more than a nodal field or a cell + * field on single geometric cell type. + * \return DataArrayDouble * - the pointer to the field values array. */ -const MEDFileFieldPerMeshPerTypePerDisc *MEDFileField1TSWithoutSDA::getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) const throw(INTERP_KERNEL::Exception) +DataArrayDouble *MEDFileField1TSWithoutSDA::getUndergroundDataArrayDouble() const throw(INTERP_KERNEL::Exception) { - int mid=getMeshIdFromMeshName(mName); - return _field_per_mesh[mid]->getLeafGivenTypeAndLocId(typ,locId); + const DataArrayDouble *ret=_arr; + if(ret) + return const_cast(ret); + else + return 0; } -std::size_t MEDFileField1TSWithoutSDA::getHeapMemorySize() const +const char *MEDFileField1TSWithoutSDA::getTypeStr() const throw(INTERP_KERNEL::Exception) { - std::size_t ret=_dt_unit.capacity()+_field_per_mesh.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh >); - if((const DataArrayDouble *)_arr) - ret+=_arr->getHeapMemorySize(); - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++) - ret+=(*it)->getHeapMemorySize(); - return ret; + return TYPE_STR; +} + +/*! + * Returns a pointer to the underground DataArrayDouble instance. So the + * caller should not decrRef() it. This method allows for a direct access to the field + * values. This method is quite unusable if there is more than a nodal field or a cell + * field on single geometric cell type. + * \return DataArrayDouble * - the pointer to the field values array. + */ +DataArray *MEDFileField1TSWithoutSDA::getUndergroundDataArray() const throw(INTERP_KERNEL::Exception) +{ + return getUndergroundDataArrayDouble(); +} + +/*! + * Returns a pointer to the underground DataArrayDouble instance and a + * sequence describing parameters of a support of each part of \a this field. The + * caller should not decrRef() the returned DataArrayDouble. This method allows for a + * direct access to the field values. This method is intended for the field lying on one + * mesh only. + * \param [in,out] entries - the sequence describing parameters of a support of each + * part of \a this field. Each item of this sequence consists of two parts. The + * first part describes a type of mesh entity and an id of discretization of a + * current field part. The second part describes a range of values [begin,end) + * within the returned array relating to the current field part. + * \return DataArrayDouble * - the pointer to the field values array. + * \throw If the number of underlying meshes is not equal to 1. + * \throw If no field values are available. + * \sa getUndergroundDataArray() + */ +DataArrayDouble *MEDFileField1TSWithoutSDA::getUndergroundDataArrayDoubleExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) +{ + if(_field_per_mesh.size()!=1) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::getUndergroundDataArrayExt : field lies on several meshes, this method has no sense !"); + if(_field_per_mesh[0]==0) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::getUndergroundDataArrayExt : no field specified !"); + _field_per_mesh[0]->getUndergroundDataArrayExt(entries); + return getUndergroundDataArrayDouble(); +} + +/*! + * Returns a pointer to the underground DataArrayDouble instance and a + * sequence describing parameters of a support of each part of \a this field. The + * caller should not decrRef() the returned DataArrayDouble. This method allows for a + * direct access to the field values. This method is intended for the field lying on one + * mesh only. + * \param [in,out] entries - the sequence describing parameters of a support of each + * part of \a this field. Each item of this sequence consists of two parts. The + * first part describes a type of mesh entity and an id of discretization of a + * current field part. The second part describes a range of values [begin,end) + * within the returned array relating to the current field part. + * \return DataArrayDouble * - the pointer to the field values array. + * \throw If the number of underlying meshes is not equal to 1. + * \throw If no field values are available. + * \sa getUndergroundDataArray() + */ +DataArray *MEDFileField1TSWithoutSDA::getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) +{ + return getUndergroundDataArrayDoubleExt(entries); +} + +MEDFileField1TSWithoutSDA::MEDFileField1TSWithoutSDA(const char *fieldName, int csit, int iteration, int order, + const std::vector& infos):MEDFileAnyTypeField1TSWithoutSDA(fieldName,csit,iteration,order) +{ + DataArrayDouble *arr=getOrCreateAndGetArrayDouble(); + arr->setInfoAndChangeNbOfCompo(infos); +} + +MEDFileField1TSWithoutSDA::MEDFileField1TSWithoutSDA():MEDFileAnyTypeField1TSWithoutSDA() +{ +} + +MEDFileAnyTypeField1TSWithoutSDA *MEDFileField1TSWithoutSDA::shallowCpy() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileField1TSWithoutSDA(*this); } -MEDFileField1TSWithoutSDA *MEDFileField1TSWithoutSDA::deepCpy() const throw(INTERP_KERNEL::Exception) +MEDFileAnyTypeField1TSWithoutSDA *MEDFileField1TSWithoutSDA::deepCpy() const throw(INTERP_KERNEL::Exception) { - MEDCouplingAutoRefCountObjectPtr ret=new MEDFileField1TSWithoutSDA(*this); + MEDCouplingAutoRefCountObjectPtr ret=static_cast(shallowCpy()); if((const DataArrayDouble *)_arr) ret->_arr=_arr->deepCpy(); std::size_t i=0; @@ -4350,7 +4651,23 @@ MEDFileField1TSWithoutSDA *MEDFileField1TSWithoutSDA::deepCpy() const throw(INTE return ret.retn(); } -DataArrayDouble *MEDFileField1TSWithoutSDA::getOrCreateAndGetArray() +void MEDFileField1TSWithoutSDA::setArray(DataArray *arr) throw(INTERP_KERNEL::Exception) +{ + if(!arr) + _arr=0; + DataArrayDouble *arrC=dynamic_cast(arr); + if(!arrC) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::setArray : the input not null array is not of type DataArrayDouble !"); + arrC->incrRef(); + _arr=arrC; +} + +DataArray *MEDFileField1TSWithoutSDA::createNewEmptyDataArrayInstance() const +{ + return DataArrayDouble::New(); +} + +DataArrayDouble *MEDFileField1TSWithoutSDA::getOrCreateAndGetArrayDouble() { DataArrayDouble *ret=_arr; if(ret) @@ -4359,7 +4676,12 @@ DataArrayDouble *MEDFileField1TSWithoutSDA::getOrCreateAndGetArray() return _arr; } -const DataArrayDouble *MEDFileField1TSWithoutSDA::getOrCreateAndGetArray() const +DataArray *MEDFileField1TSWithoutSDA::getOrCreateAndGetArray() +{ + return getOrCreateAndGetArrayDouble(); +} + +const DataArrayDouble *MEDFileField1TSWithoutSDA::getOrCreateAndGetArrayDouble() const { const DataArrayDouble *ret=_arr; if(ret) @@ -4369,168 +4691,223 @@ const DataArrayDouble *MEDFileField1TSWithoutSDA::getOrCreateAndGetArray() const return ret2; } -/*! - * Returns a new instance of MEDFileField1TS holding data of the first time step of - * the first field that has been read from a specified MED file. - * \param [in] fileName - the name of the MED file to read. - * \return MEDFileField1TS * - a new instance of MEDFileFieldMultiTS. The caller - * is to delete this field using decrRef() as it is no more needed. - * \throw If reading the file fails. - */ -MEDFileField1TS *MEDFileField1TS::New(const char *fileName) throw(INTERP_KERNEL::Exception) +const DataArray *MEDFileField1TSWithoutSDA::getOrCreateAndGetArray() const { - return new MEDFileField1TS(fileName); + return getOrCreateAndGetArrayDouble(); } -/*! - * Returns a new instance of MEDFileField1TS holding data of the first time step of - * a given field that has been read from a specified MED file. - * \param [in] fileName - the name of the MED file to read. - * \param [in] fieldName - the name of the field to read. - * \return MEDFileField1TS * - a new instance of MEDFileFieldMultiTS. The caller - * is to delete this field using decrRef() as it is no more needed. - * \throw If reading the file fails. - * \throw If there is no field named \a fieldName in the file. - */ -MEDFileField1TS *MEDFileField1TS::New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) +//= MEDFileIntField1TSWithoutSDA + +MEDFileIntField1TSWithoutSDA *MEDFileIntField1TSWithoutSDA::New(const char *fieldName, int csit, int iteration, int order, + const std::vector& infos) +{ + return new MEDFileIntField1TSWithoutSDA(fieldName,csit,iteration,order,infos); +} + +MEDFileIntField1TSWithoutSDA::MEDFileIntField1TSWithoutSDA():MEDFileAnyTypeField1TSWithoutSDA() +{ +} + +MEDFileIntField1TSWithoutSDA::MEDFileIntField1TSWithoutSDA(const char *fieldName, int csit, int iteration, int order, + const std::vector& infos):MEDFileAnyTypeField1TSWithoutSDA(fieldName,csit,iteration,order) +{ + DataArrayInt *arr=getOrCreateAndGetArrayInt(); + arr->setInfoAndChangeNbOfCompo(infos); +} + +const char *MEDFileIntField1TSWithoutSDA::getTypeStr() const throw(INTERP_KERNEL::Exception) { - return new MEDFileField1TS(fileName,fieldName); + return TYPE_STR; } /*! - * Returns a new instance of MEDFileField1TS holding data of a given time step of - * a given field that has been read from a specified MED file. - * \param [in] fileName - the name of the MED file to read. - * \param [in] fieldName - the name of the field to read. - * \param [in] iteration - the iteration number of a required time step. - * \param [in] order - the iteration order number of required time step. - * \return MEDFileField1TS * - a new instance of MEDFileFieldMultiTS. The caller - * is to delete this field using decrRef() as it is no more needed. - * \throw If reading the file fails. - * \throw If there is no field named \a fieldName in the file. - * \throw If the required time step is missing from the file. + * Returns a pointer to the underground DataArrayInt instance. So the + * caller should not decrRef() it. This method allows for a direct access to the field + * values. This method is quite unusable if there is more than a nodal field or a cell + * field on single geometric cell type. + * \return DataArrayInt * - the pointer to the field values array. */ -MEDFileField1TS *MEDFileField1TS::New(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception) +DataArray *MEDFileIntField1TSWithoutSDA::getUndergroundDataArray() const throw(INTERP_KERNEL::Exception) { - return new MEDFileField1TS(fileName,fieldName,iteration,order); + return getUndergroundDataArrayInt(); } /*! - * Returns a new instance of MEDFileField1TS holding either deep or shallow copy - * of a given MEDFileField1TSWithoutSDA. - * \warning this is a shallow copy constructor - * \param [in] other - a MEDFileField1TSWithoutSDA to copy. - * \param [in] shallowCopyOfContent - if \c true, a shallow copy of \a other is created. - * \return MEDFileField1TS * - a new instance of MEDFileFieldMultiTS. The caller - * is to delete this field using decrRef() as it is no more needed. + * Returns a pointer to the underground DataArrayInt instance. So the + * caller should not decrRef() it. This method allows for a direct access to the field + * values. This method is quite unusable if there is more than a nodal field or a cell + * field on single geometric cell type. + * \return DataArrayInt * - the pointer to the field values array. */ -MEDFileField1TS *MEDFileField1TS::New(const MEDFileField1TSWithoutSDA& other, bool shallowCopyOfContent) +DataArrayInt *MEDFileIntField1TSWithoutSDA::getUndergroundDataArrayInt() const throw(INTERP_KERNEL::Exception) { - return new MEDFileField1TS(other,shallowCopyOfContent); + const DataArrayInt *ret=_arr; + if(ret) + return const_cast(ret); + else + return 0; } /*! - * Returns a new empty instance of MEDFileField1TS. - * \return MEDFileField1TS * - a new instance of MEDFileField1TS. The caller - * is to delete this field using decrRef() as it is no more needed. + * Returns a pointer to the underground DataArrayInt instance and a + * sequence describing parameters of a support of each part of \a this field. The + * caller should not decrRef() the returned DataArrayInt. This method allows for a + * direct access to the field values. This method is intended for the field lying on one + * mesh only. + * \param [in,out] entries - the sequence describing parameters of a support of each + * part of \a this field. Each item of this sequence consists of two parts. The + * first part describes a type of mesh entity and an id of discretization of a + * current field part. The second part describes a range of values [begin,end) + * within the returned array relating to the current field part. + * \return DataArrayInt * - the pointer to the field values array. + * \throw If the number of underlying meshes is not equal to 1. + * \throw If no field values are available. + * \sa getUndergroundDataArray() */ -MEDFileField1TS *MEDFileField1TS::New() +DataArray *MEDFileIntField1TSWithoutSDA::getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) { - return new MEDFileField1TS; + return getUndergroundDataArrayIntExt(entries); } /*! - * Returns a string describing \a this field. This string is outputted - * by \c print Python command. + * Returns a pointer to the underground DataArrayInt instance and a + * sequence describing parameters of a support of each part of \a this field. The + * caller should not decrRef() the returned DataArrayInt. This method allows for a + * direct access to the field values. This method is intended for the field lying on one + * mesh only. + * \param [in,out] entries - the sequence describing parameters of a support of each + * part of \a this field. Each item of this sequence consists of two parts. The + * first part describes a type of mesh entity and an id of discretization of a + * current field part. The second part describes a range of values [begin,end) + * within the returned array relating to the current field part. + * \return DataArrayInt * - the pointer to the field values array. + * \throw If the number of underlying meshes is not equal to 1. + * \throw If no field values are available. + * \sa getUndergroundDataArray() */ -std::string MEDFileField1TS::simpleRepr() const +DataArrayInt *MEDFileIntField1TSWithoutSDA::getUndergroundDataArrayIntExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) { - std::ostringstream oss; - _content->simpleRepr(0,oss,-1); - MEDFileFieldGlobsReal::simpleRepr(oss); - return oss.str(); + if(_field_per_mesh.size()!=1) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::getUndergroundDataArrayExt : field lies on several meshes, this method has no sense !"); + if(_field_per_mesh[0]==0) + throw INTERP_KERNEL::Exception("MEDFileField1TSWithoutSDA::getUndergroundDataArrayExt : no field specified !"); + _field_per_mesh[0]->getUndergroundDataArrayExt(entries); + return getUndergroundDataArrayInt(); } -void MEDFileField1TS::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) +MEDFileAnyTypeField1TSWithoutSDA *MEDFileIntField1TSWithoutSDA::shallowCpy() const throw(INTERP_KERNEL::Exception) { - int nbComp=getNumberOfComponents(); - INTERP_KERNEL::AutoPtr comp=MEDLoaderBase::buildEmptyString(nbComp*MED_SNAME_SIZE); - INTERP_KERNEL::AutoPtr unit=MEDLoaderBase::buildEmptyString(nbComp*MED_SNAME_SIZE); - for(int i=0;i ret=static_cast(shallowCpy()); + if((const DataArrayInt *)_arr) + ret->_arr=_arr->deepCpy(); + std::size_t i=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > >::const_iterator it=_field_per_mesh.begin();it!=_field_per_mesh.end();it++,i++) { - std::string info=getInfo()[i]; - std::string c,u; - MEDLoaderBase::splitIntoNameAndUnit(info,c,u); - MEDLoaderBase::safeStrCpy2(c.c_str(),MED_SNAME_SIZE,comp+i*MED_SNAME_SIZE,_too_long_str); - MEDLoaderBase::safeStrCpy2(u.c_str(),MED_SNAME_SIZE,unit+i*MED_SNAME_SIZE,_too_long_str); + if((const MEDFileFieldPerMesh *)*it) + ret->_field_per_mesh[i]=(*it)->deepCpy((MEDFileIntField1TSWithoutSDA *)ret); } - if(getName().empty()) - throw INTERP_KERNEL::Exception("MEDFileField1TS::write : MED file does not accept field with empty name !"); - MEDfieldCr(fid,getName().c_str(),MED_FLOAT64,nbComp,comp,unit,getDtUnit().c_str(),getMeshName().c_str()); - writeGlobals(fid,*this); - _content->writeLL(fid,*this); + return ret.retn(); } -/*! - * Writes \a this field into a MED file specified by its name. - * \param [in] fileName - the MED file name. - * \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics. - * - 2 - erase; an existing file is removed. - * - 1 - append; same data should not be present in an existing file. - * - 0 - overwrite; same data present in an existing file is overwritten. - * \throw If the field name is not set. - * \throw If no field data is set. - * \throw If \a mode == 1 and the same data is present in an existing file. - */ -void MEDFileField1TS::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception) +void MEDFileIntField1TSWithoutSDA::setArray(DataArray *arr) throw(INTERP_KERNEL::Exception) { - med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod); - writeLL(fid); + if(!arr) + _arr=0; + DataArrayInt *arrC=dynamic_cast(arr); + if(!arrC) + throw INTERP_KERNEL::Exception("MEDFileIntField1TSWithoutSDA::setArray : the input not null array is not of type DataArrayInt !"); + _arr=arrC; } -MEDFileField1TS::MEDFileField1TS(const char *fileName) throw(INTERP_KERNEL::Exception) -try:MEDFileFieldGlobsReal(fileName) +DataArray *MEDFileIntField1TSWithoutSDA::createNewEmptyDataArrayInstance() const +{ + return DataArrayInt::New(); +} + +DataArrayInt *MEDFileIntField1TSWithoutSDA::getOrCreateAndGetArrayInt() +{ + DataArrayInt *ret=_arr; + if(ret) + return ret; + _arr=DataArrayInt::New(); + return _arr; +} + +DataArray *MEDFileIntField1TSWithoutSDA::getOrCreateAndGetArray() +{ + return getOrCreateAndGetArrayInt(); +} + +const DataArrayInt *MEDFileIntField1TSWithoutSDA::getOrCreateAndGetArrayInt() const +{ + const DataArrayInt *ret=_arr; + if(ret) + return ret; + DataArrayInt *ret2=DataArrayInt::New(); + const_cast(this)->_arr=DataArrayInt::New(); + return ret2; +} + +const DataArray *MEDFileIntField1TSWithoutSDA::getOrCreateAndGetArray() const +{ + return getOrCreateAndGetArrayInt(); +} + +MEDFileAnyTypeField1TS::MEDFileAnyTypeField1TS() +{ +} + +//= MEDFileAnyTypeField1TS + +MEDFileAnyTypeField1TSWithoutSDA *MEDFileAnyTypeField1TS::BuildContentFrom(med_idt fid, const char *fileName) throw(INTERP_KERNEL::Exception) { - MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); med_field_type typcha; // - int nbFields=MEDnField(fid); - if(nbFields<1) + std::vector infos; + std::string dtunit,fieldName; + LocateField2(fid,fileName,0,true,fieldName,typcha,infos,dtunit); + MEDCouplingAutoRefCountObjectPtr ret; + switch(typcha) { - std::ostringstream oss; oss << "MEDFileField1TS(fileName) : no field present in file \'" << fileName << "\' !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - int ncomp=MEDfieldnComponent(fid,1); - INTERP_KERNEL::AutoPtr comp=MEDLoaderBase::buildEmptyString(ncomp*MED_SNAME_SIZE); - INTERP_KERNEL::AutoPtr unit=MEDLoaderBase::buildEmptyString(ncomp*MED_SNAME_SIZE); - INTERP_KERNEL::AutoPtr dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE); - INTERP_KERNEL::AutoPtr nomcha=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); - INTERP_KERNEL::AutoPtr nomMaa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); - med_bool localMesh; - int nbOfStep; - MEDfieldInfo(fid,1,nomcha,nomMaa,&localMesh,&typcha,comp,unit,dtunit,&nbOfStep); - std::string fieldName(nomcha); - if(nbOfStep<1) - { - std::ostringstream oss; oss << "MEDFileField1TS(fileName) : file \'" << fileName << "\' contains field with name \'" << fieldName << "\' but there is no time steps on it !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); + case MED_FLOAT64: + { + ret=MEDFileField1TSWithoutSDA::New(fieldName.c_str(),-1,-1/*iteration*/,-1/*order*/,std::vector()); + break; + } + case MED_INT32: + { + ret=MEDFileIntField1TSWithoutSDA::New(fieldName.c_str(),-1,-1/*iteration*/,-1/*order*/,std::vector()); + break; + } + default: + { + std::ostringstream oss; oss << "MEDFileAnyTypeField1TS::BuildContentFrom(fileName) : file \'" << fileName << "\' contains field with name \'" << fieldName << "\' but the type of the first field is not in [MED_FLOAT64, MED_INT32] !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } } - std::vector infos(ncomp); - for(int j=0;j()); - _content->getOrCreateAndGetArray()->setInfoAndChangeNbOfCompo(infos); + ret->setDtUnit(dtunit.c_str()); + ret->getOrCreateAndGetArray()->setInfoAndChangeNbOfCompo(infos); // med_int numdt,numit; med_float dt; MEDfieldComputingStepInfo(fid,fieldName.c_str(),1,&numdt,&numit,&dt); - _content->setTime(numdt,numit,dt); - _content->_csit=1; - _content->_field_type=MEDFileUtilities::TraduceFieldType(typcha); - _content->finishLoading(fid); - // + ret->setTime(numdt,numit,dt); + ret->_csit=1; + ret->finishLoading(fid,*((const MEDFileAnyTypeField1TSWithoutSDA*)ret)); + return ret.retn(); +} + +MEDFileAnyTypeField1TS::MEDFileAnyTypeField1TS(const char *fileName) throw(INTERP_KERNEL::Exception) +try:MEDFileFieldGlobsReal(fileName) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + _content=BuildContentFrom(fid,fileName); loadGlobals(fid); } catch(INTERP_KERNEL::Exception& e) @@ -4538,13 +4915,35 @@ catch(INTERP_KERNEL::Exception& e) throw e; } -MEDFileField1TS::MEDFileField1TS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) -try:MEDFileFieldGlobsReal(fileName),_content(MEDFileField1TSWithoutSDA::New(fieldName,-1,-1,-1/*iteration*/,-1/*order*/,std::vector())) +MEDFileAnyTypeField1TSWithoutSDA *MEDFileAnyTypeField1TS::BuildContentFrom(med_idt fid, const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) { - MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); med_field_type typcha; - int nbSteps=locateField(fid,fileName,fieldName,typcha); + std::vector infos; + std::string dtunit; + int iii=-1; + int nbSteps=LocateField(fid,fileName,fieldName,iii,typcha,infos,dtunit); + MEDCouplingAutoRefCountObjectPtr ret; + switch(typcha) + { + case MED_FLOAT64: + { + ret=MEDFileField1TSWithoutSDA::New(fieldName,-1,-1/*iteration*/,-1/*order*/,std::vector()); + break; + } + case MED_INT32: + { + ret=MEDFileIntField1TSWithoutSDA::New(fieldName,-1,-1/*iteration*/,-1/*order*/,std::vector()); + break; + } + default: + { + std::ostringstream oss; oss << "MEDFileAnyTypeField1TS::BuildContentFrom(fileName,fieldName) : file \'" << fileName << "\' contains field with name \'" << fieldName << "\' but the type of field is not in [MED_FLOAT64, MED_INT32] !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + ret->setDtUnit(dtunit.c_str()); + ret->getOrCreateAndGetArray()->setInfoAndChangeNbOfCompo(infos); + // if(nbSteps<1) { std::ostringstream oss; oss << "MEDFileField1TS(fileName,fieldName) : file \'" << fileName << "\' contains field with name \'" << fieldName << "\' but there is no time steps on it !"; @@ -4554,11 +4953,18 @@ try:MEDFileFieldGlobsReal(fileName),_content(MEDFileField1TSWithoutSDA::New(fiel med_int numdt,numit; med_float dt; MEDfieldComputingStepInfo(fid,fieldName,1,&numdt,&numit,&dt); - _content->setTime(numdt,numit,dt); - _content->_csit=1; - _content->_field_type=MEDFileUtilities::TraduceFieldType(typcha); - _content->finishLoading(fid); - // + ret->setTime(numdt,numit,dt); + ret->_csit=1; + ret->finishLoading(fid,*((const MEDFileAnyTypeField1TSWithoutSDA*)ret)); + return ret.retn(); +} + +MEDFileAnyTypeField1TS::MEDFileAnyTypeField1TS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) +try:MEDFileFieldGlobsReal(fileName) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + _content=BuildContentFrom(fid,fileName,fieldName); loadGlobals(fid); } catch(INTERP_KERNEL::Exception& e) @@ -4566,13 +4972,86 @@ catch(INTERP_KERNEL::Exception& e) throw e; } -MEDFileField1TS::MEDFileField1TS(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception) -try:MEDFileFieldGlobsReal(fileName),_content(MEDFileField1TSWithoutSDA::New(fieldName,-1,-1,iteration,order,std::vector())) +MEDFileAnyTypeField1TS *MEDFileAnyTypeField1TS::BuildNewInstanceFromContent(MEDFileAnyTypeField1TSWithoutSDA *c, const char *fileName) throw(INTERP_KERNEL::Exception) +{ + if(!c) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TS::BuildNewInstanceFromContent : empty content in input : unable to build a new instance !"); + if(dynamic_cast(c)) + { + MEDCouplingAutoRefCountObjectPtr ret=MEDFileField1TS::New(); + ret->setFileName(fileName); + ret->_content=c; c->incrRef(); + return ret.retn(); + } + if(dynamic_cast(c)) + { + MEDCouplingAutoRefCountObjectPtr ret=MEDFileIntField1TS::New(); + ret->setFileName(fileName); + ret->_content=c; c->incrRef(); + return ret.retn(); + } + throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TS::BuildNewInstanceFromContent : internal error ! a content of type different from FLOAT64 and INT32 has been built but not intercepted !"); +} + +MEDFileAnyTypeField1TS *MEDFileAnyTypeField1TS::New(const char *fileName) throw(INTERP_KERNEL::Exception) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + MEDCouplingAutoRefCountObjectPtr c=BuildContentFrom(fid,fileName); + MEDCouplingAutoRefCountObjectPtr ret=BuildNewInstanceFromContent(c,fileName); + ret->loadGlobals(fid); + return ret.retn(); +} + +MEDFileAnyTypeField1TS *MEDFileAnyTypeField1TS::New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + MEDCouplingAutoRefCountObjectPtr c=BuildContentFrom(fid,fileName,fieldName); + MEDCouplingAutoRefCountObjectPtr ret=BuildNewInstanceFromContent(c,fileName); + ret->loadGlobals(fid); + return ret.retn(); +} + +MEDFileAnyTypeField1TS *MEDFileAnyTypeField1TS::New(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception) { MEDFileUtilities::CheckFileForRead(fileName); MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + MEDCouplingAutoRefCountObjectPtr c=BuildContentFrom(fid,fileName,fieldName,iteration,order); + MEDCouplingAutoRefCountObjectPtr ret=BuildNewInstanceFromContent(c,fileName); + ret->loadGlobals(fid); + return ret.retn(); +} + +MEDFileAnyTypeField1TSWithoutSDA *MEDFileAnyTypeField1TS::BuildContentFrom(med_idt fid, const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception) +{ med_field_type typcha; - int nbOfStep2=locateField(fid,fileName,fieldName,typcha); + std::vector infos; + std::string dtunit; + int iii=-1; + int nbOfStep2=LocateField(fid,fileName,fieldName,iii,typcha,infos,dtunit); + MEDCouplingAutoRefCountObjectPtr ret; + switch(typcha) + { + case MED_FLOAT64: + { + ret=MEDFileField1TSWithoutSDA::New(fieldName,-1,iteration,order,std::vector()); + break; + } + case MED_INT32: + { + ret=MEDFileIntField1TSWithoutSDA::New(fieldName,-1,iteration,order,std::vector()); + break; + } + default: + { + std::ostringstream oss; oss << "MEDFileAnyTypeField1TS::BuildContentFrom(fileName,fieldName,iteration,order) : file \'" << fileName << "\' contains field with name \'" << fieldName << "\' but the type of field is not in [MED_FLOAT64, MED_INT32] !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + ret->setDtUnit(dtunit.c_str()); + ret->getOrCreateAndGetArray()->setInfoAndChangeNbOfCompo(infos); + // bool found=false; std::vector< std::pair > dtits(nbOfStep2); for(int i=0;i_csit=i+1; - _content->_field_type=MEDFileUtilities::TraduceFieldType(typcha); + ret->_csit=i+1; } else dtits[i]=std::pair(numdt,numit); @@ -4596,8 +5074,16 @@ try:MEDFileFieldGlobsReal(fileName),_content(MEDFileField1TSWithoutSDA::New(fiel oss << "(" << (*iter).first << "," << (*iter).second << "), "; throw INTERP_KERNEL::Exception(oss.str().c_str()); } - _content->finishLoading(fid); - // + ret->finishLoading(fid,*((const MEDFileAnyTypeField1TSWithoutSDA*)ret)); + return ret.retn(); +} + +MEDFileAnyTypeField1TS::MEDFileAnyTypeField1TS(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception) +try:MEDFileFieldGlobsReal(fileName) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + _content=BuildContentFrom(fid,fileName,fieldName,iteration,order); loadGlobals(fid); } catch(INTERP_KERNEL::Exception& e) @@ -4606,24 +5092,51 @@ catch(INTERP_KERNEL::Exception& e) } /*! + * This constructor is a shallow copy constructor. If \a shallowCopyOfContent is true the content of \a other is shallow copied. + * If \a shallowCopyOfContent is false, \a other is taken to be the content of \a this. + * * \warning this is a shallow copy constructor */ -MEDFileField1TS::MEDFileField1TS(const MEDFileField1TSWithoutSDA& other, bool shallowCopyOfContent) +MEDFileAnyTypeField1TS::MEDFileAnyTypeField1TS(const MEDFileAnyTypeField1TSWithoutSDA& other, bool shallowCopyOfContent) { if(!shallowCopyOfContent) { - const MEDFileField1TSWithoutSDA *otherPtr(&other); + const MEDFileAnyTypeField1TSWithoutSDA *otherPtr(&other); otherPtr->incrRef(); - _content=const_cast(otherPtr); + _content=const_cast(otherPtr); } else { - _content=new MEDFileField1TSWithoutSDA(other); + _content=other.shallowCpy(); } } -MEDFileField1TS::MEDFileField1TS():_content(new MEDFileField1TSWithoutSDA) +int MEDFileAnyTypeField1TS::LocateField2(med_idt fid, const char *fileName, int fieldIdCFormat, bool checkFieldId, std::string& fieldName, med_field_type& typcha, std::vector& infos, std::string& dtunitOut) throw(INTERP_KERNEL::Exception) { + if(checkFieldId) + { + int nbFields=MEDnField(fid); + if(fieldIdCFormat>=nbFields) + { + std::ostringstream oss; oss << "MEDFileAnyTypeField1TS::LocateField2(fileName) : in file \'" << fileName << "\' number of fields is " << nbFields << " ! Trying to request for id " << fieldIdCFormat << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + int ncomp=MEDfieldnComponent(fid,fieldIdCFormat+1); + INTERP_KERNEL::AutoPtr comp=MEDLoaderBase::buildEmptyString(ncomp*MED_SNAME_SIZE); + INTERP_KERNEL::AutoPtr unit=MEDLoaderBase::buildEmptyString(ncomp*MED_SNAME_SIZE); + INTERP_KERNEL::AutoPtr dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE); + INTERP_KERNEL::AutoPtr nomcha=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); + INTERP_KERNEL::AutoPtr nomMaa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); + med_bool localMesh; + int nbOfStep; + MEDfieldInfo(fid,fieldIdCFormat+1,nomcha,nomMaa,&localMesh,&typcha,comp,unit,dtunit,&nbOfStep); + fieldName=MEDLoaderBase::buildStringFromFortran(nomcha,MED_NAME_SIZE); + dtunitOut=MEDLoaderBase::buildStringFromFortran(dtunit,MED_LNAME_SIZE); + infos.clear(); infos.resize(ncomp); + for(int j=0;j& infos, std::string& dtunitOut) throw(INTERP_KERNEL::Exception) { int nbFields=MEDnField(fid); bool found=false; @@ -4640,27 +5153,12 @@ int MEDFileField1TS::locateField(med_idt fid, const char *fileName, const char * int nbOfStep2=-1; for(int i=0;i comp=MEDLoaderBase::buildEmptyString(ncomp*MED_SNAME_SIZE); - INTERP_KERNEL::AutoPtr unit=MEDLoaderBase::buildEmptyString(ncomp*MED_SNAME_SIZE); - INTERP_KERNEL::AutoPtr dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE); - INTERP_KERNEL::AutoPtr nomcha=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); - INTERP_KERNEL::AutoPtr nomMaa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); - med_bool localMesh; - int nbOfStep; - MEDfieldInfo(fid,i+1,nomcha,nomMaa,&localMesh,&typcha,comp,unit,dtunit,&nbOfStep); - std::string tmp(nomcha); + std::string tmp; + nbOfStep2=LocateField2(fid,fileName,i,false,tmp,typcha,infos,dtunitOut); fns[i]=tmp; found=(tmp==fieldName); if(found) - { - nbOfStep2=nbOfStep; - std::string mname=MEDLoaderBase::buildStringFromFortran(nomMaa,MED_NAME_SIZE); - std::vector infos(ncomp); - for(int j=0;jgetOrCreateAndGetArray()->setInfoAndChangeNbOfCompo(infos); - } + posCFormat=i; } if(!found) { @@ -4673,1242 +5171,2987 @@ int MEDFileField1TS::locateField(med_idt fid, const char *fileName, const char * } /*! - * This method returns all profiles whose name is non empty used. - * \b WARNING If profile is used several times it will be reported \b only \b once. - * To get non empty name profiles as time as they appear in \b this call MEDFileField1TS::getPflsReallyUsedMulti instead. + * This method as MEDFileField1TSW::setLocNameOnLeaf, is dedicated for advanced user that a want a very fine control on their data structure + * without overhead. This method can be called only regarding information returned by MEDFileField1TSWithoutSDA::getFieldSplitedByType or MEDFileField1TSWithoutSDA::getFieldSplitedByType2. + * This method changes the attribute (here it's profile name) of the leaf datastructure (MEDFileFieldPerMeshPerTypePerDisc instance). + * It is the responsability of the caller to invoke MEDFileFieldGlobs::appendProfile or MEDFileFieldGlobs::getProfile + * to keep a valid instance. + * If \b this do not have any leaf that correspond to the request of the input parameter (\b mName, \b typ, \b locId) an INTERP_KERNEL::Exception will be thrown. + * If \b newPflName profile name does not already exist the profile with old name will be renamed with name \b newPflName. + * If \b newPflName already exists and that \b forceRenameOnGlob is false (the default) an INTERP_KERNEL::Exception will be thrown to avoid big confusion. In this case the called should rename before the profile name with name \b newPflName. + * + * \param [in] mName specifies the underlying mesh name. This value can be pointer 0 for users that do not deal with fields on multi mesh. + * \param [in] typ is for the geometric cell type (or INTERP_KERNEL::NORM_ERROR for node field) entry to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. + * \param [in] locId is the localization id to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. It corresponds to the position of + * \c pfls[std::distance(types.begin(),std::find(types.begin(),typ)] vector in MEDFileField1TSWithoutSDA::getFieldSplitedByType. For non gausspoints field users, the value is 0. + * \param [in] newLocName is the new localization name. + * \param [in] forceRenameOnGlob specifies the behaviour in case of profile \b newPflName already exists. If true, the renaming is done without check. It can lead to major bug. + * If false, an exception will be thrown to force user to change previously the name of the profile with name \b newPflName */ -std::vector MEDFileField1TS::getPflsReallyUsed() const +void MEDFileAnyTypeField1TS::setProfileNameOnLeaf(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId, const char *newPflName, bool forceRenameOnGlob) throw(INTERP_KERNEL::Exception) { - return _content->getPflsReallyUsed2(); + MEDFileFieldPerMeshPerTypePerDisc *disc=getLeafGivenMeshAndTypeAndLocId(mName,typ,locId); + std::string oldPflName=disc->getProfile(); + std::vector vv=getPflsReallyUsedMulti(); + int nbOfOcc=std::count(vv.begin(),vv.end(),oldPflName); + if(forceRenameOnGlob || (!existsPfl(newPflName) && nbOfOcc==1)) + { + disc->setProfile(newPflName); + DataArrayInt *pfl=getProfile(oldPflName.c_str()); + pfl->setName(newPflName); + } + else + { + std::ostringstream oss; oss << "MEDFileField1TS::setProfileNameOnLeaf : Profile \"" << newPflName << "\" already exists or referenced more than one !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } } /*! - * This method returns all localizations whose name is non empty used. - * \b WARNING If localization is used several times it will be reported \b only \b once. + * This method as MEDFileField1TSW::setProfileNameOnLeaf, is dedicated for advanced user that a want a very fine control on their data structure + * without overhead. This method can be called only regarding information returned by MEDFileField1TSWithoutSDA::getFieldSplitedByType or MEDFileField1TSWithoutSDA::getFieldSplitedByType2. + * This method changes the attribute (here it's localization name) of the leaf datastructure (MEDFileFieldPerMeshPerTypePerDisc instance). + * It is the responsability of the caller to invoke MEDFileFieldGlobs::appendProfile or MEDFileFieldGlobs::getProfile + * to keep a valid instance. + * If \b this do not have any leaf that correspond to the request of the input parameter (\b mName, \b typ, \b locId) an INTERP_KERNEL::Exception will be thrown. + * This method is an extension of MEDFileField1TSWithoutSDA::setProfileNameOnLeafExt method because it performs a modification of global info. + * If \b newLocName profile name does not already exist the localization with old name will be renamed with name \b newLocName. + * If \b newLocName already exists an INTERP_KERNEL::Exception will be thrown to avoid big confusion. In this case the called should rename before the profile name with name \b newLocName. + * + * \param [in] mName specifies the underlying mesh name. This value can be pointer 0 for users that do not deal with fields on multi mesh. + * \param [in] typ is for the geometric cell type (or INTERP_KERNEL::NORM_ERROR for node field) entry to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. + * \param [in] locId is the localization id to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. It corresponds to the position of + * \c pfls[std::distance(types.begin(),std::find(types.begin(),typ)] vector in MEDFileField1TSWithoutSDA::getFieldSplitedByType. For non gausspoints field users, the value is 0. + * \param [in] newLocName is the new localization name. + * \param [in] forceRenameOnGlob specifies the behaviour in case of profile \b newLocName already exists. If true, the renaming is done without check. It can lead to major bug. + * If false, an exception will be thrown to force user to change previously the name of the profile with name \b newLocName */ -std::vector MEDFileField1TS::getLocsReallyUsed() const +void MEDFileAnyTypeField1TS::setLocNameOnLeaf(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId, const char *newLocName, bool forceRenameOnGlob) throw(INTERP_KERNEL::Exception) { - return _content->getLocsReallyUsed2(); + MEDFileFieldPerMeshPerTypePerDisc *disc=getLeafGivenMeshAndTypeAndLocId(mName,typ,locId); + std::string oldLocName=disc->getLocalization(); + std::vector vv=getLocsReallyUsedMulti(); + int nbOfOcc=std::count(vv.begin(),vv.end(),oldLocName); + if(forceRenameOnGlob || (!existsLoc(newLocName) && nbOfOcc==1)) + { + disc->setLocalization(newLocName); + MEDFileFieldLoc& loc=getLocalization(oldLocName.c_str()); + loc.setName(newLocName); + } + else + { + std::ostringstream oss; oss << "MEDFileField1TS::setLocNameOnLeaf : Localization \"" << newLocName << "\" already exists or referenced more than one !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } } -/*! - * This method returns all profiles whose name is non empty used. - * \b WARNING contrary to MEDFileField1TS::getPflsReallyUsed, if profile is used several times it will be reported as time as it appears. - */ -std::vector MEDFileField1TS::getPflsReallyUsedMulti() const +MEDFileAnyTypeField1TSWithoutSDA *MEDFileAnyTypeField1TS::contentNotNullBase() throw(INTERP_KERNEL::Exception) { - return _content->getPflsReallyUsedMulti2(); + MEDFileAnyTypeField1TSWithoutSDA *ret=_content; + if(!ret) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TS : content is expected to be not null !"); + return ret; } -/*! - * This method returns all localizations whose name is non empty used. - * \b WARNING contrary to MEDFileField1TS::getLocsReallyUsed if localization is used several times it will be reported as time as it appears. +const MEDFileAnyTypeField1TSWithoutSDA *MEDFileAnyTypeField1TS::contentNotNullBase() const throw(INTERP_KERNEL::Exception) +{ + const MEDFileAnyTypeField1TSWithoutSDA *ret=_content; + if(!ret) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TS : const content is expected to be not null !"); + return ret; +} + +/*! + * Writes \a this field into a MED file specified by its name. + * \param [in] fileName - the MED file name. + * \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics. + * - 2 - erase; an existing file is removed. + * - 1 - append; same data should not be present in an existing file. + * - 0 - overwrite; same data present in an existing file is overwritten. + * \throw If the field name is not set. + * \throw If no field data is set. + * \throw If \a mode == 1 and the same data is present in an existing file. */ -std::vector MEDFileField1TS::getLocsReallyUsedMulti() const +void MEDFileAnyTypeField1TS::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception) { - return _content->getLocsReallyUsedMulti2(); + med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod); + writeLL(fid); } -void MEDFileField1TS::changePflsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) +void MEDFileAnyTypeField1TS::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) { - _content->changePflsRefsNamesGen2(mapOfModif); + int nbComp=getNumberOfComponents(); + INTERP_KERNEL::AutoPtr comp=MEDLoaderBase::buildEmptyString(nbComp*MED_SNAME_SIZE); + INTERP_KERNEL::AutoPtr unit=MEDLoaderBase::buildEmptyString(nbComp*MED_SNAME_SIZE); + for(int i=0;iwriteLL(fid,*this,*contentNotNullBase()); } -void MEDFileField1TS::changeLocsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) +std::size_t MEDFileAnyTypeField1TS::getHeapMemorySize() const { - _content->changeLocsRefsNamesGen2(mapOfModif); + std::size_t ret=0; + if((const MEDFileAnyTypeField1TSWithoutSDA *)_content) + ret+=_content->getHeapMemorySize(); + return ret+MEDFileFieldGlobsReal::getHeapMemorySize(); } /*! - * Returns a new MEDCouplingFieldDouble of a given type lying on - * mesh entities of a given dimension of the first mesh in MED file. If \a this field - * has not been constructed via file reading, an exception is thrown. - * For more info, see \ref AdvMEDLoaderAPIFieldRW - * \param [in] type - a spatial discretization of interest. - * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. - * \param [in] renumPol - specifies how to permute values of the result field according to - * the optional numbers of cells and nodes, if any. The valid values are - * - 0 - do not permute. - * - 1 - permute cells. - * - 2 - permute nodes. - * - 3 - permute cells and nodes. - * - * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The - * caller is to delete this field using decrRef() as it is no more needed. - * \throw If \a this field has not been constructed via file reading. - * \throw If the MED file is not readable. - * \throw If there is no mesh in the MED file. - * \throw If there are no mesh entities of \a meshDimRelToMax dimension in the mesh. - * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. - * \sa getFieldOnMeshAtLevel() + * Returns a string describing \a this field. This string is outputted + * by \c print Python command. */ -MEDCouplingFieldDouble *MEDFileField1TS::getFieldAtLevel(TypeOfField type, int meshDimRelToMax, int renumPol) const throw(INTERP_KERNEL::Exception) +std::string MEDFileAnyTypeField1TS::simpleRepr() const { - if(getFileName2().empty()) - throw INTERP_KERNEL::Exception("MEDFileField1TS::getFieldAtLevel : Request for a method that can be used for instances coming from file loading ! Use getFieldOnMeshAtLevel method instead !"); - return _content->getFieldAtLevel(type,meshDimRelToMax,0,renumPol,this); + std::ostringstream oss; + contentNotNullBase()->simpleRepr(0,oss,-1); + simpleReprGlobs(oss); + return oss.str(); } + /*! - * Returns a new MEDCouplingFieldDouble of a given type lying on - * the top level cells of the first mesh in MED file. If \a this field - * has not been constructed via file reading, an exception is thrown. - * For more info, see \ref AdvMEDLoaderAPIFieldRW - * \param [in] type - a spatial discretization of interest. - * \param [in] renumPol - specifies how to permute values of the result field according to - * the optional numbers of cells and nodes, if any. The valid values are - * - 0 - do not permute. - * - 1 - permute cells. - * - 2 - permute nodes. - * - 3 - permute cells and nodes. - * - * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The - * caller is to delete this field using decrRef() as it is no more needed. - * \throw If \a this field has not been constructed via file reading. - * \throw If the MED file is not readable. - * \throw If there is no mesh in the MED file. - * \throw If no field values of the given \a type. - * \throw If no field values lying on the top level support. - * \sa getFieldAtLevel() + * This method returns all profiles whose name is non empty used. + * \b WARNING If profile is used several times it will be reported \b only \b once. + * To get non empty name profiles as time as they appear in \b this call MEDFileField1TS::getPflsReallyUsedMulti instead. */ -MEDCouplingFieldDouble *MEDFileField1TS::getFieldAtTopLevel(TypeOfField type, int renumPol) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileAnyTypeField1TS::getPflsReallyUsed() const { - if(getFileName2().empty()) - throw INTERP_KERNEL::Exception("MEDFileField1TS::getFieldAtTopLevel : Request for a method that can be used for instances coming from file loading ! Use getFieldOnMeshAtTopLevel method instead !"); - return _content->getFieldAtTopLevel(type,0,renumPol,this); + return contentNotNullBase()->getPflsReallyUsed2(); } - /*! - * Returns a new MEDCouplingFieldDouble of given type lying on a given mesh. - * For more info, see \ref AdvMEDLoaderAPIFieldRW - * \param [in] type - a spatial discretization of the new field. - * \param [in] mesh - the supporting mesh. - * \param [in] renumPol - specifies how to permute values of the result field according to - * the optional numbers of cells and nodes, if any. The valid values are - * - 0 - do not permute. - * - 1 - permute cells. - * - 2 - permute nodes. - * - 3 - permute cells and nodes. - * - * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The - * caller is to delete this field using decrRef() as it is no more needed. - * \throw If no field of \a this is lying on \a mesh. - * \throw If the mesh is empty. - * \throw If no field values of the given \a type are available. - * \sa getFieldAtLevel() - * \sa getFieldOnMeshAtLevel() + * This method returns all localizations whose name is non empty used. + * \b WARNING If localization is used several times it will be reported \b only \b once. */ -MEDCouplingFieldDouble *MEDFileField1TS::getFieldOnMeshAtLevel(TypeOfField type, const MEDCouplingMesh *mesh, int renumPol) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileAnyTypeField1TS::getLocsReallyUsed() const { - return _content->getFieldOnMeshAtLevel(type,renumPol,this,mesh,0,0); + return contentNotNullBase()->getLocsReallyUsed2(); } /*! - * Returns a new MEDCouplingFieldDouble of a given type lying on a given support. - * For more info, see \ref AdvMEDLoaderAPIFieldRW - * \param [in] type - a spatial discretization of interest. - * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. - * \param [in] mesh - the supporting mesh. - * \param [in] renumPol - specifies how to permute values of the result field according to - * the optional numbers of cells and nodes, if any. The valid values are - * - 0 - do not permute. - * - 1 - permute cells. - * - 2 - permute nodes. - * - 3 - permute cells and nodes. - * - * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The - * caller is to delete this field using decrRef() as it is no more needed. - * \throw If there are no mesh entities of \a meshDimRelToMax dimension in the mesh. - * \throw If no field of \a this is lying on \a mesh. - * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. - * \sa getFieldAtLevel() - * \sa getFieldOnMeshAtLevel() + * This method returns all profiles whose name is non empty used. + * \b WARNING contrary to MEDFileField1TS::getPflsReallyUsed, if profile is used several times it will be reported as time as it appears. */ -MEDCouplingFieldDouble *MEDFileField1TS::getFieldOnMeshAtLevel(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, int renumPol) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileAnyTypeField1TS::getPflsReallyUsedMulti() const { - return _content->getFieldOnMeshAtLevel(type,meshDimRelToMax,renumPol,this,mesh); + return contentNotNullBase()->getPflsReallyUsedMulti2(); } /*! - * Returns a new MEDCouplingFieldDouble of a given type lying on a given support. - * This method is called "Old" because in MED3 norm a field has only one meshName - * attached, so this method is for readers of MED2 files. If \a this field - * has not been constructed via file reading, an exception is thrown. - * For more info, see \ref AdvMEDLoaderAPIFieldRW - * \param [in] type - a spatial discretization of interest. - * \param [in] mName - a name of the supporting mesh. - * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. - * \param [in] renumPol - specifies how to permute values of the result field according to - * the optional numbers of cells and nodes, if any. The valid values are - * - 0 - do not permute. - * - 1 - permute cells. - * - 2 - permute nodes. - * - 3 - permute cells and nodes. - * - * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The - * caller is to delete this field using decrRef() as it is no more needed. - * \throw If the MED file is not readable. - * \throw If there is no mesh named \a mName in the MED file. - * \throw If there are no mesh entities of \a meshDimRelToMax dimension in the mesh. - * \throw If \a this field has not been constructed via file reading. - * \throw If no field of \a this is lying on the mesh named \a mName. - * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. - * \sa getFieldAtLevel() + * This method returns all localizations whose name is non empty used. + * \b WARNING contrary to MEDFileField1TS::getLocsReallyUsed if localization is used several times it will be reported as time as it appears. */ -MEDCouplingFieldDouble *MEDFileField1TS::getFieldAtLevelOld(TypeOfField type, const char *mname, int meshDimRelToMax, int renumPol) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileAnyTypeField1TS::getLocsReallyUsedMulti() const { - if(getFileName2().empty()) - throw INTERP_KERNEL::Exception("MEDFileField1TS::getFieldAtLevel : Request for a method that can be used for instances coming from file loading ! Use getFieldOnMeshAtLevel method instead !"); - return _content->getFieldAtLevel(type,meshDimRelToMax,mname,renumPol,this); + return contentNotNullBase()->getLocsReallyUsedMulti2(); } +void MEDFileAnyTypeField1TS::changePflsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) +{ + contentNotNullBase()->changePflsRefsNamesGen2(mapOfModif); +} -/*! - * Returns values and a profile of the field of a given type lying on a given support. - * For more info, see \ref AdvMEDLoaderAPIFieldRW - * \param [in] type - a spatial discretization of the field. - * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. - * \param [in] mesh - the supporting mesh. - * \param [out] pfl - a new instance of DataArrayInt holding ids of mesh entities the - * field of interest lies on. If the field lies on all entities of the given - * dimension, all ids in \a pfl are zero. The caller is to delete this array - * using decrRef() as it is no more needed. - * \return DataArrayDouble * - a new instance of DataArrayDouble holding values of the - * field. The caller is to delete this array using decrRef() as it is no more needed. - * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a mesh. - * \throw If no field of \a this is lying on \a mesh. - * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. - */ -DataArrayDouble *MEDFileField1TS::getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl) const throw(INTERP_KERNEL::Exception) +void MEDFileAnyTypeField1TS::changeLocsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) { - return _content->getFieldWithProfile(type,meshDimRelToMax,mesh,pfl,this); + contentNotNullBase()->changeLocsRefsNamesGen2(mapOfModif); } -/*! - * Adds a MEDCouplingFieldDouble to \a this. The underlying mesh of the given field is - * checked if its elements are sorted suitable for writing to MED file ("STB" stands for - * "Sort By Type"), if not, an exception is thrown. - * For more info, see \ref AdvMEDLoaderAPIFieldRW - * \param [in] field - the field to add to \a this. - * \throw If the name of \a field is empty. - * \throw If the data array of \a field is not set. - * \throw If the data array is already allocated but has different number of components - * than \a field. - * \throw If the underlying mesh of \a field has no name. - * \throw If elements in the mesh are not in the order suitable for writing to the MED file. - */ -void MEDFileField1TS::setFieldNoProfileSBT(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception) +int MEDFileAnyTypeField1TS::getDimension() const { - setFileName(""); - _content->setFieldNoProfileSBT(field,*this); + return contentNotNullBase()->getDimension(); } -/*! - * Adds a MEDCouplingFieldDouble to \a this. Specified entities of a given dimension - * of a given mesh are used as the support of the given field (a real support is not used). - * Elements of the given mesh must be sorted suitable for writing to MED file. - * Order of underlying mesh entities of the given field specified by \a profile parameter - * is not prescribed; this method permutes field values to have them sorted by element - * type as required for writing to MED file. A new profile is added only if no equal - * profile is missing. - * For more info, see \ref AdvMEDLoaderAPIFieldRW - * \param [in] field - the field to add to \a this. - * \param [in] mesh - the supporting mesh of \a field. - * \param [in] meshDimRelToMax - a relative dimension of mesh entities \a field lies on. - * \param [in] profile - ids of mesh entities on which corresponding field values lie. - * \throw If either \a field or \a mesh or \a profile has an empty name. - * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a mesh. - * \throw If the data array of \a field is not set. - * \throw If the data array of \a this is already allocated but has different number of - * components than \a field. - * \throw If elements in \a mesh are not in the order suitable for writing to the MED file. - * \sa setFieldNoProfileSBT() - */ -void MEDFileField1TS::setFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception) +int MEDFileAnyTypeField1TS::getIteration() const { - setFileName(""); - _content->setFieldProfile(field,mesh,meshDimRelToMax,profile,*this); + return contentNotNullBase()->getIteration(); } -/*! - * This method as MEDFileField1TSW::setLocNameOnLeaf, is dedicated for advanced user that a want a very fine control on their data structure - * without overhead. This method can be called only regarding information returned by MEDFileField1TSWithoutSDA::getFieldSplitedByType or MEDFileField1TSWithoutSDA::getFieldSplitedByType2. - * This method changes the attribute (here it's profile name) of the leaf datastructure (MEDFileFieldPerMeshPerTypePerDisc instance). - * It is the responsability of the caller to invoke MEDFileFieldGlobs::appendProfile or MEDFileFieldGlobs::getProfile - * to keep a valid instance. - * If \b this do not have any leaf that correspond to the request of the input parameter (\b mName, \b typ, \b locId) an INTERP_KERNEL::Exception will be thrown. - * If \b newPflName profile name does not already exist the profile with old name will be renamed with name \b newPflName. - * If \b newPflName already exists and that \b forceRenameOnGlob is false (the default) an INTERP_KERNEL::Exception will be thrown to avoid big confusion. In this case the called should rename before the profile name with name \b newPflName. - * - * \param [in] mName specifies the underlying mesh name. This value can be pointer 0 for users that do not deal with fields on multi mesh. - * \param [in] typ is for the geometric cell type (or INTERP_KERNEL::NORM_ERROR for node field) entry to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. - * \param [in] locId is the localization id to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. It corresponds to the position of - * \c pfls[std::distance(types.begin(),std::find(types.begin(),typ)] vector in MEDFileField1TSWithoutSDA::getFieldSplitedByType. For non gausspoints field users, the value is 0. - * \param [in] newLocName is the new localization name. - * \param [in] forceRenameOnGlob specifies the behaviour in case of profile \b newPflName already exists. If true, the renaming is done without check. It can lead to major bug. - * If false, an exception will be thrown to force user to change previously the name of the profile with name \b newPflName - */ -void MEDFileField1TS::setProfileNameOnLeaf(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId, const char *newPflName, bool forceRenameOnGlob) throw(INTERP_KERNEL::Exception) +int MEDFileAnyTypeField1TS::getOrder() const { - MEDFileFieldPerMeshPerTypePerDisc *disc=getLeafGivenMeshAndTypeAndLocId(mName,typ,locId); - std::string oldPflName=disc->getProfile(); - std::vector vv=getPflsReallyUsedMulti(); - int nbOfOcc=std::count(vv.begin(),vv.end(),oldPflName); - if(forceRenameOnGlob || (!existsPfl(newPflName) && nbOfOcc==1)) - { - disc->setProfile(newPflName); - DataArrayInt *pfl=getProfile(oldPflName.c_str()); - pfl->setName(newPflName); - } - else - { - std::ostringstream oss; oss << "MEDFileField1TS::setProfileNameOnLeaf : Profile \"" << newPflName << "\" already exists or referenced more than one !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } + return contentNotNullBase()->getOrder(); } -/*! - * This method as MEDFileField1TSW::setProfileNameOnLeaf, is dedicated for advanced user that a want a very fine control on their data structure - * without overhead. This method can be called only regarding information returned by MEDFileField1TSWithoutSDA::getFieldSplitedByType or MEDFileField1TSWithoutSDA::getFieldSplitedByType2. - * This method changes the attribute (here it's localization name) of the leaf datastructure (MEDFileFieldPerMeshPerTypePerDisc instance). - * It is the responsability of the caller to invoke MEDFileFieldGlobs::appendProfile or MEDFileFieldGlobs::getProfile - * to keep a valid instance. - * If \b this do not have any leaf that correspond to the request of the input parameter (\b mName, \b typ, \b locId) an INTERP_KERNEL::Exception will be thrown. - * This method is an extension of MEDFileField1TSWithoutSDA::setProfileNameOnLeafExt method because it performs a modification of global info. - * If \b newLocName profile name does not already exist the localization with old name will be renamed with name \b newLocName. - * If \b newLocName already exists an INTERP_KERNEL::Exception will be thrown to avoid big confusion. In this case the called should rename before the profile name with name \b newLocName. - * - * \param [in] mName specifies the underlying mesh name. This value can be pointer 0 for users that do not deal with fields on multi mesh. - * \param [in] typ is for the geometric cell type (or INTERP_KERNEL::NORM_ERROR for node field) entry to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. - * \param [in] locId is the localization id to find the right MEDFileFieldPerMeshPerTypePerDisc instance to set. It corresponds to the position of - * \c pfls[std::distance(types.begin(),std::find(types.begin(),typ)] vector in MEDFileField1TSWithoutSDA::getFieldSplitedByType. For non gausspoints field users, the value is 0. - * \param [in] newLocName is the new localization name. - * \param [in] forceRenameOnGlob specifies the behaviour in case of profile \b newLocName already exists. If true, the renaming is done without check. It can lead to major bug. - * If false, an exception will be thrown to force user to change previously the name of the profile with name \b newLocName - */ -void MEDFileField1TS::setLocNameOnLeaf(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId, const char *newLocName, bool forceRenameOnGlob) throw(INTERP_KERNEL::Exception) -{ - MEDFileFieldPerMeshPerTypePerDisc *disc=getLeafGivenMeshAndTypeAndLocId(mName,typ,locId); - std::string oldLocName=disc->getLocalization(); - std::vector vv=getLocsReallyUsedMulti(); - int nbOfOcc=std::count(vv.begin(),vv.end(),oldLocName); - if(forceRenameOnGlob || (!existsLoc(newLocName) && nbOfOcc==1)) - { - disc->setLocalization(newLocName); - MEDFileFieldLoc& loc=getLocalization(oldLocName.c_str()); - loc.setName(newLocName); - } - else - { - std::ostringstream oss; oss << "MEDFileField1TS::setLocNameOnLeaf : Localization \"" << newLocName << "\" already exists or referenced more than one !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } -} - -std::size_t MEDFileField1TS::getHeapMemorySize() const -{ - std::size_t ret=0; - if((const MEDFileField1TSWithoutSDA *)_content) - ret+=_content->getHeapMemorySize(); - return ret+MEDFileFieldGlobsReal::getHeapMemorySize(); -} - -MEDFileField1TS *MEDFileField1TS::deepCpy() const throw(INTERP_KERNEL::Exception) -{ - MEDCouplingAutoRefCountObjectPtr ret=new MEDFileField1TS(*this); - if((const MEDFileField1TSWithoutSDA *)_content) - ret->_content=_content->deepCpy(); - ret->deepCpyGlobs(*this); - return ret.retn(); -} - -int MEDFileField1TS::copyTinyInfoFrom(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception) -{ - return _content->copyTinyInfoFrom(field); -} - -int MEDFileField1TS::getDimension() const -{ - return _content->getDimension(); -} - -int MEDFileField1TS::getIteration() const +double MEDFileAnyTypeField1TS::getTime(int& iteration, int& order) const { - return _content->getIteration(); + return contentNotNullBase()->getTime(iteration,order); } -int MEDFileField1TS::getOrder() const +void MEDFileAnyTypeField1TS::setTime(int iteration, int order, double val) { - return _content->getOrder(); + contentNotNullBase()->setTime(iteration,order,val); } -double MEDFileField1TS::getTime(int& iteration, int& order) const +std::string MEDFileAnyTypeField1TS::getName() const { - return _content->getTime(iteration,order); + return contentNotNullBase()->getName(); } -void MEDFileField1TS::setTime(int iteration, int order, double val) +void MEDFileAnyTypeField1TS::setName(const char *name) { - _content->setTime(iteration,order,val); + contentNotNullBase()->setName(name); } -std::string MEDFileField1TS::getName() const +void MEDFileAnyTypeField1TS::simpleRepr(int bkOffset, std::ostream& oss, int f1tsId) const { - return _content->getName(); + contentNotNullBase()->simpleRepr(bkOffset,oss,f1tsId); } -void MEDFileField1TS::setName(const char *name) +std::string MEDFileAnyTypeField1TS::getDtUnit() const throw(INTERP_KERNEL::Exception) { - _content->setName(name); + return contentNotNullBase()->getDtUnit(); } -void MEDFileField1TS::simpleRepr(int bkOffset, std::ostream& oss, int f1tsId) const +void MEDFileAnyTypeField1TS::setDtUnit(const char *dtUnit) throw(INTERP_KERNEL::Exception) { - _content->simpleRepr(bkOffset,oss,f1tsId); + contentNotNullBase()->setDtUnit(dtUnit); } -const std::string& MEDFileField1TS::getDtUnit() const +std::string MEDFileAnyTypeField1TS::getMeshName() const throw(INTERP_KERNEL::Exception) { - return _content->getDtUnit(); + return contentNotNullBase()->getMeshName(); } -std::string MEDFileField1TS::getMeshName() const throw(INTERP_KERNEL::Exception) +void MEDFileAnyTypeField1TS::setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception) { - return _content->getMeshName(); + contentNotNullBase()->setMeshName(newMeshName); } -void MEDFileField1TS::setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception) +bool MEDFileAnyTypeField1TS::changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception) { - _content->setMeshName(newMeshName); + return contentNotNullBase()->changeMeshNames(modifTab); } -bool MEDFileField1TS::changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception) +int MEDFileAnyTypeField1TS::getMeshIteration() const throw(INTERP_KERNEL::Exception) { - return _content->changeMeshNames(modifTab); + return contentNotNullBase()->getMeshIteration(); } -int MEDFileField1TS::getMeshIteration() const throw(INTERP_KERNEL::Exception) +int MEDFileAnyTypeField1TS::getMeshOrder() const throw(INTERP_KERNEL::Exception) { - return _content->getMeshIteration(); + return contentNotNullBase()->getMeshOrder(); } -int MEDFileField1TS::getMeshOrder() const throw(INTERP_KERNEL::Exception) +int MEDFileAnyTypeField1TS::getNumberOfComponents() const { - return _content->getMeshOrder(); + return contentNotNullBase()->getNumberOfComponents(); } -int MEDFileField1TS::getNumberOfComponents() const +bool MEDFileAnyTypeField1TS::isDealingTS(int iteration, int order) const { - return _content->getNumberOfComponents(); + return contentNotNullBase()->isDealingTS(iteration,order); } -bool MEDFileField1TS::isDealingTS(int iteration, int order) const +std::pair MEDFileAnyTypeField1TS::getDtIt() const { - return _content->isDealingTS(iteration,order); + return contentNotNullBase()->getDtIt(); } -std::pair MEDFileField1TS::getDtIt() const +void MEDFileAnyTypeField1TS::fillIteration(std::pair& p) const { - return _content->getDtIt(); + contentNotNullBase()->fillIteration(p); } -void MEDFileField1TS::fillIteration(std::pair& p) const +void MEDFileAnyTypeField1TS::fillTypesOfFieldAvailable(std::vector& types) const throw(INTERP_KERNEL::Exception) { - _content->fillIteration(p); -} -void MEDFileField1TS::fillTypesOfFieldAvailable(std::vector& types) const throw(INTERP_KERNEL::Exception) -{ - _content->fillTypesOfFieldAvailable(types); + contentNotNullBase()->fillTypesOfFieldAvailable(types); } -const std::vector& MEDFileField1TS::getInfo() const -{ - return _content->getInfo(); -} -std::vector& MEDFileField1TS::getInfo() +void MEDFileAnyTypeField1TS::setInfo(const std::vector& infos) throw(INTERP_KERNEL::Exception) { - return _content->getInfo(); + contentNotNullBase()->setInfo(infos); } -DataArrayDouble *MEDFileField1TS::getUndergroundDataArray() const throw(INTERP_KERNEL::Exception) +const std::vector& MEDFileAnyTypeField1TS::getInfo() const { - return _content->getUndergroundDataArray(); + return contentNotNullBase()->getInfo(); } - -DataArrayDouble *MEDFileField1TS::getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) +std::vector& MEDFileAnyTypeField1TS::getInfo() { - return _content->getUndergroundDataArrayExt(entries); + return contentNotNullBase()->getInfo(); } -MEDFileFieldPerMeshPerTypePerDisc *MEDFileField1TS::getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) throw(INTERP_KERNEL::Exception) +MEDFileFieldPerMeshPerTypePerDisc *MEDFileAnyTypeField1TS::getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) throw(INTERP_KERNEL::Exception) { - return _content->getLeafGivenMeshAndTypeAndLocId(mName,typ,locId); + return contentNotNullBase()->getLeafGivenMeshAndTypeAndLocId(mName,typ,locId); } -const MEDFileFieldPerMeshPerTypePerDisc *MEDFileField1TS::getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) const throw(INTERP_KERNEL::Exception) +const MEDFileFieldPerMeshPerTypePerDisc *MEDFileAnyTypeField1TS::getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) const throw(INTERP_KERNEL::Exception) { - return _content->getLeafGivenMeshAndTypeAndLocId(mName,typ,locId); + return contentNotNullBase()->getLeafGivenMeshAndTypeAndLocId(mName,typ,locId); } -int MEDFileField1TS::getNonEmptyLevels(const char *mname, std::vector& levs) const throw(INTERP_KERNEL::Exception) +int MEDFileAnyTypeField1TS::getNonEmptyLevels(const char *mname, std::vector& levs) const throw(INTERP_KERNEL::Exception) { - return _content->getNonEmptyLevels(mname,levs); + return contentNotNullBase()->getNonEmptyLevels(mname,levs); } -std::vector MEDFileField1TS::getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception) +std::vector MEDFileAnyTypeField1TS::getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception) { - return _content->getTypesOfFieldAvailable(); + return contentNotNullBase()->getTypesOfFieldAvailable(); } -std::vector< std::vector > > MEDFileField1TS::getFieldSplitedByType(const char *mname, std::vector& types, std::vector< std::vector >& typesF, +std::vector< std::vector > > MEDFileAnyTypeField1TS::getFieldSplitedByType(const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) { - return _content->getFieldSplitedByType(mname,types,typesF,pfls,locs); -} -std::vector< std::vector > MEDFileField1TS::getFieldSplitedByType2(const char *mname, std::vector& types, std::vector< std::vector >& typesF, - std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) -{ - return _content->getFieldSplitedByType2(mname,types,typesF,pfls,locs); -} - -MEDFileFieldMultiTSWithoutSDA *MEDFileFieldMultiTSWithoutSDA::New(med_idt fid, const char *fieldName, int id, int ft, const std::vector& infos, int nbOfStep) throw(INTERP_KERNEL::Exception) -{ - return new MEDFileFieldMultiTSWithoutSDA(fid,fieldName,id,ft,infos,nbOfStep); -} - -MEDFileFieldMultiTSWithoutSDA::MEDFileFieldMultiTSWithoutSDA():_field_type(-1) -{ -} - -MEDFileFieldMultiTSWithoutSDA::MEDFileFieldMultiTSWithoutSDA(const char *fieldName):_name(fieldName),_field_type(-1) -{ + return contentNotNullBase()->getFieldSplitedByType(mname,types,typesF,pfls,locs); } /*! - * \param [in] fieldId field id in C mode + * This method returns as MEDFileAnyTypeField1TS new instances as number of components in \a this. + * The returned instances are deep copy of \a this except that for globals that are share with those contained in \a this. + * ** WARNING ** do no forget to rename the ouput instances to avoid to write n-times in the same MED file field ! */ -MEDFileFieldMultiTSWithoutSDA::MEDFileFieldMultiTSWithoutSDA(med_idt fid, int fieldId) throw(INTERP_KERNEL::Exception) -try:_name("") +std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeField1TS > > MEDFileAnyTypeField1TS::splitComponents() const throw(INTERP_KERNEL::Exception) { - med_field_type typcha; - // - int ncomp=MEDfieldnComponent(fid,fieldId+1); - INTERP_KERNEL::AutoPtr comp=MEDLoaderBase::buildEmptyString(ncomp*MED_SNAME_SIZE); - INTERP_KERNEL::AutoPtr unit=MEDLoaderBase::buildEmptyString(ncomp*MED_SNAME_SIZE); - INTERP_KERNEL::AutoPtr dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE); - INTERP_KERNEL::AutoPtr nomcha=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); - INTERP_KERNEL::AutoPtr nomMaa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); - med_bool localMesh; - int nbOfStep; - MEDfieldInfo(fid,fieldId+1,nomcha,nomMaa,&localMesh,&typcha,comp,unit,dtunit,&nbOfStep); - _name=MEDLoaderBase::buildStringFromFortran(nomcha,MED_NAME_SIZE); - _field_type=MEDFileUtilities::TraduceFieldType(typcha); - _infos.resize(ncomp); - for(int j=0;j > contentsSplit=content->splitComponents(); + std::size_t sz(contentsSplit.size()); + std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeField1TS > > ret(sz); + for(std::size_t i=0;i_content=contentsSplit[i]; + } + return ret; } -catch(INTERP_KERNEL::Exception& e) - { - throw e; - } -MEDFileFieldMultiTSWithoutSDA::MEDFileFieldMultiTSWithoutSDA(med_idt fid, const char *fieldName, int id, int ft, const std::vector& infos, int nbOfStep) throw(INTERP_KERNEL::Exception) -try:_name(fieldName),_infos(infos),_field_type(ft) -{ - finishLoading(fid,nbOfStep); -} -catch(INTERP_KERNEL::Exception& e) +MEDFileAnyTypeField1TS *MEDFileAnyTypeField1TS::deepCpy() const throw(INTERP_KERNEL::Exception) { - throw e; + MEDCouplingAutoRefCountObjectPtr ret=shallowCpy(); + if((const MEDFileAnyTypeField1TSWithoutSDA *)_content) + ret->_content=_content->deepCpy(); + ret->deepCpyGlobs(*this); + return ret.retn(); } -std::size_t MEDFileFieldMultiTSWithoutSDA::getHeapMemorySize() const +int MEDFileAnyTypeField1TS::copyTinyInfoFrom(const MEDCouplingFieldDouble *field, const DataArray *arr) throw(INTERP_KERNEL::Exception) { - std::size_t ret=_name.capacity()+_infos.capacity()*sizeof(std::string)+_time_steps.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr); - for(std::vector::const_iterator it=_infos.begin();it!=_infos.end();it++) - ret+=(*it).capacity(); - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++) - if((const MEDFileField1TSWithoutSDA *)(*it)) - ret+=(*it)->getHeapMemorySize(); - return ret; + return contentNotNullBase()->copyTinyInfoFrom(field,arr); } -MEDFileFieldMultiTSWithoutSDA *MEDFileFieldMultiTSWithoutSDA::deepCpy() const throw(INTERP_KERNEL::Exception) -{ - MEDCouplingAutoRefCountObjectPtr ret=new MEDFileFieldMultiTSWithoutSDA(*this); - std::size_t i=0; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++,i++) - { - if((const MEDFileField1TSWithoutSDA *)*it) - ret->_time_steps[i]=(*it)->deepCpy(); - } - return ret.retn(); -} +//= MEDFileField1TS -const std::vector& MEDFileFieldMultiTSWithoutSDA::getInfo() const throw(INTERP_KERNEL::Exception) +/*! + * Returns a new instance of MEDFileField1TS holding data of the first time step of + * the first field that has been read from a specified MED file. + * \param [in] fileName - the name of the MED file to read. + * \return MEDFileField1TS * - a new instance of MEDFileFieldMultiTS. The caller + * is to delete this field using decrRef() as it is no more needed. + * \throw If reading the file fails. + */ +MEDFileField1TS *MEDFileField1TS::New(const char *fileName) throw(INTERP_KERNEL::Exception) { - if(_time_steps.empty()) - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::getInfos : not time steps !"); - return _time_steps[0]->getInfo(); + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileField1TS(fileName); + ret->contentNotNull(); + return ret.retn(); } /*! - * See doc at MEDFileField1TSWithoutSDA::getUndergroundDataArray + * Returns a new instance of MEDFileField1TS holding data of the first time step of + * a given field that has been read from a specified MED file. + * \param [in] fileName - the name of the MED file to read. + * \param [in] fieldName - the name of the field to read. + * \return MEDFileField1TS * - a new instance of MEDFileFieldMultiTS. The caller + * is to delete this field using decrRef() as it is no more needed. + * \throw If reading the file fails. + * \throw If there is no field named \a fieldName in the file. */ -DataArrayDouble *MEDFileFieldMultiTSWithoutSDA::getUndergroundDataArray(int iteration, int order) const throw(INTERP_KERNEL::Exception) +MEDFileField1TS *MEDFileField1TS::New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) { - return getTimeStepEntry(iteration,order).getUndergroundDataArray(); + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileField1TS(fileName,fieldName); + ret->contentNotNull(); + return ret.retn(); } /*! - * See doc at MEDFileField1TSWithoutSDA::getUndergroundDataArrayExt + * Returns a new instance of MEDFileField1TS holding data of a given time step of + * a given field that has been read from a specified MED file. + * \param [in] fileName - the name of the MED file to read. + * \param [in] fieldName - the name of the field to read. + * \param [in] iteration - the iteration number of a required time step. + * \param [in] order - the iteration order number of required time step. + * \return MEDFileField1TS * - a new instance of MEDFileFieldMultiTS. The caller + * is to delete this field using decrRef() as it is no more needed. + * \throw If reading the file fails. + * \throw If there is no field named \a fieldName in the file. + * \throw If the required time step is missing from the file. */ -DataArrayDouble *MEDFileFieldMultiTSWithoutSDA::getUndergroundDataArrayExt(int iteration, int order, std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) +MEDFileField1TS *MEDFileField1TS::New(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception) { - return getTimeStepEntry(iteration,order).getUndergroundDataArrayExt(entries); + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileField1TS(fileName,fieldName,iteration,order); + ret->contentNotNull(); + return ret.retn(); } -std::string MEDFileFieldMultiTSWithoutSDA::getMeshName() const throw(INTERP_KERNEL::Exception) +/*! + * Returns a new instance of MEDFileField1TS. If \a shallowCopyOfContent is true the content of \a other is shallow copied. + * If \a shallowCopyOfContent is false, \a other is taken to be the content of \a this. + * + * Returns a new instance of MEDFileField1TS holding either a shallow copy + * of a given MEDFileField1TSWithoutSDA ( \a other ) or \a other itself. + * \warning this is a shallow copy constructor + * \param [in] other - a MEDFileField1TSWithoutSDA to copy. + * \param [in] shallowCopyOfContent - if \c true, a shallow copy of \a other is created. + * \return MEDFileField1TS * - a new instance of MEDFileField1TS. The caller + * is to delete this field using decrRef() as it is no more needed. + */ +MEDFileField1TS *MEDFileField1TS::New(const MEDFileField1TSWithoutSDA& other, bool shallowCopyOfContent) { - if(_time_steps.empty()) - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::getMeshName : not time steps !"); - return _time_steps[0]->getMeshName(); + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileField1TS(other,shallowCopyOfContent); + ret->contentNotNull(); + return ret.retn(); } -void MEDFileFieldMultiTSWithoutSDA::setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception) +/*! + * Returns a new empty instance of MEDFileField1TS. + * \return MEDFileField1TS * - a new instance of MEDFileField1TS. The caller + * is to delete this field using decrRef() as it is no more needed. + */ +MEDFileField1TS *MEDFileField1TS::New() { - std::string oldName(getMeshName()); - std::vector< std::pair > v(1); - v[0].first=oldName; v[0].second=newMeshName; - changeMeshNames(v); + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileField1TS; + ret->contentNotNull(); + return ret.retn(); } -bool MEDFileFieldMultiTSWithoutSDA::changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception) +const MEDFileField1TSWithoutSDA *MEDFileField1TS::contentNotNull() const throw(INTERP_KERNEL::Exception) { - bool ret=false; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_time_steps.begin();it!=_time_steps.end();it++) - { - MEDFileField1TSWithoutSDA *cur(*it); - if(cur) - ret=cur->changeMeshNames(modifTab) || ret; - } + const MEDFileAnyTypeField1TSWithoutSDA *pt(_content); + if(!pt) + throw INTERP_KERNEL::Exception("MEDFileField1TS::contentNotNull : the content pointer is null !"); + const MEDFileField1TSWithoutSDA *ret=dynamic_cast(pt); + if(!ret) + throw INTERP_KERNEL::Exception("MEDFileField1TS::contentNotNull : the content pointer is not null but it is not of type double ! Reason is maybe that the read field has not the type FLOAT64 !"); return ret; } -bool MEDFileFieldMultiTSWithoutSDA::renumberEntitiesLyingOnMesh(const char *meshName, const std::vector& oldCode, const std::vector& newCode, const DataArrayInt *renumO2N, - MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +MEDFileField1TSWithoutSDA *MEDFileField1TS::contentNotNull() throw(INTERP_KERNEL::Exception) { - bool ret=false; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_time_steps.begin();it!=_time_steps.end();it++) - { - MEDFileField1TSWithoutSDA *f1ts(*it); - if(f1ts) - ret=f1ts->renumberEntitiesLyingOnMesh(meshName,oldCode,newCode,renumO2N,glob) || ret; - } + MEDFileAnyTypeField1TSWithoutSDA *pt(_content); + if(!pt) + throw INTERP_KERNEL::Exception("MEDFileField1TS::contentNotNull : the non const content pointer is null !"); + MEDFileField1TSWithoutSDA *ret=dynamic_cast(pt); + if(!ret) + throw INTERP_KERNEL::Exception("MEDFileField1TS::contentNotNull : the non const content pointer is not null but it is not of type double ! Reason is maybe that the read field has not the type FLOAT64 !"); return ret; } -void MEDFileFieldMultiTSWithoutSDA::appendFieldNoProfileSBT(const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +void MEDFileField1TS::SetDataArrayDoubleInField(MEDCouplingFieldDouble *f, MEDCouplingAutoRefCountObjectPtr& arr) throw(INTERP_KERNEL::Exception) { - if(_time_steps.empty()) - { - MEDCouplingAutoRefCountObjectPtr obj=new MEDFileField1TSWithoutSDA; - obj->setFieldNoProfileSBT(field,glob); - copyTinyInfoFrom(field); - _time_steps.push_back(obj); - } - else - { - checkCoherencyOfTinyInfo(field); - MEDCouplingAutoRefCountObjectPtr obj=new MEDFileField1TSWithoutSDA; - obj->setFieldNoProfileSBT(field,glob); - _time_steps.push_back(obj); - } + if(!f) + throw INTERP_KERNEL::Exception("MEDFileField1TS::SetDataArrayDoubleInField : input field is NULL !"); + if(!((DataArray*)arr)) + throw INTERP_KERNEL::Exception("MEDFileField1TS::SetDataArrayDoubleInField : no array !"); + DataArrayDouble *arrOutC=dynamic_cast((DataArray*)arr); + if(!arrOutC) + throw INTERP_KERNEL::Exception("MEDFileField1TS::SetDataArrayDoubleInField : mismatch between dataArrays type and MEDFileField1TS ! Expected double !"); + f->setArray(arrOutC); } -void MEDFileFieldMultiTSWithoutSDA::appendFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +DataArrayDouble *MEDFileField1TS::ReturnSafelyDataArrayDouble(MEDCouplingAutoRefCountObjectPtr& arr) throw(INTERP_KERNEL::Exception) { - if(_time_steps.empty()) - { - MEDCouplingAutoRefCountObjectPtr obj=new MEDFileField1TSWithoutSDA; - obj->setFieldProfile(field,mesh,meshDimRelToMax,profile,glob); - copyTinyInfoFrom(field); - _time_steps.push_back(obj); - } - else - { - checkCoherencyOfTinyInfo(field); - MEDCouplingAutoRefCountObjectPtr obj=new MEDFileField1TSWithoutSDA; - obj->setFieldProfile(field,mesh,meshDimRelToMax,profile,glob); - _time_steps.push_back(obj); - } + if(!((DataArray*)arr)) + throw INTERP_KERNEL::Exception("MEDFileField1TS::ReturnSafelyDataArrayDouble : no array !"); + DataArrayDouble *arrOutC=dynamic_cast((DataArray*)arr); + if(!arrOutC) + throw INTERP_KERNEL::Exception("MEDFileField1TS::ReturnSafelyDataArrayDouble : mismatch between dataArrays type and MEDFileField1TS ! Expected double !"); + arrOutC->incrRef(); + return arrOutC; } -std::string MEDFileFieldMultiTSWithoutSDA::getDtUnit() const throw(INTERP_KERNEL::Exception) +MEDFileField1TS::MEDFileField1TS(const char *fileName) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeField1TS(fileName) { - if(_time_steps.empty()) - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::getMeshName : not time steps !"); - return _time_steps[0]->getDtUnit(); } +catch(INTERP_KERNEL::Exception& e) + { throw e; } -std::string MEDFileFieldMultiTSWithoutSDA::getName() const +MEDFileField1TS::MEDFileField1TS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeField1TS(fileName,fieldName) { - return _name; } +catch(INTERP_KERNEL::Exception& e) + { throw e; } -void MEDFileFieldMultiTSWithoutSDA::setName(const char *name) +MEDFileField1TS::MEDFileField1TS(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeField1TS(fileName,fieldName,iteration,order) { - _name=name; } +catch(INTERP_KERNEL::Exception& e) + { throw e; } -void MEDFileFieldMultiTSWithoutSDA::simpleRepr(int bkOffset, std::ostream& oss, int fmtsId) const +/*! + * This constructor is a shallow copy constructor. If \a shallowCopyOfContent is true the content of \a other is shallow copied. + * If \a shallowCopyOfContent is false, \a other is taken to be the content of \a this. + * + * \warning this is a shallow copy constructor + */ +MEDFileField1TS::MEDFileField1TS(const MEDFileField1TSWithoutSDA& other, bool shallowCopyOfContent) +try:MEDFileAnyTypeField1TS(other,shallowCopyOfContent) { - std::string startLine(bkOffset,' '); - oss << startLine << "Field multi time steps"; - if(fmtsId>=0) - oss << " (" << fmtsId << ")"; - oss << " has the following name: \"" << _name << "\"." << std::endl; - oss << startLine << "Field multi time steps has " << _infos.size() << " components with the following infos :" << std::endl; - for(std::vector::const_iterator it=_infos.begin();it!=_infos.end();it++) - { - oss << startLine << " - \"" << *it << "\"" << std::endl; - } - int i=0; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++,i++) - { - std::string chapter(17,'0'+i); - oss << startLine << chapter << std::endl; - const MEDFileField1TSWithoutSDA *cur=(*it); - if(cur) - cur->simpleRepr(bkOffset+2,oss,i); - else - oss << startLine << " Field on one time step #" << i << " is not defined !" << std::endl; - oss << startLine << chapter << std::endl; - } } +catch(INTERP_KERNEL::Exception& e) + { throw e; } -std::vector< std::pair > MEDFileFieldMultiTSWithoutSDA::getTimeSteps(std::vector& ret1) const throw(INTERP_KERNEL::Exception) +MEDFileField1TS::MEDFileField1TS() { - std::size_t sz=_time_steps.size(); - std::vector< std::pair > ret(sz); - ret1.resize(sz); - for(std::size_t i=0;igetTime(ret[i].first,ret[i].second); - } - else - { - std::ostringstream oss; oss << "MEDFileFieldMultiTSWithoutSDA::getTimeSteps : At rank #" << i << " time step is not defined. Invoke eraseEmptyTS method !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - } - return ret; + _content=new MEDFileField1TSWithoutSDA; } -void MEDFileFieldMultiTSWithoutSDA::finishLoading(med_idt fid, int nbPdt) throw(INTERP_KERNEL::Exception) -{ - _time_steps.resize(nbPdt); - for(int i=0;i > ts; - med_int numdt=0,numo=0; +/*! + * Returns a new MEDCouplingFieldDouble of a given type lying on + * mesh entities of a given dimension of the first mesh in MED file. If \a this field + * has not been constructed via file reading, an exception is thrown. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of interest. + * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. + * \param [in] renumPol - specifies how to permute values of the result field according to + * the optional numbers of cells and nodes, if any. The valid values are + * - 0 - do not permute. + * - 1 - permute cells. + * - 2 - permute nodes. + * - 3 - permute cells and nodes. + * + * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The + * caller is to delete this field using decrRef() as it is no more needed. + * \throw If \a this field has not been constructed via file reading. + * \throw If the MED file is not readable. + * \throw If there is no mesh in the MED file. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in the mesh. + * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. + * \sa getFieldOnMeshAtLevel() + */ +MEDCouplingFieldDouble *MEDFileField1TS::getFieldAtLevel(TypeOfField type, int meshDimRelToMax, int renumPol) const throw(INTERP_KERNEL::Exception) +{ + if(getFileName2().empty()) + throw INTERP_KERNEL::Exception("MEDFileField1TS::getFieldAtLevel : Request for a method that can be used for instances coming from file loading ! Use getFieldOnMeshAtLevel method instead !"); + MEDCouplingAutoRefCountObjectPtr arrOut; + MEDCouplingAutoRefCountObjectPtr ret=contentNotNull()->getFieldAtLevel(type,meshDimRelToMax,0,renumPol,this,arrOut,*contentNotNull()); + MEDFileField1TS::SetDataArrayDoubleInField(ret,arrOut); + return ret.retn(); +} + +/*! + * Returns a new MEDCouplingFieldDouble of a given type lying on + * the top level cells of the first mesh in MED file. If \a this field + * has not been constructed via file reading, an exception is thrown. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of interest. + * \param [in] renumPol - specifies how to permute values of the result field according to + * the optional numbers of cells and nodes, if any. The valid values are + * - 0 - do not permute. + * - 1 - permute cells. + * - 2 - permute nodes. + * - 3 - permute cells and nodes. + * + * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The + * caller is to delete this field using decrRef() as it is no more needed. + * \throw If \a this field has not been constructed via file reading. + * \throw If the MED file is not readable. + * \throw If there is no mesh in the MED file. + * \throw If no field values of the given \a type. + * \throw If no field values lying on the top level support. + * \sa getFieldAtLevel() + */ +MEDCouplingFieldDouble *MEDFileField1TS::getFieldAtTopLevel(TypeOfField type, int renumPol) const throw(INTERP_KERNEL::Exception) +{ + if(getFileName2().empty()) + throw INTERP_KERNEL::Exception("MEDFileField1TS::getFieldAtTopLevel : Request for a method that can be used for instances coming from file loading ! Use getFieldOnMeshAtTopLevel method instead !"); + MEDCouplingAutoRefCountObjectPtr arrOut; + MEDCouplingAutoRefCountObjectPtr ret=contentNotNull()->getFieldAtTopLevel(type,0,renumPol,this,arrOut,*contentNotNull()); + MEDFileField1TS::SetDataArrayDoubleInField(ret,arrOut); + return ret.retn(); +} + +/*! + * Returns a new MEDCouplingFieldDouble of given type lying on a given mesh. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of the new field. + * \param [in] mesh - the supporting mesh. + * \param [in] renumPol - specifies how to permute values of the result field according to + * the optional numbers of cells and nodes, if any. The valid values are + * - 0 - do not permute. + * - 1 - permute cells. + * - 2 - permute nodes. + * - 3 - permute cells and nodes. + * + * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The + * caller is to delete this field using decrRef() as it is no more needed. + * \throw If no field of \a this is lying on \a mesh. + * \throw If the mesh is empty. + * \throw If no field values of the given \a type are available. + * \sa getFieldAtLevel() + * \sa getFieldOnMeshAtLevel() + */ +MEDCouplingFieldDouble *MEDFileField1TS::getFieldOnMeshAtLevel(TypeOfField type, const MEDCouplingMesh *mesh, int renumPol) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr arrOut; + MEDCouplingAutoRefCountObjectPtr ret=contentNotNull()->getFieldOnMeshAtLevel(type,renumPol,this,mesh,0,0,arrOut,*contentNotNull()); + MEDFileField1TS::SetDataArrayDoubleInField(ret,arrOut); + return ret.retn(); +} + +/*! + * Returns a new MEDCouplingFieldDouble of a given type lying on a given support. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of interest. + * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. + * \param [in] mesh - the supporting mesh. + * \param [in] renumPol - specifies how to permute values of the result field according to + * the optional numbers of cells and nodes, if any. The valid values are + * - 0 - do not permute. + * - 1 - permute cells. + * - 2 - permute nodes. + * - 3 - permute cells and nodes. + * + * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The + * caller is to delete this field using decrRef() as it is no more needed. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in the mesh. + * \throw If no field of \a this is lying on \a mesh. + * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. + * \sa getFieldAtLevel() + * \sa getFieldOnMeshAtLevel() + */ +MEDCouplingFieldDouble *MEDFileField1TS::getFieldOnMeshAtLevel(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, int renumPol) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr arrOut; + MEDCouplingAutoRefCountObjectPtr ret=contentNotNull()->getFieldOnMeshAtLevel(type,meshDimRelToMax,renumPol,this,mesh,arrOut,*contentNotNull()); + MEDFileField1TS::SetDataArrayDoubleInField(ret,arrOut); + return ret.retn(); +} + +/*! + * Returns a new MEDCouplingFieldDouble of a given type lying on a given support. + * This method is called "Old" because in MED3 norm a field has only one meshName + * attached, so this method is for readers of MED2 files. If \a this field + * has not been constructed via file reading, an exception is thrown. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of interest. + * \param [in] mName - a name of the supporting mesh. + * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. + * \param [in] renumPol - specifies how to permute values of the result field according to + * the optional numbers of cells and nodes, if any. The valid values are + * - 0 - do not permute. + * - 1 - permute cells. + * - 2 - permute nodes. + * - 3 - permute cells and nodes. + * + * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The + * caller is to delete this field using decrRef() as it is no more needed. + * \throw If the MED file is not readable. + * \throw If there is no mesh named \a mName in the MED file. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in the mesh. + * \throw If \a this field has not been constructed via file reading. + * \throw If no field of \a this is lying on the mesh named \a mName. + * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. + * \sa getFieldAtLevel() + */ +MEDCouplingFieldDouble *MEDFileField1TS::getFieldAtLevelOld(TypeOfField type, const char *mname, int meshDimRelToMax, int renumPol) const throw(INTERP_KERNEL::Exception) +{ + if(getFileName2().empty()) + throw INTERP_KERNEL::Exception("MEDFileField1TS::getFieldAtLevelOld : Request for a method that can be used for instances coming from file loading ! Use getFieldOnMeshAtLevel method instead !"); + MEDCouplingAutoRefCountObjectPtr arrOut; + MEDCouplingAutoRefCountObjectPtr ret=contentNotNull()->getFieldAtLevel(type,meshDimRelToMax,mname,renumPol,this,arrOut,*contentNotNull()); + MEDFileField1TS::SetDataArrayDoubleInField(ret,arrOut); + return ret.retn(); +} + +/*! + * Returns values and a profile of the field of a given type lying on a given support. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of the field. + * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. + * \param [in] mesh - the supporting mesh. + * \param [out] pfl - a new instance of DataArrayInt holding ids of mesh entities the + * field of interest lies on. If the field lies on all entities of the given + * dimension, all ids in \a pfl are zero. The caller is to delete this array + * using decrRef() as it is no more needed. + * \return DataArrayDouble * - a new instance of DataArrayDouble holding values of the + * field. The caller is to delete this array using decrRef() as it is no more needed. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a mesh. + * \throw If no field of \a this is lying on \a mesh. + * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. + */ +DataArrayDouble *MEDFileField1TS::getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=contentNotNull()->getFieldWithProfile(type,meshDimRelToMax,mesh,pfl,this,*contentNotNull()); + return MEDFileField1TS::ReturnSafelyDataArrayDouble(ret); +} + +/*! + * Adds a MEDCouplingFieldDouble to \a this. The underlying mesh of the given field is + * checked if its elements are sorted suitable for writing to MED file ("STB" stands for + * "Sort By Type"), if not, an exception is thrown. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] field - the field to add to \a this. + * \throw If the name of \a field is empty. + * \throw If the data array of \a field is not set. + * \throw If the data array is already allocated but has different number of components + * than \a field. + * \throw If the underlying mesh of \a field has no name. + * \throw If elements in the mesh are not in the order suitable for writing to the MED file. + */ +void MEDFileField1TS::setFieldNoProfileSBT(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception) +{ + setFileName(""); + contentNotNull()->setFieldNoProfileSBT(field,field->getArray(),*this,*contentNotNull()); +} + +/*! + * Adds a MEDCouplingFieldDouble to \a this. Specified entities of a given dimension + * of a given mesh are used as the support of the given field (a real support is not used). + * Elements of the given mesh must be sorted suitable for writing to MED file. + * Order of underlying mesh entities of the given field specified by \a profile parameter + * is not prescribed; this method permutes field values to have them sorted by element + * type as required for writing to MED file. A new profile is added only if no equal + * profile is missing. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] field - the field to add to \a this. + * \param [in] mesh - the supporting mesh of \a field. + * \param [in] meshDimRelToMax - a relative dimension of mesh entities \a field lies on. + * \param [in] profile - ids of mesh entities on which corresponding field values lie. + * \throw If either \a field or \a mesh or \a profile has an empty name. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a mesh. + * \throw If the data array of \a field is not set. + * \throw If the data array of \a this is already allocated but has different number of + * components than \a field. + * \throw If elements in \a mesh are not in the order suitable for writing to the MED file. + * \sa setFieldNoProfileSBT() + */ +void MEDFileField1TS::setFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception) +{ + setFileName(""); + contentNotNull()->setFieldProfile(field,field->getArray(),mesh,meshDimRelToMax,profile,*this,*contentNotNull()); +} + +MEDFileAnyTypeField1TS *MEDFileField1TS::shallowCpy() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileField1TS(*this); +} + +DataArrayDouble *MEDFileField1TS::getUndergroundDataArray() const throw(INTERP_KERNEL::Exception) +{ + return contentNotNull()->getUndergroundDataArrayDouble(); +} + +DataArrayDouble *MEDFileField1TS::getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) +{ + return contentNotNull()->getUndergroundDataArrayDoubleExt(entries); +} + +std::vector< std::vector > MEDFileField1TS::getFieldSplitedByType2(const char *mname, std::vector& types, std::vector< std::vector >& typesF, + std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) +{ + return contentNotNull()->getFieldSplitedByType2(mname,types,typesF,pfls,locs); +} + +//= MEDFileIntField1TS + +MEDFileIntField1TS *MEDFileIntField1TS::New() +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileIntField1TS; + ret->contentNotNull(); + return ret.retn(); +} + +MEDFileIntField1TS *MEDFileIntField1TS::New(const char *fileName) throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileIntField1TS(fileName); + ret->contentNotNull(); + return ret.retn(); +} + +MEDFileIntField1TS *MEDFileIntField1TS::New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileIntField1TS(fileName,fieldName); + ret->contentNotNull(); + return ret.retn(); +} + +MEDFileIntField1TS *MEDFileIntField1TS::New(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileIntField1TS(fileName,fieldName,iteration,order); + ret->contentNotNull(); + return ret.retn(); +} + +MEDFileIntField1TS *MEDFileIntField1TS::New(const MEDFileIntField1TSWithoutSDA& other, bool shallowCopyOfContent) +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileIntField1TS(other,shallowCopyOfContent); + ret->contentNotNull(); + return ret.retn(); +} + +MEDFileIntField1TS::MEDFileIntField1TS() +{ + _content=new MEDFileIntField1TSWithoutSDA; +} + +MEDFileIntField1TS::MEDFileIntField1TS(const char *fileName) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeField1TS(fileName) +{ +} +catch(INTERP_KERNEL::Exception& e) + { throw e; } + +MEDFileIntField1TS::MEDFileIntField1TS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeField1TS(fileName,fieldName) +{ +} +catch(INTERP_KERNEL::Exception& e) + { throw e; } + +MEDFileIntField1TS::MEDFileIntField1TS(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeField1TS(fileName,fieldName,iteration,order) +{ +} +catch(INTERP_KERNEL::Exception& e) + { throw e; } + +/*! + * This constructor is a shallow copy constructor. If \a shallowCopyOfContent is true the content of \a other is shallow copied. + * If \a shallowCopyOfContent is false, \a other is taken to be the content of \a this. + * + * \warning this is a shallow copy constructor + */ +MEDFileIntField1TS::MEDFileIntField1TS(const MEDFileIntField1TSWithoutSDA& other, bool shallowCopyOfContent):MEDFileAnyTypeField1TS(other,shallowCopyOfContent) +{ +} + +MEDFileAnyTypeField1TS *MEDFileIntField1TS::shallowCpy() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileIntField1TS(*this); +} + +/*! + * Adds a MEDCouplingFieldDouble to \a this. The underlying mesh of the given field is + * checked if its elements are sorted suitable for writing to MED file ("STB" stands for + * "Sort By Type"), if not, an exception is thrown. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] field - the field to add to \a this. The field double values are ignored. + * \param [in] arrOfVals - the values of the field \a field used. + * \throw If the name of \a field is empty. + * \throw If the data array of \a field is not set. + * \throw If the data array is already allocated but has different number of components + * than \a field. + * \throw If the underlying mesh of \a field has no name. + * \throw If elements in the mesh are not in the order suitable for writing to the MED file. + */ +void MEDFileIntField1TS::setFieldNoProfileSBT(const MEDCouplingFieldDouble *field, const DataArrayInt *arrOfVals) throw(INTERP_KERNEL::Exception) +{ + setFileName(""); + contentNotNull()->setFieldNoProfileSBT(field,arrOfVals,*this,*contentNotNull()); +} + +/*! + * Adds a MEDCouplingFieldDouble to \a this. Specified entities of a given dimension + * of a given mesh are used as the support of the given field (a real support is not used). + * Elements of the given mesh must be sorted suitable for writing to MED file. + * Order of underlying mesh entities of the given field specified by \a profile parameter + * is not prescribed; this method permutes field values to have them sorted by element + * type as required for writing to MED file. A new profile is added only if no equal + * profile is missing. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] field - the field to add to \a this. The field double values are ignored. + * \param [in] arrOfVals - the values of the field \a field used. + * \param [in] mesh - the supporting mesh of \a field. + * \param [in] meshDimRelToMax - a relative dimension of mesh entities \a field lies on. + * \param [in] profile - ids of mesh entities on which corresponding field values lie. + * \throw If either \a field or \a mesh or \a profile has an empty name. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a mesh. + * \throw If the data array of \a field is not set. + * \throw If the data array of \a this is already allocated but has different number of + * components than \a field. + * \throw If elements in \a mesh are not in the order suitable for writing to the MED file. + * \sa setFieldNoProfileSBT() + */ +void MEDFileIntField1TS::setFieldProfile(const MEDCouplingFieldDouble *field, const DataArrayInt *arrOfVals, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception) +{ + setFileName(""); + contentNotNull()->setFieldProfile(field,arrOfVals,mesh,meshDimRelToMax,profile,*this,*contentNotNull()); +} + +const MEDFileIntField1TSWithoutSDA *MEDFileIntField1TS::contentNotNull() const throw(INTERP_KERNEL::Exception) +{ + const MEDFileAnyTypeField1TSWithoutSDA *pt(_content); + if(!pt) + throw INTERP_KERNEL::Exception("MEDFileIntField1TS::contentNotNull : the content pointer is null !"); + const MEDFileIntField1TSWithoutSDA *ret=dynamic_cast(pt); + if(!ret) + throw INTERP_KERNEL::Exception("MEDFileIntField1TS::contentNotNull : the content pointer is not null but it is not of type int32 ! Reason is maybe that the read field has not the type INT32 !"); + return ret; +} + +MEDCouplingFieldDouble *MEDFileIntField1TS::getFieldAtLevel(TypeOfField type, int meshDimRelToMax, DataArrayInt* &arrOut, int renumPol) const throw(INTERP_KERNEL::Exception) +{ + if(getFileName2().empty()) + throw INTERP_KERNEL::Exception("MEDFileIntField1TS::getFieldAtLevel : Request for a method that can be used for instances coming from file loading ! Use getFieldOnMeshAtLevel method instead !"); + MEDCouplingAutoRefCountObjectPtr arrOut2; + MEDCouplingAutoRefCountObjectPtr ret=contentNotNull()->getFieldAtLevel(type,meshDimRelToMax,0,renumPol,this,arrOut2,*contentNotNull()); + DataArrayInt *arrOutC=dynamic_cast((DataArray *)arrOut2); + if(!arrOutC) + throw INTERP_KERNEL::Exception("MEDFileIntField1TS::getFieldAtLevelOld : mismatch between dataArrays type and MEDFileIntField1TS ! Expected int32 !"); + arrOut=arrOutC; + return ret.retn(); +} + +DataArrayInt *MEDFileIntField1TS::ReturnSafelyDataArrayInt(MEDCouplingAutoRefCountObjectPtr& arr) throw(INTERP_KERNEL::Exception) +{ + if(!((DataArray *)arr)) + throw INTERP_KERNEL::Exception("MEDFileIntField1TS::ReturnSafelyDataArrayInt : input DataArray is NULL !"); + DataArrayInt *arrC=dynamic_cast((DataArray *)arr); + if(!arrC) + throw INTERP_KERNEL::Exception("MEDFileIntField1TS::ReturnSafelyDataArrayInt : input DataArray is not of type INT32 !"); + arrC->incrRef(); + return arrC; +} + +/*! + * Returns a new MEDCouplingFieldDouble of a given type lying on + * the top level cells of the first mesh in MED file. If \a this field + * has not been constructed via file reading, an exception is thrown. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of interest. + * \param [out] arrOut - the DataArrayInt containing values of field. + * \param [in] renumPol - specifies how to permute values of the result field according to + * the optional numbers of cells and nodes, if any. The valid values are + * - 0 - do not permute. + * - 1 - permute cells. + * - 2 - permute nodes. + * - 3 - permute cells and nodes. + * + * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The + * caller is to delete this field using decrRef() as it is no more needed. + * \throw If \a this field has not been constructed via file reading. + * \throw If the MED file is not readable. + * \throw If there is no mesh in the MED file. + * \throw If no field values of the given \a type. + * \throw If no field values lying on the top level support. + * \sa getFieldAtLevel() + */ +MEDCouplingFieldDouble *MEDFileIntField1TS::getFieldAtTopLevel(TypeOfField type, DataArrayInt* &arrOut, int renumPol) const throw(INTERP_KERNEL::Exception) +{ + if(getFileName2().empty()) + throw INTERP_KERNEL::Exception("MEDFileField1TS::getFieldAtTopLevel : Request for a method that can be used for instances coming from file loading ! Use getFieldOnMeshAtTopLevel method instead !"); + MEDCouplingAutoRefCountObjectPtr arr; + MEDCouplingAutoRefCountObjectPtr ret=contentNotNull()->getFieldAtTopLevel(type,0,renumPol,this,arr,*contentNotNull()); + arrOut=MEDFileIntField1TS::ReturnSafelyDataArrayInt(arr); + return ret.retn(); +} + +/*! + * Returns a new MEDCouplingFieldDouble of given type lying on a given mesh. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of the new field. + * \param [in] mesh - the supporting mesh. + * \param [out] arrOut - the DataArrayInt containing values of field. + * \param [in] renumPol - specifies how to permute values of the result field according to + * the optional numbers of cells and nodes, if any. The valid values are + * - 0 - do not permute. + * - 1 - permute cells. + * - 2 - permute nodes. + * - 3 - permute cells and nodes. + * + * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The + * caller is to delete this field using decrRef() as it is no more needed. + * \throw If no field of \a this is lying on \a mesh. + * \throw If the mesh is empty. + * \throw If no field values of the given \a type are available. + * \sa getFieldAtLevel() + * \sa getFieldOnMeshAtLevel() + */ +MEDCouplingFieldDouble *MEDFileIntField1TS::getFieldOnMeshAtLevel(TypeOfField type, const MEDCouplingMesh *mesh, DataArrayInt* &arrOut, int renumPol) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr arr; + MEDCouplingAutoRefCountObjectPtr ret=contentNotNull()->getFieldOnMeshAtLevel(type,renumPol,this,mesh,0,0,arr,*contentNotNull()); + arrOut=MEDFileIntField1TS::ReturnSafelyDataArrayInt(arr); + return ret.retn(); +} + +/*! + * Returns a new MEDCouplingFieldDouble of a given type lying on a given support. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of interest. + * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. + * \param [out] arrOut - the DataArrayInt containing values of field. + * \param [in] mesh - the supporting mesh. + * \param [in] renumPol - specifies how to permute values of the result field according to + * the optional numbers of cells and nodes, if any. The valid values are + * - 0 - do not permute. + * - 1 - permute cells. + * - 2 - permute nodes. + * - 3 - permute cells and nodes. + * + * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The + * caller is to delete this field using decrRef() as it is no more needed. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in the mesh. + * \throw If no field of \a this is lying on \a mesh. + * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. + * \sa getFieldAtLevel() + * \sa getFieldOnMeshAtLevel() + */ +MEDCouplingFieldDouble *MEDFileIntField1TS::getFieldOnMeshAtLevel(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt* &arrOut, int renumPol) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr arr; + MEDCouplingAutoRefCountObjectPtr ret=contentNotNull()->getFieldOnMeshAtLevel(type,meshDimRelToMax,renumPol,this,mesh,arr,*contentNotNull()); + arrOut=MEDFileIntField1TS::ReturnSafelyDataArrayInt(arr); + return ret.retn(); +} + +/*! + * Returns a new MEDCouplingFieldDouble of a given type lying on a given support. + * This method is called "Old" because in MED3 norm a field has only one meshName + * attached, so this method is for readers of MED2 files. If \a this field + * has not been constructed via file reading, an exception is thrown. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of interest. + * \param [in] mName - a name of the supporting mesh. + * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. + * \param [out] arrOut - the DataArrayInt containing values of field. + * \param [in] renumPol - specifies how to permute values of the result field according to + * the optional numbers of cells and nodes, if any. The valid values are + * - 0 - do not permute. + * - 1 - permute cells. + * - 2 - permute nodes. + * - 3 - permute cells and nodes. + * + * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The + * caller is to delete this field using decrRef() as it is no more needed. + * \throw If the MED file is not readable. + * \throw If there is no mesh named \a mName in the MED file. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in the mesh. + * \throw If \a this field has not been constructed via file reading. + * \throw If no field of \a this is lying on the mesh named \a mName. + * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. + * \sa getFieldAtLevel() + */ +MEDCouplingFieldDouble *MEDFileIntField1TS::getFieldAtLevelOld(TypeOfField type, const char *mname, int meshDimRelToMax, DataArrayInt* &arrOut, int renumPol) const throw(INTERP_KERNEL::Exception) +{ + if(getFileName2().empty()) + throw INTERP_KERNEL::Exception("MEDFileField1TS::getFieldAtLevelOld : Request for a method that can be used for instances coming from file loading ! Use getFieldOnMeshAtLevel method instead !"); + MEDCouplingAutoRefCountObjectPtr arr; + MEDCouplingAutoRefCountObjectPtr ret=contentNotNull()->getFieldAtLevel(type,meshDimRelToMax,mname,renumPol,this,arr,*contentNotNull()); + arrOut=MEDFileIntField1TS::ReturnSafelyDataArrayInt(arr); + return ret.retn(); +} + +/*! + * Returns values and a profile of the field of a given type lying on a given support. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of the field. + * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. + * \param [in] mesh - the supporting mesh. + * \param [out] pfl - a new instance of DataArrayInt holding ids of mesh entities the + * field of interest lies on. If the field lies on all entities of the given + * dimension, all ids in \a pfl are zero. The caller is to delete this array + * using decrRef() as it is no more needed. + * \return DataArrayInt * - a new instance of DataArrayInt holding values of the + * field. The caller is to delete this array using decrRef() as it is no more needed. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a mesh. + * \throw If no field of \a this is lying on \a mesh. + * \throw If no field values of the given \a type or given \a meshDimRelToMax are available. + */ +DataArrayInt *MEDFileIntField1TS::getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr arr=contentNotNull()->getFieldWithProfile(type,meshDimRelToMax,mesh,pfl,this,*contentNotNull()); + return MEDFileIntField1TS::ReturnSafelyDataArrayInt(arr); +} + +MEDFileIntField1TSWithoutSDA *MEDFileIntField1TS::contentNotNull() throw(INTERP_KERNEL::Exception) +{ + MEDFileAnyTypeField1TSWithoutSDA *pt(_content); + if(!pt) + throw INTERP_KERNEL::Exception("MEDFileIntField1TS::contentNotNull : the non const content pointer is null !"); + MEDFileIntField1TSWithoutSDA *ret=dynamic_cast(pt); + if(!ret) + throw INTERP_KERNEL::Exception("MEDFileIntField1TS::contentNotNull : the non const content pointer is not null but it is not of type int32 ! Reason is maybe that the read field has not the type INT32 !"); + return ret; +} + +DataArrayInt *MEDFileIntField1TS::getUndergroundDataArray() const throw(INTERP_KERNEL::Exception) +{ + return contentNotNull()->getUndergroundDataArrayInt(); +} + +//= MEDFileAnyTypeFieldMultiTSWithoutSDA + +MEDFileAnyTypeFieldMultiTSWithoutSDA::MEDFileAnyTypeFieldMultiTSWithoutSDA() +{ +} + +MEDFileAnyTypeFieldMultiTSWithoutSDA::MEDFileAnyTypeFieldMultiTSWithoutSDA(const char *fieldName):MEDFileFieldNameScope(fieldName) +{ +} + +/*! + * \param [in] fieldId field id in C mode + */ +MEDFileAnyTypeFieldMultiTSWithoutSDA::MEDFileAnyTypeFieldMultiTSWithoutSDA(med_idt fid, int fieldId) throw(INTERP_KERNEL::Exception) +{ + med_field_type typcha; + std::string dtunitOut; + int nbOfStep=MEDFileAnyTypeField1TS::LocateField2(fid,"",fieldId,false,_name,typcha,_infos,dtunitOut); + setDtUnit(dtunitOut.c_str()); + finishLoading(fid,nbOfStep,typcha); +} + +MEDFileAnyTypeFieldMultiTSWithoutSDA::MEDFileAnyTypeFieldMultiTSWithoutSDA(med_idt fid, const char *fieldName, med_field_type fieldTyp, const std::vector& infos, int nbOfStep, const std::string& dtunit) throw(INTERP_KERNEL::Exception) +try:MEDFileFieldNameScope(fieldName),_infos(infos) +{ + setDtUnit(dtunit.c_str()); + finishLoading(fid,nbOfStep,fieldTyp); +} +catch(INTERP_KERNEL::Exception& e) +{ + throw e; +} + +std::size_t MEDFileAnyTypeFieldMultiTSWithoutSDA::getHeapMemorySize() const +{ + std::size_t ret=_name.capacity()+_infos.capacity()*sizeof(std::string)+_time_steps.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr); + for(std::vector::const_iterator it=_infos.begin();it!=_infos.end();it++) + ret+=(*it).capacity(); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++) + if((const MEDFileAnyTypeField1TSWithoutSDA *)(*it)) + ret+=(*it)->getHeapMemorySize(); + return ret; +} + +/*! + * If one of the id in [ \a startIds , \a endIds ) points to a null element, there is not throw. Simply, this empty element is added as if it were not + * NULL. + */ +MEDFileAnyTypeFieldMultiTSWithoutSDA *MEDFileAnyTypeFieldMultiTSWithoutSDA::buildFromTimeStepIds(const int *startIds, const int *endIds) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=createNew(); + ret->setInfo(_infos); + int sz=(int)_time_steps.size(); + for(const int *id=startIds;id!=endIds;id++) + { + if(*id>=0 && *id tse2; + if(tse) + { + tse->incrRef(); + tse2=(const_cast(tse)); + } + ret->pushBackTimeStep(tse2); + } + else + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTSWithoutSDA::buildFromTimeStepIds : At pos #" << std::distance(startIds,id) << " value is " << *id; + oss << " ! Should be in [0," << sz << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + if(ret->getNumberOfTS()>0) + ret->synchronizeNameScope(); + ret->copyNameScope(*this); + return ret.retn(); +} + +/*! + * If one of the id in the input range points to a null element, there is not throw. Simply, this empty element is added as if it were not + * NULL. + */ +MEDFileAnyTypeFieldMultiTSWithoutSDA *MEDFileAnyTypeFieldMultiTSWithoutSDA::buildFromTimeStepIds2(int bg, int end, int step) const throw(INTERP_KERNEL::Exception) +{ + static const char msg[]="MEDFileAnyTypeFieldMultiTSWithoutSDA::buildFromTimeStepIds2"; + int nbOfEntriesToKeep=DataArrayInt::GetNumberOfItemGivenBESRelative(bg,end,step,msg); + MEDCouplingAutoRefCountObjectPtr ret=createNew(); + ret->setInfo(_infos); + int sz=(int)_time_steps.size(); + int j=bg; + for(int i=0;i=0 && j tse2; + if(tse) + { + tse->incrRef(); + tse2=(const_cast(tse)); + } + ret->pushBackTimeStep(tse2); + } + else + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTSWithoutSDA::buildFromTimeStepIds : At pos #" << i << " value is " << j; + oss << " ! Should be in [0," << sz << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + if(ret->getNumberOfTS()>0) + ret->synchronizeNameScope(); + ret->copyNameScope(*this); + return ret.retn(); +} + +MEDFileAnyTypeFieldMultiTSWithoutSDA *MEDFileAnyTypeFieldMultiTSWithoutSDA::partOfThisLyingOnSpecifiedTimeSteps(const std::vector< std::pair >& timeSteps) const throw(INTERP_KERNEL::Exception) +{ + int id=0; + MEDCouplingAutoRefCountObjectPtr ids=DataArrayInt::New(); ids->alloc(0,1); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++,id++) + { + const MEDFileAnyTypeField1TSWithoutSDA *cur(*it); + if(!cur) + continue; + std::pair p(cur->getIteration(),cur->getOrder()); + if(std::find(timeSteps.begin(),timeSteps.end(),p)!=timeSteps.end()) + ids->pushBackSilent(id); + } + return buildFromTimeStepIds(ids->begin(),ids->end()); +} + +MEDFileAnyTypeFieldMultiTSWithoutSDA *MEDFileAnyTypeFieldMultiTSWithoutSDA::partOfThisNotLyingOnSpecifiedTimeSteps(const std::vector< std::pair >& timeSteps) const throw(INTERP_KERNEL::Exception) +{ + int id=0; + MEDCouplingAutoRefCountObjectPtr ids=DataArrayInt::New(); ids->alloc(0,1); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++,id++) + { + const MEDFileAnyTypeField1TSWithoutSDA *cur(*it); + if(!cur) + continue; + std::pair p(cur->getIteration(),cur->getOrder()); + if(std::find(timeSteps.begin(),timeSteps.end(),p)==timeSteps.end()) + ids->pushBackSilent(id); + } + return buildFromTimeStepIds(ids->begin(),ids->end()); +} + +const std::vector& MEDFileAnyTypeFieldMultiTSWithoutSDA::getInfo() const throw(INTERP_KERNEL::Exception) +{ + return _infos; +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::setInfo(const std::vector& info) throw(INTERP_KERNEL::Exception) +{ + _infos=info; +} + +int MEDFileAnyTypeFieldMultiTSWithoutSDA::getTimeStepPos(int iteration, int order) const throw(INTERP_KERNEL::Exception) +{ + int ret=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++,ret++) + { + const MEDFileAnyTypeField1TSWithoutSDA *pt(*it); + if(pt->isDealingTS(iteration,order)) + return ret; + } + std::ostringstream oss; oss << "MEDFileFieldMultiTS::getTimeStepPos : Muli timestep field on time (" << iteration << "," << order << ") does not exist ! Available (iteration,order) are :\n"; + std::vector< std::pair > vp=getIterations(); + for(std::vector< std::pair >::const_iterator it2=vp.begin();it2!=vp.end();it2++) + oss << "(" << (*it2).first << "," << (*it2).second << ") "; + throw INTERP_KERNEL::Exception(oss.str().c_str()); +} + +const MEDFileAnyTypeField1TSWithoutSDA& MEDFileAnyTypeFieldMultiTSWithoutSDA::getTimeStepEntry(int iteration, int order) const throw(INTERP_KERNEL::Exception) +{ + return *_time_steps[getTimeStepPos(iteration,order)]; +} + +MEDFileAnyTypeField1TSWithoutSDA& MEDFileAnyTypeFieldMultiTSWithoutSDA::getTimeStepEntry(int iteration, int order) throw(INTERP_KERNEL::Exception) +{ + return *_time_steps[getTimeStepPos(iteration,order)]; +} + +std::string MEDFileAnyTypeFieldMultiTSWithoutSDA::getMeshName() const throw(INTERP_KERNEL::Exception) +{ + if(_time_steps.empty()) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::getMeshName : not time steps !"); + return _time_steps[0]->getMeshName(); +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception) +{ + std::string oldName(getMeshName()); + std::vector< std::pair > v(1); + v[0].first=oldName; v[0].second=newMeshName; + changeMeshNames(v); +} + +bool MEDFileAnyTypeFieldMultiTSWithoutSDA::changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception) +{ + bool ret=false; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_time_steps.begin();it!=_time_steps.end();it++) + { + MEDFileAnyTypeField1TSWithoutSDA *cur(*it); + if(cur) + ret=cur->changeMeshNames(modifTab) || ret; + } + return ret; +} + +/*! + * See doc at MEDFileField1TSWithoutSDA::getUndergroundDataArray + */ +DataArray *MEDFileAnyTypeFieldMultiTSWithoutSDA::getUndergroundDataArray(int iteration, int order) const throw(INTERP_KERNEL::Exception) +{ + return getTimeStepEntry(iteration,order).getUndergroundDataArray(); +} + +/*! + * See doc at MEDFileField1TSWithoutSDA::getUndergroundDataArrayExt + */ +DataArray *MEDFileAnyTypeFieldMultiTSWithoutSDA::getUndergroundDataArrayExt(int iteration, int order, std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) +{ + return getTimeStepEntry(iteration,order).getUndergroundDataArrayExt(entries); +} + +bool MEDFileAnyTypeFieldMultiTSWithoutSDA::renumberEntitiesLyingOnMesh(const char *meshName, const std::vector& oldCode, const std::vector& newCode, const DataArrayInt *renumO2N, + MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +{ + bool ret=false; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_time_steps.begin();it!=_time_steps.end();it++) + { + MEDFileAnyTypeField1TSWithoutSDA *f1ts(*it); + if(f1ts) + ret=f1ts->renumberEntitiesLyingOnMesh(meshName,oldCode,newCode,renumO2N,glob) || ret; + } + return ret; +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::simpleRepr(int bkOffset, std::ostream& oss, int fmtsId) const +{ + std::string startLine(bkOffset,' '); + oss << startLine << "Field multi time steps [Type=" << getTypeStr() << "]"; + if(fmtsId>=0) + oss << " (" << fmtsId << ")"; + oss << " has the following name: \"" << _name << "\"." << std::endl; + oss << startLine << "Field multi time steps has " << _infos.size() << " components with the following infos :" << std::endl; + for(std::vector::const_iterator it=_infos.begin();it!=_infos.end();it++) + { + oss << startLine << " - \"" << *it << "\"" << std::endl; + } + int i=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++,i++) + { + std::string chapter(17,'0'+i); + oss << startLine << chapter << std::endl; + const MEDFileAnyTypeField1TSWithoutSDA *cur=(*it); + if(cur) + cur->simpleRepr(bkOffset+2,oss,i); + else + oss << startLine << " Field on one time step #" << i << " is not defined !" << std::endl; + oss << startLine << chapter << std::endl; + } +} + +std::vector< std::pair > MEDFileAnyTypeFieldMultiTSWithoutSDA::getTimeSteps(std::vector& ret1) const throw(INTERP_KERNEL::Exception) +{ + std::size_t sz=_time_steps.size(); + std::vector< std::pair > ret(sz); + ret1.resize(sz); + for(std::size_t i=0;igetTime(ret[i].first,ret[i].second); + } + else + { + std::ostringstream oss; oss << "MEDFileFieldMultiTSWithoutSDA::getTimeSteps : At rank #" << i << " time step is not defined. Invoke eraseEmptyTS method !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + return ret; +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::pushBackTimeStep(MEDCouplingAutoRefCountObjectPtr& tse) throw(INTERP_KERNEL::Exception) +{ + MEDFileAnyTypeField1TSWithoutSDA *tse2(tse); + if(!tse2) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTSWithoutSDA::pushBackTimeStep : input content object is null !"); + checkCoherencyOfType(tse2); + if(_time_steps.empty()) + { + setName(tse2->getName().c_str()); + setInfo(tse2->getInfo()); + } + checkThatComponentsMatch(tse2->getInfo()); + _time_steps.push_back(tse); +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::synchronizeNameScope() throw(INTERP_KERNEL::Exception) +{ + std::size_t nbOfCompo=_infos.size(); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_time_steps.begin();it!=_time_steps.end();it++) + { + MEDFileAnyTypeField1TSWithoutSDA *cur=(*it); + if(cur) + { + if((cur->getInfo()).size()!=nbOfCompo) + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTSWithoutSDA::synchronizeNameScope : Mismatch in the number of components of parts ! Should be " << nbOfCompo; + oss << " ! but the field at iteration=" << cur->getIteration() << " order=" << cur->getOrder() << " has " << (cur->getInfo()).size() << " components !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + cur->copyNameScope(*this); + } + } +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::finishLoading(med_idt fid, int nbPdt, med_field_type fieldTyp) throw(INTERP_KERNEL::Exception) +{ + _time_steps.resize(nbPdt); + for(int i=0;i > ts; + med_int numdt=0,numo=0; med_int meshIt=0,meshOrder=0; med_float dt=0.0; MEDfieldComputingStepMeshInfo(fid,_name.c_str(),i+1,&numdt,&numo,&dt,&meshIt,&meshOrder); - _time_steps[i]=MEDFileField1TSWithoutSDA::New(_name.c_str(),i+1,_field_type,numdt,numo,_infos); - _time_steps[i]->finishLoading(fid); + switch(fieldTyp) + { + case MED_FLOAT64: + { + _time_steps[i]=MEDFileField1TSWithoutSDA::New(_name.c_str(),i+1,numdt,numo,_infos); + break; + } + case MED_INT32: + { + _time_steps[i]=MEDFileIntField1TSWithoutSDA::New(_name.c_str(),i+1,numdt,numo,_infos); + break; + } + default: + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTSWithoutSDA::finishLoading : managed field type are : FLOAT64, INT32 !"); + } + _time_steps[i]->finishLoading(fid,*this); + } +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::writeLL(med_idt fid, const MEDFileWritable& opts) const throw(INTERP_KERNEL::Exception) +{ + if(_time_steps.empty()) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::writeLL : no time steps set !"); + checkThatNbOfCompoOfTSMatchThis(); + std::vector infos(getInfo()); + int nbComp=infos.size(); + INTERP_KERNEL::AutoPtr comp=MEDLoaderBase::buildEmptyString(nbComp*MED_SNAME_SIZE); + INTERP_KERNEL::AutoPtr unit=MEDLoaderBase::buildEmptyString(nbComp*MED_SNAME_SIZE); + for(int i=0;iwriteLL(fid,opts,*this); +} + +int MEDFileAnyTypeFieldMultiTSWithoutSDA::getNumberOfTS() const +{ + return _time_steps.size(); +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::eraseEmptyTS() throw(INTERP_KERNEL::Exception) +{ + std::vector< MEDCouplingAutoRefCountObjectPtr > newTS; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++) + { + const MEDFileAnyTypeField1TSWithoutSDA *tmp=(*it); + if(tmp) + newTS.push_back(*it); + } + _time_steps=newTS; +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::eraseTimeStepIds(const int *startIds, const int *endIds) throw(INTERP_KERNEL::Exception) +{ + std::vector< MEDCouplingAutoRefCountObjectPtr > newTS; + int maxId=(int)_time_steps.size(); + int ii=0; + std::set idsToDel; + for(const int *id=startIds;id!=endIds;id++,ii++) + { + if(*id>=0 && *id b(sz,true); + int j=bg; + for(int i=0;i > newTS; + for(std::size_t i=0;i >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++,ret++) + { + const MEDFileAnyTypeField1TSWithoutSDA *tmp(*it); + if(tmp) + { + int it2,ord; + tmp->getTime(it2,ord); + if(it2==iteration && order==ord) + return ret; + else + oss << "(" << it2 << "," << ord << "), "; + } + } + throw INTERP_KERNEL::Exception(oss.str().c_str()); +} + +int MEDFileAnyTypeFieldMultiTSWithoutSDA::getPosGivenTime(double time, double eps) const throw(INTERP_KERNEL::Exception) +{ + int ret=0; + std::ostringstream oss; oss << "MEDFileFieldMultiTSWithoutSDA::getPosGivenTime : No such time step " << time << "! \nPossibilities are : "; + oss.precision(15); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++,ret++) + { + const MEDFileAnyTypeField1TSWithoutSDA *tmp(*it); + if(tmp) + { + int it2,ord; + double ti=tmp->getTime(it2,ord); + if(fabs(time-ti) > MEDFileAnyTypeFieldMultiTSWithoutSDA::getIterations() const +{ + int lgth=_time_steps.size(); + std::vector< std::pair > ret(lgth); + for(int i=0;ifillIteration(ret[i]); + return ret; +} + +/*! + * This method has 3 inputs 'iteration' 'order' 'mname'. 'mname' can be null if the user is the general case where there is only one meshName lying on 'this' + * This method returns two things. + * - The absolute dimension of 'this' in first parameter. + * - The available ext levels relative to the absolute dimension returned in first parameter. These relative levels are relative + * to the first output parameter. The values in 'levs' will be returned in decreasing order. + * + * This method is designed for MEDFileFieldMultiTS instances that have a discritization ON_CELLS, ON_GAUSS_NE and ON_GAUSS. + * Only these 3 discretizations will be taken into account here. + * + * If 'this' is empty this method will throw an INTERP_KERNEL::Exception. + * If there is \b only node fields defined in 'this' -1 is returned and 'levs' output parameter will be empty. In this + * case the caller has to know the underlying mesh it refers to. By defaut it is the level 0 of the corresponding mesh. + * + * This method is usefull to make the link between meshDimension of the underlying mesh in 'this' and the levels on 'this'. + * It is possible (even if it is not common) that the highest level in 'this' were not equal to the meshDimension of the underlying mesh in 'this'. + * + * Let's consider the typical following case : + * - a mesh 'm1' has a meshDimension 3 and has the following non empty levels + * [0,-1,-2] for example 'm1' lies on TETRA4, HEXA8 TRI3 and SEG2 + * - 'f1' lies on 'm1' and is defined on 3D and 1D cells for example + * TETRA4 and SEG2 + * - 'f2' lies on 'm1' too and is defined on 2D and 1D cells for example TRI3 and SEG2 + * + * In this case f1->getNonEmptyLevelsExt will return (3,[0,-2]) and f2->getNonEmptyLevelsExt will return (2,[0,-1]) + * + * To retrieve the highest level of f1 it should be done, f1->getFieldAtLevel(ON_CELLS,3-3+0);//absDim-meshDim+relativeLev + * To retrieve the lowest level of f1 it should be done, f1->getFieldAtLevel(ON_CELLS,3-3+(-2));//absDim-meshDim+relativeLev + * To retrieve the highest level of f2 it should be done, f1->getFieldAtLevel(ON_CELLS,2-3+0);//absDim-meshDim+relativeLev + * To retrieve the lowest level of f2 it should be done, f1->getFieldAtLevel(ON_CELLS,2-3+(-1));//absDim-meshDim+relativeLev + */ +int MEDFileAnyTypeFieldMultiTSWithoutSDA::getNonEmptyLevels(int iteration, int order, const char *mname, std::vector& levs) const throw(INTERP_KERNEL::Exception) +{ + return getTimeStepEntry(iteration,order).getNonEmptyLevels(mname,levs); +} + +const MEDFileAnyTypeField1TSWithoutSDA *MEDFileAnyTypeFieldMultiTSWithoutSDA::getTimeStepAtPos2(int pos) const throw(INTERP_KERNEL::Exception) +{ + if(pos<0 || pos>=(int)_time_steps.size()) + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTSWithoutSDA::getTimeStepAtPos2 : request for pos #" << pos << " whereas should be in [0," << _time_steps.size() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + const MEDFileAnyTypeField1TSWithoutSDA *item=_time_steps[pos]; + if(item==0) + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTSWithoutSDA::getTimeStepAtPos2 : request for pos #" << pos << ", this pos id exists but the underlying Field1TS is null !"; + oss << "\nTry to use following method eraseEmptyTS !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + return item; +} + +MEDFileAnyTypeField1TSWithoutSDA *MEDFileAnyTypeFieldMultiTSWithoutSDA::getTimeStepAtPos2(int pos) throw(INTERP_KERNEL::Exception) +{ + if(pos<0 || pos>=(int)_time_steps.size()) + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTSWithoutSDA::getTimeStepAtPos2 : request for pos #" << pos << " whereas should be in [0," << _time_steps.size() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + MEDFileAnyTypeField1TSWithoutSDA *item=_time_steps[pos]; + if(item==0) + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTSWithoutSDA::getTimeStepAtPos2 : request for pos #" << pos << ", this pos id exists but the underlying Field1TS is null !"; + oss << "\nTry to use following method eraseEmptyTS !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + return item; +} + +std::vector MEDFileAnyTypeFieldMultiTSWithoutSDA::getPflsReallyUsed2() const +{ + std::vector ret; + std::set ret2; + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeField1TSWithoutSDA > >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++) + { + std::vector tmp=(*it)->getPflsReallyUsed2(); + for(std::vector::const_iterator it2=tmp.begin();it2!=tmp.end();it2++) + if(ret2.find(*it2)==ret2.end()) + { + ret.push_back(*it2); + ret2.insert(*it2); + } + } + return ret; +} + +std::vector MEDFileAnyTypeFieldMultiTSWithoutSDA::getLocsReallyUsed2() const +{ + std::vector ret; + std::set ret2; + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeField1TSWithoutSDA > >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++) + { + std::vector tmp=(*it)->getLocsReallyUsed2(); + for(std::vector::const_iterator it2=tmp.begin();it2!=tmp.end();it2++) + if(ret2.find(*it2)==ret2.end()) + { + ret.push_back(*it2); + ret2.insert(*it2); + } + } + return ret; +} + +std::vector MEDFileAnyTypeFieldMultiTSWithoutSDA::getPflsReallyUsedMulti2() const +{ + std::vector ret; + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeField1TSWithoutSDA > >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++) + { + std::vector tmp=(*it)->getPflsReallyUsedMulti2(); + ret.insert(ret.end(),tmp.begin(),tmp.end()); + } + return ret; +} + +std::vector MEDFileAnyTypeFieldMultiTSWithoutSDA::getLocsReallyUsedMulti2() const +{ + std::vector ret; + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeField1TSWithoutSDA > >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++) + { + std::vector tmp=(*it)->getLocsReallyUsedMulti2(); + ret.insert(ret.end(),tmp.begin(),tmp.end()); + } + return ret; +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::changePflsRefsNamesGen2(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) +{ + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeField1TSWithoutSDA > >::iterator it=_time_steps.begin();it!=_time_steps.end();it++) + (*it)->changePflsRefsNamesGen2(mapOfModif); +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::changeLocsRefsNamesGen2(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) +{ + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeField1TSWithoutSDA > >::iterator it=_time_steps.begin();it!=_time_steps.end();it++) + (*it)->changeLocsRefsNamesGen2(mapOfModif); +} + +std::vector< std::vector > MEDFileAnyTypeFieldMultiTSWithoutSDA::getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception) +{ + int lgth=_time_steps.size(); + std::vector< std::vector > ret(lgth); + for(int i=0;ifillTypesOfFieldAvailable(ret[i]); + return ret; +} + +/*! + * entry point for users that want to iterate into MEDFile DataStructure without any overhead. + */ +std::vector< std::vector< std::pair > > MEDFileAnyTypeFieldMultiTSWithoutSDA::getFieldSplitedByType(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) +{ + return getTimeStepEntry(iteration,order).getFieldSplitedByType(mname,types,typesF,pfls,locs); +} + +MEDFileAnyTypeFieldMultiTSWithoutSDA *MEDFileAnyTypeFieldMultiTSWithoutSDA::deepCpy() const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=shallowCpy(); + std::size_t i=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++,i++) + { + if((const MEDFileAnyTypeField1TSWithoutSDA *)*it) + ret->_time_steps[i]=(*it)->deepCpy(); + } + return ret.retn(); +} + +std::vector< MEDCouplingAutoRefCountObjectPtr > MEDFileAnyTypeFieldMultiTSWithoutSDA::splitComponents() const throw(INTERP_KERNEL::Exception) +{ + std::size_t sz(_infos.size()),sz2(_time_steps.size()); + std::vector< MEDCouplingAutoRefCountObjectPtr > ret(sz); + std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr > > ts(sz2); + for(std::size_t i=0;i_infos.resize(1); ret[i]->_infos[0]=_infos[i]; + } + for(std::size_t i=0;i > ret1=_time_steps[i]->splitComponents(); + if(ret1.size()!=sz) + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTSWithoutSDA::splitComponents : At rank #" << i << " number of components is " << ret1.size() << " whereas it should be for all time steps " << sz << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + ts[i]=ret1; + } + for(std::size_t i=0;i_time_steps[j]=ts[j][i]; + return ret; +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::copyTinyInfoFrom(const MEDCouplingFieldDouble *field, const DataArray *arr) throw(INTERP_KERNEL::Exception) +{ + _name=field->getName(); + if(_name.empty()) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::copyTinyInfoFrom : unsupported fields with no name in MED file !"); + if(!arr) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::copyTinyInfoFrom : no array set !"); + _infos=arr->getInfoOnComponents(); +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::checkCoherencyOfTinyInfo(const MEDCouplingFieldDouble *field, const DataArray *arr) const throw(INTERP_KERNEL::Exception) +{ + static const char MSG[]="MEDFileFieldMultiTSWithoutSDA::checkCoherencyOfTinyInfo : invalid "; + if(_name!=field->getName()) + { + std::ostringstream oss; oss << MSG << "name ! should be \"" << _name; + oss << "\" and it is set in input field to \"" << field->getName() << "\" !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + if(!arr) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::checkCoherencyOfTinyInfo : no array set !"); + checkThatComponentsMatch(arr->getInfoOnComponents()); +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::checkThatComponentsMatch(const std::vector& compos) const throw(INTERP_KERNEL::Exception) +{ + static const char MSG[]="MEDFileFieldMultiTSWithoutSDA::checkThatComponentsMatch : "; + if(getInfo().size()!=compos.size()) + { + std::ostringstream oss; oss << MSG << "mismatch of number of components between this (" << getInfo().size() << ") and "; + oss << " number of components of element to append (" << compos.size() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + if(_infos!=compos) + { + std::ostringstream oss; oss << MSG << "components have same size but are different ! should be \""; + std::copy(_infos.begin(),_infos.end(),std::ostream_iterator(oss,", ")); + oss << " But compo in input fields are : "; + std::copy(compos.begin(),compos.end(),std::ostream_iterator(oss,", ")); + oss << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::checkThatNbOfCompoOfTSMatchThis() const throw(INTERP_KERNEL::Exception) +{ + std::size_t sz=_infos.size(); + int j=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++,j++) + { + const MEDFileAnyTypeField1TSWithoutSDA *elt(*it); + if(elt) + if(elt->getInfo().size()!=sz) + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTSWithoutSDA::checkThatNbOfCompoOfTSMatchThis : At pos #" << j << " the number of components is equal to "; + oss << elt->getInfo().size() << " whereas it is expected to be equal to " << sz << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::appendFieldNoProfileSBT(const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +{ + if(!field) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTSWithoutSDA::appendFieldNoProfileSBT : input field is NULL !"); + if(!_time_steps.empty()) + checkCoherencyOfTinyInfo(field,arr); + MEDFileAnyTypeField1TSWithoutSDA *objC=createNew1TSWithoutSDAEmptyInstance(); + MEDCouplingAutoRefCountObjectPtr obj(objC); + objC->setFieldNoProfileSBT(field,arr,glob,*this); + copyTinyInfoFrom(field,arr); + _time_steps.push_back(obj); +} + +void MEDFileAnyTypeFieldMultiTSWithoutSDA::appendFieldProfile(const MEDCouplingFieldDouble *field, const DataArray *arr, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception) +{ + if(!field) + throw INTERP_KERNEL::Exception("MEDFileIntFieldMultiTSWithoutSDA::appendFieldNoProfileSBT : input field is NULL !"); + if(!_time_steps.empty()) + checkCoherencyOfTinyInfo(field,arr); + MEDFileField1TSWithoutSDA *objC=new MEDFileField1TSWithoutSDA; + MEDCouplingAutoRefCountObjectPtr obj(objC); + objC->setFieldProfile(field,arr,mesh,meshDimRelToMax,profile,glob,*this); + copyTinyInfoFrom(field,arr); + _time_steps.push_back(obj); +} + +//= MEDFileFieldMultiTSWithoutSDA + +MEDFileFieldMultiTSWithoutSDA *MEDFileFieldMultiTSWithoutSDA::New(med_idt fid, const char *fieldName, med_field_type fieldTyp, const std::vector& infos, int nbOfStep, const std::string& dtunit) throw(INTERP_KERNEL::Exception) +{ + return new MEDFileFieldMultiTSWithoutSDA(fid,fieldName,fieldTyp,infos,nbOfStep,dtunit); +} + +MEDFileFieldMultiTSWithoutSDA::MEDFileFieldMultiTSWithoutSDA() +{ +} + +MEDFileFieldMultiTSWithoutSDA::MEDFileFieldMultiTSWithoutSDA(const char *fieldName):MEDFileAnyTypeFieldMultiTSWithoutSDA(fieldName) +{ +} + +/*! + * \param [in] fieldId field id in C mode + */ +MEDFileFieldMultiTSWithoutSDA::MEDFileFieldMultiTSWithoutSDA(med_idt fid, int fieldId) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeFieldMultiTSWithoutSDA(fid,fieldId) +{ +} +catch(INTERP_KERNEL::Exception& e) + { throw e; } + +MEDFileFieldMultiTSWithoutSDA::MEDFileFieldMultiTSWithoutSDA(med_idt fid, const char *fieldName, med_field_type fieldTyp, const std::vector& infos, int nbOfStep, const std::string& dtunit) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeFieldMultiTSWithoutSDA(fid,fieldName,fieldTyp,infos,nbOfStep,dtunit) +{ +} +catch(INTERP_KERNEL::Exception& e) +{ throw e; } + +MEDFileAnyTypeField1TSWithoutSDA *MEDFileFieldMultiTSWithoutSDA::createNew1TSWithoutSDAEmptyInstance() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileField1TSWithoutSDA; +} + +void MEDFileFieldMultiTSWithoutSDA::checkCoherencyOfType(const MEDFileAnyTypeField1TSWithoutSDA *f1ts) const throw(INTERP_KERNEL::Exception) +{ + if(!f1ts) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::checkCoherencyOfType : input field1TS is NULL ! Impossible to check !"); + const MEDFileField1TSWithoutSDA *f1tsC=dynamic_cast(f1ts); + if(!f1tsC) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::checkCoherencyOfType : the input field1TS is not a FLOAT64 type !"); +} + +const char *MEDFileFieldMultiTSWithoutSDA::getTypeStr() const throw(INTERP_KERNEL::Exception) +{ + return MEDFileField1TSWithoutSDA::TYPE_STR; +} + +MEDFileAnyTypeFieldMultiTSWithoutSDA *MEDFileFieldMultiTSWithoutSDA::shallowCpy() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileFieldMultiTSWithoutSDA(*this); +} + +MEDFileAnyTypeFieldMultiTSWithoutSDA *MEDFileFieldMultiTSWithoutSDA::createNew() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileFieldMultiTSWithoutSDA; +} + +/*! + * entry point for users that want to iterate into MEDFile DataStructure with a reduced overhead because output arrays are extracted (created) specially + * for the call of this method. That's why the DataArrayDouble instance in returned vector of vector should be dealed by the caller. + */ +std::vector< std::vector > MEDFileFieldMultiTSWithoutSDA::getFieldSplitedByType2(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) +{ + const MEDFileAnyTypeField1TSWithoutSDA& myF1TS=getTimeStepEntry(iteration,order); + const MEDFileField1TSWithoutSDA *myF1TSC=dynamic_cast(&myF1TS); + if(!myF1TSC) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::getFieldSplitedByType2 : mismatch of type of field expecting FLOAT64 !"); + return myF1TSC->getFieldSplitedByType2(mname,types,typesF,pfls,locs); +} + +MEDFileAnyTypeFieldMultiTS::MEDFileAnyTypeFieldMultiTS() +{ +} + +MEDFileAnyTypeFieldMultiTS::MEDFileAnyTypeFieldMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception) +try:MEDFileFieldGlobsReal(fileName) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + _content=BuildContentFrom(fid,fileName); + loadGlobals(fid); +} +catch(INTERP_KERNEL::Exception& e) + { + throw e; + } + +MEDFileAnyTypeFieldMultiTSWithoutSDA *MEDFileAnyTypeFieldMultiTS::BuildContentFrom(med_idt fid, const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) +{ + med_field_type typcha; + std::vector infos; + std::string dtunit; + int i=-1; + MEDFileAnyTypeField1TS::LocateField(fid,fileName,fieldName,i,typcha,infos,dtunit); + MEDCouplingAutoRefCountObjectPtr ret; + switch(typcha) + { + case MED_FLOAT64: + { + ret=new MEDFileFieldMultiTSWithoutSDA(fid,i); + break; + } + case MED_INT32: + { + ret=new MEDFileIntFieldMultiTSWithoutSDA(fid,i); + break; + } + default: + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTS::BuildContentFrom(fileName,fieldName) : file \'" << fileName << "\' contains field with name \'" << fieldName << "\' but the type of field is not in [MED_FLOAT64, MED_INT32] !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + ret->setDtUnit(dtunit.c_str()); + return ret.retn(); +} + +MEDFileAnyTypeFieldMultiTSWithoutSDA *MEDFileAnyTypeFieldMultiTS::BuildContentFrom(med_idt fid, const char *fileName) throw(INTERP_KERNEL::Exception) +{ + med_field_type typcha; + // + std::vector infos; + std::string dtunit,fieldName; + MEDFileAnyTypeField1TS::LocateField2(fid,fileName,0,true,fieldName,typcha,infos,dtunit); + MEDCouplingAutoRefCountObjectPtr ret; + switch(typcha) + { + case MED_FLOAT64: + { + ret=new MEDFileFieldMultiTSWithoutSDA(fid,0); + break; + } + case MED_INT32: + { + ret=new MEDFileIntFieldMultiTSWithoutSDA(fid,0); + break; + } + default: + { + std::ostringstream oss; oss << "MEDFileAnyTypeFieldMultiTS::BuildContentFrom(fileName) : file \'" << fileName << "\' contains field with name \'" << fieldName << "\' but the type of the first field is not in [MED_FLOAT64, MED_INT32] !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + ret->setDtUnit(dtunit.c_str()); + return ret.retn(); +} + +MEDFileAnyTypeFieldMultiTS *MEDFileAnyTypeFieldMultiTS::BuildNewInstanceFromContent(MEDFileAnyTypeFieldMultiTSWithoutSDA *c, const char *fileName) throw(INTERP_KERNEL::Exception) +{ + if(!c) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::BuildNewInstanceFromContent : empty content in input : unable to build a new instance !"); + if(dynamic_cast(c)) + { + MEDCouplingAutoRefCountObjectPtr ret=MEDFileFieldMultiTS::New(); + ret->setFileName(fileName); + ret->_content=c; c->incrRef(); + return ret.retn(); + } + if(dynamic_cast(c)) + { + MEDCouplingAutoRefCountObjectPtr ret=MEDFileIntFieldMultiTS::New(); + ret->setFileName(fileName); + ret->_content=c; c->incrRef(); + return ret.retn(); + } + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::BuildNewInstanceFromContent : internal error ! a content of type different from FLOAT64 and INT32 has been built but not intercepted !"); +} + +MEDFileAnyTypeFieldMultiTS::MEDFileAnyTypeFieldMultiTS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) +try:MEDFileFieldGlobsReal(fileName) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + _content=BuildContentFrom(fid,fileName,fieldName); + loadGlobals(fid); +} +catch(INTERP_KERNEL::Exception& e) + { + throw e; + } + +//= MEDFileIntFieldMultiTSWithoutSDA + +MEDFileIntFieldMultiTSWithoutSDA *MEDFileIntFieldMultiTSWithoutSDA::New(med_idt fid, const char *fieldName, med_field_type fieldTyp, const std::vector& infos, int nbOfStep, const std::string& dtunit) throw(INTERP_KERNEL::Exception) +{ + return new MEDFileIntFieldMultiTSWithoutSDA(fid,fieldName,fieldTyp,infos,nbOfStep,dtunit); +} + +MEDFileIntFieldMultiTSWithoutSDA::MEDFileIntFieldMultiTSWithoutSDA() +{ +} + +MEDFileIntFieldMultiTSWithoutSDA::MEDFileIntFieldMultiTSWithoutSDA(const char *fieldName):MEDFileAnyTypeFieldMultiTSWithoutSDA(fieldName) +{ +} + +MEDFileIntFieldMultiTSWithoutSDA::MEDFileIntFieldMultiTSWithoutSDA(med_idt fid, const char *fieldName, med_field_type fieldTyp, const std::vector& infos, int nbOfStep, const std::string& dtunit) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeFieldMultiTSWithoutSDA(fid,fieldName,fieldTyp,infos,nbOfStep,dtunit) +{ +} +catch(INTERP_KERNEL::Exception& e) +{ throw e; } + +/*! + * \param [in] fieldId field id in C mode + */ +MEDFileIntFieldMultiTSWithoutSDA::MEDFileIntFieldMultiTSWithoutSDA(med_idt fid, int fieldId) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeFieldMultiTSWithoutSDA(fid,fieldId) +{ +} +catch(INTERP_KERNEL::Exception& e) + { throw e; } + +MEDFileAnyTypeField1TSWithoutSDA *MEDFileIntFieldMultiTSWithoutSDA::createNew1TSWithoutSDAEmptyInstance() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileIntField1TSWithoutSDA; +} + +void MEDFileIntFieldMultiTSWithoutSDA::checkCoherencyOfType(const MEDFileAnyTypeField1TSWithoutSDA *f1ts) const throw(INTERP_KERNEL::Exception) +{ + if(!f1ts) + throw INTERP_KERNEL::Exception("MEDFileIntFieldMultiTSWithoutSDA::checkCoherencyOfType : input field1TS is NULL ! Impossible to check !"); + const MEDFileIntField1TSWithoutSDA *f1tsC=dynamic_cast(f1ts); + if(!f1tsC) + throw INTERP_KERNEL::Exception("MEDFileIntFieldMultiTSWithoutSDA::checkCoherencyOfType : the input field1TS is not a INT32 type !"); +} + +const char *MEDFileIntFieldMultiTSWithoutSDA::getTypeStr() const throw(INTERP_KERNEL::Exception) +{ + return MEDFileIntField1TSWithoutSDA::TYPE_STR; +} + +MEDFileAnyTypeFieldMultiTSWithoutSDA *MEDFileIntFieldMultiTSWithoutSDA::shallowCpy() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileIntFieldMultiTSWithoutSDA(*this); +} + +MEDFileAnyTypeFieldMultiTSWithoutSDA *MEDFileIntFieldMultiTSWithoutSDA::createNew() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileIntFieldMultiTSWithoutSDA; +} + +//= MEDFileAnyTypeFieldMultiTS + +/*! + * Returns a new instance of MEDFileFieldMultiTS or MEDFileIntFieldMultiTS holding data of the first field + * that has been read from a specified MED file. + * \param [in] fileName - the name of the MED file to read. + * \return MEDFileFieldMultiTS * - a new instance of MEDFileFieldMultiTS or MEDFileIntFieldMultiTS. The caller + * is to delete this field using decrRef() as it is no more needed. + * \throw If reading the file fails. + */ +MEDFileAnyTypeFieldMultiTS *MEDFileAnyTypeFieldMultiTS::New(const char *fileName) throw(INTERP_KERNEL::Exception) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + MEDCouplingAutoRefCountObjectPtr c=BuildContentFrom(fid,fileName); + MEDCouplingAutoRefCountObjectPtr ret=BuildNewInstanceFromContent(c,fileName); + ret->loadGlobals(fid); + return ret.retn(); +} + +/*! + * Returns a new instance of MEDFileFieldMultiTS or MEDFileIntFieldMultiTS holding data of a given field + * that has been read from a specified MED file. + * \param [in] fileName - the name of the MED file to read. + * \param [in] fieldName - the name of the field to read. + * \return MEDFileFieldMultiTS * - a new instance of MEDFileFieldMultiTS or MEDFileIntFieldMultiTS. The caller + * is to delete this field using decrRef() as it is no more needed. + * \throw If reading the file fails. + * \throw If there is no field named \a fieldName in the file. + */ +MEDFileAnyTypeFieldMultiTS *MEDFileAnyTypeFieldMultiTS::New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + MEDCouplingAutoRefCountObjectPtr c=BuildContentFrom(fid,fileName,fieldName); + MEDCouplingAutoRefCountObjectPtr ret=BuildNewInstanceFromContent(c,fileName); + ret->loadGlobals(fid); + return ret.retn(); +} + +/*! + * This constructor is a shallow copy constructor. If \a shallowCopyOfContent is true the content of \a other is shallow copied. + * If \a shallowCopyOfContent is false, \a other is taken to be the content of \a this. + * + * \warning this is a shallow copy constructor + */ +MEDFileAnyTypeFieldMultiTS::MEDFileAnyTypeFieldMultiTS(const MEDFileAnyTypeFieldMultiTSWithoutSDA& other, bool shallowCopyOfContent) +{ + if(!shallowCopyOfContent) + { + const MEDFileAnyTypeFieldMultiTSWithoutSDA *otherPtr(&other); + otherPtr->incrRef(); + _content=const_cast(otherPtr); + } + else + { + _content=other.shallowCpy(); } } -void MEDFileFieldMultiTSWithoutSDA::copyTinyInfoFrom(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception) +MEDFileAnyTypeFieldMultiTSWithoutSDA *MEDFileAnyTypeFieldMultiTS::contentNotNullBase() throw(INTERP_KERNEL::Exception) { - _name=field->getName(); - if(_name.empty()) - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::copyTinyInfoFrom : unsupported fields with no name in MED file !"); - const DataArrayDouble *arr=field->getArray(); - if(!arr) - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::copyTinyInfoFrom : no array set !"); - _infos=arr->getInfoOnComponents(); + MEDFileAnyTypeFieldMultiTSWithoutSDA *ret=_content; + if(!ret) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS : content is expected to be not null !"); + return ret; +} + +const MEDFileAnyTypeFieldMultiTSWithoutSDA *MEDFileAnyTypeFieldMultiTS::contentNotNullBase() const throw(INTERP_KERNEL::Exception) +{ + const MEDFileAnyTypeFieldMultiTSWithoutSDA *ret=_content; + if(!ret) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS : const content is expected to be not null !"); + return ret; +} + +std::vector MEDFileAnyTypeFieldMultiTS::getPflsReallyUsed() const +{ + return contentNotNullBase()->getPflsReallyUsed2(); +} + +std::vector MEDFileAnyTypeFieldMultiTS::getLocsReallyUsed() const +{ + return contentNotNullBase()->getLocsReallyUsed2(); +} + +std::vector MEDFileAnyTypeFieldMultiTS::getPflsReallyUsedMulti() const +{ + return contentNotNullBase()->getPflsReallyUsedMulti2(); +} + +std::vector MEDFileAnyTypeFieldMultiTS::getLocsReallyUsedMulti() const +{ + return contentNotNullBase()->getLocsReallyUsedMulti2(); +} + +void MEDFileAnyTypeFieldMultiTS::changePflsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) +{ + contentNotNullBase()->changePflsRefsNamesGen2(mapOfModif); +} + +void MEDFileAnyTypeFieldMultiTS::changeLocsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) +{ + contentNotNullBase()->changeLocsRefsNamesGen2(mapOfModif); +} + +int MEDFileAnyTypeFieldMultiTS::getNumberOfTS() const +{ + return contentNotNullBase()->getNumberOfTS(); +} + +void MEDFileAnyTypeFieldMultiTS::eraseEmptyTS() throw(INTERP_KERNEL::Exception) +{ + contentNotNullBase()->eraseEmptyTS(); +} + +void MEDFileAnyTypeFieldMultiTS::eraseTimeStepIds(const int *startIds, const int *endIds) throw(INTERP_KERNEL::Exception) +{ + contentNotNullBase()->eraseTimeStepIds(startIds,endIds); +} + +void MEDFileAnyTypeFieldMultiTS::eraseTimeStepIds2(int bg, int end, int step) throw(INTERP_KERNEL::Exception) +{ + contentNotNullBase()->eraseTimeStepIds2(bg,end,step); +} + +MEDFileAnyTypeFieldMultiTS *MEDFileAnyTypeFieldMultiTS::buildSubPart(const int *startIds, const int *endIds) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr c=contentNotNullBase()->buildFromTimeStepIds(startIds,endIds); + MEDCouplingAutoRefCountObjectPtr ret=shallowCpy(); + ret->_content=c; + return ret.retn(); +} + +MEDFileAnyTypeFieldMultiTS *MEDFileAnyTypeFieldMultiTS::buildSubPartSlice(int bg, int end, int step) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr c=contentNotNullBase()->buildFromTimeStepIds2(bg,end,step); + MEDCouplingAutoRefCountObjectPtr ret=shallowCpy(); + ret->_content=c; + return ret.retn(); +} + +std::vector< std::pair > MEDFileAnyTypeFieldMultiTS::getIterations() const +{ + return contentNotNullBase()->getIterations(); +} + +void MEDFileAnyTypeFieldMultiTS::pushBackTimeSteps(const std::vector& f1ts) throw(INTERP_KERNEL::Exception) +{ + for(std::vector::const_iterator it=f1ts.begin();it!=f1ts.end();it++) + pushBackTimeStep(*it); +} + +void MEDFileAnyTypeFieldMultiTS::pushBackTimeStep(MEDFileAnyTypeField1TS *f1ts) throw(INTERP_KERNEL::Exception) +{ + if(!f1ts) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTSWithoutSDA::pushBackTimeStep : input pointer is NULL !"); + checkCoherencyOfType(f1ts); + f1ts->incrRef(); + MEDCouplingAutoRefCountObjectPtr f1tsSafe(f1ts); + MEDFileAnyTypeField1TSWithoutSDA *c=f1ts->contentNotNullBase(); + c->incrRef(); + MEDCouplingAutoRefCountObjectPtr cSafe(c); + if(!((MEDFileAnyTypeFieldMultiTSWithoutSDA *)_content)) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTSWithoutSDA::pushBackTimeStep : no content in this !"); + _content->pushBackTimeStep(cSafe); + appendGlobs(*f1ts,1e-12); +} + +void MEDFileAnyTypeFieldMultiTS::synchronizeNameScope() throw(INTERP_KERNEL::Exception) +{ + contentNotNullBase()->synchronizeNameScope(); +} + +int MEDFileAnyTypeFieldMultiTS::getPosOfTimeStep(int iteration, int order) const throw(INTERP_KERNEL::Exception) +{ + return contentNotNullBase()->getPosOfTimeStep(iteration,order); +} + +int MEDFileAnyTypeFieldMultiTS::getPosGivenTime(double time, double eps) const throw(INTERP_KERNEL::Exception) +{ + return contentNotNullBase()->getPosGivenTime(time,eps); +} + +int MEDFileAnyTypeFieldMultiTS::getNonEmptyLevels(int iteration, int order, const char *mname, std::vector& levs) const throw(INTERP_KERNEL::Exception) +{ + return contentNotNullBase()->getNonEmptyLevels(iteration,order,mname,levs); +} + +std::vector< std::vector > MEDFileAnyTypeFieldMultiTS::getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception) +{ + return contentNotNullBase()->getTypesOfFieldAvailable(); +} + +std::vector< std::vector< std::pair > > MEDFileAnyTypeFieldMultiTS::getFieldSplitedByType(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) +{ + return contentNotNullBase()->getFieldSplitedByType(iteration,order,mname,types,typesF,pfls,locs); +} + +std::string MEDFileAnyTypeFieldMultiTS::getName() const +{ + return contentNotNullBase()->getName(); +} + +void MEDFileAnyTypeFieldMultiTS::setName(const char *name) +{ + contentNotNullBase()->setName(name); +} + +std::string MEDFileAnyTypeFieldMultiTS::getDtUnit() const throw(INTERP_KERNEL::Exception) +{ + return contentNotNullBase()->getDtUnit(); +} + +void MEDFileAnyTypeFieldMultiTS::setDtUnit(const char *dtUnit) throw(INTERP_KERNEL::Exception) +{ + contentNotNullBase()->setDtUnit(dtUnit); +} + +void MEDFileAnyTypeFieldMultiTS::simpleRepr(int bkOffset, std::ostream& oss, int fmtsId) const +{ + contentNotNullBase()->simpleRepr(bkOffset,oss,fmtsId); +} + +std::vector< std::pair > MEDFileAnyTypeFieldMultiTS::getTimeSteps(std::vector& ret1) const throw(INTERP_KERNEL::Exception) +{ + return contentNotNullBase()->getTimeSteps(ret1); +} + +std::string MEDFileAnyTypeFieldMultiTS::getMeshName() const throw(INTERP_KERNEL::Exception) +{ + return contentNotNullBase()->getMeshName(); +} + +void MEDFileAnyTypeFieldMultiTS::setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception) +{ + contentNotNullBase()->setMeshName(newMeshName); +} + +bool MEDFileAnyTypeFieldMultiTS::changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception) +{ + return contentNotNullBase()->changeMeshNames(modifTab); +} + +const std::vector& MEDFileAnyTypeFieldMultiTS::getInfo() const throw(INTERP_KERNEL::Exception) +{ + return contentNotNullBase()->getInfo(); +} + +void MEDFileAnyTypeFieldMultiTS::setInfo(const std::vector& info) throw(INTERP_KERNEL::Exception) +{ + return contentNotNullBase()->setInfo(info); +} + +int MEDFileAnyTypeFieldMultiTS::getNumberOfComponents() const throw(INTERP_KERNEL::Exception) +{ + const std::vector ret=getInfo(); + return (int)ret.size(); +} + +void MEDFileAnyTypeFieldMultiTS::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) +{ + writeGlobals(fid,*this); + contentNotNullBase()->writeLL(fid,*this); +} + +/*! + * Writes \a this field into a MED file specified by its name. + * \param [in] fileName - the MED file name. + * \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics. + * - 2 - erase; an existing file is removed. + * - 1 - append; same data should not be present in an existing file. + * - 0 - overwrite; same data present in an existing file is overwritten. + * \throw If the field name is not set. + * \throw If no field data is set. + * \throw If \a mode == 1 and the same data is present in an existing file. + */ +void MEDFileAnyTypeFieldMultiTS::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception) +{ + med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod); + writeLL(fid); +} + +std::string MEDFileAnyTypeFieldMultiTS::simpleRepr() const +{ + std::ostringstream oss; + contentNotNullBase()->simpleRepr(0,oss,-1); + simpleReprGlobs(oss); + return oss.str(); +} + +std::size_t MEDFileAnyTypeFieldMultiTS::getHeapMemorySize() const +{ + std::size_t ret=0; + if((const MEDFileAnyTypeFieldMultiTSWithoutSDA*)_content) + ret+=_content->getHeapMemorySize(); + return ret+MEDFileFieldGlobsReal::getHeapMemorySize(); +} + +/*! + * This method returns as MEDFileAnyTypeField1TS new instances as number of components in \a this. + * The returned instances are deep copy of \a this except that for globals that are share with those contained in \a this. + * ** WARNING ** do no forget to rename the ouput instances to avoid to write n-times in the same MED file field ! + */ +std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeFieldMultiTS > > MEDFileAnyTypeFieldMultiTS::splitComponents() const throw(INTERP_KERNEL::Exception) +{ + const MEDFileAnyTypeFieldMultiTSWithoutSDA *content(_content); + if(!content) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::splitComponents : no content in this ! Unable to split components !"); + std::vector< MEDCouplingAutoRefCountObjectPtr > contentsSplit=content->splitComponents(); + std::size_t sz(contentsSplit.size()); + std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeFieldMultiTS > > ret(sz); + for(std::size_t i=0;i_content=contentsSplit[i]; + } + return ret; +} + +MEDFileAnyTypeFieldMultiTS *MEDFileAnyTypeFieldMultiTS::deepCpy() const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=shallowCpy(); + if((const MEDFileAnyTypeFieldMultiTSWithoutSDA *)_content) + ret->_content=_content->deepCpy(); + ret->deepCpyGlobs(*this); + return ret.retn(); +} + +MEDCouplingAutoRefCountObjectPtr MEDFileAnyTypeFieldMultiTS::getContent() +{ + return _content; +} + +/*! + * Returns a new MEDFileField1TS or MEDFileIntField1TS holding data of a given time step of \a this field. + * \param [in] iteration - the iteration number of a required time step. + * \param [in] order - the iteration order number of required time step. + * \return MEDFileField1TS * or MEDFileIntField1TS *- a new instance of MEDFileField1TS or MEDFileIntField1TS. The caller is to + * delete this field using decrRef() as it is no more needed. + * \throw If there is no required time step in \a this field. + */ +MEDFileAnyTypeField1TS *MEDFileAnyTypeFieldMultiTS::getTimeStep(int iteration, int order) const throw(INTERP_KERNEL::Exception) +{ + int pos=getPosOfTimeStep(iteration,order); + return getTimeStepAtPos(pos); +} + +/*! + * Returns a new MEDFileField1TS or MEDFileIntField1TS holding data of a given time step of \a this field. + * \param [in] time - the time of the time step of interest. + * \param [in] eps - a precision used to compare time values. + * \return MEDFileField1TS * - a new instance of MEDFileField1TS. The caller is to + * delete this field using decrRef() as it is no more needed. + * \throw If there is no required time step in \a this field. + */ +MEDFileAnyTypeField1TS *MEDFileAnyTypeFieldMultiTS::getTimeStepGivenTime(double time, double eps) const throw(INTERP_KERNEL::Exception) +{ + int pos=getPosGivenTime(time,eps); + return getTimeStepAtPos(pos); +} + +MEDFileAnyTypeFieldMultiTSIterator *MEDFileAnyTypeFieldMultiTS::iterator() throw(INTERP_KERNEL::Exception) +{ + return new MEDFileAnyTypeFieldMultiTSIterator(this); +} + +//= MEDFileFieldMultiTS + +/*! + * Returns a new empty instance of MEDFileFieldMultiTS. + * \return MEDFileFieldMultiTS * - a new instance of MEDFileFieldMultiTS. The caller + * is to delete this field using decrRef() as it is no more needed. + */ +MEDFileFieldMultiTS *MEDFileFieldMultiTS::New() +{ + return new MEDFileFieldMultiTS; +} + +/*! + * Returns a new instance of MEDFileFieldMultiTS holding data of the first field + * that has been read from a specified MED file. + * \param [in] fileName - the name of the MED file to read. + * \return MEDFileFieldMultiTS * - a new instance of MEDFileFieldMultiTS. The caller + * is to delete this field using decrRef() as it is no more needed. + * \throw If reading the file fails. + */ +MEDFileFieldMultiTS *MEDFileFieldMultiTS::New(const char *fileName) throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileFieldMultiTS(fileName); + ret->contentNotNull();//to check that content type matches with \a this type. + return ret.retn(); } -void MEDFileFieldMultiTSWithoutSDA::checkCoherencyOfTinyInfo(const MEDCouplingFieldDouble *field) const throw(INTERP_KERNEL::Exception) +/*! + * Returns a new instance of MEDFileFieldMultiTS holding data of a given field + * that has been read from a specified MED file. + * \param [in] fileName - the name of the MED file to read. + * \param [in] fieldName - the name of the field to read. + * \return MEDFileFieldMultiTS * - a new instance of MEDFileFieldMultiTS. The caller + * is to delete this field using decrRef() as it is no more needed. + * \throw If reading the file fails. + * \throw If there is no field named \a fieldName in the file. + */ +MEDFileFieldMultiTS *MEDFileFieldMultiTS::New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) { - static const char MSG[]="MEDFileFieldMultiTSWithoutSDA::checkCoherencyOfTinyInfo : invalid "; - if(_name!=field->getName()) - { - std::ostringstream oss; oss << MSG << "name ! should be \"" << _name; - oss << "\" and it is set in input field to \"" << field->getName() << "\" !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - const DataArrayDouble *arr=field->getArray(); - if(!arr) - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::checkCoherencyOfTinyInfo : no array set !"); - if(_infos!=arr->getInfoOnComponents()) - { - std::ostringstream oss; oss << MSG << "components ! should be \""; - std::copy(_infos.begin(),_infos.end(),std::ostream_iterator(oss,", ")); - oss << " But compo in input fields are : "; - std::vector tmp=arr->getInfoOnComponents(); - std::copy(tmp.begin(),tmp.end(),std::ostream_iterator(oss,", ")); - oss << " !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileFieldMultiTS(fileName,fieldName); + ret->contentNotNull();//to check that content type matches with \a this type. + return ret.retn(); } -void MEDFileFieldMultiTSWithoutSDA::writeLL(med_idt fid, const MEDFileWritable& opts) const throw(INTERP_KERNEL::Exception) +/*! + * Returns a new instance of MEDFileFieldMultiTS. If \a shallowCopyOfContent is true the content of \a other is shallow copied. + * If \a shallowCopyOfContent is false, \a other is taken to be the content of \a this. + * + * Returns a new instance of MEDFileFieldMultiTS holding either a shallow copy + * of a given MEDFileFieldMultiTSWithoutSDA ( \a other ) or \a other itself. + * \warning this is a shallow copy constructor + * \param [in] other - a MEDFileField1TSWithoutSDA to copy. + * \param [in] shallowCopyOfContent - if \c true, a shallow copy of \a other is created. + * \return MEDFileFieldMultiTS * - a new instance of MEDFileFieldMultiTS. The caller + * is to delete this field using decrRef() as it is no more needed. + */ +MEDFileFieldMultiTS *MEDFileFieldMultiTS::New(const MEDFileFieldMultiTSWithoutSDA& other, bool shallowCopyOfContent) { - if(_time_steps.empty()) - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTSWithoutSDA::writeLL : no time steps set !"); - std::vector infos(getInfo()); - int nbComp=infos.size(); - INTERP_KERNEL::AutoPtr comp=MEDLoaderBase::buildEmptyString(nbComp*MED_SNAME_SIZE); - INTERP_KERNEL::AutoPtr unit=MEDLoaderBase::buildEmptyString(nbComp*MED_SNAME_SIZE); - for(int i=0;iwriteLL(fid,opts); + return new MEDFileFieldMultiTS(other,shallowCopyOfContent); } -int MEDFileFieldMultiTSWithoutSDA::getNumberOfTS() const +MEDFileAnyTypeFieldMultiTS *MEDFileFieldMultiTS::shallowCpy() const throw(INTERP_KERNEL::Exception) { - return _time_steps.size(); + return new MEDFileFieldMultiTS(*this); } -void MEDFileFieldMultiTSWithoutSDA::eraseEmptyTS() throw(INTERP_KERNEL::Exception) +void MEDFileFieldMultiTS::checkCoherencyOfType(const MEDFileAnyTypeField1TS *f1ts) const throw(INTERP_KERNEL::Exception) { - std::vector< MEDCouplingAutoRefCountObjectPtr > newTS; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++) - { - const MEDFileField1TSWithoutSDA *tmp=(*it); - if(tmp) - newTS.push_back(*it); - } - _time_steps=newTS; + if(!f1ts) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::checkCoherencyOfType : input field1TS is NULL ! Impossible to check !"); + const MEDFileField1TS *f1tsC=dynamic_cast(f1ts); + if(!f1tsC) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::checkCoherencyOfType : the input field1TS is not a FLOAT64 type !"); } -void MEDFileFieldMultiTSWithoutSDA::eraseTimeStepIds(const int *startIds, const int *endIds) throw(INTERP_KERNEL::Exception) +/*! + * Returns a new MEDFileField1TS holding data of a given time step of \a this field. + * \param [in] pos - a time step id. + * \return MEDFileField1TS * - a new instance of MEDFileField1TS. The caller is to + * delete this field using decrRef() as it is no more needed. + * \throw If \a pos is not a valid time step id. + */ +MEDFileAnyTypeField1TS *MEDFileFieldMultiTS::getTimeStepAtPos(int pos) const throw(INTERP_KERNEL::Exception) { - std::vector< MEDCouplingAutoRefCountObjectPtr > newTS; - int maxId=(int)_time_steps.size(); - int ii=0; - std::set idsToDel; - for(const int *id=startIds;id!=endIds;id++,ii++) + const MEDFileAnyTypeField1TSWithoutSDA *item=contentNotNullBase()->getTimeStepAtPos2(pos); + if(!item) { - if(*id>=0 && *id >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++,ret++) + const MEDFileField1TSWithoutSDA *itemC=dynamic_cast(item); + if(itemC) { - const MEDFileField1TSWithoutSDA *tmp(*it); - if(tmp) - { - int it2,ord; - tmp->getTime(it2,ord); - if(it2==iteration && order==ord) - return ret; - else - oss << "(" << it2 << "," << ord << "), "; - } + MEDCouplingAutoRefCountObjectPtr ret=MEDFileField1TS::New(*itemC,false); + ret->shallowCpyGlobs(*this); + return ret.retn(); } + std::ostringstream oss; oss << "MEDFileFieldMultiTS::getTimeStepAtPos : type of field at pos #" << pos << " is not FLOAT64 !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } -int MEDFileFieldMultiTSWithoutSDA::getPosGivenTime(double time, double eps) const throw(INTERP_KERNEL::Exception) +/*! + * Returns a new MEDCouplingFieldDouble of a given type, of a given time step, lying on + * mesh entities of a given dimension of the first mesh in MED file. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of interest. + * \param [in] iteration - the iteration number of a required time step. + * \param [in] order - the iteration order number of required time step. + * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. + * \param [in] renumPol - specifies how to permute values of the result field according to + * the optional numbers of cells and nodes, if any. The valid values are + * - 0 - do not permute. + * - 1 - permute cells. + * - 2 - permute nodes. + * - 3 - permute cells and nodes. + * + * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The + * caller is to delete this field using decrRef() as it is no more needed. + * \throw If the MED file is not readable. + * \throw If there is no mesh in the MED file. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in the mesh. + * \throw If no field values of the required parameters are available. + */ +MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, int renumPol) const throw(INTERP_KERNEL::Exception) { - int ret=0; - std::ostringstream oss; oss << "MEDFileFieldMultiTSWithoutSDA::getPosGivenTime : No such time step " << time << "! \nPossibilities are : "; - oss.precision(15); - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++,ret++) - { - const MEDFileField1TSWithoutSDA *tmp(*it); - if(tmp) - { - int it2,ord; - double ti=tmp->getTime(it2,ord); - if(fabs(time-ti)getTimeStepEntry(iteration,order); + const MEDFileField1TSWithoutSDA *myF1TSC=dynamic_cast(&myF1TS); + if(!myF1TSC) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::getFieldAtLevel : mismatch of type of field expecting FLOAT64 !"); + MEDCouplingAutoRefCountObjectPtr arrOut; + MEDCouplingAutoRefCountObjectPtr ret=myF1TSC->getFieldAtLevel(type,meshDimRelToMax,0,renumPol,this,arrOut,*contentNotNullBase()); + MEDFileField1TS::SetDataArrayDoubleInField(ret,arrOut); + return ret.retn(); } -std::vector< std::pair > MEDFileFieldMultiTSWithoutSDA::getIterations() const +/*! + * Returns a new MEDCouplingFieldDouble of a given type, of a given time step, lying on + * the top level cells of the first mesh in MED file. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of interest. + * \param [in] iteration - the iteration number of a required time step. + * \param [in] order - the iteration order number of required time step. + * \param [in] renumPol - specifies how to permute values of the result field according to + * the optional numbers of cells and nodes, if any. The valid values are + * - 0 - do not permute. + * - 1 - permute cells. + * - 2 - permute nodes. + * - 3 - permute cells and nodes. + * + * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The + * caller is to delete this field using decrRef() as it is no more needed. + * \throw If the MED file is not readable. + * \throw If there is no mesh in the MED file. + * \throw If no field values of the required parameters are available. + */ +MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldAtTopLevel(TypeOfField type, int iteration, int order, int renumPol) const throw(INTERP_KERNEL::Exception) { - int lgth=_time_steps.size(); - std::vector< std::pair > ret(lgth); - for(int i=0;ifillIteration(ret[i]); - return ret; + const MEDFileAnyTypeField1TSWithoutSDA& myF1TS=contentNotNullBase()->getTimeStepEntry(iteration,order); + const MEDFileField1TSWithoutSDA *myF1TSC=dynamic_cast(&myF1TS); + if(!myF1TSC) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::getFieldAtTopLevel : mismatch of type of field !"); + MEDCouplingAutoRefCountObjectPtr arrOut; + MEDCouplingAutoRefCountObjectPtr ret=myF1TSC->getFieldAtTopLevel(type,0,renumPol,this,arrOut,*contentNotNullBase()); + MEDFileField1TS::SetDataArrayDoubleInField(ret,arrOut); + return ret.retn(); } /*! - * This method has 3 inputs 'iteration' 'order' 'mname'. 'mname' can be null if the user is the general case where there is only one meshName lying on 'this' - * This method returns two things. - * - The absolute dimension of 'this' in first parameter. - * - The available ext levels relative to the absolute dimension returned in first parameter. These relative levels are relative - * to the first output parameter. The values in 'levs' will be returned in decreasing order. - * - * This method is designed for MEDFileFieldMultiTS instances that have a discritization ON_CELLS, ON_GAUSS_NE and ON_GAUSS. - * Only these 3 discretizations will be taken into account here. - * - * If 'this' is empty this method will throw an INTERP_KERNEL::Exception. - * If there is \b only node fields defined in 'this' -1 is returned and 'levs' output parameter will be empty. In this - * case the caller has to know the underlying mesh it refers to. By defaut it is the level 0 of the corresponding mesh. + * Returns a new MEDCouplingFieldDouble of a given type, of a given time step, lying on + * a given support. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of interest. + * \param [in] iteration - the iteration number of a required time step. + * \param [in] order - the iteration order number of required time step. + * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. + * \param [in] mesh - the supporting mesh. + * \param [in] renumPol - specifies how to permute values of the result field according to + * the optional numbers of cells and nodes, if any. The valid values are + * - 0 - do not permute. + * - 1 - permute cells. + * - 2 - permute nodes. + * - 3 - permute cells and nodes. * - * This method is usefull to make the link between meshDimension of the underlying mesh in 'this' and the levels on 'this'. - * It is possible (even if it is not common) that the highest level in 'this' were not equal to the meshDimension of the underlying mesh in 'this'. - * - * Let's consider the typical following case : - * - a mesh 'm1' has a meshDimension 3 and has the following non empty levels - * [0,-1,-2] for example 'm1' lies on TETRA4, HEXA8 TRI3 and SEG2 - * - 'f1' lies on 'm1' and is defined on 3D and 1D cells for example - * TETRA4 and SEG2 - * - 'f2' lies on 'm1' too and is defined on 2D and 1D cells for example TRI3 and SEG2 + * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The + * caller is to delete this field using decrRef() as it is no more needed. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in the mesh. + * \throw If no field of \a this is lying on \a mesh. + * \throw If no field values of the required parameters are available. + */ +MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, int renumPol) const throw(INTERP_KERNEL::Exception) +{ + const MEDFileAnyTypeField1TSWithoutSDA& myF1TS=contentNotNullBase()->getTimeStepEntry(iteration,order); + const MEDFileField1TSWithoutSDA *myF1TSC=dynamic_cast(&myF1TS); + if(!myF1TSC) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::getFieldOnMeshAtLevel : mismatch of type of field !"); + MEDCouplingAutoRefCountObjectPtr arrOut; + MEDCouplingAutoRefCountObjectPtr ret=myF1TSC->getFieldOnMeshAtLevel(type,meshDimRelToMax,renumPol,this,mesh,arrOut,*contentNotNullBase()); + MEDFileField1TS::SetDataArrayDoubleInField(ret,arrOut); + return ret.retn(); +} + +/*! + * Returns a new MEDCouplingFieldDouble of given type, of a given time step, lying on a + * given support. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of the new field. + * \param [in] iteration - the iteration number of a required time step. + * \param [in] order - the iteration order number of required time step. + * \param [in] mesh - the supporting mesh. + * \param [in] renumPol - specifies how to permute values of the result field according to + * the optional numbers of cells and nodes, if any. The valid values are + * - 0 - do not permute. + * - 1 - permute cells. + * - 2 - permute nodes. + * - 3 - permute cells and nodes. * - * In this case f1->getNonEmptyLevelsExt will return (3,[0,-2]) and f2->getNonEmptyLevelsExt will return (2,[0,-1]) - * - * To retrieve the highest level of f1 it should be done, f1->getFieldAtLevel(ON_CELLS,3-3+0);//absDim-meshDim+relativeLev - * To retrieve the lowest level of f1 it should be done, f1->getFieldAtLevel(ON_CELLS,3-3+(-2));//absDim-meshDim+relativeLev - * To retrieve the highest level of f2 it should be done, f1->getFieldAtLevel(ON_CELLS,2-3+0);//absDim-meshDim+relativeLev - * To retrieve the lowest level of f2 it should be done, f1->getFieldAtLevel(ON_CELLS,2-3+(-1));//absDim-meshDim+relativeLev + * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The + * caller is to delete this field using decrRef() as it is no more needed. + * \throw If no field of \a this is lying on \a mesh. + * \throw If no field values of the required parameters are available. + */ +MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, const MEDCouplingMesh *mesh, int renumPol) const throw(INTERP_KERNEL::Exception) +{ + const MEDFileAnyTypeField1TSWithoutSDA& myF1TS=contentNotNullBase()->getTimeStepEntry(iteration,order); + const MEDFileField1TSWithoutSDA *myF1TSC=dynamic_cast(&myF1TS); + if(!myF1TSC) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::getFieldOnMeshAtLevel : mismatch of type of field !"); + MEDCouplingAutoRefCountObjectPtr arrOut; + MEDCouplingAutoRefCountObjectPtr ret=myF1TSC->getFieldOnMeshAtLevel(type,renumPol,this,mesh,0,0,arrOut,*contentNotNullBase()); + MEDFileField1TS::SetDataArrayDoubleInField(ret,arrOut); + return ret.retn(); +} + +/*! + * This method has a close behaviour than MEDFileFieldMultiTS::getFieldAtLevel. + * This method is called 'old' because the user should give the mesh name he wants to use for it's field. + * This method is useful for MED2 file format when field on different mesh was autorized. + */ +MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldAtLevelOld(TypeOfField type, const char *mname, int iteration, int order, int meshDimRelToMax, int renumPol) const throw(INTERP_KERNEL::Exception) +{ + const MEDFileAnyTypeField1TSWithoutSDA& myF1TS=contentNotNullBase()->getTimeStepEntry(iteration,order); + const MEDFileField1TSWithoutSDA *myF1TSC=dynamic_cast(&myF1TS); + if(!myF1TSC) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::getFieldAtLevelOld : mismatch of type of field !"); + MEDCouplingAutoRefCountObjectPtr arrOut; + MEDCouplingAutoRefCountObjectPtr ret=myF1TSC->getFieldAtLevel(type,meshDimRelToMax,mname,renumPol,this,arrOut,*contentNotNullBase()); + MEDFileField1TS::SetDataArrayDoubleInField(ret,arrOut); + return ret.retn(); +} + +/*! + * Returns values and a profile of the field of a given type, of a given time step, + * lying on a given support. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] type - a spatial discretization of the field. + * \param [in] iteration - the iteration number of a required time step. + * \param [in] order - the iteration order number of required time step. + * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. + * \param [in] mesh - the supporting mesh. + * \param [out] pfl - a new instance of DataArrayInt holding ids of mesh entities the + * field of interest lies on. If the field lies on all entities of the given + * dimension, all ids in \a pfl are zero. The caller is to delete this array + * using decrRef() as it is no more needed. + * \param [in] glob - the global data storing profiles and localization. + * \return DataArrayDouble * - a new instance of DataArrayDouble holding values of the + * field. The caller is to delete this array using decrRef() as it is no more needed. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a mesh. + * \throw If no field of \a this is lying on \a mesh. + * \throw If no field values of the required parameters are available. */ -int MEDFileFieldMultiTSWithoutSDA::getNonEmptyLevels(int iteration, int order, const char *mname, std::vector& levs) const throw(INTERP_KERNEL::Exception) +DataArrayDouble *MEDFileFieldMultiTS::getFieldWithProfile(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl) const throw(INTERP_KERNEL::Exception) { - return getTimeStepEntry(iteration,order).getNonEmptyLevels(mname,levs); + const MEDFileAnyTypeField1TSWithoutSDA& myF1TS=contentNotNullBase()->getTimeStepEntry(iteration,order); + const MEDFileField1TSWithoutSDA *myF1TSC=dynamic_cast(&myF1TS); + if(!myF1TSC) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::getFieldWithProfile : mismatch of type of field !"); + MEDCouplingAutoRefCountObjectPtr ret=myF1TSC->getFieldWithProfile(type,meshDimRelToMax,mesh,pfl,this,*contentNotNullBase()); + return MEDFileField1TS::ReturnSafelyDataArrayDouble(ret); } -std::vector< std::vector > MEDFileFieldMultiTSWithoutSDA::getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception) +const MEDFileFieldMultiTSWithoutSDA *MEDFileFieldMultiTS::contentNotNull() const throw(INTERP_KERNEL::Exception) { - int lgth=_time_steps.size(); - std::vector< std::vector > ret(lgth); - for(int i=0;ifillTypesOfFieldAvailable(ret[i]); + const MEDFileAnyTypeFieldMultiTSWithoutSDA *pt(_content); + if(!pt) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::contentNotNull : the content pointer is null !"); + const MEDFileFieldMultiTSWithoutSDA *ret=dynamic_cast(pt); + if(!ret) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::contentNotNull : the content pointer is not null but it is not of type double ! Reason is maybe that the read field has not the type FLOAT64 !"); + return ret; +} + + MEDFileFieldMultiTSWithoutSDA *MEDFileFieldMultiTS::contentNotNull() throw(INTERP_KERNEL::Exception) +{ + MEDFileAnyTypeFieldMultiTSWithoutSDA *pt(_content); + if(!pt) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::contentNotNull : the non const content pointer is null !"); + MEDFileFieldMultiTSWithoutSDA *ret=dynamic_cast(pt); + if(!ret) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::contentNotNull : the non const content pointer is not null but it is not of type double ! Reason is maybe that the read field has not the type FLOAT64 !"); return ret; } /*! - * entry point for users that want to iterate into MEDFile DataStructure without any overhead. + * Adds a MEDCouplingFieldDouble to \a this as another time step. The underlying mesh of + * the given field is checked if its elements are sorted suitable for writing to MED file + * ("STB" stands for "Sort By Type"), if not, an exception is thrown. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] field - the field to add to \a this. + * \throw If the name of \a field is empty. + * \throw If the data array of \a field is not set. + * \throw If existing time steps have different name or number of components than \a field. + * \throw If the underlying mesh of \a field has no name. + * \throw If elements in the mesh are not in the order suitable for writing to the MED file. */ -std::vector< std::vector< std::pair > > MEDFileFieldMultiTSWithoutSDA::getFieldSplitedByType(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) +void MEDFileFieldMultiTS::appendFieldNoProfileSBT(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception) { - return getTimeStepEntry(iteration,order).getFieldSplitedByType(mname,types,typesF,pfls,locs); + const DataArrayDouble *arr=0; + if(field) + arr=field->getArray(); + contentNotNull()->appendFieldNoProfileSBT(field,arr,*this); } /*! - * entry point for users that want to iterate into MEDFile DataStructure with a reduced overhead because output arrays are extracted (created) specially - * for the call of this method. That's why the DataArrayDouble instance in returned vector of vector should be dealed by the caller. + * Adds a MEDCouplingFieldDouble to \a this as another time step. Specified entities of + * a given dimension of a given mesh are used as the support of the given field. + * Elements of the given mesh must be sorted suitable for writing to MED file. + * Order of underlying mesh entities of the given field specified by \a profile parameter + * is not prescribed; this method permutes field values to have them sorted by element + * type as required for writing to MED file. + * For more info, see \ref AdvMEDLoaderAPIFieldRW + * \param [in] field - the field to add to \a this. + * \param [in] mesh - the supporting mesh of \a field. + * \param [in] meshDimRelToMax - a relative dimension of mesh entities \a field lies on. + * \param [in] profile - ids of mesh entities on which corresponding field values lie. + * \throw If either \a field or \a mesh or \a profile has an empty name. + * \throw If existing time steps have different name or number of components than \a field. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a mesh. + * \throw If the data array of \a field is not set. + * \throw If elements in \a mesh are not in the order suitable for writing to the MED file. */ -std::vector< std::vector > MEDFileFieldMultiTSWithoutSDA::getFieldSplitedByType2(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) +void MEDFileFieldMultiTS::appendFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception) { - return getTimeStepEntry(iteration,order).getFieldSplitedByType2(mname,types,typesF,pfls,locs); + const DataArrayDouble *arr=0; + if(field) + arr=field->getArray(); + contentNotNull()->appendFieldProfile(field,arr,mesh,meshDimRelToMax,profile,*this); } -const MEDFileField1TSWithoutSDA& MEDFileFieldMultiTSWithoutSDA::getTimeStepEntry(int iteration, int order) const throw(INTERP_KERNEL::Exception) +MEDFileFieldMultiTS::MEDFileFieldMultiTS() { - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++) - if((*it)->isDealingTS(iteration,order)) - return *(*it); - std::ostringstream oss; oss << "MEDFileFieldMultiTS::getTimeStepEntry : Muli timestep field on time (" << iteration << "," << order << ") does not exist ! Available (iteration,order) are :\n"; - std::vector< std::pair > vp=getIterations(); - for(std::vector< std::pair >::const_iterator it2=vp.begin();it2!=vp.end();it2++) - oss << "(" << (*it2).first << "," << (*it2).second << ") "; - throw INTERP_KERNEL::Exception(oss.str().c_str()); + _content=new MEDFileFieldMultiTSWithoutSDA; } -MEDFileField1TSWithoutSDA& MEDFileFieldMultiTSWithoutSDA::getTimeStepEntry(int iteration, int order) throw(INTERP_KERNEL::Exception) +MEDFileFieldMultiTS::MEDFileFieldMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeFieldMultiTS(fileName) { - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_time_steps.begin();it!=_time_steps.end();it++) - if((*it)->isDealingTS(iteration,order)) - return *(*it); - std::ostringstream oss; oss << "MEDFileFieldMultiTS::getTimeStepEntry : Muli timestep field on time (" << iteration << "," << order << ") does not exist ! Available (iteration,order) are :\n"; - std::vector< std::pair > vp=getIterations(); - for(std::vector< std::pair >::const_iterator it2=vp.begin();it2!=vp.end();it2++) - oss << "(" << (*it2).first << "," << (*it2).second << ") "; - throw INTERP_KERNEL::Exception(oss.str().c_str()); } +catch(INTERP_KERNEL::Exception& e) + { throw e; } -const MEDFileField1TSWithoutSDA *MEDFileFieldMultiTSWithoutSDA::getTimeStepAtPos2(int pos) const throw(INTERP_KERNEL::Exception) +MEDFileFieldMultiTS::MEDFileFieldMultiTS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeFieldMultiTS(fileName,fieldName) { - if(pos<0 || pos>=(int)_time_steps.size()) - { - std::ostringstream oss; oss << "MEDFileFieldMultiTSWithoutSDA::getTimeStepAtPos2 : request for pos #" << pos << " whereas should be in [0," << _time_steps.size() << ") !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - const MEDFileField1TSWithoutSDA *item=_time_steps[pos]; - if(item==0) - { - std::ostringstream oss; oss << "MEDFileFieldMultiTSWithoutSDA::getTimeStepAtPos2 : request for pos #" << pos << ", this pos id exists but the underlying Field1TS is null !"; - oss << "\nTry to use following method eraseEmptyTS !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - return item; } +catch(INTERP_KERNEL::Exception& e) + { throw e; } -MEDFileField1TSWithoutSDA *MEDFileFieldMultiTSWithoutSDA::getTimeStepAtPos2(int pos) throw(INTERP_KERNEL::Exception) +MEDFileFieldMultiTS::MEDFileFieldMultiTS(const MEDFileFieldMultiTSWithoutSDA& other, bool shallowCopyOfContent):MEDFileAnyTypeFieldMultiTS(other,shallowCopyOfContent) { - if(pos<0 || pos>=(int)_time_steps.size()) - { - std::ostringstream oss; oss << "MEDFileFieldMultiTSWithoutSDA::getTimeStepAtPos2 : request for pos #" << pos << " whereas should be in [0," << _time_steps.size() << ") !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - MEDFileField1TSWithoutSDA *item=_time_steps[pos]; - if(item==0) - { - std::ostringstream oss; oss << "MEDFileFieldMultiTSWithoutSDA::getTimeStepAtPos2 : request for pos #" << pos << ", this pos id exists but the underlying Field1TS is null !"; - oss << "\nTry to use following method eraseEmptyTS !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - return item; } -std::vector MEDFileFieldMultiTSWithoutSDA::getPflsReallyUsed2() const +std::vector< std::vector > MEDFileFieldMultiTS::getFieldSplitedByType2(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) { - std::vector ret; - std::set ret2; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileField1TSWithoutSDA > >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++) - { - std::vector tmp=(*it)->getPflsReallyUsed2(); - for(std::vector::const_iterator it2=tmp.begin();it2!=tmp.end();it2++) - if(ret2.find(*it2)==ret2.end()) - { - ret.push_back(*it2); - ret2.insert(*it2); - } - } - return ret; + return contentNotNull()->getFieldSplitedByType2(iteration,order,mname,types,typesF,pfls,locs); } -std::vector MEDFileFieldMultiTSWithoutSDA::getLocsReallyUsed2() const +DataArrayDouble *MEDFileFieldMultiTS::getUndergroundDataArray(int iteration, int order) const throw(INTERP_KERNEL::Exception) { - std::vector ret; - std::set ret2; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileField1TSWithoutSDA > >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++) - { - std::vector tmp=(*it)->getLocsReallyUsed2(); - for(std::vector::const_iterator it2=tmp.begin();it2!=tmp.end();it2++) - if(ret2.find(*it2)==ret2.end()) - { - ret.push_back(*it2); - ret2.insert(*it2); - } - } - return ret; + return static_cast(contentNotNull()->getUndergroundDataArray(iteration,order)); } -std::vector MEDFileFieldMultiTSWithoutSDA::getPflsReallyUsedMulti2() const +DataArrayDouble *MEDFileFieldMultiTS::getUndergroundDataArrayExt(int iteration, int order, std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) { - std::vector ret; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileField1TSWithoutSDA > >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++) - { - std::vector tmp=(*it)->getPflsReallyUsedMulti2(); - ret.insert(ret.end(),tmp.begin(),tmp.end()); - } - return ret; + return static_cast(contentNotNull()->getUndergroundDataArrayExt(iteration,order,entries)); } -std::vector MEDFileFieldMultiTSWithoutSDA::getLocsReallyUsedMulti2() const +//= MEDFileAnyTypeFieldMultiTSIterator + +MEDFileAnyTypeFieldMultiTSIterator::MEDFileAnyTypeFieldMultiTSIterator(MEDFileAnyTypeFieldMultiTS *fmts):_fmts(fmts),_iter_id(0),_nb_iter(0) { - std::vector ret; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileField1TSWithoutSDA > >::const_iterator it=_time_steps.begin();it!=_time_steps.end();it++) + if(fmts) { - std::vector tmp=(*it)->getLocsReallyUsedMulti2(); - ret.insert(ret.end(),tmp.begin(),tmp.end()); + fmts->incrRef(); + _nb_iter=fmts->getNumberOfTS(); } - return ret; } -void MEDFileFieldMultiTSWithoutSDA::changePflsRefsNamesGen2(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) +MEDFileAnyTypeFieldMultiTSIterator::~MEDFileAnyTypeFieldMultiTSIterator() { - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileField1TSWithoutSDA > >::iterator it=_time_steps.begin();it!=_time_steps.end();it++) - (*it)->changePflsRefsNamesGen2(mapOfModif); } -void MEDFileFieldMultiTSWithoutSDA::changeLocsRefsNamesGen2(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) +MEDFileAnyTypeField1TS *MEDFileAnyTypeFieldMultiTSIterator::nextt() throw(INTERP_KERNEL::Exception) { - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileField1TSWithoutSDA > >::iterator it=_time_steps.begin();it!=_time_steps.end();it++) - (*it)->changeLocsRefsNamesGen2(mapOfModif); + if(_iter_id<_nb_iter) + { + MEDFileAnyTypeFieldMultiTS *fmts(_fmts); + if(fmts) + return fmts->getTimeStepAtPos(_iter_id++); + else + return 0; + } + else + return 0; } +//= MEDFileIntFieldMultiTS + /*! * Returns a new empty instance of MEDFileFieldMultiTS. - * \return MEDFileFieldMultiTS * - a new instance of MEDFileFieldMultiTS. The caller + * \return MEDFileIntFieldMultiTS * - a new instance of MEDFileIntFieldMultiTS. The caller * is to delete this field using decrRef() as it is no more needed. */ -MEDFileFieldMultiTS *MEDFileFieldMultiTS::New() +MEDFileIntFieldMultiTS *MEDFileIntFieldMultiTS::New() { - return new MEDFileFieldMultiTS; + return new MEDFileIntFieldMultiTS; } /*! - * Returns a new instance of MEDFileFieldMultiTS holding data of the first field + * Returns a new instance of MEDFileIntFieldMultiTS holding data of the first field * that has been read from a specified MED file. * \param [in] fileName - the name of the MED file to read. - * \return MEDFileFieldMultiTS * - a new instance of MEDFileFieldMultiTS. The caller + * \return MEDFileFieldMultiTS * - a new instance of MEDFileIntFieldMultiTS. The caller * is to delete this field using decrRef() as it is no more needed. * \throw If reading the file fails. */ -MEDFileFieldMultiTS *MEDFileFieldMultiTS::New(const char *fileName) throw(INTERP_KERNEL::Exception) +MEDFileIntFieldMultiTS *MEDFileIntFieldMultiTS::New(const char *fileName) throw(INTERP_KERNEL::Exception) { - return new MEDFileFieldMultiTS(fileName); + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileIntFieldMultiTS(fileName); + ret->contentNotNull();//to check that content type matches with \a this type. + return ret.retn(); } /*! - * Returns a new instance of MEDFileFieldMultiTS holding data of a given field + * Returns a new instance of MEDFileIntFieldMultiTS holding data of a given field * that has been read from a specified MED file. * \param [in] fileName - the name of the MED file to read. * \param [in] fieldName - the name of the field to read. - * \return MEDFileFieldMultiTS * - a new instance of MEDFileFieldMultiTS. The caller + * \return MEDFileFieldMultiTS * - a new instance of MEDFileIntFieldMultiTS. The caller * is to delete this field using decrRef() as it is no more needed. * \throw If reading the file fails. * \throw If there is no field named \a fieldName in the file. */ -MEDFileFieldMultiTS *MEDFileFieldMultiTS::New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) +MEDFileIntFieldMultiTS *MEDFileIntFieldMultiTS::New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) { - return new MEDFileFieldMultiTS(fileName,fieldName); + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileIntFieldMultiTS(fileName,fieldName); + ret->contentNotNull();//to check that content type matches with \a this type. + return ret.retn(); } /*! - * Returns a new instance of MEDFileFieldMultiTS holding either deep or shallow copy - * of a given MEDFileFieldMultiTSWithoutSDA. - * \param [in] other - a MEDFileFieldMultiTSWithoutSDA to copy. + * Returns a new instance of MEDFileIntFieldMultiTS. If \a shallowCopyOfContent is true the content of \a other is shallow copied. + * If \a shallowCopyOfContent is false, \a other is taken to be the content of \a this. + * + * Returns a new instance of MEDFileIntFieldMultiTS holding either a shallow copy + * of a given MEDFileIntFieldMultiTSWithoutSDA ( \a other ) or \a other itself. + * \warning this is a shallow copy constructor + * \param [in] other - a MEDFileIntField1TSWithoutSDA to copy. * \param [in] shallowCopyOfContent - if \c true, a shallow copy of \a other is created. - * \return MEDFileFieldMultiTS * - a new instance of MEDFileFieldMultiTS. The caller + * \return MEDFileIntFieldMultiTS * - a new instance of MEDFileIntFieldMultiTS. The caller * is to delete this field using decrRef() as it is no more needed. */ -MEDFileFieldMultiTS *MEDFileFieldMultiTS::New(const MEDFileFieldMultiTSWithoutSDA& other, bool shallowCopyOfContent) -{ - return new MEDFileFieldMultiTS(other,shallowCopyOfContent); -} - -std::size_t MEDFileFieldMultiTS::getHeapMemorySize() const -{ - std::size_t ret=0; - if((const MEDFileFieldMultiTSWithoutSDA*)_content) - ret+=_content->getHeapMemorySize(); - return ret+MEDFileFieldGlobsReal::getHeapMemorySize(); -} - -MEDFileFieldMultiTS *MEDFileFieldMultiTS::deepCpy() const throw(INTERP_KERNEL::Exception) -{ - MEDCouplingAutoRefCountObjectPtr ret=new MEDFileFieldMultiTS(*this); - if((const MEDFileFieldMultiTSWithoutSDA *)_content) - ret->_content=_content->deepCpy(); - ret->deepCpyGlobs(*this); - return ret.retn(); -} - -/*! - * Returns a new MEDFileField1TS holding data of a given time step of \a this field. - * \param [in] pos - a time step id. - * \return MEDFileField1TS * - a new instance of MEDFileField1TS. The caller is to - * delete this field using decrRef() as it is no more needed. - * \throw If \a pos is not a valid time step id. - */ -MEDFileField1TS *MEDFileFieldMultiTS::getTimeStepAtPos(int pos) const throw(INTERP_KERNEL::Exception) -{ - const MEDFileField1TSWithoutSDA *item=_content->getTimeStepAtPos2(pos); - MEDCouplingAutoRefCountObjectPtr ret=MEDFileField1TS::New(*item,false); - ret->shallowCpyGlobs(*this); - return ret.retn(); -} - -/*! - * Returns a new MEDFileField1TS holding data of a given time step of \a this field. - * \param [in] iteration - the iteration number of a required time step. - * \param [in] order - the iteration order number of required time step. - * \return MEDFileField1TS * - a new instance of MEDFileField1TS. The caller is to - * delete this field using decrRef() as it is no more needed. - * \throw If there is no required time step in \a this field. - */ -MEDFileField1TS *MEDFileFieldMultiTS::getTimeStep(int iteration, int order) const throw(INTERP_KERNEL::Exception) -{ - int pos=getPosOfTimeStep(iteration,order); - return getTimeStepAtPos(pos); -} - -/*! - * Returns a new MEDFileField1TS holding data of a given time step of \a this field. - * \param [in] time - the time of the time step of interest. - * \param [in] eps - a precision used to compare time values. - * \return MEDFileField1TS * - a new instance of MEDFileField1TS. The caller is to - * delete this field using decrRef() as it is no more needed. - * \throw If there is no required time step in \a this field. - */ -MEDFileField1TS *MEDFileFieldMultiTS::getTimeStepGivenTime(double time, double eps) const throw(INTERP_KERNEL::Exception) -{ - int pos=getPosGivenTime(time,eps); - return getTimeStepAtPos(pos); -} - -MEDFileFieldMultiTSIterator *MEDFileFieldMultiTS::iterator() throw(INTERP_KERNEL::Exception) -{ - return new MEDFileFieldMultiTSIterator(this); -} - -std::string MEDFileFieldMultiTS::simpleRepr() const +MEDFileIntFieldMultiTS *MEDFileIntFieldMultiTS::New(const MEDFileIntFieldMultiTSWithoutSDA& other, bool shallowCopyOfContent) { - std::ostringstream oss; - _content->simpleRepr(0,oss,-1); - MEDFileFieldGlobsReal::simpleRepr(oss); - return oss.str(); + return new MEDFileIntFieldMultiTS(other,shallowCopyOfContent); } -void MEDFileFieldMultiTS::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) +MEDFileAnyTypeFieldMultiTS *MEDFileIntFieldMultiTS::shallowCpy() const throw(INTERP_KERNEL::Exception) { - writeGlobals(fid,*this); - _content->writeLL(fid,*this); + return new MEDFileIntFieldMultiTS(*this); } -/*! - * Writes \a this field into a MED file specified by its name. - * \param [in] fileName - the MED file name. - * \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics. - * - 2 - erase; an existing file is removed. - * - 1 - append; same data should not be present in an existing file. - * - 0 - overwrite; same data present in an existing file is overwritten. - * \throw If the field name is not set. - * \throw If no field data is set. - * \throw If \a mode == 1 and the same data is present in an existing file. - */ -void MEDFileFieldMultiTS::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception) +void MEDFileIntFieldMultiTS::checkCoherencyOfType(const MEDFileAnyTypeField1TS *f1ts) const throw(INTERP_KERNEL::Exception) { - med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod); - writeLL(fid); + if(!f1ts) + throw INTERP_KERNEL::Exception("MEDFileIntFieldMultiTS::checkCoherencyOfType : input field1TS is NULL ! Impossible to check !"); + const MEDFileIntField1TS *f1tsC=dynamic_cast(f1ts); + if(!f1tsC) + throw INTERP_KERNEL::Exception("MEDFileIntFieldMultiTS::checkCoherencyOfType : the input field1TS is not a INT32 type !"); } /*! @@ -5919,6 +8162,7 @@ void MEDFileFieldMultiTS::write(const char *fileName, int mode) const throw(INTE * \param [in] iteration - the iteration number of a required time step. * \param [in] order - the iteration order number of required time step. * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. + * \param [out] arrOut - the DataArrayInt containing values of field. * \param [in] renumPol - specifies how to permute values of the result field according to * the optional numbers of cells and nodes, if any. The valid values are * - 0 - do not permute. @@ -5933,10 +8177,16 @@ void MEDFileFieldMultiTS::write(const char *fileName, int mode) const throw(INTE * \throw If there are no mesh entities of \a meshDimRelToMax dimension in the mesh. * \throw If no field values of the required parameters are available. */ -MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, int renumPol) const throw(INTERP_KERNEL::Exception) +MEDCouplingFieldDouble *MEDFileIntFieldMultiTS::getFieldAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, DataArrayInt* &arrOut, int renumPol) const throw(INTERP_KERNEL::Exception) { - const MEDFileField1TSWithoutSDA& myF1TS=_content->getTimeStepEntry(iteration,order); - return myF1TS.getFieldAtLevel(type,meshDimRelToMax,0,renumPol,this); + const MEDFileAnyTypeField1TSWithoutSDA& myF1TS=contentNotNullBase()->getTimeStepEntry(iteration,order); + const MEDFileIntField1TSWithoutSDA *myF1TSC=dynamic_cast(&myF1TS); + if(!myF1TSC) + throw INTERP_KERNEL::Exception("MEDFileIntFieldMultiTS::getFieldAtLevel : mismatch of type of field expecting INT32 !"); + MEDCouplingAutoRefCountObjectPtr arr; + MEDCouplingAutoRefCountObjectPtr ret=myF1TSC->getFieldAtLevel(type,meshDimRelToMax,0,renumPol,this,arr,*contentNotNullBase()); + arrOut=MEDFileIntField1TS::ReturnSafelyDataArrayInt(arr); + return ret.retn(); } /*! @@ -5946,6 +8196,7 @@ MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldAtLevel(TypeOfField type, i * \param [in] type - a spatial discretization of interest. * \param [in] iteration - the iteration number of a required time step. * \param [in] order - the iteration order number of required time step. + * \param [out] arrOut - the DataArrayInt containing values of field. * \param [in] renumPol - specifies how to permute values of the result field according to * the optional numbers of cells and nodes, if any. The valid values are * - 0 - do not permute. @@ -5959,10 +8210,16 @@ MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldAtLevel(TypeOfField type, i * \throw If there is no mesh in the MED file. * \throw If no field values of the required parameters are available. */ -MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldAtTopLevel(TypeOfField type, int iteration, int order, int renumPol) const throw(INTERP_KERNEL::Exception) +MEDCouplingFieldDouble *MEDFileIntFieldMultiTS::getFieldAtTopLevel(TypeOfField type, int iteration, int order, DataArrayInt* &arrOut, int renumPol) const throw(INTERP_KERNEL::Exception) { - const MEDFileField1TSWithoutSDA& myF1TS=_content->getTimeStepEntry(iteration,order); - return myF1TS.getFieldAtTopLevel(type,0,renumPol,this); + const MEDFileAnyTypeField1TSWithoutSDA& myF1TS=contentNotNullBase()->getTimeStepEntry(iteration,order); + const MEDFileIntField1TSWithoutSDA *myF1TSC=dynamic_cast(&myF1TS); + if(!myF1TSC) + throw INTERP_KERNEL::Exception("MEDFileIntFieldMultiTS::getFieldAtTopLevel : mismatch of type of field ! INT32 expected !"); + MEDCouplingAutoRefCountObjectPtr arr; + MEDCouplingAutoRefCountObjectPtr ret=myF1TSC->getFieldAtTopLevel(type,0,renumPol,this,arr,*contentNotNullBase()); + arrOut=MEDFileIntField1TS::ReturnSafelyDataArrayInt(arr); + return ret.retn(); } /*! @@ -5972,6 +8229,7 @@ MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldAtTopLevel(TypeOfField type * \param [in] type - a spatial discretization of interest. * \param [in] iteration - the iteration number of a required time step. * \param [in] order - the iteration order number of required time step. + * \param [out] arrOut - the DataArrayInt containing values of field. * \param [in] meshDimRelToMax - a relative dimension of the supporting mesh entities. * \param [in] mesh - the supporting mesh. * \param [in] renumPol - specifies how to permute values of the result field according to @@ -5987,10 +8245,16 @@ MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldAtTopLevel(TypeOfField type * \throw If no field of \a this is lying on \a mesh. * \throw If no field values of the required parameters are available. */ -MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, int renumPol) const throw(INTERP_KERNEL::Exception) +MEDCouplingFieldDouble *MEDFileIntFieldMultiTS::getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt* &arrOut, int renumPol) const throw(INTERP_KERNEL::Exception) { - const MEDFileField1TSWithoutSDA& myF1TS=_content->getTimeStepEntry(iteration,order); - return myF1TS.getFieldOnMeshAtLevel(type,meshDimRelToMax,renumPol,this,mesh); + const MEDFileAnyTypeField1TSWithoutSDA& myF1TS=contentNotNullBase()->getTimeStepEntry(iteration,order); + const MEDFileIntField1TSWithoutSDA *myF1TSC=dynamic_cast(&myF1TS); + if(!myF1TSC) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::getFieldOnMeshAtLevel : mismatch of type of field ! INT32 expected !"); + MEDCouplingAutoRefCountObjectPtr arr; + MEDCouplingAutoRefCountObjectPtr ret=myF1TSC->getFieldOnMeshAtLevel(type,meshDimRelToMax,renumPol,this,mesh,arr,*contentNotNullBase()); + arrOut=MEDFileIntField1TS::ReturnSafelyDataArrayInt(arr); + return ret.retn(); } /*! @@ -6001,6 +8265,7 @@ MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldOnMeshAtLevel(TypeOfField t * \param [in] iteration - the iteration number of a required time step. * \param [in] order - the iteration order number of required time step. * \param [in] mesh - the supporting mesh. + * \param [out] arrOut - the DataArrayInt containing values of field. * \param [in] renumPol - specifies how to permute values of the result field according to * the optional numbers of cells and nodes, if any. The valid values are * - 0 - do not permute. @@ -6013,21 +8278,33 @@ MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldOnMeshAtLevel(TypeOfField t * \throw If no field of \a this is lying on \a mesh. * \throw If no field values of the required parameters are available. */ -MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, const MEDCouplingMesh *mesh, int renumPol) const throw(INTERP_KERNEL::Exception) +MEDCouplingFieldDouble *MEDFileIntFieldMultiTS::getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, const MEDCouplingMesh *mesh, DataArrayInt* &arrOut, int renumPol) const throw(INTERP_KERNEL::Exception) { - const MEDFileField1TSWithoutSDA& myF1TS=_content->getTimeStepEntry(iteration,order); - return myF1TS.getFieldOnMeshAtLevel(type,renumPol,this,mesh,0,0); + const MEDFileAnyTypeField1TSWithoutSDA& myF1TS=contentNotNullBase()->getTimeStepEntry(iteration,order); + const MEDFileIntField1TSWithoutSDA *myF1TSC=dynamic_cast(&myF1TS); + if(!myF1TSC) + throw INTERP_KERNEL::Exception("MEDFileFieldIntMultiTS::getFieldOnMeshAtLevel : mismatch of type of field ! INT32 expected !"); + MEDCouplingAutoRefCountObjectPtr arr; + MEDCouplingAutoRefCountObjectPtr ret=myF1TSC->getFieldOnMeshAtLevel(type,renumPol,this,mesh,0,0,arr,*contentNotNullBase()); + arrOut=MEDFileIntField1TS::ReturnSafelyDataArrayInt(arr); + return ret.retn(); } /*! - * This method has a close behaviour than MEDFileFieldMultiTS::getFieldAtLevel. + * This method has a close behaviour than MEDFileIntFieldMultiTS::getFieldAtLevel. * This method is called 'old' because the user should give the mesh name he wants to use for it's field. * This method is useful for MED2 file format when field on different mesh was autorized. */ -MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldAtLevelOld(TypeOfField type, const char *mname, int iteration, int order, int meshDimRelToMax, int renumPol) const throw(INTERP_KERNEL::Exception) +MEDCouplingFieldDouble *MEDFileIntFieldMultiTS::getFieldAtLevelOld(TypeOfField type, int iteration, int order, const char *mname, int meshDimRelToMax, DataArrayInt* &arrOut, int renumPol) const throw(INTERP_KERNEL::Exception) { - const MEDFileField1TSWithoutSDA& myF1TS=_content->getTimeStepEntry(iteration,order); - return myF1TS.getFieldAtLevel(type,meshDimRelToMax,mname,renumPol,this); + const MEDFileAnyTypeField1TSWithoutSDA& myF1TS=contentNotNullBase()->getTimeStepEntry(iteration,order); + const MEDFileIntField1TSWithoutSDA *myF1TSC=dynamic_cast(&myF1TS); + if(!myF1TSC) + throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::getFieldOnMeshAtLevel : mismatch of type of field ! INT32 expected !"); + MEDCouplingAutoRefCountObjectPtr arr; + MEDCouplingAutoRefCountObjectPtr ret=myF1TSC->getFieldAtLevel(type,meshDimRelToMax,mname,renumPol,this,arr,*contentNotNullBase()); + arrOut=MEDFileIntField1TS::ReturnSafelyDataArrayInt(arr); + return ret.retn(); } /*! @@ -6044,16 +8321,46 @@ MEDCouplingFieldDouble *MEDFileFieldMultiTS::getFieldAtLevelOld(TypeOfField type * dimension, all ids in \a pfl are zero. The caller is to delete this array * using decrRef() as it is no more needed. * \param [in] glob - the global data storing profiles and localization. - * \return DataArrayDouble * - a new instance of DataArrayDouble holding values of the + * \return DataArrayInt * - a new instance of DataArrayInt holding values of the * field. The caller is to delete this array using decrRef() as it is no more needed. * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a mesh. * \throw If no field of \a this is lying on \a mesh. * \throw If no field values of the required parameters are available. */ -DataArrayDouble *MEDFileFieldMultiTS::getFieldWithProfile(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl) const throw(INTERP_KERNEL::Exception) +DataArrayInt *MEDFileIntFieldMultiTS::getFieldWithProfile(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl) const throw(INTERP_KERNEL::Exception) +{ + const MEDFileAnyTypeField1TSWithoutSDA& myF1TS=contentNotNullBase()->getTimeStepEntry(iteration,order); + const MEDFileIntField1TSWithoutSDA *myF1TSC=dynamic_cast(&myF1TS); + if(!myF1TSC) + throw INTERP_KERNEL::Exception("MEDFileIntFieldMultiTS::getFieldWithProfile : mismatch of type of field ! INT32 expected !"); + MEDCouplingAutoRefCountObjectPtr ret=myF1TSC->getFieldWithProfile(type,meshDimRelToMax,mesh,pfl,this,*contentNotNullBase()); + return MEDFileIntField1TS::ReturnSafelyDataArrayInt(ret); +} + +/*! + * Returns a new MEDFileIntField1TS holding data of a given time step of \a this field. + * \param [in] pos - a time step id. + * \return MEDFileIntField1TS * - a new instance of MEDFileIntField1TS. The caller is to + * delete this field using decrRef() as it is no more needed. + * \throw If \a pos is not a valid time step id. + */ +MEDFileAnyTypeField1TS *MEDFileIntFieldMultiTS::getTimeStepAtPos(int pos) const throw(INTERP_KERNEL::Exception) { - const MEDFileField1TSWithoutSDA& myF1TS=_content->getTimeStepEntry(iteration,order); - return myF1TS.getFieldWithProfile(type,meshDimRelToMax,mesh,pfl,this); + const MEDFileAnyTypeField1TSWithoutSDA *item=contentNotNullBase()->getTimeStepAtPos2(pos); + if(!item) + { + std::ostringstream oss; oss << "MEDFileIntFieldMultiTS::getTimeStepAtPos : field at pos #" << pos << " is null !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + const MEDFileIntField1TSWithoutSDA *itemC=dynamic_cast(item); + if(itemC) + { + MEDCouplingAutoRefCountObjectPtr ret=MEDFileIntField1TS::New(*itemC,false); + ret->shallowCpyGlobs(*this); + return ret.retn(); + } + std::ostringstream oss; oss << "MEDFileIntFieldMultiTS::getTimeStepAtPos : type of field at pos #" << pos << " is not INT32 !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); } /*! @@ -6068,9 +8375,9 @@ DataArrayDouble *MEDFileFieldMultiTS::getFieldWithProfile(TypeOfField type, int * \throw If the underlying mesh of \a field has no name. * \throw If elements in the mesh are not in the order suitable for writing to the MED file. */ -void MEDFileFieldMultiTS::appendFieldNoProfileSBT(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception) +void MEDFileIntFieldMultiTS::appendFieldNoProfileSBT(const MEDCouplingFieldDouble *field, const DataArrayInt *arrOfVals) throw(INTERP_KERNEL::Exception) { - _content->appendFieldNoProfileSBT(field,*this); + contentNotNull()->appendFieldNoProfileSBT(field,arrOfVals,*this); } /*! @@ -6091,252 +8398,62 @@ void MEDFileFieldMultiTS::appendFieldNoProfileSBT(const MEDCouplingFieldDouble * * \throw If the data array of \a field is not set. * \throw If elements in \a mesh are not in the order suitable for writing to the MED file. */ -void MEDFileFieldMultiTS::appendFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception) -{ - _content->appendFieldProfile(field,mesh,meshDimRelToMax,profile,*this); -} - -MEDCouplingAutoRefCountObjectPtr MEDFileFieldMultiTS::getContent() -{ - return _content; -} - -MEDFileFieldMultiTS::MEDFileFieldMultiTS():_content(new MEDFileFieldMultiTSWithoutSDA) -{ -} - - - -MEDFileFieldMultiTS::MEDFileFieldMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception) -try:MEDFileFieldGlobsReal(fileName) -{ - MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); - int nbFields=MEDnField(fid); - if(nbFields<1) - { - std::ostringstream oss; oss << "MEDFileFieldMultiTS(const char *fileName) constructor : no fields in file \"" << fileName << "\" !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - _content=new MEDFileFieldMultiTSWithoutSDA(fid,0); - // - loadGlobals(fid); -} -catch(INTERP_KERNEL::Exception& e) - { - throw e; - } - -MEDFileFieldMultiTS::MEDFileFieldMultiTS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) -try:MEDFileFieldGlobsReal(fileName) -{ - MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); - int nbFields=MEDnField(fid); - med_field_type typcha; - bool found=false; - std::vector fns(nbFields); - for(int i=0;i comp=MEDLoaderBase::buildEmptyString(ncomp*MED_SNAME_SIZE); - INTERP_KERNEL::AutoPtr unit=MEDLoaderBase::buildEmptyString(ncomp*MED_SNAME_SIZE); - INTERP_KERNEL::AutoPtr dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE); - INTERP_KERNEL::AutoPtr nomcha=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); - INTERP_KERNEL::AutoPtr nomMaa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); - med_bool localMesh; - int nbOfStep; - MEDfieldInfo(fid,i+1,nomcha,nomMaa,&localMesh,&typcha,comp,unit,dtunit,&nbOfStep); - std::string tmp(nomcha); - fns[i]=tmp; - found=(tmp==fieldName); - if(found) - _content=new MEDFileFieldMultiTSWithoutSDA(fid,i); - } - if(!found) - { - std::ostringstream oss; oss << "No such field '" << fieldName << "' in file '" << fileName << "' ! Available fields are : "; - std::copy(fns.begin(),fns.end(),std::ostream_iterator(oss," ")); - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - // - loadGlobals(fid); -} -catch(INTERP_KERNEL::Exception& e) - { - throw e; - } - -MEDFileFieldMultiTS::MEDFileFieldMultiTS(const MEDFileFieldMultiTSWithoutSDA& other, bool shallowCopyOfContent) -{ - if(!shallowCopyOfContent) - { - const MEDFileFieldMultiTSWithoutSDA *otherPtr(&other); - otherPtr->incrRef(); - _content=const_cast(otherPtr); - } - else - { - _content=new MEDFileFieldMultiTSWithoutSDA(other); - } -} - -std::vector MEDFileFieldMultiTS::getPflsReallyUsed() const -{ - return _content->getPflsReallyUsed2(); -} - -std::vector MEDFileFieldMultiTS::getLocsReallyUsed() const -{ - return _content->getLocsReallyUsed2(); -} - -std::vector MEDFileFieldMultiTS::getPflsReallyUsedMulti() const -{ - return _content->getPflsReallyUsedMulti2(); -} - -std::vector MEDFileFieldMultiTS::getLocsReallyUsedMulti() const -{ - return _content->getLocsReallyUsedMulti2(); -} - -void MEDFileFieldMultiTS::changePflsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) -{ - _content->changePflsRefsNamesGen2(mapOfModif); -} - -void MEDFileFieldMultiTS::changeLocsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) -{ - _content->changeLocsRefsNamesGen2(mapOfModif); -} - -int MEDFileFieldMultiTS::getNumberOfTS() const -{ - return _content->getNumberOfTS(); -} - -void MEDFileFieldMultiTS::eraseEmptyTS() throw(INTERP_KERNEL::Exception) -{ - _content->eraseEmptyTS(); -} - -void MEDFileFieldMultiTS::eraseTimeStepIds(const int *startIds, const int *endIds) throw(INTERP_KERNEL::Exception) -{ - _content->eraseTimeStepIds(startIds,endIds); -} - -std::vector< std::pair > MEDFileFieldMultiTS::getIterations() const -{ - return _content->getIterations(); -} - -int MEDFileFieldMultiTS::getPosOfTimeStep(int iteration, int order) const throw(INTERP_KERNEL::Exception) -{ - return _content->getPosOfTimeStep(iteration,order); -} - -int MEDFileFieldMultiTS::getPosGivenTime(double time, double eps) const throw(INTERP_KERNEL::Exception) -{ - return _content->getPosGivenTime(time,eps); -} - -int MEDFileFieldMultiTS::getNonEmptyLevels(int iteration, int order, const char *mname, std::vector& levs) const throw(INTERP_KERNEL::Exception) -{ - return _content->getNonEmptyLevels(iteration,order,mname,levs); -} - -std::vector< std::vector > MEDFileFieldMultiTS::getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception) -{ - return _content->getTypesOfFieldAvailable(); -} - -std::vector< std::vector< std::pair > > MEDFileFieldMultiTS::getFieldSplitedByType(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) -{ - return _content->getFieldSplitedByType(iteration,order,mname,types,typesF,pfls,locs); -} - -std::vector< std::vector > MEDFileFieldMultiTS::getFieldSplitedByType2(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception) -{ - return _content->getFieldSplitedByType2(iteration,order,mname,types,typesF,pfls,locs); -} - -std::string MEDFileFieldMultiTS::getName() const +void MEDFileIntFieldMultiTS::appendFieldProfile(const MEDCouplingFieldDouble *field, const DataArrayInt *arrOfVals, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception) { - return _content->getName(); + contentNotNull()->appendFieldProfile(field,arrOfVals,mesh,meshDimRelToMax,profile,*this); } -void MEDFileFieldMultiTS::setName(const char *name) +const MEDFileIntFieldMultiTSWithoutSDA *MEDFileIntFieldMultiTS::contentNotNull() const throw(INTERP_KERNEL::Exception) { - _content->setName(name); -} - -void MEDFileFieldMultiTS::simpleRepr(int bkOffset, std::ostream& oss, int fmtsId) const -{ - _content->simpleRepr(bkOffset,oss,fmtsId); -} - -std::vector< std::pair > MEDFileFieldMultiTS::getTimeSteps(std::vector& ret1) const throw(INTERP_KERNEL::Exception) -{ - return _content->getTimeSteps(ret1); -} - -std::string MEDFileFieldMultiTS::getMeshName() const throw(INTERP_KERNEL::Exception) -{ - return _content->getMeshName(); -} - -void MEDFileFieldMultiTS::setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception) -{ - _content->setMeshName(newMeshName); + const MEDFileAnyTypeFieldMultiTSWithoutSDA *pt(_content); + if(!pt) + throw INTERP_KERNEL::Exception("MEDFileIntFieldMultiTS::contentNotNull : the content pointer is null !"); + const MEDFileIntFieldMultiTSWithoutSDA *ret=dynamic_cast(pt); + if(!ret) + throw INTERP_KERNEL::Exception("MEDFileIntFieldMultiTS::contentNotNull : the content pointer is not null but it is not of type int ! Reason is maybe that the read field has not the type INT32 !"); + return ret; } -bool MEDFileFieldMultiTS::changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception) + MEDFileIntFieldMultiTSWithoutSDA *MEDFileIntFieldMultiTS::contentNotNull() throw(INTERP_KERNEL::Exception) { - return _content->changeMeshNames(modifTab); + MEDFileAnyTypeFieldMultiTSWithoutSDA *pt(_content); + if(!pt) + throw INTERP_KERNEL::Exception("MEDFileIntFieldMultiTS::contentNotNull : the non const content pointer is null !"); + MEDFileIntFieldMultiTSWithoutSDA *ret=dynamic_cast(pt); + if(!ret) + throw INTERP_KERNEL::Exception("MEDFileIntFieldMultiTS::contentNotNull : the non const content pointer is not null but it is not of type int ! Reason is maybe that the read field has not the type INT32 !"); + return ret; } -const std::vector& MEDFileFieldMultiTS::getInfo() const throw(INTERP_KERNEL::Exception) +MEDFileIntFieldMultiTS::MEDFileIntFieldMultiTS() { - return _content->getInfo(); + _content=new MEDFileIntFieldMultiTSWithoutSDA; } -DataArrayDouble *MEDFileFieldMultiTS::getUndergroundDataArray(int iteration, int order) const throw(INTERP_KERNEL::Exception) +MEDFileIntFieldMultiTS::MEDFileIntFieldMultiTS(const MEDFileIntFieldMultiTSWithoutSDA& other, bool shallowCopyOfContent):MEDFileAnyTypeFieldMultiTS(other,shallowCopyOfContent) { - return _content->getUndergroundDataArray(iteration,order); } -DataArrayDouble *MEDFileFieldMultiTS::getUndergroundDataArrayExt(int iteration, int order, std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) +MEDFileIntFieldMultiTS::MEDFileIntFieldMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeFieldMultiTS(fileName) { - return _content->getUndergroundDataArrayExt(iteration,order,entries); } +catch(INTERP_KERNEL::Exception& e) + { throw e; } -MEDFileFieldMultiTSIterator::MEDFileFieldMultiTSIterator(MEDFileFieldMultiTS *fmts):_fmts(fmts),_iter_id(0),_nb_iter(0) +MEDFileIntFieldMultiTS::MEDFileIntFieldMultiTS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) +try:MEDFileAnyTypeFieldMultiTS(fileName,fieldName) { - if(fmts) - { - fmts->incrRef(); - _nb_iter=fmts->getNumberOfTS(); - } } +catch(INTERP_KERNEL::Exception& e) + { throw e; } -MEDFileFieldMultiTSIterator::~MEDFileFieldMultiTSIterator() +DataArrayInt *MEDFileIntFieldMultiTS::getUndergroundDataArray(int iteration, int order) const throw(INTERP_KERNEL::Exception) { + return static_cast(contentNotNull()->getUndergroundDataArray(iteration,order)); } -MEDFileField1TS *MEDFileFieldMultiTSIterator::nextt() -{ - if(_iter_id<_nb_iter) - { - MEDFileFieldMultiTS *fmts(_fmts); - if(fmts) - return fmts->getTimeStepAtPos(_iter_id++); - else - return 0; - } - else - return 0; -} +//= MEDFileFields MEDFileFields *MEDFileFields::New() { @@ -6350,26 +8467,67 @@ MEDFileFields *MEDFileFields::New(const char *fileName) throw(INTERP_KERNEL::Exc std::size_t MEDFileFields::getHeapMemorySize() const { - std::size_t ret=_fields.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr); - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++) - if((const MEDFileFieldMultiTSWithoutSDA *)*it) + std::size_t ret=_fields.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++) + if((const MEDFileAnyTypeFieldMultiTSWithoutSDA *)*it) ret+=(*it)->getHeapMemorySize(); return ret+MEDFileFieldGlobsReal::getHeapMemorySize(); } MEDFileFields *MEDFileFields::deepCpy() const throw(INTERP_KERNEL::Exception) { - MEDCouplingAutoRefCountObjectPtr ret=new MEDFileFields(*this); + MEDCouplingAutoRefCountObjectPtr ret=shallowCpy(); std::size_t i=0; - for( std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++,i++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++,i++) { - if((const MEDFileFieldMultiTSWithoutSDA*)*it) + if((const MEDFileAnyTypeFieldMultiTSWithoutSDA*)*it) ret->_fields[i]=(*it)->deepCpy(); } ret->deepCpyGlobs(*this); return ret.retn(); } +MEDFileFields *MEDFileFields::shallowCpy() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileFields(*this); +} + +/*! + * This method scans for all fields in \a this which time steps ids are common. Time step are discriminated by the pair of integer (iteration,order) whatever + * the double time value. If all returned time steps are \b exactly those for all fields in \a this output parameter \a areThereSomeForgottenTS will be set to false. + * If \a areThereSomeForgottenTS is set to true, only the sorted intersection of time steps present for all fields in \a this will be returned. + * + * \param [out] areThereSomeForgottenTS - indicates to the caller if there is some time steps in \a this that are not present for all fields in \a this. + * \return the sorted list of time steps (specified with a pair of integer iteration first and order second) present for all fields in \a this. + * + * \sa MEDFileFields::partOfThisLyingOnSpecifiedTimeSteps, MEDFileFields::partOfThisNotLyingOnSpecifiedTimeSteps + */ +std::vector< std::pair > MEDFileFields::getCommonIterations(bool& areThereSomeForgottenTS) const throw(INTERP_KERNEL::Exception) +{ + std::set< std::pair > s; + bool firstShot=true; + areThereSomeForgottenTS=false; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++) + { + if(!(const MEDFileAnyTypeFieldMultiTSWithoutSDA*)*it) + continue; + std::vector< std::pair > v=(*it)->getIterations(); + std::set< std::pair > s1; std::copy(v.begin(),v.end(),std::inserter(s1,s1.end())); + if(firstShot) + { s=s1; firstShot=false; } + else + { + std::set< std::pair > s2; std::set_intersection(s.begin(),s.end(),s1.begin(),s1.end(),std::inserter(s2,s2.end())); + if(s!=s2) + areThereSomeForgottenTS=true; + s=s2; + } + } + std::vector< std::pair > ret; + std::copy(s.begin(),s.end(),std::back_insert_iterator< std::vector< std::pair > >(ret)); + return ret; +} + int MEDFileFields::getNumberOfFields() const { return _fields.size(); @@ -6379,9 +8537,9 @@ std::vector MEDFileFields::getFieldsNames() const throw(INTERP_KERN { std::vector ret(_fields.size()); int i=0; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++,i++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++,i++) { - const MEDFileFieldMultiTSWithoutSDA *f=(*it); + const MEDFileAnyTypeFieldMultiTSWithoutSDA *f=(*it); if(f) { ret[i]=f->getName(); @@ -6398,9 +8556,9 @@ std::vector MEDFileFields::getFieldsNames() const throw(INTERP_KERN std::vector MEDFileFields::getMeshesNames() const throw(INTERP_KERNEL::Exception) { std::vector ret; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++) { - const MEDFileFieldMultiTSWithoutSDA *cur(*it); + const MEDFileAnyTypeFieldMultiTSWithoutSDA *cur(*it); if(cur) ret.push_back(cur->getMeshName()); } @@ -6421,9 +8579,9 @@ void MEDFileFields::simpleRepr(int bkOffset, std::ostream& oss) const std::string startLine(bkOffset,' '); oss << startLine << "There are " << nbOfFields << " fields in this :" << std::endl; int i=0; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++,i++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++,i++) { - const MEDFileFieldMultiTSWithoutSDA *cur=(*it); + const MEDFileAnyTypeFieldMultiTSWithoutSDA *cur=(*it); if(cur) { oss << startLine << " - # "<< i << " has the following name : \"" << cur->getName() << "\"." << std::endl; @@ -6434,9 +8592,9 @@ void MEDFileFields::simpleRepr(int bkOffset, std::ostream& oss) const } } i=0; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++,i++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++,i++) { - const MEDFileFieldMultiTSWithoutSDA *cur=(*it); + const MEDFileAnyTypeFieldMultiTSWithoutSDA *cur=(*it); std::string chapter(17,'0'+i); oss << startLine << chapter << std::endl; if(cur) @@ -6449,7 +8607,7 @@ void MEDFileFields::simpleRepr(int bkOffset, std::ostream& oss) const } oss << startLine << chapter << std::endl; } - MEDFileFieldGlobsReal::simpleRepr(oss); + simpleReprGlobs(oss); } MEDFileFields::MEDFileFields() @@ -6466,20 +8624,27 @@ try:MEDFileFieldGlobsReal(fileName) med_field_type typcha; for(int i=0;i comp=MEDLoaderBase::buildEmptyString(ncomp*MED_SNAME_SIZE); - INTERP_KERNEL::AutoPtr unit=MEDLoaderBase::buildEmptyString(ncomp*MED_SNAME_SIZE); - INTERP_KERNEL::AutoPtr dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE); - INTERP_KERNEL::AutoPtr nomcha=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); - INTERP_KERNEL::AutoPtr nomMaa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); - med_bool localMesh; - int nbOfStep; - MEDfieldInfo(fid,i+1,nomcha,nomMaa,&localMesh,&typcha,comp,unit,dtunit,&nbOfStep); - int ft=MEDFileUtilities::TraduceFieldType(typcha); - std::vector infos(ncomp); - for(int j=0;j infos; + std::string fieldName,dtunit; + int nbOfStep=MEDFileAnyTypeField1TS::LocateField2(fid,fileName,i,false,fieldName,typcha,infos,dtunit); + switch(typcha) + { + case MED_FLOAT64: + { + _fields[i]=MEDFileFieldMultiTSWithoutSDA::New(fid,fieldName.c_str(),typcha,infos,nbOfStep,dtunit); + break; + } + case MED_INT32: + { + _fields[i]=MEDFileIntFieldMultiTSWithoutSDA::New(fid,fieldName.c_str(),typcha,infos,nbOfStep,dtunit); + break; + } + default: + { + std::ostringstream oss; oss << "constructor MEDFileFields(fileName) : file \'" << fileName << "\' at pos #" << i << " field has name \'" << fieldName << "\' but the type of field is not in [MED_FLOAT64, MED_INT32] !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } } loadAllGlobals(fid); } @@ -6492,9 +8657,9 @@ void MEDFileFields::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) { int i=0; writeGlobals(fid,*this); - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++,i++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++,i++) { - const MEDFileFieldMultiTSWithoutSDA *elt=*it; + const MEDFileAnyTypeFieldMultiTSWithoutSDA *elt=*it; if(!elt) { std::ostringstream oss; oss << "MEDFileFields::write : at rank #" << i << "/" << _fields.size() << " field is empty !"; @@ -6515,7 +8680,7 @@ std::vector MEDFileFields::getPflsReallyUsed() const { std::vector ret; std::set ret2; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldMultiTSWithoutSDA > >::const_iterator it=_fields.begin();it!=_fields.end();it++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeFieldMultiTSWithoutSDA > >::const_iterator it=_fields.begin();it!=_fields.end();it++) { std::vector tmp=(*it)->getPflsReallyUsed2(); for(std::vector::const_iterator it2=tmp.begin();it2!=tmp.end();it2++) @@ -6532,7 +8697,7 @@ std::vector MEDFileFields::getLocsReallyUsed() const { std::vector ret; std::set ret2; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldMultiTSWithoutSDA > >::const_iterator it=_fields.begin();it!=_fields.end();it++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeFieldMultiTSWithoutSDA > >::const_iterator it=_fields.begin();it!=_fields.end();it++) { std::vector tmp=(*it)->getLocsReallyUsed2(); for(std::vector::const_iterator it2=tmp.begin();it2!=tmp.end();it2++) @@ -6548,7 +8713,7 @@ std::vector MEDFileFields::getLocsReallyUsed() const std::vector MEDFileFields::getPflsReallyUsedMulti() const { std::vector ret; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldMultiTSWithoutSDA > >::const_iterator it=_fields.begin();it!=_fields.end();it++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeFieldMultiTSWithoutSDA > >::const_iterator it=_fields.begin();it!=_fields.end();it++) { std::vector tmp=(*it)->getPflsReallyUsedMulti2(); ret.insert(ret.end(),tmp.begin(),tmp.end()); @@ -6559,7 +8724,7 @@ std::vector MEDFileFields::getPflsReallyUsedMulti() const std::vector MEDFileFields::getLocsReallyUsedMulti() const { std::vector ret; - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldMultiTSWithoutSDA > >::const_iterator it=_fields.begin();it!=_fields.end();it++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeFieldMultiTSWithoutSDA > >::const_iterator it=_fields.begin();it!=_fields.end();it++) { std::vector tmp=(*it)->getLocsReallyUsed2(); ret.insert(ret.end(),tmp.begin(),tmp.end()); @@ -6569,13 +8734,13 @@ std::vector MEDFileFields::getLocsReallyUsedMulti() const void MEDFileFields::changePflsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) { - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldMultiTSWithoutSDA > >::iterator it=_fields.begin();it!=_fields.end();it++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeFieldMultiTSWithoutSDA > >::iterator it=_fields.begin();it!=_fields.end();it++) (*it)->changePflsRefsNamesGen2(mapOfModif); } void MEDFileFields::changeLocsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception) { - for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldMultiTSWithoutSDA > >::iterator it=_fields.begin();it!=_fields.end();it++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeFieldMultiTSWithoutSDA > >::iterator it=_fields.begin();it!=_fields.end();it++) (*it)->changeLocsRefsNamesGen2(mapOfModif); } @@ -6584,7 +8749,13 @@ void MEDFileFields::resize(int newSize) throw(INTERP_KERNEL::Exception) _fields.resize(newSize); } -void MEDFileFields::pushField(MEDFileFieldMultiTS *field) throw(INTERP_KERNEL::Exception) +void MEDFileFields::pushFields(const std::vector& fields) throw(INTERP_KERNEL::Exception) +{ + for(std::vector::const_iterator it=fields.begin();it!=fields.end();it++) + pushField(*it); +} + +void MEDFileFields::pushField(MEDFileAnyTypeFieldMultiTS *field) throw(INTERP_KERNEL::Exception) { if(!field) throw INTERP_KERNEL::Exception("MEDFileFields::pushMesh : invalid input pointer ! should be different from 0 !"); @@ -6592,7 +8763,7 @@ void MEDFileFields::pushField(MEDFileFieldMultiTS *field) throw(INTERP_KERNEL::E appendGlobs(*field,1e-12); } -void MEDFileFields::setFieldAtPos(int i, MEDFileFieldMultiTS *field) throw(INTERP_KERNEL::Exception) +void MEDFileFields::setFieldAtPos(int i, MEDFileAnyTypeFieldMultiTS *field) throw(INTERP_KERNEL::Exception) { if(!field) throw INTERP_KERNEL::Exception("MEDFileFields::setFieldAtPos : invalid input pointer ! should be different from 0 !"); @@ -6604,20 +8775,58 @@ void MEDFileFields::setFieldAtPos(int i, MEDFileFieldMultiTS *field) throw(INTER void MEDFileFields::destroyFieldAtPos(int i) throw(INTERP_KERNEL::Exception) { - if(i<0 || i>=(int)_fields.size()) + destroyFieldsAtPos(&i,&i+1); +} + +void MEDFileFields::destroyFieldsAtPos(const int *startIds, const int *endIds) throw(INTERP_KERNEL::Exception) +{ + std::vector b(_fields.size(),true); + for(const int *i=startIds;i!=endIds;i++) { - std::ostringstream oss; oss << "MEDFileFields::destroyMeshAtPos : Invalid given id in input (" << i << ") should be in [0," << _fields.size() << ") !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); + if(*i<0 || *i>=(int)_fields.size()) + { + std::ostringstream oss; oss << "MEDFileFields::destroyFieldsAtPos : Invalid given id in input (" << *i << ") should be in [0," << _fields.size() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + b[*i]=false; + } + std::vector< MEDCouplingAutoRefCountObjectPtr > fields(std::count(b.begin(),b.end(),true)); + std::size_t j=0; + for(std::size_t i=0;i<_fields.size();i++) + if(b[i]) + fields[j++]=_fields[i]; + _fields=fields; +} + +void MEDFileFields::destroyFieldsAtPos2(int bg, int end, int step) throw(INTERP_KERNEL::Exception) +{ + static const char msg[]="MEDFileFields::destroyFieldsAtPos2"; + int nbOfEntriesToKill=DataArrayInt::GetNumberOfItemGivenBESRelative(bg,end,step,msg); + std::vector b(_fields.size(),true); + int k=bg; + for(int i=0;i=(int)_fields.size()) + { + std::ostringstream oss; oss << "MEDFileFields::destroyFieldsAtPos2 : Invalid given id in input (" << k << ") should be in [0," << _fields.size() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + b[k]=false; } - _fields.erase(_fields.begin()+i); + std::vector< MEDCouplingAutoRefCountObjectPtr > fields(std::count(b.begin(),b.end(),true)); + std::size_t j=0; + for(std::size_t i=0;i<_fields.size();i++) + if(b[i]) + fields[j++]=_fields[i]; + _fields=fields; } bool MEDFileFields::changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception) { bool ret=false; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_fields.begin();it!=_fields.end();it++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_fields.begin();it!=_fields.end();it++) { - MEDFileFieldMultiTSWithoutSDA *cur(*it); + MEDFileAnyTypeFieldMultiTSWithoutSDA *cur(*it); if(cur) ret=cur->changeMeshNames(modifTab) || ret; } @@ -6636,9 +8845,9 @@ bool MEDFileFields::changeMeshNames(const std::vector< std::pair& oldCode, const std::vector& newCode, const DataArrayInt *renumO2N) throw(INTERP_KERNEL::Exception) { bool ret=false; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_fields.begin();it!=_fields.end();it++) + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_fields.begin();it!=_fields.end();it++) { - MEDFileFieldMultiTSWithoutSDA *fmts(*it); + MEDFileAnyTypeFieldMultiTSWithoutSDA *fmts(*it); if(fmts) { ret=fmts->renumberEntitiesLyingOnMesh(meshName,oldCode,newCode,renumO2N,*this) || ret; @@ -6647,24 +8856,136 @@ bool MEDFileFields::renumberEntitiesLyingOnMesh(const char *meshName, const std: return ret; } -MEDFileFieldMultiTS *MEDFileFields::getFieldAtPos(int i) const throw(INTERP_KERNEL::Exception) +MEDFileAnyTypeFieldMultiTS *MEDFileFields::getFieldAtPos(int i) const throw(INTERP_KERNEL::Exception) { if(i<0 || i>=(int)_fields.size()) { std::ostringstream oss; oss << "MEDFileFields::getFieldAtPos : Invalid given id in input (" << i << ") should be in [0," << _fields.size() << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } - const MEDFileFieldMultiTSWithoutSDA *fmts=_fields[i]; - MEDCouplingAutoRefCountObjectPtr ret=MEDFileFieldMultiTS::New(*fmts,false); + const MEDFileAnyTypeFieldMultiTSWithoutSDA *fmts=_fields[i]; + if(!fmts) + return 0; + MEDCouplingAutoRefCountObjectPtr ret; + const MEDFileFieldMultiTSWithoutSDA *fmtsC=dynamic_cast(fmts); + const MEDFileIntFieldMultiTSWithoutSDA *fmtsC2=dynamic_cast(fmts); + if(fmtsC) + ret=MEDFileFieldMultiTS::New(*fmtsC,false); + else if(fmtsC2) + ret=MEDFileIntFieldMultiTS::New(*fmtsC2,false); + else + { + std::ostringstream oss; oss << "MEDFileFields::getFieldAtPos : At pos #" << i << " field is neither double (FLOAT64) nor integer (INT32) !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } ret->shallowCpyGlobs(*this); return ret.retn(); } -MEDFileFieldMultiTS *MEDFileFields::getFieldWithName(const char *fieldName) const throw(INTERP_KERNEL::Exception) +/*! + * Return a shallow copy of \a this reduced to the fields ids defined in [ \a startIds , endIds ). + * This method is accessible in python using __getitem__ with a list in input. + * \return a new object that the caller should deal with. + */ +MEDFileFields *MEDFileFields::buildSubPart(const int *startIds, const int *endIds) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=shallowCpy(); + std::size_t sz=std::distance(startIds,endIds); + std::vector< MEDCouplingAutoRefCountObjectPtr > fields(sz); + int j=0; + for(const int *i=startIds;i!=endIds;i++,j++) + { + if(*i<0 || *i>=(int)_fields.size()) + { + std::ostringstream oss; oss << "MEDFileFields::buildSubPart : Invalid given id in input (" << *i << ") should be in [0," << _fields.size() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + fields[j]=_fields[*i]; + } + ret->_fields=fields; + return ret.retn(); +} + +MEDFileAnyTypeFieldMultiTS *MEDFileFields::getFieldWithName(const char *fieldName) const throw(INTERP_KERNEL::Exception) { return getFieldAtPos(getPosFromFieldName(fieldName)); } +/*! + * This method returns a new object containing part of \a this fields lying on mesh name specified by the input parameter \a meshName. + * This method can be seen as a filter applied on \a this, that returns an object containing + * reduced the list of fields compared to those in \a this. The returned object is a new object but the object on which it lies are only + * shallow copied from \a this. + * + * \param [in] meshName - the name of the mesh on w + * \return a new object that the caller should deal with. + */ +MEDFileFields *MEDFileFields::partOfThisLyingOnSpecifiedMeshName(const char *meshName) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=MEDFileFields::New(); + ret->shallowCpyOnlyUsedGlobs(*this); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++) + { + const MEDFileAnyTypeFieldMultiTSWithoutSDA *cur=(*it); + if(!cur) + continue; + if(cur->getMeshName()==meshName) + { + cur->incrRef(); + MEDCouplingAutoRefCountObjectPtr cur2(const_cast(cur)); + ret->_fields.push_back(cur2); + } + } + return ret.retn(); +} + +/*! + * This method returns a new object containing part of \a this fields lying ** exactly ** on the time steps specified by input parameter \a timeSteps. + * Input time steps are specified using a pair of integer (iteration, order). + * This method can be seen as a filter applied on \a this, that returns an object containing the same number of fields than those in \a this, + * but for each multitimestep only the time steps in \a timeSteps are kept. + * Typically the input parameter \a timeSteps comes from the call of MEDFileFields::getCommonIterations. + * + * The returned object points to shallow copy of elements in \a this. + * + * \param [in] timeSteps - the time steps given by a vector of pair of integers (iteration,order) + * \throw If there is a field in \a this that is \b not defined on a time step in the input \a timeSteps. + * \sa MEDFileFields::getCommonIterations, MEDFileFields::partOfThisNotLyingOnSpecifiedTimeSteps + */ +MEDFileFields *MEDFileFields::partOfThisLyingOnSpecifiedTimeSteps(const std::vector< std::pair >& timeSteps) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=MEDFileFields::New(); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++) + { + const MEDFileAnyTypeFieldMultiTSWithoutSDA *cur=(*it); + if(!cur) + continue; + MEDCouplingAutoRefCountObjectPtr elt=cur->partOfThisLyingOnSpecifiedTimeSteps(timeSteps); + ret->_fields.push_back(elt); + } + ret->shallowCpyOnlyUsedGlobs(*this); + return ret.retn(); +} + +/*! + * \sa MEDFileFields::getCommonIterations, MEDFileFields::partOfThisLyingOnSpecifiedTimeSteps + */ +MEDFileFields *MEDFileFields::partOfThisNotLyingOnSpecifiedTimeSteps(const std::vector< std::pair >& timeSteps) const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=MEDFileFields::New(); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_fields.begin();it!=_fields.end();it++) + { + const MEDFileAnyTypeFieldMultiTSWithoutSDA *cur=(*it); + if(!cur) + continue; + MEDCouplingAutoRefCountObjectPtr elt=cur->partOfThisNotLyingOnSpecifiedTimeSteps(timeSteps); + if(elt->getNumberOfTS()!=0) + ret->_fields.push_back(elt); + } + ret->shallowCpyOnlyUsedGlobs(*this); + return ret.retn(); +} + MEDFileFieldsIterator *MEDFileFields::iterator() throw(INTERP_KERNEL::Exception) { return new MEDFileFieldsIterator(this); @@ -6676,7 +8997,7 @@ int MEDFileFields::getPosFromFieldName(const char *fieldName) const throw(INTERP std::vector poss; for(std::size_t i=0;i<_fields.size();i++) { - const MEDFileFieldMultiTSWithoutSDA *f=_fields[i]; + const MEDFileAnyTypeFieldMultiTSWithoutSDA *f=_fields[i]; if(f) { std::string fname(f->getName()); @@ -6705,7 +9026,7 @@ MEDFileFieldsIterator::~MEDFileFieldsIterator() { } -MEDFileFieldMultiTS *MEDFileFieldsIterator::nextt() +MEDFileAnyTypeFieldMultiTS *MEDFileFieldsIterator::nextt() { if(_iter_id<_nb_iter) { diff --git a/src/MEDLoader/MEDFileField.hxx b/src/MEDLoader/MEDFileField.hxx index 38193c808..fdf54072f 100644 --- a/src/MEDLoader/MEDFileField.hxx +++ b/src/MEDLoader/MEDFileField.hxx @@ -84,8 +84,10 @@ namespace ParaMEDMEM }; /// @cond INTERNAL + class MEDFileAnyTypeField1TSWithoutSDA; class MEDFileFieldPerMeshPerType; class MEDFileField1TSWithoutSDA; + class MEDFileFieldNameScope; class MEDFileFieldGlobsReal; class MEDFileFieldPerMesh; @@ -97,19 +99,18 @@ namespace ParaMEDMEM static MEDFileFieldPerMeshPerTypePerDisc *New(const MEDFileFieldPerMeshPerTypePerDisc& other); std::size_t getHeapMemorySize() const; MEDFileFieldPerMeshPerTypePerDisc *deepCpy(MEDFileFieldPerMeshPerType *father) const throw(INTERP_KERNEL::Exception); - void assignFieldNoProfile(int& start, int offset, int nbOfCells, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); - void assignFieldProfile(int& start, const DataArrayInt *multiTypePfl, const DataArrayInt *idsInPfl, DataArrayInt *locIds, int nbOfEltsInWholeMesh, const MEDCouplingFieldDouble *field, const MEDCouplingMesh *mesh, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); - void assignNodeFieldNoProfile(int& start, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); + void assignFieldNoProfile(int& start, int offset, int nbOfCells, const MEDCouplingFieldDouble *field, const DataArray *arrr, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void assignFieldProfile(int& start, const DataArrayInt *multiTypePfl, const DataArrayInt *idsInPfl, DataArrayInt *locIds, int nbOfEltsInWholeMesh, const MEDCouplingFieldDouble *field, const DataArray *arrr, const MEDCouplingMesh *mesh, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void assignNodeFieldNoProfile(int& start, const MEDCouplingFieldDouble *field, const DataArray *arrr, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); void getCoarseData(TypeOfField& type, std::pair& dad, std::string& pfl, std::string& loc) const throw(INTERP_KERNEL::Exception); - void writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception); + void writeLL(med_idt fid, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); const MEDFileFieldPerMeshPerType *getFather() const; - void prepareLoading(med_idt fid, int profileIt, int& start) throw(INTERP_KERNEL::Exception); - void finishLoading(med_idt fid, int profileIt, int ft) throw(INTERP_KERNEL::Exception); + void prepareLoading(med_idt fid, int profileIt, int& start, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void finishLoading(med_idt fid, int profileIt, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); void setNewStart(int newValueOfStart) throw(INTERP_KERNEL::Exception); int getIteration() const; int getOrder() const; double getTime() const; - std::string getName() const; std::string getMeshName() const; TypeOfField getType() const; void simpleRepr(int bkOffset, std::ostream& oss, int id) const; @@ -119,8 +120,10 @@ namespace ParaMEDMEM int getNumberOfComponents() const; int getNumberOfTuples() const; int getStart() const { return _start; } - DataArrayDouble *getArray(); - const DataArrayDouble *getArray() const; + DataArray *getArray(); + const DataArray *getArray() const; + const DataArrayDouble *getArrayDouble() const; + DataArrayDouble *getArrayDouble(); const std::vector& getInfo() const; std::string getProfile() const; void setProfile(const char *newPflName); @@ -168,31 +171,32 @@ namespace ParaMEDMEM { public: static MEDFileFieldPerMeshPerType *New(MEDFileFieldPerMesh *fath, INTERP_KERNEL::NormalizedCellType geoType) throw(INTERP_KERNEL::Exception); - static MEDFileFieldPerMeshPerType *NewOnRead(med_idt fid, MEDFileFieldPerMesh *fath, TypeOfField type, INTERP_KERNEL::NormalizedCellType geoType) throw(INTERP_KERNEL::Exception); + static MEDFileFieldPerMeshPerType *NewOnRead(med_idt fid, MEDFileFieldPerMesh *fath, TypeOfField type, INTERP_KERNEL::NormalizedCellType geoType, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); std::size_t getHeapMemorySize() const; MEDFileFieldPerMeshPerType *deepCpy(MEDFileFieldPerMesh *father) const throw(INTERP_KERNEL::Exception); - void assignFieldNoProfile(int& start, int offset, int nbOfCells, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); - void assignFieldProfile(int& start, const DataArrayInt *multiTypePfl, const DataArrayInt *idsInPfl, DataArrayInt *locIds, int nbOfEltsInWholeMesh, const MEDCouplingFieldDouble *field, const MEDCouplingMesh *mesh, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); - void assignNodeFieldNoProfile(int& start, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); - void assignNodeFieldProfile(int& start, const DataArrayInt *pfl, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); + void assignFieldNoProfile(int& start, int offset, int nbOfCells, const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void assignFieldProfile(int& start, const DataArrayInt *multiTypePfl, const DataArrayInt *idsInPfl, DataArrayInt *locIds, int nbOfEltsInWholeMesh, const MEDCouplingFieldDouble *field, const DataArray *arr, const MEDCouplingMesh *mesh, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void assignNodeFieldNoProfile(int& start, const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); + void assignNodeFieldProfile(int& start, const DataArrayInt *pfl, const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); const MEDFileFieldPerMesh *getFather() const; - void prepareLoading(med_idt fid, int &start) throw(INTERP_KERNEL::Exception); - void finishLoading(med_idt fid, int ft) throw(INTERP_KERNEL::Exception); - void writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception); + void prepareLoading(med_idt fid, int &start, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void finishLoading(med_idt fid, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void writeLL(med_idt fid, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); void getDimension(int& dim) const; void fillTypesOfFieldAvailable(std::set& types) const throw(INTERP_KERNEL::Exception); void fillFieldSplitedByType(std::vector< std::pair >& dads, std::vector& types, std::vector& pfls, std::vector& locs) const throw(INTERP_KERNEL::Exception); int getIteration() const; int getOrder() const; double getTime() const; - std::string getName() const; std::string getMeshName() const; void simpleRepr(int bkOffset, std::ostream& oss, int id) const; void getSizes(int& globalSz, int& nbOfEntries) const; INTERP_KERNEL::NormalizedCellType getGeoType() const; int getNumberOfComponents() const; - DataArrayDouble *getArray(); - const DataArrayDouble *getArray() const; + DataArray *getArray(); + const DataArray *getArray() const; + const DataArrayDouble *getArrayDouble() const; + DataArrayDouble *getArrayDouble(); const std::vector& getInfo() const; std::vector getPflsReallyUsed() const; std::vector getLocsReallyUsed() const; @@ -211,7 +215,7 @@ namespace ParaMEDMEM std::vector addNewEntryIfNecessaryGauss(const MEDCouplingFieldDouble *field, int offset, int nbOfCells) throw(INTERP_KERNEL::Exception); std::vector addNewEntryIfNecessary(const MEDCouplingFieldDouble *field, const DataArrayInt *subCells) throw(INTERP_KERNEL::Exception); std::vector addNewEntryIfNecessaryGauss(const MEDCouplingFieldDouble *field, const DataArrayInt *subCells) throw(INTERP_KERNEL::Exception); - MEDFileFieldPerMeshPerType(med_idt fid, MEDFileFieldPerMesh *fath, TypeOfField type, INTERP_KERNEL::NormalizedCellType geoType) throw(INTERP_KERNEL::Exception); + MEDFileFieldPerMeshPerType(med_idt fid, MEDFileFieldPerMesh *fath, TypeOfField type, INTERP_KERNEL::NormalizedCellType geoType, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); MEDFileFieldPerMeshPerType(MEDFileFieldPerMesh *fath, INTERP_KERNEL::NormalizedCellType geoType) throw(INTERP_KERNEL::Exception); private: MEDFileFieldPerMesh *_father; @@ -222,19 +226,19 @@ namespace ParaMEDMEM class MEDFileFieldPerMesh : public RefCountObject, public MEDFileWritable { public: - static MEDFileFieldPerMesh *New(MEDFileField1TSWithoutSDA *fath, const MEDCouplingMesh *mesh); - static MEDFileFieldPerMesh *NewOnRead(med_idt fid, MEDFileField1TSWithoutSDA *fath, int meshCsit, int meshIteration, int meshOrder) throw(INTERP_KERNEL::Exception); + static MEDFileFieldPerMesh *New(MEDFileAnyTypeField1TSWithoutSDA *fath, const MEDCouplingMesh *mesh); + static MEDFileFieldPerMesh *NewOnRead(med_idt fid, MEDFileAnyTypeField1TSWithoutSDA *fath, int meshCsit, int meshIteration, int meshOrder, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); std::size_t getHeapMemorySize() const; - MEDFileFieldPerMesh *deepCpy(MEDFileField1TSWithoutSDA *_father) const throw(INTERP_KERNEL::Exception); + MEDFileFieldPerMesh *deepCpy(MEDFileAnyTypeField1TSWithoutSDA *father) const throw(INTERP_KERNEL::Exception); void simpleRepr(int bkOffset,std::ostream& oss, int id) const; void copyTinyInfoFrom(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception); - void assignFieldProfile(int& start, const DataArrayInt *multiTypePfl, const std::vector& code, const std::vector& code2, const std::vector& idsInPflPerType, const std::vector& idsPerType, const MEDCouplingFieldDouble *field, const MEDCouplingMesh *mesh, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); - void assignFieldNoProfileNoRenum(int& start, const std::vector& code, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); - void assignNodeFieldNoProfile(int& start, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); - void assignNodeFieldProfile(int& start, const DataArrayInt *pfl, const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); - void prepareLoading(med_idt fid, int &start) throw(INTERP_KERNEL::Exception); - void finishLoading(med_idt fid, int ft) throw(INTERP_KERNEL::Exception); - void writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception); + void assignFieldProfile(int& start, const DataArrayInt *multiTypePfl, const std::vector& code, const std::vector& code2, const std::vector& idsInPflPerType, const std::vector& idsPerType, const MEDCouplingFieldDouble *field, const DataArray *arr, const MEDCouplingMesh *mesh, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void assignFieldNoProfileNoRenum(int& start, const std::vector& code, const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void assignNodeFieldNoProfile(int& start, const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); + void assignNodeFieldProfile(int& start, const DataArrayInt *pfl, const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void prepareLoading(med_idt fid, int &start, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void finishLoading(med_idt fid, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void writeLL(med_idt fid, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); void fillTypesOfFieldAvailable(std::set& types) const throw(INTERP_KERNEL::Exception); std::vector< std::vector< std::pair > > getFieldSplitedByType(std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception); void getDimension(int& dim) const; @@ -243,12 +247,12 @@ namespace ParaMEDMEM int getOrder() const; int getMeshIteration() const { return _mesh_iteration; } int getMeshOrder() const { return _mesh_order; } - const std::string& getDtUnit() const; - std::string getName() const; std::string getMeshName() const { return _mesh_name; } int getNumberOfComponents() const; - DataArrayDouble *getArray(); - const DataArrayDouble *getArray() const; + DataArray *getArray(); + const DataArray *getArray() const; + DataArrayDouble *getArrayDouble(); + const DataArrayDouble *getArrayDouble() const; const std::vector& getInfo() const; std::vector getPflsReallyUsed() const; std::vector getLocsReallyUsed() const; @@ -258,36 +262,36 @@ namespace ParaMEDMEM bool renumberEntitiesLyingOnMesh(const char *meshName, const std::vector& oldCode, const std::vector& newCode, const DataArrayInt *renumO2N, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); void changePflsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception); void changeLocsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, const MEDFileFieldGlobsReal *glob, const MEDCouplingMesh *mesh, bool& isPfl) const throw(INTERP_KERNEL::Exception); - DataArrayDouble *getFieldOnMeshAtLevelWithPfl(TypeOfField type, const MEDCouplingMesh *mesh, DataArrayInt *&pfl, const MEDFileFieldGlobsReal *glob) const throw(INTERP_KERNEL::Exception); - DataArrayDouble *getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, const MEDFileFieldGlobsReal *glob, const MEDCouplingMesh *mesh, bool& isPfl, MEDCouplingAutoRefCountObjectPtr &arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); + DataArray *getFieldOnMeshAtLevelWithPfl(TypeOfField type, const MEDCouplingMesh *mesh, DataArrayInt *&pfl, const MEDFileFieldGlobsReal *glob, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); + void getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception); MEDFileFieldPerMeshPerTypePerDisc *getLeafGivenTypeAndLocId(INTERP_KERNEL::NormalizedCellType typ, int locId) throw(INTERP_KERNEL::Exception); const MEDFileFieldPerMeshPerTypePerDisc *getLeafGivenTypeAndLocId(INTERP_KERNEL::NormalizedCellType typ, int locId) const throw(INTERP_KERNEL::Exception); private: int addNewEntryIfNecessary(INTERP_KERNEL::NormalizedCellType type); MEDCouplingFieldDouble *finishField(TypeOfField type, const MEDFileFieldGlobsReal *glob, - const std::vector< std::pair >& dads, const std::vector& locs, const MEDCouplingMesh *mesh, bool& isPfl) const throw(INTERP_KERNEL::Exception); + const std::vector< std::pair >& dads, const std::vector& locs, const MEDCouplingMesh *mesh, bool& isPfl, MEDCouplingAutoRefCountObjectPtr &arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); MEDCouplingFieldDouble *finishField2(TypeOfField type, const MEDFileFieldGlobsReal *glob, const std::vector< std::pair >& dads, const std::vector& locs, const std::vector& geoTypes, - const MEDCouplingMesh *mesh, const DataArrayInt *da, bool& isPfl) const throw(INTERP_KERNEL::Exception); + const MEDCouplingMesh *mesh, const DataArrayInt *da, bool& isPfl, MEDCouplingAutoRefCountObjectPtr &arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); MEDCouplingFieldDouble *finishFieldNode2(const MEDFileFieldGlobsReal *glob, const std::vector< std::pair >& dads, const std::vector& locs, - const MEDCouplingMesh *mesh, const DataArrayInt *da, bool& isPfl) const throw(INTERP_KERNEL::Exception); - DataArrayDouble *finishField4(const std::vector< std::pair >& dads, const DataArrayInt *pflIn, int nbOfElems, DataArrayInt *&pflOut) const throw(INTERP_KERNEL::Exception); + const MEDCouplingMesh *mesh, const DataArrayInt *da, bool& isPfl, MEDCouplingAutoRefCountObjectPtr &arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); + DataArray *finishField4(const std::vector< std::pair >& dads, const DataArrayInt *pflIn, int nbOfElems, DataArrayInt *&pflOut) const throw(INTERP_KERNEL::Exception); void assignNewLeaves(const std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMeshPerTypePerDisc > >& leaves) throw(INTERP_KERNEL::Exception); static void SortArraysPerType(const MEDFileFieldGlobsReal *glob, TypeOfField type, const std::vector& geoTypes, const std::vector< std::pair >& dads, const std::vector& pfls, const std::vector& locs, std::vector& code, std::vector& notNullPfls); static int ComputeNbOfElems(const MEDFileFieldGlobsReal *glob, TypeOfField type, const std::vector& geoTypes, const std::vector< std::pair >& dads, const std::vector& locs) throw(INTERP_KERNEL::Exception); - MEDFileFieldPerMesh(med_idt fid, MEDFileField1TSWithoutSDA *fath, int meshCsit, int meshIteration, int meshOrder) throw(INTERP_KERNEL::Exception); - MEDFileFieldPerMesh(MEDFileField1TSWithoutSDA *fath, const MEDCouplingMesh *mesh); + MEDFileFieldPerMesh(med_idt fid, MEDFileAnyTypeField1TSWithoutSDA *fath, int meshCsit, int meshIteration, int meshOrder, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + MEDFileFieldPerMesh(MEDFileAnyTypeField1TSWithoutSDA *fath, const MEDCouplingMesh *mesh); private: std::string _mesh_name; int _mesh_iteration; int _mesh_order; int _mesh_csit; - MEDFileField1TSWithoutSDA *_father; + MEDFileAnyTypeField1TSWithoutSDA *_father; std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMeshPerType > > _field_pm_pt; }; @@ -300,8 +304,12 @@ namespace ParaMEDMEM static MEDFileFieldGlobs *New(); std::size_t getHeapMemorySize() const; MEDFileFieldGlobs *deepCpy() const throw(INTERP_KERNEL::Exception); + MEDFileFieldGlobs *shallowCpyPart(const std::vector& pfls, const std::vector& locs) const throw(INTERP_KERNEL::Exception); + MEDFileFieldGlobs *deepCpyPart(const std::vector& pfls, const std::vector& locs) const throw(INTERP_KERNEL::Exception); void simpleRepr(std::ostream& oss) const; void appendGlobs(const MEDFileFieldGlobs& other, double eps) throw(INTERP_KERNEL::Exception); + void checkGlobsPflsPartCoherency(const std::vector& pflsUsed) const throw(INTERP_KERNEL::Exception); + void checkGlobsLocsPartCoherency(const std::vector& locsUsed) const throw(INTERP_KERNEL::Exception); void loadProfileInFile(med_idt fid, int id, const char *pflName) throw(INTERP_KERNEL::Exception); void loadProfileInFile(med_idt fid, int id); void loadGlobals(med_idt fid, const MEDFileFieldGlobsReal& real) throw(INTERP_KERNEL::Exception); @@ -355,10 +363,16 @@ namespace ParaMEDMEM MEDFileFieldGlobsReal(const char *fname); MEDFileFieldGlobsReal(); std::size_t getHeapMemorySize() const; - void simpleRepr(std::ostream& oss) const; + void simpleReprGlobs(std::ostream& oss) const; + void resetContent(); void shallowCpyGlobs(const MEDFileFieldGlobsReal& other); void deepCpyGlobs(const MEDFileFieldGlobsReal& other); + void shallowCpyOnlyUsedGlobs(const MEDFileFieldGlobsReal& other) throw(INTERP_KERNEL::Exception); + void deepCpyOnlyUsedGlobs(const MEDFileFieldGlobsReal& other) throw(INTERP_KERNEL::Exception); void appendGlobs(const MEDFileFieldGlobsReal& other, double eps) throw(INTERP_KERNEL::Exception); + void checkGlobsCoherency() const throw(INTERP_KERNEL::Exception); + void checkGlobsPflsPartCoherency() const throw(INTERP_KERNEL::Exception); + void checkGlobsLocsPartCoherency() const throw(INTERP_KERNEL::Exception); virtual std::vector getPflsReallyUsed() const = 0; virtual std::vector getLocsReallyUsed() const = 0; virtual std::vector getPflsReallyUsedMulti() const = 0; @@ -406,38 +420,51 @@ namespace ParaMEDMEM // void appendProfile(DataArrayInt *pfl) throw(INTERP_KERNEL::Exception); void appendLoc(const char *locName, INTERP_KERNEL::NormalizedCellType geoType, const std::vector& refCoo, const std::vector& gsCoo, const std::vector& w) throw(INTERP_KERNEL::Exception); + protected: + MEDFileFieldGlobs *contentNotNull() throw(INTERP_KERNEL::Exception); + const MEDFileFieldGlobs *contentNotNull() const throw(INTERP_KERNEL::Exception); protected: MEDCouplingAutoRefCountObjectPtr< MEDFileFieldGlobs > _globals; }; + class MEDLOADER_EXPORT MEDFileFieldNameScope + { + public: + MEDFileFieldNameScope(); + MEDFileFieldNameScope(const char *fieldName); + std::string getName() const throw(INTERP_KERNEL::Exception); + void setName(const char *fieldName) throw(INTERP_KERNEL::Exception); + std::string getDtUnit() const throw(INTERP_KERNEL::Exception); + void setDtUnit(const char *dtUnit) throw(INTERP_KERNEL::Exception); + void copyNameScope(const MEDFileFieldNameScope& other); + protected: + std::string _name; + std::string _dt_unit; + }; + /*! * SDA is for Shared Data Arrays such as profiles. */ - class MEDLOADER_EXPORT MEDFileField1TSWithoutSDA : public RefCountObject + class MEDLOADER_EXPORT MEDFileAnyTypeField1TSWithoutSDA : public RefCountObject, public MEDFileFieldNameScope { public: - int copyTinyInfoFrom(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception); - int getDimension() const; + MEDFileAnyTypeField1TSWithoutSDA(); + MEDFileAnyTypeField1TSWithoutSDA(const char *fieldName, int csit, int iteration, int order); int getIteration() const { return _iteration; } int getOrder() const { return _order; } double getTime(int& iteration, int& order) const { iteration=_iteration; order=_order; return _dt; } void setTime(int iteration, int order, double val) { _dt=val; _iteration=iteration; _order=order; } - std::string getName() const; - void setName(const char *name); - void simpleRepr(int bkOffset, std::ostream& oss, int f1tsId) const; - const std::string& getDtUnit() const { return _dt_unit; } + int getDimension() const; std::string getMeshName() const throw(INTERP_KERNEL::Exception); void setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception); bool changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception); int getMeshIteration() const throw(INTERP_KERNEL::Exception); int getMeshOrder() const throw(INTERP_KERNEL::Exception); - int getNumberOfComponents() const; bool isDealingTS(int iteration, int order) const; std::pair getDtIt() const; void fillIteration(std::pair& p) const; void fillTypesOfFieldAvailable(std::vector& types) const throw(INTERP_KERNEL::Exception); - const std::vector& getInfo() const; - std::vector& getInfo(); + std::vector getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception); // std::vector getPflsReallyUsed2() const; std::vector getLocsReallyUsed2() const; @@ -445,41 +472,47 @@ namespace ParaMEDMEM std::vector getLocsReallyUsedMulti2() const; void changePflsRefsNamesGen2(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception); void changeLocsRefsNamesGen2(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception); - DataArrayDouble *getUndergroundDataArray() const throw(INTERP_KERNEL::Exception); - DataArrayDouble *getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception); + // int getNonEmptyLevels(const char *mname, std::vector& levs) const throw(INTERP_KERNEL::Exception); - std::vector getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception); std::vector< std::vector > > getFieldSplitedByType(const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception); - std::vector< std::vector > getFieldSplitedByType2(const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception); - MEDFileFieldPerMeshPerTypePerDisc *getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) throw(INTERP_KERNEL::Exception); + // + MEDFileFieldPerMeshPerTypePerDisc *getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) throw(INTERP_KERNEL::Exception); const MEDFileFieldPerMeshPerTypePerDisc *getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) const throw(INTERP_KERNEL::Exception); - static void CheckMeshDimRel(int meshDimRelToMax) throw(INTERP_KERNEL::Exception); - static std::vector CheckSBTMesh(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception); - static MEDFileField1TSWithoutSDA *New(const char *fieldName, int csit, int fieldtype, int iteration, int order, const std::vector& infos); public: - void finishLoading(med_idt fid) throw(INTERP_KERNEL::Exception); - virtual void writeLL(med_idt fid, const MEDFileWritable& opts) const throw(INTERP_KERNEL::Exception); - void setFieldNoProfileSBT(const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); - void setFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); + int getNumberOfComponents() const; + const std::vector& getInfo() const; + std::vector& getInfo(); + void setInfo(const std::vector& infos) throw(INTERP_KERNEL::Exception); + std::size_t getHeapMemorySize() const; + int copyTinyInfoFrom(const MEDCouplingFieldDouble *field, const DataArray *arr) throw(INTERP_KERNEL::Exception); + void setFieldNoProfileSBT(const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void setFieldProfile(const MEDCouplingFieldDouble *field, const DataArray *arrOfVals, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile, MEDFileFieldGlobsReal& glob, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + virtual void simpleRepr(int bkOffset, std::ostream& oss, int f1tsId) const; + virtual MEDFileAnyTypeField1TSWithoutSDA *deepCpy() const throw(INTERP_KERNEL::Exception) = 0; + virtual MEDFileAnyTypeField1TSWithoutSDA *shallowCpy() const throw(INTERP_KERNEL::Exception) = 0; + virtual std::vector< MEDCouplingAutoRefCountObjectPtr > splitComponents() const throw(INTERP_KERNEL::Exception); + virtual const char *getTypeStr() const throw(INTERP_KERNEL::Exception) = 0; + virtual DataArray *getUndergroundDataArray() const throw(INTERP_KERNEL::Exception) = 0; + virtual DataArray *getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception) = 0; + virtual void setArray(DataArray *arr) throw(INTERP_KERNEL::Exception) = 0; + virtual DataArray *createNewEmptyDataArrayInstance() const = 0; + virtual DataArray *getOrCreateAndGetArray() = 0; + virtual const DataArray *getOrCreateAndGetArray() const = 0; + public: + MEDCouplingFieldDouble *getFieldAtLevel(TypeOfField type, int meshDimRelToMax, const char *mName, int renumPol, const MEDFileFieldGlobsReal *glob, MEDCouplingAutoRefCountObjectPtr &arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int meshDimRelToMax, int renumPol, const MEDFileFieldGlobsReal *glob, const MEDFileMesh *mesh, MEDCouplingAutoRefCountObjectPtr &arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldAtTopLevel(TypeOfField type, const char *mName, int renumPol, const MEDFileFieldGlobsReal *glob, MEDCouplingAutoRefCountObjectPtr &arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int renumPol, const MEDFileFieldGlobsReal *glob, const MEDCouplingMesh *mesh, const DataArrayInt *cellRenum, const DataArrayInt *nodeRenum, MEDCouplingAutoRefCountObjectPtr &arrOut, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); + DataArray *getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl, const MEDFileFieldGlobsReal *glob, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); + public: bool renumberEntitiesLyingOnMesh(const char *meshName, const std::vector& oldCode, const std::vector& newCode, const DataArrayInt *renumO2N, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldAtLevel(TypeOfField type, int meshDimRelToMax, const char *mName, int renumPol, const MEDFileFieldGlobsReal *glob) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int meshDimRelToMax, int renumPol, const MEDFileFieldGlobsReal *glob, const MEDFileMesh *mesh) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldAtTopLevel(TypeOfField type, const char *mName, int renumPol, const MEDFileFieldGlobsReal *glob) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int renumPol, const MEDFileFieldGlobsReal *glob, const MEDCouplingMesh *mesh, const DataArrayInt *cellRenum, const DataArrayInt *nodeRenum) const throw(INTERP_KERNEL::Exception); - DataArrayDouble *getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl, const MEDFileFieldGlobsReal *glob) const throw(INTERP_KERNEL::Exception); + public: + virtual void finishLoading(med_idt fid, const MEDFileFieldNameScope& nasc) throw(INTERP_KERNEL::Exception); + void writeLL(med_idt fid, const MEDFileWritable& opts, const MEDFileFieldNameScope& nasc) const throw(INTERP_KERNEL::Exception); protected: - int addNewEntryIfNecessary(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception); int getMeshIdFromMeshName(const char *mName) const throw(INTERP_KERNEL::Exception); - public: - MEDFileField1TSWithoutSDA(); - MEDFileField1TSWithoutSDA(const char *fieldName, int csit, int fieldtype, int iteration, int order, const std::vector& infos); - MEDFileField1TSWithoutSDA *deepCpy() const throw(INTERP_KERNEL::Exception); - std::size_t getHeapMemorySize() const; - DataArrayDouble *getOrCreateAndGetArray(); - const DataArrayDouble *getOrCreateAndGetArray() const; + int addNewEntryIfNecessary(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception); protected: - std::string _dt_unit; - MEDCouplingAutoRefCountObjectPtr< DataArrayDouble > _arr; std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldPerMesh > > _field_per_mesh; int _iteration; int _order; @@ -487,37 +520,90 @@ namespace ParaMEDMEM public: //! only useable on reading mutable int _csit; - //! only useable on reading. 0 is for float, 1 for int32, 2 for int64 - mutable int _field_type; + }; + + /*! + * SDA is for Shared Data Arrays such as profiles. + */ + class MEDLOADER_EXPORT MEDFileField1TSWithoutSDA : public MEDFileAnyTypeField1TSWithoutSDA + { + public: + const char *getTypeStr() const throw(INTERP_KERNEL::Exception); + DataArray *getUndergroundDataArray() const throw(INTERP_KERNEL::Exception); + DataArray *getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception); + DataArrayDouble *getUndergroundDataArrayDouble() const throw(INTERP_KERNEL::Exception); + DataArrayDouble *getUndergroundDataArrayDoubleExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception); + std::vector< std::vector > getFieldSplitedByType2(const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception); + static void CheckMeshDimRel(int meshDimRelToMax) throw(INTERP_KERNEL::Exception); + static std::vector CheckSBTMesh(const MEDCouplingMesh *mesh) throw(INTERP_KERNEL::Exception); + static MEDFileField1TSWithoutSDA *New(const char *fieldName, int csit, int iteration, int order, const std::vector& infos); + public: + MEDFileField1TSWithoutSDA(); + MEDFileField1TSWithoutSDA(const char *fieldName, int csit, int iteration, int order, const std::vector& infos); + MEDFileAnyTypeField1TSWithoutSDA *shallowCpy() const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TSWithoutSDA *deepCpy() const throw(INTERP_KERNEL::Exception); + void setArray(DataArray *arr) throw(INTERP_KERNEL::Exception); + DataArray *createNewEmptyDataArrayInstance() const; + DataArray *getOrCreateAndGetArray(); + const DataArray *getOrCreateAndGetArray() const; + DataArrayDouble *getOrCreateAndGetArrayDouble(); + const DataArrayDouble *getOrCreateAndGetArrayDouble() const; + protected: + MEDCouplingAutoRefCountObjectPtr< DataArrayDouble > _arr; + public: + static const char TYPE_STR[]; }; /*! - * User class. + * SDA is for Shared Data Arrays such as profiles. */ - class MEDLOADER_EXPORT MEDFileField1TS : public RefCountObject, public MEDFileWritable, public MEDFileFieldGlobsReal + class MEDLOADER_EXPORT MEDFileIntField1TSWithoutSDA : public MEDFileAnyTypeField1TSWithoutSDA { public: - static MEDFileField1TS *New(const char *fileName) throw(INTERP_KERNEL::Exception); - static MEDFileField1TS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); - static MEDFileField1TS *New(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception); - static MEDFileField1TS *New(const MEDFileField1TSWithoutSDA& other, bool shallowCopyOfContent); - static MEDFileField1TS *New(); - std::string simpleRepr() const; - void write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldAtLevel(TypeOfField type, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldAtTopLevel(TypeOfField type, int renumPol=0) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, const MEDCouplingMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldAtLevelOld(TypeOfField type, const char *mname, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception); - DataArrayDouble *getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl) const throw(INTERP_KERNEL::Exception); - // - void setFieldNoProfileSBT(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception); - void setFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception); - // direct forwarding to MEDFileField1TSWithoutSDA instance _content + MEDFileIntField1TSWithoutSDA(); + static MEDFileIntField1TSWithoutSDA *New(const char *fieldName, int csit, int iteration, int order, const std::vector& infos); + MEDFileAnyTypeField1TSWithoutSDA *deepCpy() const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TSWithoutSDA *shallowCpy() const throw(INTERP_KERNEL::Exception); + const char *getTypeStr() const throw(INTERP_KERNEL::Exception); + DataArray *getUndergroundDataArray() const throw(INTERP_KERNEL::Exception); + DataArray *getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception); + void setArray(DataArray *arr) throw(INTERP_KERNEL::Exception); + DataArray *createNewEmptyDataArrayInstance() const; + DataArray *getOrCreateAndGetArray(); + const DataArray *getOrCreateAndGetArray() const; + DataArrayInt *getOrCreateAndGetArrayInt(); + const DataArrayInt *getOrCreateAndGetArrayInt() const; + DataArrayInt *getUndergroundDataArrayInt() const throw(INTERP_KERNEL::Exception); + DataArrayInt *getUndergroundDataArrayIntExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception); + protected: + MEDFileIntField1TSWithoutSDA(const char *fieldName, int csit, int iteration, int order, const std::vector& infos); + protected: + MEDCouplingAutoRefCountObjectPtr< DataArrayInt > _arr; public: - std::size_t getHeapMemorySize() const; - MEDFileField1TS *deepCpy() const throw(INTERP_KERNEL::Exception); - int copyTinyInfoFrom(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception); + static const char TYPE_STR[]; + }; + + /*! + * User class. + */ + class MEDLOADER_EXPORT MEDFileAnyTypeField1TS : public RefCountObject, public MEDFileWritable, public MEDFileFieldGlobsReal + { + protected: + MEDFileAnyTypeField1TS(); + MEDFileAnyTypeField1TS(const char *fileName) throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TS(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TS(const MEDFileAnyTypeField1TSWithoutSDA& other, bool shallowCopyOfContent); + static MEDFileAnyTypeField1TS *BuildNewInstanceFromContent(MEDFileAnyTypeField1TSWithoutSDA *c, const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileAnyTypeField1TSWithoutSDA *BuildContentFrom(med_idt fid, const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileAnyTypeField1TSWithoutSDA *BuildContentFrom(med_idt fid, const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + static MEDFileAnyTypeField1TSWithoutSDA *BuildContentFrom(med_idt fid, const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception); + void writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception); + // direct forwarding to MEDFileAnyTypeField1TSWithoutSDA instance _content + public: + static MEDFileAnyTypeField1TS *New(const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileAnyTypeField1TS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + static MEDFileAnyTypeField1TS *New(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception); int getDimension() const; int getIteration() const; int getOrder() const; @@ -525,8 +611,10 @@ namespace ParaMEDMEM void setTime(int iteration, int order, double val); std::string getName() const; void setName(const char *name); + std::string simpleRepr() const; void simpleRepr(int bkOffset, std::ostream& oss, int f1tsId) const; - const std::string& getDtUnit() const; + std::string getDtUnit() const throw(INTERP_KERNEL::Exception); + void setDtUnit(const char *dtUnit) throw(INTERP_KERNEL::Exception); std::string getMeshName() const throw(INTERP_KERNEL::Exception); void setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception); bool changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception); @@ -537,76 +625,173 @@ namespace ParaMEDMEM std::pair getDtIt() const; void fillIteration(std::pair& p) const; void fillTypesOfFieldAvailable(std::vector& types) const throw(INTERP_KERNEL::Exception); + void setInfo(const std::vector& infos) throw(INTERP_KERNEL::Exception); const std::vector& getInfo() const; std::vector& getInfo(); - DataArrayDouble *getUndergroundDataArray() const throw(INTERP_KERNEL::Exception); - DataArrayDouble *getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception); - MEDFileFieldPerMeshPerTypePerDisc *getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) throw(INTERP_KERNEL::Exception); - const MEDFileFieldPerMeshPerTypePerDisc *getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) const throw(INTERP_KERNEL::Exception); - int getNonEmptyLevels(const char *mname, std::vector& levs) const throw(INTERP_KERNEL::Exception); std::vector getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception); std::vector< std::vector > > getFieldSplitedByType(const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception); - std::vector< std::vector > getFieldSplitedByType2(const char *mname, std::vector& types, std::vector< std::vector >& typesF, - std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception); + MEDFileFieldPerMeshPerTypePerDisc *getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) throw(INTERP_KERNEL::Exception); + const MEDFileFieldPerMeshPerTypePerDisc *getLeafGivenMeshAndTypeAndLocId(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId) const throw(INTERP_KERNEL::Exception); + int getNonEmptyLevels(const char *mname, std::vector& levs) const throw(INTERP_KERNEL::Exception); + public: + void write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception); + std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeField1TS > > splitComponents() const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TS *deepCpy() const throw(INTERP_KERNEL::Exception); + int copyTinyInfoFrom(const MEDCouplingFieldDouble *field, const DataArray *arr) throw(INTERP_KERNEL::Exception); + virtual MEDFileAnyTypeField1TS *shallowCpy() const throw(INTERP_KERNEL::Exception) = 0; public: //! underground method see MEDFileField1TSWithoutSDA::setProfileNameOnLeaf void setProfileNameOnLeaf(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId, const char *newPflName, bool forceRenameOnGlob=false) throw(INTERP_KERNEL::Exception); //! underground method see MEDFileField1TSWithoutSDA::setLocNameOnLeaf void setLocNameOnLeaf(const char *mName, INTERP_KERNEL::NormalizedCellType typ, int locId, const char *newLocName, bool forceRenameOnGlob=false) throw(INTERP_KERNEL::Exception); + std::size_t getHeapMemorySize() const; std::vector getPflsReallyUsed() const; std::vector getLocsReallyUsed() const; std::vector getPflsReallyUsedMulti() const; std::vector getLocsReallyUsedMulti() const; void changePflsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception); void changeLocsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception); + public: + static int LocateField2(med_idt fid, const char *fileName, int fieldIdCFormat, bool checkFieldId, std::string& fieldName, med_field_type& typcha, std::vector& infos, std::string& dtunitOut) throw(INTERP_KERNEL::Exception); + static int LocateField(med_idt fid, const char *fileName, const char *fieldName, int& posCFormat, med_field_type& typcha, std::vector& infos, std::string& dtunitOut) throw(INTERP_KERNEL::Exception); + public: + virtual med_field_type getMEDFileFieldType() const = 0; + MEDFileAnyTypeField1TSWithoutSDA *contentNotNullBase() throw(INTERP_KERNEL::Exception); + const MEDFileAnyTypeField1TSWithoutSDA *contentNotNullBase() const throw(INTERP_KERNEL::Exception); + protected: + MEDCouplingAutoRefCountObjectPtr _content; + }; + + /*! + * User class. + */ + class MEDLOADER_EXPORT MEDFileField1TS : public MEDFileAnyTypeField1TS + { + public: + static MEDFileField1TS *New(const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileField1TS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + static MEDFileField1TS *New(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception); + static MEDFileField1TS *New(const MEDFileField1TSWithoutSDA& other, bool shallowCopyOfContent); + static MEDFileField1TS *New(); + MEDCouplingFieldDouble *getFieldAtLevel(TypeOfField type, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldAtTopLevel(TypeOfField type, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, const MEDCouplingMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldAtLevelOld(TypeOfField type, const char *mname, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception); + DataArrayDouble *getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl) const throw(INTERP_KERNEL::Exception); + // + void setFieldNoProfileSBT(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception); + void setFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception); + // direct forwarding to MEDFileField1TSWithoutSDA instance _content + public: + MEDFileAnyTypeField1TS *shallowCpy() const throw(INTERP_KERNEL::Exception); + DataArrayDouble *getUndergroundDataArray() const throw(INTERP_KERNEL::Exception); + DataArrayDouble *getUndergroundDataArrayExt(std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception); + + std::vector< std::vector > getFieldSplitedByType2(const char *mname, std::vector& types, std::vector< std::vector >& typesF, + std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception); + public: + static void SetDataArrayDoubleInField(MEDCouplingFieldDouble *f, MEDCouplingAutoRefCountObjectPtr& arr) throw(INTERP_KERNEL::Exception); + static DataArrayDouble *ReturnSafelyDataArrayDouble(MEDCouplingAutoRefCountObjectPtr& arr) throw(INTERP_KERNEL::Exception); + private: + med_field_type getMEDFileFieldType() const { return MED_FLOAT64; } + const MEDFileField1TSWithoutSDA *contentNotNull() const throw(INTERP_KERNEL::Exception); + MEDFileField1TSWithoutSDA *contentNotNull() throw(INTERP_KERNEL::Exception); private: - void writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception); MEDFileField1TS(const char *fileName) throw(INTERP_KERNEL::Exception); MEDFileField1TS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); MEDFileField1TS(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception); MEDFileField1TS(const MEDFileField1TSWithoutSDA& other, bool shallowCopyOfContent); MEDFileField1TS(); - int locateField(med_idt fid, const char *fileName, const char *fieldName, med_field_type& typcha) throw(INTERP_KERNEL::Exception); - protected: - MEDCouplingAutoRefCountObjectPtr _content; + }; + + class MEDLOADER_EXPORT MEDFileIntField1TS : public MEDFileAnyTypeField1TS + { + public: + static MEDFileIntField1TS *New(); + static MEDFileIntField1TS *New(const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileIntField1TS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + static MEDFileIntField1TS *New(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception); + static MEDFileIntField1TS *New(const MEDFileIntField1TSWithoutSDA& other, bool shallowCopyOfContent); + MEDFileAnyTypeField1TS *shallowCpy() const throw(INTERP_KERNEL::Exception); + // + MEDCouplingFieldDouble *getFieldAtLevel(TypeOfField type, int meshDimRelToMax, DataArrayInt* &arrOut, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldAtTopLevel(TypeOfField type, DataArrayInt* &arrOut, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt* &arrOut, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, const MEDCouplingMesh *mesh, DataArrayInt* &arrOut, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldAtLevelOld(TypeOfField type, const char *mname, int meshDimRelToMax, DataArrayInt* &arrOut, int renumPol=0) const throw(INTERP_KERNEL::Exception); + DataArrayInt *getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl) const throw(INTERP_KERNEL::Exception); + // + void setFieldNoProfileSBT(const MEDCouplingFieldDouble *field, const DataArrayInt *arrOfVals) throw(INTERP_KERNEL::Exception); + void setFieldProfile(const MEDCouplingFieldDouble *field, const DataArrayInt *arrOfVals, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception); + DataArrayInt *getUndergroundDataArray() const throw(INTERP_KERNEL::Exception); + public: + static DataArrayInt *ReturnSafelyDataArrayInt(MEDCouplingAutoRefCountObjectPtr& arr) throw(INTERP_KERNEL::Exception); + private: + med_field_type getMEDFileFieldType() const { return MED_INT32; } + const MEDFileIntField1TSWithoutSDA *contentNotNull() const throw(INTERP_KERNEL::Exception); + MEDFileIntField1TSWithoutSDA *contentNotNull() throw(INTERP_KERNEL::Exception); + private: + MEDFileIntField1TS(); + MEDFileIntField1TS(const char *fileName) throw(INTERP_KERNEL::Exception); + MEDFileIntField1TS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + MEDFileIntField1TS(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception); + MEDFileIntField1TS(const MEDFileIntField1TSWithoutSDA& other, bool shallowCopyOfContent); }; - class MEDLOADER_EXPORT MEDFileFieldMultiTSWithoutSDA : public RefCountObject + class MEDLOADER_EXPORT MEDFileAnyTypeFieldMultiTSWithoutSDA : public RefCountObject, public MEDFileFieldNameScope { + protected: + MEDFileAnyTypeFieldMultiTSWithoutSDA(); + MEDFileAnyTypeFieldMultiTSWithoutSDA(const char *fieldName); + MEDFileAnyTypeFieldMultiTSWithoutSDA(med_idt fid, int fieldId) throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTSWithoutSDA(med_idt fid, const char *fieldName, med_field_type fieldTyp, const std::vector& infos, int nbOfStep, const std::string& dtunit) throw(INTERP_KERNEL::Exception); public: - static MEDFileFieldMultiTSWithoutSDA *New(med_idt fid, const char *fieldName, int id, int ft, const std::vector& infos, int nbOfStep) throw(INTERP_KERNEL::Exception); - MEDFileFieldMultiTSWithoutSDA(med_idt fid, int fieldId) throw(INTERP_KERNEL::Exception); std::size_t getHeapMemorySize() const; - MEDFileFieldMultiTSWithoutSDA *deepCpy() const throw(INTERP_KERNEL::Exception); + virtual MEDFileAnyTypeFieldMultiTSWithoutSDA *deepCpy() const throw(INTERP_KERNEL::Exception); + virtual std::vector< MEDCouplingAutoRefCountObjectPtr > splitComponents() const throw(INTERP_KERNEL::Exception); + virtual const char *getTypeStr() const throw(INTERP_KERNEL::Exception) = 0; + virtual MEDFileAnyTypeFieldMultiTSWithoutSDA *shallowCpy() const throw(INTERP_KERNEL::Exception) = 0; + virtual MEDFileAnyTypeFieldMultiTSWithoutSDA *createNew() const throw(INTERP_KERNEL::Exception) = 0; + virtual MEDFileAnyTypeField1TSWithoutSDA *createNew1TSWithoutSDAEmptyInstance() const throw(INTERP_KERNEL::Exception) = 0; + virtual void checkCoherencyOfType(const MEDFileAnyTypeField1TSWithoutSDA *f1ts) const throw(INTERP_KERNEL::Exception) = 0; + const std::vector& getInfo() const throw(INTERP_KERNEL::Exception); + void setInfo(const std::vector& info) throw(INTERP_KERNEL::Exception); + int getTimeStepPos(int iteration, int order) const throw(INTERP_KERNEL::Exception); + const MEDFileAnyTypeField1TSWithoutSDA& getTimeStepEntry(int iteration, int order) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TSWithoutSDA& getTimeStepEntry(int iteration, int order) throw(INTERP_KERNEL::Exception); + std::string getMeshName() const throw(INTERP_KERNEL::Exception); + void setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception); + bool changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception); int getNumberOfTS() const; void eraseEmptyTS() throw(INTERP_KERNEL::Exception); void eraseTimeStepIds(const int *startIds, const int *endIds) throw(INTERP_KERNEL::Exception); - std::vector< std::pair > getIterations() const; + void eraseTimeStepIds2(int bg, int end, int step) throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTSWithoutSDA *buildFromTimeStepIds(const int *startIds, const int *endIds) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTSWithoutSDA *buildFromTimeStepIds2(int bg, int end, int step) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTSWithoutSDA *partOfThisLyingOnSpecifiedTimeSteps(const std::vector< std::pair >& timeSteps) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTSWithoutSDA *partOfThisNotLyingOnSpecifiedTimeSteps(const std::vector< std::pair >& timeSteps) const throw(INTERP_KERNEL::Exception); int getPosOfTimeStep(int iteration, int order) const throw(INTERP_KERNEL::Exception); int getPosGivenTime(double time, double eps=1e-8) const throw(INTERP_KERNEL::Exception); + std::vector< std::pair > getIterations() const; + std::vector< std::pair > getTimeSteps(std::vector& ret1) const throw(INTERP_KERNEL::Exception); + void pushBackTimeStep(MEDCouplingAutoRefCountObjectPtr& tse) throw(INTERP_KERNEL::Exception); + void synchronizeNameScope() throw(INTERP_KERNEL::Exception); + void simpleRepr(int bkOffset, std::ostream& oss, int fmtsId) const; int getNonEmptyLevels(int iteration, int order, const char *mname, std::vector& levs) const throw(INTERP_KERNEL::Exception); - std::vector< std::vector > getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception); + void appendFieldNoProfileSBT(const MEDCouplingFieldDouble *field, const DataArray *arr, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); + void appendFieldProfile(const MEDCouplingFieldDouble *field, const DataArray *arr, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); std::vector< std::vector< std::pair > > getFieldSplitedByType(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception); - std::vector< std::vector > getFieldSplitedByType2(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception); - virtual void writeLL(med_idt fid, const MEDFileWritable& opts) const throw(INTERP_KERNEL::Exception); - std::string getName() const; - void setName(const char *name); - void simpleRepr(int bkOffset, std::ostream& oss, int fmtsId) const; - std::vector< std::pair > getTimeSteps(std::vector& ret1) const throw(INTERP_KERNEL::Exception); - std::string getMeshName() const throw(INTERP_KERNEL::Exception); - void setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception); - bool changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception); - const std::vector& getInfo() const throw(INTERP_KERNEL::Exception); - DataArrayDouble *getUndergroundDataArray(int iteration, int order) const throw(INTERP_KERNEL::Exception); - DataArrayDouble *getUndergroundDataArrayExt(int iteration, int order, std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception); + std::vector< std::vector > getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception); + DataArray *getUndergroundDataArray(int iteration, int order) const throw(INTERP_KERNEL::Exception); + DataArray *getUndergroundDataArrayExt(int iteration, int order, std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception); bool renumberEntitiesLyingOnMesh(const char *meshName, const std::vector& oldCode, const std::vector& newCode, const DataArrayInt *renumO2N, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); - void appendFieldNoProfileSBT(const MEDCouplingFieldDouble *field, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); - void appendFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile, MEDFileFieldGlobsReal& glob) throw(INTERP_KERNEL::Exception); + void finishLoading(med_idt fid, int nbPdt, med_field_type fieldTyp) throw(INTERP_KERNEL::Exception); + void writeLL(med_idt fid, const MEDFileWritable& opts) const throw(INTERP_KERNEL::Exception); public: - const MEDFileField1TSWithoutSDA *getTimeStepAtPos2(int pos) const throw(INTERP_KERNEL::Exception); - MEDFileField1TSWithoutSDA *getTimeStepAtPos2(int pos) throw(INTERP_KERNEL::Exception); - const MEDFileField1TSWithoutSDA& getTimeStepEntry(int iteration, int order) const throw(INTERP_KERNEL::Exception); + const MEDFileAnyTypeField1TSWithoutSDA *getTimeStepAtPos2(int pos) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TSWithoutSDA *getTimeStepAtPos2(int pos) throw(INTERP_KERNEL::Exception); std::vector getPflsReallyUsed2() const; std::vector getLocsReallyUsed2() const; std::vector getPflsReallyUsedMulti2() const; @@ -614,76 +799,113 @@ namespace ParaMEDMEM void changePflsRefsNamesGen2(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception); void changeLocsRefsNamesGen2(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception); protected: - MEDFileField1TSWithoutSDA& getTimeStepEntry(int iteration, int order) throw(INTERP_KERNEL::Exception); - std::string getDtUnit() const throw(INTERP_KERNEL::Exception); + virtual med_field_type getMEDFileFieldType() const = 0; + void copyTinyInfoFrom(const MEDCouplingFieldDouble *field, const DataArray *arr) throw(INTERP_KERNEL::Exception); + void checkCoherencyOfTinyInfo(const MEDCouplingFieldDouble *field, const DataArray *arr) const throw(INTERP_KERNEL::Exception); + void checkThatComponentsMatch(const std::vector& compos) const throw(INTERP_KERNEL::Exception); + void checkThatNbOfCompoOfTSMatchThis() const throw(INTERP_KERNEL::Exception); + protected: + std::vector _infos; + std::vector< MEDCouplingAutoRefCountObjectPtr > _time_steps; + }; + + class MEDLOADER_EXPORT MEDFileFieldMultiTSWithoutSDA : public MEDFileAnyTypeFieldMultiTSWithoutSDA + { + public: + static MEDFileFieldMultiTSWithoutSDA *New(med_idt fid, const char *fieldName, med_field_type fieldTyp, const std::vector& infos, int nbOfStep, const std::string& dtunit) throw(INTERP_KERNEL::Exception); + MEDFileFieldMultiTSWithoutSDA(med_idt fid, int fieldId) throw(INTERP_KERNEL::Exception); + const char *getTypeStr() const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTSWithoutSDA *shallowCpy() const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTSWithoutSDA *createNew() const throw(INTERP_KERNEL::Exception); + std::vector< std::vector > getFieldSplitedByType2(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception); + protected: MEDFileFieldMultiTSWithoutSDA(const char *fieldName); - MEDFileFieldMultiTSWithoutSDA(med_idt fid, const char *fieldName, int id, int ft, const std::vector& infos, int nbOfStep) throw(INTERP_KERNEL::Exception); - void finishLoading(med_idt fid, int nbPdt) throw(INTERP_KERNEL::Exception); - void copyTinyInfoFrom(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception); - void checkCoherencyOfTinyInfo(const MEDCouplingFieldDouble *field) const throw(INTERP_KERNEL::Exception); + MEDFileFieldMultiTSWithoutSDA(med_idt fid, const char *fieldName, med_field_type fieldTyp, const std::vector& infos, int nbOfStep, const std::string& dtunit) throw(INTERP_KERNEL::Exception); + med_field_type getMEDFileFieldType() const { return MED_FLOAT64; } + MEDFileAnyTypeField1TSWithoutSDA *createNew1TSWithoutSDAEmptyInstance() const throw(INTERP_KERNEL::Exception); + void checkCoherencyOfType(const MEDFileAnyTypeField1TSWithoutSDA *f1ts) const throw(INTERP_KERNEL::Exception); public: MEDFileFieldMultiTSWithoutSDA(); - protected: - std::string _name; - std::vector _infos; - //! only useable on reading. 0 is for float, 1 for int32, 2 for int64 - mutable int _field_type; - std::vector< MEDCouplingAutoRefCountObjectPtr > _time_steps; }; - class MEDFileFieldMultiTSIterator; + class MEDLOADER_EXPORT MEDFileIntFieldMultiTSWithoutSDA : public MEDFileAnyTypeFieldMultiTSWithoutSDA + { + public: + static MEDFileIntFieldMultiTSWithoutSDA *New(med_idt fid, const char *fieldName, med_field_type fieldTyp, const std::vector& infos, int nbOfStep, const std::string& dtunit) throw(INTERP_KERNEL::Exception); + MEDFileIntFieldMultiTSWithoutSDA(med_idt fid, int fieldId) throw(INTERP_KERNEL::Exception); + const char *getTypeStr() const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTSWithoutSDA *shallowCpy() const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTSWithoutSDA *createNew() const throw(INTERP_KERNEL::Exception); + protected: + MEDFileIntFieldMultiTSWithoutSDA(const char *fieldName); + MEDFileIntFieldMultiTSWithoutSDA(med_idt fid, const char *fieldName, med_field_type fieldTyp, const std::vector& infos, int nbOfStep, const std::string& dtunit) throw(INTERP_KERNEL::Exception); + med_field_type getMEDFileFieldType() const { return MED_INT32; } + MEDFileAnyTypeField1TSWithoutSDA *createNew1TSWithoutSDAEmptyInstance() const throw(INTERP_KERNEL::Exception); + void checkCoherencyOfType(const MEDFileAnyTypeField1TSWithoutSDA *f1ts) const throw(INTERP_KERNEL::Exception); + public: + MEDFileIntFieldMultiTSWithoutSDA(); + }; + class MEDFileAnyTypeFieldMultiTSIterator; + /*! * User class. */ - class MEDLOADER_EXPORT MEDFileFieldMultiTS : public RefCountObject, public MEDFileWritable, public MEDFileFieldGlobsReal + class MEDLOADER_EXPORT MEDFileAnyTypeFieldMultiTS : public RefCountObject, public MEDFileWritable, public MEDFileFieldGlobsReal { + protected: + MEDFileAnyTypeFieldMultiTS(); + MEDFileAnyTypeFieldMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTS(const MEDFileAnyTypeFieldMultiTSWithoutSDA& other, bool shallowCopyOfContent); + static MEDFileAnyTypeFieldMultiTS *BuildNewInstanceFromContent(MEDFileAnyTypeFieldMultiTSWithoutSDA *c, const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileAnyTypeFieldMultiTSWithoutSDA *BuildContentFrom(med_idt fid, const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileAnyTypeFieldMultiTSWithoutSDA *BuildContentFrom(med_idt fid, const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); public: - static MEDFileFieldMultiTS *New(); - static MEDFileFieldMultiTS *New(const char *fileName) throw(INTERP_KERNEL::Exception); - static MEDFileFieldMultiTS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); - static MEDFileFieldMultiTS *New(const MEDFileFieldMultiTSWithoutSDA& other, bool shallowCopyOfContent); - std::size_t getHeapMemorySize() const; - MEDFileFieldMultiTS *deepCpy() const throw(INTERP_KERNEL::Exception); - // - MEDFileField1TS *getTimeStepAtPos(int pos) const throw(INTERP_KERNEL::Exception); - MEDFileField1TS *getTimeStep(int iteration, int order) const throw(INTERP_KERNEL::Exception); - MEDFileField1TS *getTimeStepGivenTime(double time, double eps=1e-8) const throw(INTERP_KERNEL::Exception); - MEDFileFieldMultiTSIterator *iterator() throw(INTERP_KERNEL::Exception); - // - std::string simpleRepr() const; + static MEDFileAnyTypeFieldMultiTS *New(const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileAnyTypeFieldMultiTS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); void write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception); void writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldAtTopLevel(TypeOfField type, int iteration, int order, int renumPol=0) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, const MEDCouplingMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldAtLevelOld(TypeOfField type, const char *mname, int iteration, int order, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception); - DataArrayDouble *getFieldWithProfile(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl) const throw(INTERP_KERNEL::Exception); + std::size_t getHeapMemorySize() const; + virtual MEDFileAnyTypeFieldMultiTS *deepCpy() const throw(INTERP_KERNEL::Exception); + std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeFieldMultiTS > > splitComponents() const throw(INTERP_KERNEL::Exception); + virtual MEDFileAnyTypeFieldMultiTS *shallowCpy() const throw(INTERP_KERNEL::Exception) = 0; + virtual void checkCoherencyOfType(const MEDFileAnyTypeField1TS *f1ts) const throw(INTERP_KERNEL::Exception) = 0; // - void appendFieldNoProfileSBT(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception); - void appendFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception); + virtual MEDFileAnyTypeField1TS *getTimeStepAtPos(int pos) const throw(INTERP_KERNEL::Exception) = 0; + MEDFileAnyTypeField1TS *getTimeStep(int iteration, int order) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TS *getTimeStepGivenTime(double time, double eps=1e-8) const throw(INTERP_KERNEL::Exception); public:// direct forwarding to MEDFileField1TSWithoutSDA instance _content + std::string getName() const; + void setName(const char *name); + std::string getDtUnit() const throw(INTERP_KERNEL::Exception); + void setDtUnit(const char *dtUnit) throw(INTERP_KERNEL::Exception); + std::string getMeshName() const throw(INTERP_KERNEL::Exception); + void setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception); + std::string simpleRepr() const; + void simpleRepr(int bkOffset, std::ostream& oss, int fmtsId) const; int getNumberOfTS() const; void eraseEmptyTS() throw(INTERP_KERNEL::Exception); void eraseTimeStepIds(const int *startIds, const int *endIds) throw(INTERP_KERNEL::Exception); + void eraseTimeStepIds2(int bg, int end, int step) throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTS *buildSubPart(const int *startIds, const int *endIds) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTS *buildSubPartSlice(int bg, int end, int step) const throw(INTERP_KERNEL::Exception); + std::vector< std::pair > getTimeSteps(std::vector& ret1) const throw(INTERP_KERNEL::Exception); std::vector< std::pair > getIterations() const; + void pushBackTimeSteps(const std::vector& f1ts) throw(INTERP_KERNEL::Exception); + void pushBackTimeStep(MEDFileAnyTypeField1TS *f1ts) throw(INTERP_KERNEL::Exception); + void synchronizeNameScope() throw(INTERP_KERNEL::Exception); int getPosOfTimeStep(int iteration, int order) const throw(INTERP_KERNEL::Exception); int getPosGivenTime(double time, double eps=1e-8) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTSIterator *iterator() throw(INTERP_KERNEL::Exception); + bool changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception); + const std::vector& getInfo() const throw(INTERP_KERNEL::Exception); + void setInfo(const std::vector& info) throw(INTERP_KERNEL::Exception); + int getNumberOfComponents() const throw(INTERP_KERNEL::Exception); int getNonEmptyLevels(int iteration, int order, const char *mname, std::vector& levs) const throw(INTERP_KERNEL::Exception); std::vector< std::vector > getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception); std::vector< std::vector< std::pair > > getFieldSplitedByType(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception); -std::vector< std::vector > getFieldSplitedByType2(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception); - std::string getName() const; - void setName(const char *name); - void simpleRepr(int bkOffset, std::ostream& oss, int fmtsId) const; - std::vector< std::pair > getTimeSteps(std::vector& ret1) const throw(INTERP_KERNEL::Exception); - std::string getMeshName() const throw(INTERP_KERNEL::Exception); - void setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception); - bool changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception); - const std::vector& getInfo() const throw(INTERP_KERNEL::Exception); - DataArrayDouble *getUndergroundDataArray(int iteration, int order) const throw(INTERP_KERNEL::Exception); - DataArrayDouble *getUndergroundDataArrayExt(int iteration, int order, std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception); + MEDCouplingAutoRefCountObjectPtr getContent(); public: std::vector getPflsReallyUsed() const; std::vector getLocsReallyUsed() const; @@ -691,25 +913,95 @@ std::vector< std::vector > getFieldSplitedByType2(int iterati std::vector getLocsReallyUsedMulti() const; void changePflsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception); void changeLocsRefsNamesGen(const std::vector< std::pair, std::string > >& mapOfModif) throw(INTERP_KERNEL::Exception); + protected: + MEDFileAnyTypeFieldMultiTSWithoutSDA *contentNotNullBase() throw(INTERP_KERNEL::Exception); + const MEDFileAnyTypeFieldMultiTSWithoutSDA *contentNotNullBase() const throw(INTERP_KERNEL::Exception); + protected: + MEDCouplingAutoRefCountObjectPtr _content; + }; + + /*! + * User class. + */ + class MEDLOADER_EXPORT MEDFileFieldMultiTS : public MEDFileAnyTypeFieldMultiTS + { public: - MEDCouplingAutoRefCountObjectPtr getContent(); + static MEDFileFieldMultiTS *New(); + static MEDFileFieldMultiTS *New(const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileFieldMultiTS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + static MEDFileFieldMultiTS *New(const MEDFileFieldMultiTSWithoutSDA& other, bool shallowCopyOfContent); + MEDFileAnyTypeFieldMultiTS *shallowCpy() const throw(INTERP_KERNEL::Exception); + void checkCoherencyOfType(const MEDFileAnyTypeField1TS *f1ts) const throw(INTERP_KERNEL::Exception); + // + MEDFileAnyTypeField1TS *getTimeStepAtPos(int pos) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TS *getTimeStep(int iteration, int order) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TS *getTimeStepGivenTime(double time, double eps=1e-8) const throw(INTERP_KERNEL::Exception); + // + MEDCouplingFieldDouble *getFieldAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldAtTopLevel(TypeOfField type, int iteration, int order, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, const MEDCouplingMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldAtLevelOld(TypeOfField type, const char *mname, int iteration, int order, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception); + DataArrayDouble *getFieldWithProfile(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl) const throw(INTERP_KERNEL::Exception); + // + void appendFieldNoProfileSBT(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception); + void appendFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception); +std::vector< std::vector > getFieldSplitedByType2(int iteration, int order, const char *mname, std::vector& types, std::vector< std::vector >& typesF, std::vector< std::vector >& pfls, std::vector< std::vector >& locs) const throw(INTERP_KERNEL::Exception); + DataArrayDouble *getUndergroundDataArray(int iteration, int order) const throw(INTERP_KERNEL::Exception); + DataArrayDouble *getUndergroundDataArrayExt(int iteration, int order, std::vector< std::pair,std::pair > >& entries) const throw(INTERP_KERNEL::Exception); + private: + const MEDFileFieldMultiTSWithoutSDA *contentNotNull() const throw(INTERP_KERNEL::Exception); + MEDFileFieldMultiTSWithoutSDA *contentNotNull() throw(INTERP_KERNEL::Exception); private: MEDFileFieldMultiTS(); MEDFileFieldMultiTS(const MEDFileFieldMultiTSWithoutSDA& other, bool shallowCopyOfContent); MEDFileFieldMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception); MEDFileFieldMultiTS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); - protected: - MEDCouplingAutoRefCountObjectPtr _content; }; - class MEDCOUPLING_EXPORT MEDFileFieldMultiTSIterator + /*! + * User class. + */ + class MEDLOADER_EXPORT MEDFileIntFieldMultiTS : public MEDFileAnyTypeFieldMultiTS { public: - MEDFileFieldMultiTSIterator(MEDFileFieldMultiTS *fmts); - ~MEDFileFieldMultiTSIterator(); - MEDFileField1TS *nextt(); + static MEDFileIntFieldMultiTS *New(); + static MEDFileIntFieldMultiTS *New(const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileIntFieldMultiTS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + static MEDFileIntFieldMultiTS *New(const MEDFileIntFieldMultiTSWithoutSDA& other, bool shallowCopyOfContent); + MEDFileAnyTypeFieldMultiTS *shallowCpy() const throw(INTERP_KERNEL::Exception); + void checkCoherencyOfType(const MEDFileAnyTypeField1TS *f1ts) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TS *getTimeStepAtPos(int pos) const throw(INTERP_KERNEL::Exception); + // + MEDCouplingFieldDouble *getFieldAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, DataArrayInt* &arrOut, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldAtTopLevel(TypeOfField type, int iteration, int order, DataArrayInt* &arrOut, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt* &arrOut, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, const MEDCouplingMesh *mesh, DataArrayInt* &arrOut, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldAtLevelOld(TypeOfField type, int iteration, int order, const char *mname, int meshDimRelToMax, DataArrayInt* &arrOut, int renumPol=0) const throw(INTERP_KERNEL::Exception); + DataArrayInt *getFieldWithProfile(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, DataArrayInt *&pfl) const throw(INTERP_KERNEL::Exception); + // + void appendFieldNoProfileSBT(const MEDCouplingFieldDouble *field, const DataArrayInt *arrOfVals) throw(INTERP_KERNEL::Exception); + void appendFieldProfile(const MEDCouplingFieldDouble *field, const DataArrayInt *arrOfVals, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception); + // + DataArrayInt *getUndergroundDataArray(int iteration, int order) const throw(INTERP_KERNEL::Exception); private: - MEDCouplingAutoRefCountObjectPtr _fmts; + const MEDFileIntFieldMultiTSWithoutSDA *contentNotNull() const throw(INTERP_KERNEL::Exception); + MEDFileIntFieldMultiTSWithoutSDA *contentNotNull() throw(INTERP_KERNEL::Exception); + private: + MEDFileIntFieldMultiTS(); + MEDFileIntFieldMultiTS(const MEDFileIntFieldMultiTSWithoutSDA& other, bool shallowCopyOfContent); + MEDFileIntFieldMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception); + MEDFileIntFieldMultiTS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + }; + + class MEDCOUPLING_EXPORT MEDFileAnyTypeFieldMultiTSIterator + { + public: + MEDFileAnyTypeFieldMultiTSIterator(MEDFileAnyTypeFieldMultiTS *fmts); + ~MEDFileAnyTypeFieldMultiTSIterator(); + MEDFileAnyTypeField1TS *nextt() throw(INTERP_KERNEL::Exception); + private: + MEDCouplingAutoRefCountObjectPtr _fmts; int _iter_id; int _nb_iter; }; @@ -726,25 +1018,34 @@ std::vector< std::vector > getFieldSplitedByType2(int iterati static MEDFileFields *New(const char *fileName) throw(INTERP_KERNEL::Exception); std::size_t getHeapMemorySize() const; MEDFileFields *deepCpy() const throw(INTERP_KERNEL::Exception); + MEDFileFields *shallowCpy() const throw(INTERP_KERNEL::Exception); void write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception); void writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception); int getNumberOfFields() const; + std::vector< std::pair > getCommonIterations(bool& areThereSomeForgottenTS) const throw(INTERP_KERNEL::Exception); std::vector getFieldsNames() const throw(INTERP_KERNEL::Exception); std::vector getMeshesNames() const throw(INTERP_KERNEL::Exception); std::string simpleRepr() const; void simpleRepr(int bkOffset, std::ostream& oss) const; // void resize(int newSize) throw(INTERP_KERNEL::Exception); - void pushField(MEDFileFieldMultiTS *field) throw(INTERP_KERNEL::Exception); - void setFieldAtPos(int i, MEDFileFieldMultiTS *field) throw(INTERP_KERNEL::Exception); - MEDFileFieldMultiTS *getFieldAtPos(int i) const throw(INTERP_KERNEL::Exception); - MEDFileFieldMultiTS *getFieldWithName(const char *fieldName) const throw(INTERP_KERNEL::Exception); + void pushField(MEDFileAnyTypeFieldMultiTS *field) throw(INTERP_KERNEL::Exception); + void pushFields(const std::vector& fields) throw(INTERP_KERNEL::Exception); + void setFieldAtPos(int i, MEDFileAnyTypeFieldMultiTS *field) throw(INTERP_KERNEL::Exception); + int getPosFromFieldName(const char *fieldName) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTS *getFieldAtPos(int i) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTS *getFieldWithName(const char *fieldName) const throw(INTERP_KERNEL::Exception); + MEDFileFields *buildSubPart(const int *startIds, const int *endIds) const throw(INTERP_KERNEL::Exception); + MEDFileFields *partOfThisLyingOnSpecifiedMeshName(const char *meshName) const throw(INTERP_KERNEL::Exception); + MEDFileFields *partOfThisLyingOnSpecifiedTimeSteps(const std::vector< std::pair >& timeSteps) const throw(INTERP_KERNEL::Exception); + MEDFileFields *partOfThisNotLyingOnSpecifiedTimeSteps(const std::vector< std::pair >& timeSteps) const throw(INTERP_KERNEL::Exception); MEDFileFieldsIterator *iterator() throw(INTERP_KERNEL::Exception); void destroyFieldAtPos(int i) throw(INTERP_KERNEL::Exception); + void destroyFieldsAtPos(const int *startIds, const int *endIds) throw(INTERP_KERNEL::Exception); + void destroyFieldsAtPos2(int bg, int end, int step) throw(INTERP_KERNEL::Exception); bool changeMeshNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception); bool renumberEntitiesLyingOnMesh(const char *meshName, const std::vector& oldCode, const std::vector& newCode, const DataArrayInt *renumO2N) throw(INTERP_KERNEL::Exception); public: - int getPosFromFieldName(const char *fieldName) const throw(INTERP_KERNEL::Exception); std::vector getPflsReallyUsed() const; std::vector getLocsReallyUsed() const; std::vector getPflsReallyUsedMulti() const; @@ -755,7 +1056,7 @@ std::vector< std::vector > getFieldSplitedByType2(int iterati MEDFileFields(); MEDFileFields(const char *fileName) throw(INTERP_KERNEL::Exception); private: - std::vector< MEDCouplingAutoRefCountObjectPtr > _fields; + std::vector< MEDCouplingAutoRefCountObjectPtr > _fields; }; class MEDCOUPLING_EXPORT MEDFileFieldsIterator @@ -763,7 +1064,7 @@ std::vector< std::vector > getFieldSplitedByType2(int iterati public: MEDFileFieldsIterator(MEDFileFields *fs); ~MEDFileFieldsIterator(); - MEDFileFieldMultiTS *nextt(); + MEDFileAnyTypeFieldMultiTS *nextt(); private: MEDCouplingAutoRefCountObjectPtr _fs; int _iter_id; diff --git a/src/MEDLoader/MEDFileMesh.cxx b/src/MEDLoader/MEDFileMesh.cxx index 9b0363e9e..48dc0c5e3 100644 --- a/src/MEDLoader/MEDFileMesh.cxx +++ b/src/MEDLoader/MEDFileMesh.cxx @@ -485,6 +485,27 @@ void MEDFileMesh::assignFamilyNameWithGroupName() throw(INTERP_KERNEL::Exception _groups=groups; } +/*! + * Removes all groups lying on no family. If there is no empty groups, \a this is let untouched. + * + * \return the removed groups. + */ +std::vector MEDFileMesh::removeEmptyGroups() throw(INTERP_KERNEL::Exception) +{ + std::vector ret; + std::map > newGrps; + for(std::map >::const_iterator it=_groups.begin();it!=_groups.end();it++) + { + if((*it).second.empty()) + ret.push_back((*it).first); + else + newGrps[(*it).first]=(*it).second; + } + if(!ret.empty()) + _groups=newGrps; + return ret; +} + /*! * Removes a group from \a this mesh. * \param [in] name - the name of the group to remove. @@ -530,6 +551,62 @@ void MEDFileMesh::removeFamily(const char *name) throw(INTERP_KERNEL::Exception) } } +/*! + * Removes all groups in \a this that are orphan. A group is orphan if this group lies on + * a set of families, themselves orphan. A family is said orphan if its id appears nowhere in + * family field whatever its level. This method also suppresses the orphan families. + * + * \return - The list of removed groups names. + * + * \sa MEDFileMesh::removeOrphanFamilies. + */ +std::vector MEDFileMesh::removeOrphanGroups() throw(INTERP_KERNEL::Exception) +{ + removeOrphanFamilies(); + return removeEmptyGroups(); +} + +/*! + * Removes all families in \a this that are orphan. A family is said orphan if its id appears nowhere in + * family field whatever its level. Groups are updated in consequence, that is to say all groups lying on orphan family, will see their families list modified. + * + * \return - The list of removed families names. + * \sa MEDFileMesh::removeOrphanGroups. + */ +std::vector MEDFileMesh::removeOrphanFamilies() throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr allFamIdsInUse=computeAllFamilyIdsInUse(); + std::vector ret; + if(!((DataArrayInt*)allFamIdsInUse)) + { + ret=getFamiliesNames(); + _families.clear(); _groups.clear(); + return ret; + } + std::map famMap; + std::map > grps(_groups); + for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) + { + if(allFamIdsInUse->presenceOfValue((*it).second)) + famMap[(*it).first]=(*it).second; + else + { + ret.push_back((*it).first); + std::vector grpsOnEraseFam=getGroupsOnFamily((*it).first.c_str()); + for(std::vector::const_iterator it2=grpsOnEraseFam.begin();it2!=grpsOnEraseFam.end();it2++) + { + std::map >::iterator it3=grps.find(*it2);//it3!=grps.empty() thanks to copy + std::vector& famv=(*it3).second; + std::vector::iterator it4=std::find(famv.begin(),famv.end(),(*it).first);//it4!=famv.end() thanks to copy + famv.erase(it4); + } + } + } + if(!ret.empty()) + { _families=famMap; _groups=grps; } + return ret; +} + /*! * Renames a group in \a this mesh. * \param [in] oldName - a current name of the group to rename. @@ -549,8 +626,8 @@ void MEDFileMesh::changeGroupName(const char *oldName, const char *newName) thro throw INTERP_KERNEL::Exception(oss.str().c_str()); } std::string nname(newName); - it=_groups.find(nname); - if(it!=_groups.end()) + std::map >::iterator it2=_groups.find(nname); + if(it2!=_groups.end()) { std::ostringstream oss; oss << "Such groupname \"" << newName << "\" already exists ! Kill it before !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); @@ -1065,6 +1142,23 @@ std::vector MEDFileMesh::getFamiliesIds(const std::vector& fam return ret; } +/*! + * Returns a maximal abs(id) of families in \a this mesh. + * \return int - the maximal norm of family id. + * \throw If there are no families in \a this mesh. + */ +int MEDFileMesh::getMaxAbsFamilyId() const throw(INTERP_KERNEL::Exception) +{ + if(_families.empty()) + throw INTERP_KERNEL::Exception("MEDFileMesh::getMaxFamilyId : no families set !"); + int ret=-std::numeric_limits::max(); + for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) + { + ret=std::max(std::abs((*it).second),ret); + } + return ret; +} + /*! * Returns a maximal id of families in \a this mesh. * \return int - the maximal family id. @@ -1073,7 +1167,7 @@ std::vector MEDFileMesh::getFamiliesIds(const std::vector& fam int MEDFileMesh::getMaxFamilyId() const throw(INTERP_KERNEL::Exception) { if(_families.empty()) - throw INTERP_KERNEL::Exception("MEDFileUMesh::getMaxFamilyId : no families set !"); + throw INTERP_KERNEL::Exception("MEDFileMesh::getMaxFamilyId : no families set !"); int ret=-std::numeric_limits::max(); for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) { @@ -1090,7 +1184,7 @@ int MEDFileMesh::getMaxFamilyId() const throw(INTERP_KERNEL::Exception) int MEDFileMesh::getMinFamilyId() const throw(INTERP_KERNEL::Exception) { if(_families.empty()) - throw INTERP_KERNEL::Exception("MEDFileUMesh::getMinFamilyId : no families set !"); + throw INTERP_KERNEL::Exception("MEDFileMesh::getMinFamilyId : no families set !"); int ret=std::numeric_limits::max(); for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) { @@ -1099,6 +1193,20 @@ int MEDFileMesh::getMinFamilyId() const throw(INTERP_KERNEL::Exception) return ret; } +/*! + * Returns a maximal id of families in \a this mesh. Not only named families are + * considered but all family fields as well. + * \return int - the maximal family id. + */ +int MEDFileMesh::getTheMaxAbsFamilyId() const throw(INTERP_KERNEL::Exception) +{ + int m1=-std::numeric_limits::max(); + for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) + m1=std::max(std::abs((*it).second),m1); + int m2=getMaxAbsFamilyIdInArrays(); + return std::max(m1,m2); +} + /*! * Returns a maximal id of families in \a this mesh. Not only named families are * considered but all family fields as well. @@ -1113,6 +1221,11 @@ int MEDFileMesh::getTheMaxFamilyId() const throw(INTERP_KERNEL::Exception) return std::max(m1,m2); } +/*! + * Returns a minimal id of families in \a this mesh. Not only named families are + * considered but all family fields as well. + * \return int - the minimal family id. + */ int MEDFileMesh::getTheMinFamilyId() const throw(INTERP_KERNEL::Exception) { int m1=std::numeric_limits::max(); @@ -1122,6 +1235,11 @@ int MEDFileMesh::getTheMinFamilyId() const throw(INTERP_KERNEL::Exception) return std::min(m1,m2); } +/*! + * This method only considers the maps. The contain of family array is ignored here. + * + * \sa MEDFileMesh::computeAllFamilyIdsInUse + */ DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); @@ -1133,6 +1251,27 @@ DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const throw(INTERP_KERN return ret.retn(); } +/*! + * This method does not consider map of family name, family id. Only family field array on different levels is considered. + * + * \sa MEDFileMesh::getAllFamiliesIdsReferenced + */ +DataArrayInt *MEDFileMesh::computeAllFamilyIdsInUse() const throw(INTERP_KERNEL::Exception) +{ + std::vector famLevs=getFamArrNonEmptyLevelsExt(); + MEDCouplingAutoRefCountObjectPtr ret; + for(std::vector::const_iterator it=famLevs.begin();it!=famLevs.end();it++) + { + const DataArrayInt *arr=getFamilyFieldAtLevel(*it);//arr not null due to spec of getFamArrNonEmptyLevelsExt + MEDCouplingAutoRefCountObjectPtr dv=arr->getDifferentValues(); + if((DataArrayInt *) ret) + ret=dv->buildUnion(ret); + else + ret=dv; + } + return ret.retn(); +} + /*! * true is returned if no modification has been needed. false if family * renumbering has been needed. @@ -1321,7 +1460,7 @@ void MEDFileMesh::normalizeFamIdsMEDFile() throw(INTERP_KERNEL::Exception) refId=-1; for(std::set::const_reverse_iterator it2=levsS.rbegin();it2!=levsS.rend();it2++) { - const DataArrayInt *fam=getFamilyFieldAtLevel(1); + const DataArrayInt *fam=getFamilyFieldAtLevel(*it2); if(fam) { MEDCouplingAutoRefCountObjectPtr tmp=fam->getDifferentValues(); @@ -1565,8 +1704,8 @@ void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector ids=fam->getDifferentValues(); appendFamilyEntries(ids,fidsOfGroups,grpsName2); setFamilyFieldArr(meshDimRelToMaxExt,fam); @@ -1599,9 +1738,13 @@ void MEDFileMesh::appendFamilyEntries(const DataArrayInt *famIds, const std::vec void MEDFileMesh::TranslateFamilyIds(int offset, DataArrayInt *famArr, std::vector< std::vector >& famIdsPerGrp) { - famArr->applyLin(1,offset,0); + famArr->applyLin(offset>0?1:-1,offset,0); for(std::vector< std::vector >::iterator it1=famIdsPerGrp.begin();it1!=famIdsPerGrp.end();it1++) - std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::bind2nd(std::plus(),offset)); + { + if(offset<0) + std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::negate()); + std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::bind2nd(std::plus(),offset)); + } } /*! @@ -1795,6 +1938,11 @@ MEDFileMesh *MEDFileUMesh::shallowCpy() const throw(INTERP_KERNEL::Exception) return ret.retn(); } +MEDFileMesh *MEDFileUMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileUMesh; +} + MEDFileMesh *MEDFileUMesh::deepCpy() const throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr ret=new MEDFileUMesh(*this); @@ -2067,6 +2215,57 @@ std::vector MEDFileUMesh::getNonEmptyLevelsExt() const return ret0; } +std::vector MEDFileUMesh::getFamArrNonEmptyLevelsExt() const +{ + std::vector ret; + const DataArrayInt *famCoo(_fam_coords); + if(famCoo) + ret.push_back(1); + int lev=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--) + { + const MEDFileUMeshSplitL1 *cur(*it); + if(cur) + if(cur->getFamilyField()) + ret.push_back(lev); + } + return ret; +} + +std::vector MEDFileUMesh::getNumArrNonEmptyLevelsExt() const +{ + std::vector ret; + const DataArrayInt *numCoo(_num_coords); + if(numCoo) + ret.push_back(1); + int lev=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--) + { + const MEDFileUMeshSplitL1 *cur(*it); + if(cur) + if(cur->getNumberField()) + ret.push_back(lev); + } + return ret; +} + +std::vector MEDFileUMesh::getNameArrNonEmptyLevelsExt() const +{ + std::vector ret; + const DataArrayAsciiChar *nameCoo(_name_coords); + if(nameCoo) + ret.push_back(1); + int lev=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--) + { + const MEDFileUMeshSplitL1 *cur(*it); + if(cur) + if(cur->getNameField()) + ret.push_back(lev); + } + return ret; +} + /*! * Returns all relative mesh levels (**excluding nodes**) where a given group is defined. * To include nodes, call getGrpNonEmptyLevelsExt() method. @@ -2195,6 +2394,29 @@ std::vector MEDFileUMesh::getGroupsOnSpecifiedLev(int meshDimRelToM return ret; } +int MEDFileUMesh::getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) +{ + int ret=-std::numeric_limits::max(),tmp=-1; + if((const DataArrayInt *)_fam_coords) + { + int val=_fam_coords->getMaxValue(tmp); + ret=std::max(ret,std::abs(val)); + } + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++) + { + if((const MEDFileUMeshSplitL1 *)(*it)) + { + const DataArrayInt *da=(*it)->getFamilyField(); + if(da) + { + int val=da->getMaxValue(tmp); + ret=std::max(ret,std::abs(val)); + } + } + } + return ret; +} + int MEDFileUMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) { int ret=-std::numeric_limits::max(),tmp=-1; @@ -3027,9 +3249,19 @@ void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids) throw(INTERP_KERNEL::Ex if(!((DataArrayInt *)_fam_coords)) { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); } // - addGroupUnderground(ids,_fam_coords); + addGroupUnderground(true,ids,_fam_coords); } +/*! + * Adds a group of nodes/cells/faces/edges to \a this mesh. + * \param [in] ids - a DataArrayInt providing ids and a name of the group to add. + * The ids should be sorted and different each other (MED file norm). + * \throw If the node coordinates array is not set. + * \throw If \a ids == \c NULL. + * \throw If \a ids->getName() == "". + * \throw If \a ids does not respect the MED file norm. + * \throw If a group with name \a ids->getName() already exists. + */ void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids) throw(INTERP_KERNEL::Exception) { std::vector levs=getNonEmptyLevelsExt(); @@ -3042,14 +3274,14 @@ void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids) thr { addNodeGroup(ids); return ; } MEDFileUMeshSplitL1 *lev=getMeshAtLevSafe(meshDimRelToMaxExt); DataArrayInt *fam=lev->getOrCreateAndGetFamilyField(); - addGroupUnderground(ids,fam); + addGroupUnderground(false,ids,fam); } /*! * \param [in] ids ids and group name of the new group to add. The ids should be sorted and different each other (MED file norm). * \parma [in,out] famArr family array on level of interest to be renumbered. The input pointer should be not \c NULL (no check of that will be performed) */ -void MEDFileUMesh::addGroupUnderground(const DataArrayInt *ids, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception) +void MEDFileUMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception) { if(!ids) throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !"); @@ -3070,7 +3302,7 @@ void MEDFileUMesh::addGroupUnderground(const DataArrayInt *ids, DataArrayInt *fa MEDCouplingAutoRefCountObjectPtr diffFamIds=famIds->getDifferentValues(); std::vector familyIds; std::vector< MEDCouplingAutoRefCountObjectPtr > idsPerfamiliyIds; - int maxVal=getTheMaxFamilyId()+1; + int maxVal=getTheMaxAbsFamilyId()+1; std::map families(_families); std::map > groups(_groups); std::vector fams; @@ -3090,7 +3322,8 @@ void MEDFileUMesh::addGroupUnderground(const DataArrayInt *ids, DataArrayInt *fa { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp else { - familyIds.push_back(maxVal); idsPerfamiliyIds.push_back(ids2); std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,maxVal,created); + familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ids2); + std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created); fams.push_back(locFamName); if(existsFamily(*famId)) { @@ -3102,12 +3335,12 @@ void MEDFileUMesh::addGroupUnderground(const DataArrayInt *ids, DataArrayInt *fa } else { - familyIds.push_back(maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1 - familyIds.push_back(maxVal+1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1 - std::string n2(FindOrCreateAndGiveFamilyWithId(families,maxVal+1,created)); fams.push_back(n2); + familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1 + familyIds.push_back(isNodeGroup?maxVal+1:-maxVal-1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1 + std::string n2(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal+1:-maxVal-1,created)); fams.push_back(n2); if(existsFamily(*famId)) { - std::string n1(FindOrCreateAndGiveFamilyWithId(families,maxVal,created)); std::vector v(2); v[0]=n1; v[1]=n2; + std::string n1(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created)); std::vector v(2); v[0]=n1; v[1]=n2; ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v); } maxVal+=2; @@ -3371,6 +3604,13 @@ void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumA return _ms[traducedRk]->setRenumArr(renumArr); } +/*! + * Sets the optional names of mesh entities of a given dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \param [in] nameArr - the array of the names. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + * \throw If \a nameArr has an invalid size. + */ void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception) { if(meshDimRelToMaxExt==1) @@ -3382,14 +3622,14 @@ void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiCha } DataArrayDouble *coo(_coords); if(!coo) - throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !"); - nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! "); + throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !"); + nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! "); nameArr->incrRef(); _name_coords=nameArr; return ; } if(meshDimRelToMaxExt>1) - throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !"); + throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !"); int traducedRk=-meshDimRelToMaxExt; if(traducedRk>=(int)_ms.size()) throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !"); @@ -3470,6 +3710,22 @@ std::size_t MEDFileStructuredMesh::getHeapMemorySize() const return ret; } +int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) +{ + int ret=-std::numeric_limits::max(),tmp=-1; + if((const DataArrayInt *)_fam_nodes) + { + int val=_fam_nodes->getMaxValue(tmp); + ret=std::max(ret,std::abs(val)); + } + if((const DataArrayInt *)_fam_cells) + { + int val=_fam_cells->getMaxValue(tmp); + ret=std::max(ret,std::abs(val)); + } + return ret; +} + int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) { int ret=-std::numeric_limits::max(),tmp=-1; @@ -3744,6 +4000,13 @@ void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayIn renumArr->incrRef(); } +/*! + * Sets the optional names of mesh entities of a given dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \param [in] nameArr - the array of the names. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + * \throw If \a nameArr has an invalid size. + */ void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception) { if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) @@ -3871,6 +4134,46 @@ std::vector MEDFileStructuredMesh::getNonEmptyLevelsExt() const return ret; } +/*! + * Returns the set of extensive levels (nodes included) where not NULL family arr are defined. + */ +std::vector MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const +{ + std::vector ret; + const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells); + if(famNodes) + ret.push_back(1); + if(famCells) + ret.push_back(0); + return ret; +} + +/*! + * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined. + */ +std::vector MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const +{ + std::vector ret; + const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells); + if(numNodes) + ret.push_back(1); + if(numCells) + ret.push_back(0); + return ret; +} + +/*! + * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined. + */ +std::vector MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const +{ + std::vector ret; + const DataArrayAsciiChar *namesCells(_names_cells); + if(namesCells) + ret.push_back(0); + return ret; +} + /*! * no implementation here, it is not a bug, but intresically no polyhedra in \a this. */ @@ -4180,6 +4483,11 @@ MEDFileMesh *MEDFileCMesh::shallowCpy() const throw(INTERP_KERNEL::Exception) return ret.retn(); } +MEDFileMesh *MEDFileCMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileCMesh; +} + MEDFileMesh *MEDFileCMesh::deepCpy() const throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr ret=new MEDFileCMesh(*this); @@ -4385,6 +4693,11 @@ MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const throw(INTERP_KERNEL::Exc return ret.retn(); } +MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileCurveLinearMesh; +} + MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr ret=new MEDFileCurveLinearMesh(*this); diff --git a/src/MEDLoader/MEDFileMesh.hxx b/src/MEDLoader/MEDFileMesh.hxx index cb1207799..05b7143bc 100644 --- a/src/MEDLoader/MEDFileMesh.hxx +++ b/src/MEDLoader/MEDFileMesh.hxx @@ -36,6 +36,7 @@ namespace ParaMEDMEM static MEDFileMesh *New(const char *fileName) throw(INTERP_KERNEL::Exception); static MEDFileMesh *New(const char *fileName, const char *mName, int dt=-1, int it=-1) throw(INTERP_KERNEL::Exception); std::size_t getHeapMemorySize() const; + virtual MEDFileMesh *createNewEmpty() const throw(INTERP_KERNEL::Exception) = 0; virtual MEDFileMesh *deepCpy() const throw(INTERP_KERNEL::Exception) = 0; virtual MEDFileMesh *shallowCpy() const throw(INTERP_KERNEL::Exception) = 0; virtual bool isEqual(const MEDFileMesh *other, double eps, std::string& what) const; @@ -61,6 +62,9 @@ namespace ParaMEDMEM virtual int getNumberOfNodes() const throw(INTERP_KERNEL::Exception) = 0; virtual std::vector getNonEmptyLevels() const = 0; virtual std::vector getNonEmptyLevelsExt() const = 0; + virtual std::vector getFamArrNonEmptyLevelsExt() const = 0; + virtual std::vector getNumArrNonEmptyLevelsExt() const = 0; + virtual std::vector getNameArrNonEmptyLevelsExt() const = 0; virtual void write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception); virtual void write(med_idt fid) const throw(INTERP_KERNEL::Exception); virtual int getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) = 0; @@ -93,20 +97,27 @@ namespace ParaMEDMEM std::vector getGroupsNames() const; std::vector getFamiliesNames() const; void assignFamilyNameWithGroupName() throw(INTERP_KERNEL::Exception); + std::vector removeEmptyGroups() throw(INTERP_KERNEL::Exception); void removeGroup(const char *name) throw(INTERP_KERNEL::Exception); void removeFamily(const char *name) throw(INTERP_KERNEL::Exception); + std::vector removeOrphanGroups() throw(INTERP_KERNEL::Exception); + std::vector removeOrphanFamilies() throw(INTERP_KERNEL::Exception); void changeGroupName(const char *oldName, const char *newName) throw(INTERP_KERNEL::Exception); void changeFamilyName(const char *oldName, const char *newName) throw(INTERP_KERNEL::Exception); void changeFamilyId(int oldId, int newId) throw(INTERP_KERNEL::Exception); void changeAllGroupsContainingFamily(const char *familyNameToChange, const std::vector& newFamiliesNames) throw(INTERP_KERNEL::Exception); int getFamilyId(const char *name) const throw(INTERP_KERNEL::Exception); + int getMaxAbsFamilyId() const throw(INTERP_KERNEL::Exception); int getMaxFamilyId() const throw(INTERP_KERNEL::Exception); int getMinFamilyId() const throw(INTERP_KERNEL::Exception); + int getTheMaxAbsFamilyId() const throw(INTERP_KERNEL::Exception); int getTheMaxFamilyId() const throw(INTERP_KERNEL::Exception); int getTheMinFamilyId() const throw(INTERP_KERNEL::Exception); + virtual int getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) = 0; virtual int getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) = 0; virtual int getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) = 0; DataArrayInt *getAllFamiliesIdsReferenced() const throw(INTERP_KERNEL::Exception); + DataArrayInt *computeAllFamilyIdsInUse() const throw(INTERP_KERNEL::Exception); std::vector getFamiliesIds(const std::vector& famNames) const throw(INTERP_KERNEL::Exception); std::string getFamilyNameGivenId(int id) const throw(INTERP_KERNEL::Exception); bool ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception); @@ -175,12 +186,14 @@ namespace ParaMEDMEM static MEDFileUMesh *New(const char *fileName) throw(INTERP_KERNEL::Exception); static MEDFileUMesh *New(); std::size_t getHeapMemorySize() const; + MEDFileMesh *createNewEmpty() const throw(INTERP_KERNEL::Exception); MEDFileMesh *deepCpy() const throw(INTERP_KERNEL::Exception); MEDFileMesh *shallowCpy() const throw(INTERP_KERNEL::Exception); bool isEqual(const MEDFileMesh *other, double eps, std::string& what) const; void clearNonDiscrAttributes() const; ~MEDFileUMesh(); // + int getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception); int getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception); int getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception); int getMeshDimension() const throw(INTERP_KERNEL::Exception); @@ -195,6 +208,9 @@ namespace ParaMEDMEM int getNumberOfNodes() const throw(INTERP_KERNEL::Exception); std::vector getNonEmptyLevels() const; std::vector getNonEmptyLevelsExt() const; + std::vector getFamArrNonEmptyLevelsExt() const; + std::vector getNumArrNonEmptyLevelsExt() const; + std::vector getNameArrNonEmptyLevelsExt() const; std::vector getGrpNonEmptyLevels(const char *grp) const throw(INTERP_KERNEL::Exception); std::vector getGrpNonEmptyLevelsExt(const char *grp) const throw(INTERP_KERNEL::Exception); std::vector getFamNonEmptyLevels(const char *fam) const throw(INTERP_KERNEL::Exception); @@ -247,7 +263,7 @@ namespace ParaMEDMEM void synchronizeTinyInfoOnLeaves() const; void changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception); std::list< MEDCouplingAutoRefCountObjectPtr > getAllNonNullFamilyIds() const; - void addGroupUnderground(const DataArrayInt *ids, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception); + void addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception); private: std::vector< MEDCouplingAutoRefCountObjectPtr > _ms; MEDCouplingAutoRefCountObjectPtr _coords; @@ -262,6 +278,7 @@ namespace ParaMEDMEM friend class MEDFileMesh; public: std::size_t getHeapMemorySize() const; + int getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception); int getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception); int getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception); bool isEqual(const MEDFileMesh *other, double eps, std::string& what) const; @@ -276,6 +293,9 @@ namespace ParaMEDMEM const DataArrayAsciiChar *getNameFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception); std::vector getNonEmptyLevels() const; std::vector getNonEmptyLevelsExt() const; + std::vector getFamArrNonEmptyLevelsExt() const; + std::vector getNumArrNonEmptyLevelsExt() const; + std::vector getNameArrNonEmptyLevelsExt() const; MEDCouplingMesh *getGenMeshAtLevel(int meshDimRelToMax, bool renum=false) const throw(INTERP_KERNEL::Exception); int getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception); int getNumberOfNodes() const throw(INTERP_KERNEL::Exception); @@ -307,6 +327,7 @@ namespace ParaMEDMEM static MEDFileCMesh *New(const char *fileName) throw(INTERP_KERNEL::Exception); static MEDFileCMesh *New(const char *fileName, const char *mName, int dt=-1, int it=-1) throw(INTERP_KERNEL::Exception); std::size_t getHeapMemorySize() const; + MEDFileMesh *createNewEmpty() const throw(INTERP_KERNEL::Exception); MEDFileMesh *deepCpy() const throw(INTERP_KERNEL::Exception); MEDFileMesh *shallowCpy() const throw(INTERP_KERNEL::Exception); bool isEqual(const MEDFileMesh *other, double eps, std::string& what) const; @@ -335,6 +356,7 @@ namespace ParaMEDMEM static MEDFileCurveLinearMesh *New(const char *fileName) throw(INTERP_KERNEL::Exception); static MEDFileCurveLinearMesh *New(const char *fileName, const char *mName, int dt=-1, int it=-1) throw(INTERP_KERNEL::Exception); std::size_t getHeapMemorySize() const; + MEDFileMesh *createNewEmpty() const throw(INTERP_KERNEL::Exception); MEDFileMesh *deepCpy() const throw(INTERP_KERNEL::Exception); MEDFileMesh *shallowCpy() const throw(INTERP_KERNEL::Exception); bool isEqual(const MEDFileMesh *other, double eps, std::string& what) const; diff --git a/src/MEDLoader/MEDFileUtilities.cxx b/src/MEDLoader/MEDFileUtilities.cxx index aa87b2bf1..7d529b413 100644 --- a/src/MEDLoader/MEDFileUtilities.cxx +++ b/src/MEDLoader/MEDFileUtilities.cxx @@ -38,16 +38,19 @@ med_access_mode MEDFileUtilities::TraduceWriteMode(int medloaderwritemode) throw } } -int MEDFileUtilities::TraduceFieldType(med_field_type ft) throw(INTERP_KERNEL::Exception) +const char *MEDFileUtilities::GetReadableMEDFieldType(med_field_type ft) throw(INTERP_KERNEL::Exception) { + static const char medFloat64[]="MED_FLOAT64"; + static const char medInt32[]="MED_INT32"; + static const char medInt64[]="MED_INT64"; switch(ft) { case MED_FLOAT64: - return 0; + return medFloat64; case MED_INT32: - return 1; + return medInt32; case MED_INT64: - return 2; + return medInt64; default: throw INTERP_KERNEL::Exception("Non supported field type ! Should be FLOAT64, INT32 or INT64 !"); } diff --git a/src/MEDLoader/MEDFileUtilities.hxx b/src/MEDLoader/MEDFileUtilities.hxx index e2465dbe6..6d2c05eb2 100644 --- a/src/MEDLoader/MEDFileUtilities.hxx +++ b/src/MEDLoader/MEDFileUtilities.hxx @@ -29,7 +29,7 @@ namespace MEDFileUtilities { med_access_mode TraduceWriteMode(int medloaderwritemode) throw(INTERP_KERNEL::Exception); - int TraduceFieldType(med_field_type ft) throw(INTERP_KERNEL::Exception); + const char *GetReadableMEDFieldType(med_field_type ft) throw(INTERP_KERNEL::Exception); void CheckMEDCode(int code, med_idt fid, const char *msg) throw(INTERP_KERNEL::Exception); void CheckFileForRead(const char *fileName) throw(INTERP_KERNEL::Exception); diff --git a/src/MEDLoader/SauvWriter.cxx b/src/MEDLoader/SauvWriter.cxx index 88d17854d..13f44b92f 100644 --- a/src/MEDLoader/SauvWriter.cxx +++ b/src/MEDLoader/SauvWriter.cxx @@ -244,7 +244,10 @@ void SauvWriter::setMEDFileDS(const MEDFileData* medData, if ( fields ) for ( int i = 0; i < fields->getNumberOfFields(); ++i ) { - MEDFileFieldMultiTS * f = fields->getFieldAtPos(i); + MEDFileAnyTypeFieldMultiTS * fB = fields->getFieldAtPos(i); + MEDFileFieldMultiTS * f = dynamic_cast(fB); + if(!f) + continue;// fields on int32 not managed if ( f->getMeshName() == _fileMesh->getName() ) { vector< vector > fTypes = f->getTypesOfFieldAvailable(); diff --git a/src/MEDLoader/Swig/CMakeLists.txt b/src/MEDLoader/Swig/CMakeLists.txt index 91ba8b348..b6b8b0889 100644 --- a/src/MEDLoader/Swig/CMakeLists.txt +++ b/src/MEDLoader/Swig/CMakeLists.txt @@ -66,11 +66,15 @@ INSTALL(FILES MEDLoader.i MEDLoaderTypemaps.i MEDLoaderCommon.i DESTINATION ${ME SET(PYFILES_TO_INSTALL ${CMAKE_CURRENT_BINARY_DIR}/MEDLoader.py ${CMAKE_CURRENT_SOURCE_DIR}/libMEDLoader_Swig.py) INSTALL_AND_COMPILE_PYTHON_FILE("${PYFILES_TO_INSTALL}" ${MED_salomescript_PYTHON}) -INSTALL(FILES MEDLoaderDataForTest.py MEDLoaderTest.py MEDLoaderTest2.py MEDLoaderTest3.py medutilities.py DESTINATION ${MED_salomescript_PYTHON}) -INSTALL(FILES med2sauv sauv2med PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ DESTINATION ${MED_salomescript_PYTHON} ) +INSTALL(FILES MEDLoaderDataForTest.py MEDLoaderTest.py MEDLoaderTest2.py MEDLoaderTest3.py MEDLoaderCouplingTrainingSession.py CaseIO.py CaseReader.py CaseWriter.py MEDLoaderSplitter.py medutilities.py DESTINATION ${MED_salomescript_PYTHON}) +INSTALL(FILES med2sauv PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ DESTINATION ${MED_salomescript_PYTHON} ) +INSTALL(FILES sauv2med PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ DESTINATION ${MED_salomescript_PYTHON} ) +INSTALL(FILES case2med PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ DESTINATION ${MED_salomescript_PYTHON} ) +INSTALL(FILES med2case PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ DESTINATION ${MED_salomescript_PYTHON} ) ADD_TEST(MEDLoaderTest ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/MEDLoaderTest.py) ADD_TEST(MEDLoaderTest2 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/MEDLoaderTest2.py) ADD_TEST(MEDLoaderTest3 ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/MEDLoaderTest3.py) ADD_TEST(MEDLoaderExamplesTest ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/MEDLoaderExamplesTest.py) ADD_TEST(SauvLoaderTest ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/SauvLoaderTest.py) +ADD_TEST(MEDLoaderCouplingTrainingSession ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/MEDLoaderCouplingTrainingSession.py) diff --git a/src/MEDLoader/Swig/CaseIO.py b/src/MEDLoader/Swig/CaseIO.py new file mode 100644 index 000000000..d472c3e7d --- /dev/null +++ b/src/MEDLoader/Swig/CaseIO.py @@ -0,0 +1,31 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2007-2013 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 +# +# Author Anthony GEAY (CEA/DEN/DM2S/STMF/LGLS) + +from MEDLoader import * + +class CaseIO: + dictMCTyp={NORM_HEXA8:"hexa8",NORM_POLYHED:"nfaced",NORM_QUAD4:"quad4",NORM_POLYGON:"nsided",NORM_POINT1:"point",NORM_SEG2:"bar2",NORM_SEG3:"bar3",NORM_TRI3:"tria3",NORM_TRI6:"tria6",NORM_QUAD8:"quad8",NORM_TETRA4:"tetra4",NORM_TETRA10:"tetra10",NORM_PYRA5:"pyramid5",NORM_PYRA13:"pyramid13",NORM_PENTA6:"penta6",NORM_PENTA15:"penta15",NORM_HEXA20:"hexa20"} + discSpatial={ON_CELLS:"element",ON_NODES:"node"} + dictCompo={1:"scalar",3:"vector",6:"tensor",9:"tensor9"} + dictMCTyp2=dict((v,k) for k,v in dictMCTyp.iteritems()) + discSpatial2=dict((v,k) for k,v in discSpatial.iteritems()) + dictCompo2=dict((v,k) for k,v in dictCompo.iteritems()) + pass diff --git a/src/MEDLoader/Swig/CaseReader.py b/src/MEDLoader/Swig/CaseReader.py new file mode 100644 index 000000000..87d2fbcce --- /dev/null +++ b/src/MEDLoader/Swig/CaseReader.py @@ -0,0 +1,268 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2007-2013 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 +# +# Author Anthony GEAY (CEA/DEN/DM2S/STMF/LGLS) + +import numpy as np +from MEDLoader import * +from CaseIO import CaseIO +import sys,re + +class CaseReader(CaseIO): + """ Converting a file in the Case format (Ensight) to the MED format. + A new file with the same base name and the .med extension is created. + """ + + @classmethod + def New(cls,fileName): + """ Static constructor. """ + return CaseReader(fileName) + pass + + def __init__(self,fileName): + """ Constructor """ + self._fileName=fileName + self._dirName=os.path.dirname(self._fileName) + pass + + def __traduceMesh(self,name,typ,coords,cells): + """ Convert a CASE mesh into a MEDCouplingUMesh. """ + nbCoords=len(coords) + coo=np.array(coords,dtype="float64") ; coo=coo.reshape(nbCoords,3) + coo=DataArrayDouble(coo) ; coo=coo.fromNoInterlace() + ct=self.dictMCTyp2[typ] + m=MEDCouplingUMesh(name,MEDCouplingUMesh.GetDimensionOfGeometricType(ct)) + m.setCoords(coo) + nbNodesPerCell=MEDCouplingMesh.GetNumberOfNodesOfGeometricType(ct) + cI=DataArrayInt(len(cells)+1) ; cI.iota() ; cI*=nbNodesPerCell+1 + # + cells2=cells.reshape(len(cells),nbNodesPerCell) + c2=DataArrayInt(cells2) + c=DataArrayInt(len(cells),nbNodesPerCell+1) ; c[:,0]=ct ; c[:,1:]=c2-1 ; c.rearrange(1) + m.setConnectivity(c,cI,True) + m.checkCoherency2() + return m + + def __traduceMeshForPolyhed(self,name,coords,arr0,arr1,arr2): + nbCoords=len(coords) + coo=np.array(coords,dtype="float64") ; coo=coo.reshape(nbCoords,3) + coo=DataArrayDouble(coo) ; coo=coo.fromNoInterlace() + m=MEDCouplingUMesh(name,3) + m.setCoords(coo) + # + arr2=arr2[:]-1 + arr0mc0=DataArrayInt(arr0) ; arr0mc0.computeOffsets2() + arr0mc1=DataArrayInt(arr0).deepCpy() + arr0mc2=DataArrayInt(len(arr0),2) ; arr0mc2[:,0]=DataArrayInt(arr0)-1 ; arr0mc2[:,1]=1 ; arr0mc2.rearrange(1) ; arr0mc2.computeOffsets2() + arr0mc3=DataArrayInt.Range(0,2*len(arr0),2).buildExplicitArrByRanges(arr0mc2) + arr1mc0=DataArrayInt(arr1) ; arr1mc0.computeOffsets2() + arr1mc1=arr1mc0[arr0mc0] ; arr1mc1[1:]+=arr0mc0[1:] + arr1mc2=DataArrayInt(arr1).deepCpy() ; arr1mc2+=1 ; arr1mc2.computeOffsets2() + arr2mc0=(arr1mc2[1:])[arr0mc3] + # + c=DataArrayInt(arr1.size+arr2.size) + c[arr1mc1[:-1]]=NORM_POLYHED + c[arr2mc0]=-1 + a=arr2mc0.buildUnion(arr1mc1[:-1]).buildComplement(len(c)) + c[a]=DataArrayInt(arr2) + # + m.setConnectivity(c,arr1mc1,True) + m.checkCoherency2() + return m + + def __traduceMeshForPolygon(self,name,coords,arr0,arr1): + nbCoords=len(coords) + coo=np.array(coords,dtype="float64") ; coo=coo.reshape(nbCoords,3) + coo=DataArrayDouble(coo) ; coo=coo.fromNoInterlace() + m=MEDCouplingUMesh(name,2) + m.setCoords(coo) + # + arr0_0=DataArrayInt(arr0+1) ; arr0_0.computeOffsets2() + arr0_1=DataArrayInt(len(arr0),2) ; arr0_1[:,1]=DataArrayInt(arr0) ; arr0_1[:,0]=1 ; arr0_1.rearrange(1) ; arr0_1.computeOffsets2() + arr0_2=DataArrayInt.Range(1,2*len(arr0),2).buildExplicitArrByRanges(arr0_1) + c=DataArrayInt(len(arr0)+len(arr1)) ; c[:]=0 ; c[arr0_0[:-1]]=NORM_POLYGON + c[arr0_2]=DataArrayInt(arr1-1) + # + m.setConnectivity(c,arr0_0,True) + m.checkCoherency2() + return m + + def __convertGeo2MED(self,geoFileName): + """ Convert all the geometry (all the meshes) contained in teh CASE file into MEDCouplingUMesh'es. """ + fd=open(os.path.join(self._dirName,geoFileName),"r+b") ; fd.seek(0,2) ; end=fd.tell() ; fd.seek(0) ; fd.readline() ; fd.readline() + name=fd.readline().strip() ; fd.readline() ; fd.readline() + pos=fd.tell() + mcmeshes=[] + elt=fd.read(80) ; elt=elt.strip() ; pos+=80 + while pos!=end: + if elt!="part": + raise Exception("Error on reading mesh #1 !") + fd.seek(fd.tell()+4) + meshName=fd.read(80).strip() + if fd.read(len("coordinates"))!="coordinates": + raise Exception("Error on reading mesh #2 !") + pos=fd.tell() + typeOfCoo=np.memmap(fd,dtype='byte',mode='r',offset=int(pos),shape=(1)).tolist()[0] + pos+=1+17*4 + nbNodes=np.memmap(fd,dtype='int32',mode='r',offset=int(pos),shape=(1,)).tolist()[0] + pos+=4 + coo=np.memmap(fd,dtype='float32',mode='r',offset=int(pos),shape=(nbNodes,3)) + pos+=nbNodes*3*4 ; fd.seek(pos)#np.array(0,dtype='float%i'%(typeOfCoo)).nbytes + typ=fd.read(80).strip() ; pos=fd.tell() + mcmeshes2=[] + while pos!=end and typ!="part": + mctyp=self.dictMCTyp2[typ] + nbCellsOfType=np.memmap(fd,dtype='int32',mode='r',offset=int(pos),shape=(1,)).tolist()[0] + pos+=4 + if mctyp!=NORM_POLYHED and mctyp!=NORM_POLYGON: + nbNodesPerCell=MEDCouplingMesh.GetNumberOfNodesOfGeometricType(mctyp) + cells=np.memmap(fd,dtype='int32',mode='r',offset=pos,shape=(nbCellsOfType,nbNodesPerCell)) + pos+=nbCellsOfType*nbNodesPerCell*4 + fd.seek(pos) + mcmeshes2.append(self.__traduceMesh(meshName,typ,coo,cells)) + elif mctyp==NORM_POLYHED: + nbOfFacesPerCell=np.memmap(fd,dtype='int32',mode='r',offset=int(pos),shape=(nbCellsOfType,)) + pos+=nbCellsOfType*4 + szOfNbOfNodesPerFacePerCellArr=int(nbOfFacesPerCell.sum()) + arr1=np.memmap(fd,dtype='int32',mode='r',offset=int(pos),shape=(szOfNbOfNodesPerFacePerCellArr,))#arr1 -> nbOfNodesPerFacePerCellArr + pos+=szOfNbOfNodesPerFacePerCellArr*4 + szOfNodesPerFacePerCellArr=arr1.sum() + arr2=np.memmap(fd,dtype='int32',mode='r',offset=int(pos),shape=(szOfNodesPerFacePerCellArr,))#arr2 -> nodesPerFacePerCellArr + pos+=szOfNodesPerFacePerCellArr*4 ; fd.seek(pos) + mcmeshes2.append(self.__traduceMeshForPolyhed(meshName,coo,nbOfFacesPerCell,arr1,arr2)) + pass + else: + nbOfNodesPerCell=np.memmap(fd,dtype='int32',mode='r',offset=int(pos),shape=(nbCellsOfType,)) + pos+=nbCellsOfType*4 + szOfNbOfNodesPerCellArr=int(nbOfNodesPerCell.sum()) + arr1=np.memmap(fd,dtype='int32',mode='r',offset=int(pos),shape=(szOfNbOfNodesPerCellArr,)) + pos+=szOfNbOfNodesPerCellArr*4 ; fd.seek(pos) + mcmeshes2.append(self.__traduceMeshForPolygon(meshName,coo,nbOfNodesPerCell,arr1)) + if pos!=end: + elt=fd.read(80) ; elt=elt.strip() ; typ=elt[:] ; pos+=80 + pass + pass + coo=mcmeshes2[0].getCoords() ; name=mcmeshes2[0].getName() + for itmesh in mcmeshes2: itmesh.setCoords(coo) + m=MEDCouplingUMesh.MergeUMeshesOnSameCoords(mcmeshes2) ; m.setName(name) + mcmeshes.append(m) + pass + # + ms=MEDFileMeshes() + ms.resize(len(mcmeshes)) + for i,m in enumerate(mcmeshes): + mlm=MEDFileUMesh() + mlm.setMeshAtLevel(0,m) + ms.setMeshAtPos(i,mlm) + pass + return mcmeshes,ms + + def __convertField(self,mlfields, mcmeshes, fileName, fieldName, discr, nbCompo, locId, it): + """ Convert the fields. """ + stars=re.search("[\*]+",fileName).group() + st="%0"+str(len(stars))+"i" + trueFileName=fileName.replace(stars,st%(it)) + fd=open(os.path.join(self._dirName,trueFileName),"r+b") ; fd.seek(0,2) ; end=fd.tell() ; fd.seek(0) + name=fd.readline().strip().split(" ")[0] + if name!=fieldName: + raise Exception("ConvertField : mismatch") + pos=fd.tell() + st=fd.read(80) ; st=st.strip() ; pos=fd.tell() + while pos!=end: + if st!="part": + raise Exception("ConvertField : mismatch #2") + fdisc=MEDCouplingFieldDiscretization.New(self.discSpatial2[discr]) + meshId=np.memmap(fd,dtype='int32',mode='r',offset=int(pos),shape=(1)).tolist()[0]-1 + nbOfValues=fdisc.getNumberOfTuples(mcmeshes[meshId]) + vals2=DataArrayDouble(nbOfValues,nbCompo) + fd.seek(pos+4) + st=fd.read(80).strip() ; pos=fd.tell() + offset=0 + while pos!=end and st!="part": + if st!="coordinates": + nbOfValsOfTyp=mcmeshes[meshId].getNumberOfCellsWithType(self.dictMCTyp2[st]) + else: + nbOfValsOfTyp=nbOfValues + pass + vals=np.memmap(fd,dtype='float32',mode='r',offset=int(pos),shape=(nbOfValsOfTyp,nbCompo))#np.memmap(fd,dtype='int32',mode='r',offset=159,shape=(1)) + vals2[offset:offset+nbOfValsOfTyp]=DataArrayDouble(np.array(vals,dtype='float64')).fromNoInterlace() + pos+=nbOfValsOfTyp*nbCompo*4 ; fd.seek(pos) + st=fd.read(80) ; st=st.strip() ; pos=fd.tell() + offset+=nbOfValsOfTyp + pass + f=MEDCouplingFieldDouble(self.discSpatial2[discr],ONE_TIME) ; f.setName("%s_%s"%(fieldName,mcmeshes[meshId].getName())) + f.setMesh(mcmeshes[meshId]) ; f.setArray(vals2) ; f.setTime(float(it),it,-1) + f.checkCoherency() + mlfields[locId+meshId].appendFieldNoProfileSBT(f) + pass + pass + + def loadInMEDFileDS(self): + """ Load a CASE file into a MEDFileData object. """ + f=file(self._fileName) + lines=f.readlines() + ind=lines.index("GEOMETRY\n") + if ind==-1: + raise Exception("Error with file %s"%(fname)) + geoName=re.match("model:([\W]*)([\w\.]+)",lines[ind+1]).group(2) + m1,m2=self.__convertGeo2MED(geoName) + ind=lines.index("VARIABLE\n") + fieldsInfo=[] + for i in xrange(ind+1,lines.index("TIME\n")): + m=re.match("^([\w]+)[\s]+\per[\s]+([\w]+)[\s]*\:[\s]*([\w]+)[\s]+([\S]+)$",lines[i]) + if m: + spatialDisc=m.groups()[1] ; fieldName=m.groups()[2] ; nbOfCompo=self.dictCompo2[m.groups()[0]] ; fieldFileName=m.groups()[3] + fieldsInfo.append((fieldName,spatialDisc,nbOfCompo,fieldFileName)) + pass + pass + + expr=re.compile("number[\s]+of[\s]+steps[\s]*\:[\s]*([\d]+)") + nbOfTimeSteps=int(expr.search(filter(expr.search,lines)[0]).group(1)) + + expr=re.compile("filename[\s]+start[\s]+number[\s]*\:[\s]*([\d]+)") + startIt=int(expr.search(filter(expr.search,lines)[0]).group(1)) + + expr=re.compile("filename[\s]+increment[\s]*\:[\s]*([\d]+)") + incrIt=int(expr.search(filter(expr.search,lines)[0]).group(1)) + + curIt=startIt + mlfields=MEDFileFields() + mlfields.resize(len(fieldsInfo)*len(m1)) + i=0 + for field in fieldsInfo: + for m in m1: + mlfields.setFieldAtPos(i,MEDFileFieldMultiTS()) + i+=1 + pass + pass + for ts in xrange(nbOfTimeSteps): + i=0 + for field in fieldsInfo: + self.__convertField(mlfields,m1,field[3],field[0],field[1],field[2],i,curIt) + i+=len(m1) + pass + curIt+=incrIt + pass + ret=MEDFileData() + ret.setMeshes(m2) + del mlfields[filter(lambda x: len(mlfields[x])==0,range(len(mlfields)))] + ret.setFields(mlfields) + return ret + + pass diff --git a/src/MEDLoader/Swig/CaseWriter.py b/src/MEDLoader/Swig/CaseWriter.py new file mode 100644 index 000000000..d6ea392af --- /dev/null +++ b/src/MEDLoader/Swig/CaseWriter.py @@ -0,0 +1,349 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2007-2013 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 +# +# Author Anthony GEAY (CEA/DEN/DM2S/STMF/LGLS) + +import numpy as np +from CaseIO import CaseIO +from MEDLoader import * +import sys,re,os,mmap + +### www-vis.lbl.gov/NERSC/Software/ensight/doc/OnlineHelp/UM-C11.pdf + +class CaseWriter(CaseIO): + """ Converting MED file format in memory to a the Case file format (Ensight). + A new file with the same base name and the .case extension is created with its depencies (.geo ...). + """ + + header="""FORMAT +type: ensight gold +GEOMETRY +model: %(geofilewithoutpath)s +""" + header_varpart="""VARIABLE""" + header_timepart="""TIME +time set: 1 +number of steps: %(NbTimeSteps)i +filename start number: 0 +filename increment: 1 +time values: +%(TimeValues)s +""" + + @classmethod + def New(cls): + """ Static constructor. """ + return CaseWriter() + pass + + def __init__(self): + """ Constructor """ + self.__export_groups=False + pass + + def setMEDFileDS(self,medData): + """ Input should be MEDFileData instance """ + self._med_data=medData + pass + + def isExportingGroups(self): + """ return the status of exporting groups policy """ + return self.__export_groups + + def setExportingGroups(self,status): + assert(isinstance(status,bool)) + self.__export_groups=status + pass + + + def write(self,fileName): + """ Write into the specified fileName series the result """ + self._file_name=fileName + self._base_name_without_dir=os.path.splitext(os.path.basename(self._file_name))[0] + self._l=self._file_name.split(os.path.sep) ; self._l[-1]=os.path.splitext(self._l[-1])[0] + self._base_name_with_dir=os.path.sep.join(self._l) + self._real_written_file_name=[] + self._dico={} + for mesh in self._med_data.getMeshes(): + additionnalFileNamePart="" + if len(self._med_data.getMeshes())!=1: + additionnalFileNamePart="_%s"%(mesh.getName()) + pass + self._dico["geofilewithoutpath"]="%s%s.geo"%(self._base_name_without_dir,additionnalFileNamePart) + h0=self.header%self._dico + self.__writeMeshesPart(mesh,"%s%s.geo"%(self._base_name_with_dir,additionnalFileNamePart)) + # + h2=self.__writeFieldsPart(self._med_data.getFields().partOfThisLyingOnSpecifiedMeshName(mesh.getName())) + realWrittenCaseFileNameForCurMesh="%s%s.case"%(self._base_name_with_dir,additionnalFileNamePart) + fheader=open(realWrittenCaseFileNameForCurMesh,"w") ; fheader.write((h0+h2)%self._dico) + self._real_written_file_name.append(realWrittenCaseFileNameForCurMesh) + pass + return self._real_written_file_name + + def __writeMeshesPart(self,mdm,meshfn): + try: + os.remove(meshfn) + except: + pass + f=open(meshfn,"w+b") + sz=5*80 + # + assert(isinstance(mdm,MEDFileUMesh)) + ms2=[[mdm.getMeshAtLevel(lev) for lev in mdm.getNonEmptyLevels()[:1]]] + if self.__export_groups: + for grpnm in mdm.getGroupsNames(): + ms3=[] + for lev in mdm.getGrpNonEmptyLevels(grpnm)[:1]: + m=mdm.getGroup(lev,grpnm) ; m.zipCoords() + ms3.append(m) + pass + ms2.append(ms3) + pass + pass + for ms in ms2: + nn=ms[0].getNumberOfNodes() + sz+=self.__computeSizeOfGeoFile(ms,nn) + pass + pass + a=np.memmap(f,dtype='byte',mode='w+',offset=0,shape=(sz,)) ; a.flush() # truncate to set the size of the file + mm=mmap.mmap(f.fileno(),offset=0,length=0) + mm.write(self.__str80("C Binary")) + mm.write(self.__str80("Exported from MEDCoupling/MEDLoader SALOME version %s"%(MEDCouplingVersionStr()))) + mm.write(self.__str80("Conversion using CaseWriter class")) + mm.write(self.__str80("node id off")) + mm.write(self.__str80("element id off")) + for iii,ms in enumerate(ms2): + nn=ms[0].getNumberOfNodes() + mm.write(self.__str80("part")) + a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(1,)) + a[0]=iii+1 ; a.flush() ; mm.seek(mm.tell()+4) # part number maybe to change ? + name=ms[0].getName() + if iii>0: + name="%s_%s"%(ms2[0][0].getName(),name) + pass + mm.write(self.__str80(name)) + mm.write(self.__str80("coordinates")) + a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(1,)) + a[0]=nn ; a.flush() # number of nodes + mm.seek(mm.tell()+4) + coo=ms[0].getCoords() + spaceDim=coo.getNumberOfComponents() + if spaceDim!=3: + coo=coo.changeNbOfComponents(3,0.) + pass + a=np.memmap(f,dtype='float32',mode='w+',offset=mm.tell(),shape=(3,nn)) + c=coo.toNoInterlace() ; c.rearrange(1) ; cnp=c.toNumPyArray() ; cnp=cnp.reshape(3,nn) + a[:]=cnp ; a.flush() ; mm.seek(mm.tell()+3*nn*4) + for m in ms: + i=0 + for typ2,nbelem,dummy in m.getDistributionOfTypes(): + typ=typ2 + if typ not in self.dictMCTyp: + typ=MEDCouplingMesh.GetCorrespondingPolyType(typ) + pass + mp=m[i:i+nbelem] + mm.write(self.__str80(self.dictMCTyp[typ])) + a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(1,)) + a[0]=nbelem ; a.flush() ; mm.seek(mm.tell()+4) + if typ!=NORM_POLYHED and typ!=NORM_POLYGON: + nbNodesPerElem=MEDCouplingMesh.GetNumberOfNodesOfGeometricType(typ) + c=mp.getNodalConnectivity() ; c.rearrange(nbNodesPerElem+1) ; c=c[:,1:] ; c.rearrange(1) ; c+=1 + a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(nbNodesPerElem*nbelem,)) + a[:]=c.toNumPyArray() ; a.flush() ; mm.seek(mm.tell()+nbNodesPerElem*nbelem*4) + pass + elif typ==NORM_POLYHED: + mp.orientCorrectlyPolyhedrons() + c=mp.computeNbOfFacesPerCell() + a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(nbelem,)) + a[:]=c.toNumPyArray(); a.flush() ; mm.seek(mm.tell()+nbelem*4) + c=mp.getNodalConnectivity()[:] ; c.pushBackSilent(-1) ; c[mp.getNodalConnectivityIndex()[:-1]]=-1 ; ids=c.getIdsEqual(-1) ; nbOfNodesPerFace=ids.deltaShiftIndex()-1 + a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(len(nbOfNodesPerFace),)) + a[:]=nbOfNodesPerFace.toNumPyArray() ; a.flush() ; mm.seek(mm.tell()+len(nbOfNodesPerFace)*4) + ids2=ids.buildComplement(ids.back()+1) + c2=mp.getNodalConnectivity()[ids2]+1 + a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(len(c2),)) + a[:]=c2.toNumPyArray() ; a.flush() ; mm.seek(mm.tell()+len(c2)*4) + pass + else: + nbOfNodesPerCell=mp.getNodalConnectivityIndex().deltaShiftIndex()-1 + a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(len(nbOfNodesPerCell),)) + a[:]=nbOfNodesPerCell.toNumPyArray() ; a.flush() ; mm.seek(mm.tell()+len(nbOfNodesPerCell)*4) + ids2=mp.getNodalConnectivityIndex().buildComplement(mp.getNodalConnectivityIndex().back()+1) + c2=mp.getNodalConnectivity()[ids2]+1 + a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(len(c2),)) + a[:]=c2.toNumPyArray() ; a.flush() ; mm.seek(mm.tell()+len(c2)*4) + pass + i+=nbelem + pass + pass + pass + pass + + def __writeFieldsPart(self,mdfs): + if not mdfs: + return "" + self._ze_top_dict={} + its,areForgottenTS=mdfs.getCommonIterations() + if areForgottenTS: + print "WARNING : some iterations are NOT present in all fields ! Kept iterations are : %s !"%(str(its)) + pass + TimeValues="" + for it in its: + TimeValues+="%s\n"%(str(mdfs[0][it].getTime()[-1])) + pass + dictVars={} + for mdf in mdfs: + nbCompo=mdf.getNumberOfComponents() + if nbCompo not in self.dictCompo: + l=filter(lambda x:x-nbCompo>0,self.dictCompo.keys()) + if len(l)==0: + print "Field \"%s\" will be ignored because number of components (%i) is too big to be %s supported by case files !"%(mdf.getName(),nbCompo,str(self.dictCompo.keys())) + continue + pass + print "WARNING : Field \"%s\" will have its number of components (%i) set to %i, in order to be supported by case files (must be in %s) !"%(mdf.getName(),nbCompo,l[0],str(self.dictCompo.keys())) + nbCompo=l[0] + pass + if nbCompo in dictVars: + dictVars[nbCompo].append(mdf) + pass + else: + dictVars[nbCompo]=[mdf] + pass + pass + for mdf in mdfs: + nbCompo=mdf.getNumberOfComponents() + if nbCompo not in self.dictCompo: + l=filter(lambda x:x-nbCompo>0,self.dictCompo.keys()) + if len(l)==0: + continue; + nbCompo=l[0] + pass + for iii,it in enumerate(its): + ff=mdf[it] + isMultiDisc=len(ff.getTypesOfFieldAvailable())>1 + for typ in ff.getTypesOfFieldAvailable(): + l=self._l[:] ; l[-1]="%s%s.%s"%(self._base_name_without_dir,str(iii).rjust(4,"0"),ff.getName()) + if isMultiDisc: + l[-1]="%s_%s"(l[-1],MEDCouplingFieldDiscretization.New(typ).getStringRepr()) + pass + fffn=l[-1] + try: + os.remove(os.path.sep.join(l)) + except: + pass + f=open(os.path.sep.join(l),"w+b") + summ=0 + for geo,[(curTyp,(bg,end),pfl,loc)] in ff.getFieldSplitedByType(): + if typ==curTyp: + summ+=4*nbCompo*(end-bg)+80 + pass + pass + a=np.memmap(f,dtype='byte',mode='w+',offset=0,shape=(2*80+4+summ,)) ; a.flush() # truncate to set the size of the file + mm=mmap.mmap(f.fileno(),offset=0,length=0) + k1=ff.getName() + if isMultiDisc: + k1="%s_%s"%(k1,MEDCouplingFieldDiscretization.New(typ).getStringRepr()) + pass + mm.write(self.__str80(k1)) + mm.write(self.__str80("part")) + a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(1,)) + a[0]=1 ; a.flush() ; mm.seek(mm.tell()+4) # part number maybe to change ? + for geo,[(curTyp,(bg,end),pfl,loc)] in ff.getFieldSplitedByType(): + if pfl!="": + raise Exception("Field \"%s\" contains profiles ! Profiles are not supported yet !"%(mdf.getName())) + if typ==curTyp: + arr=ff.getUndergroundDataArray()[bg:end].changeNbOfComponents(nbCompo,0.) ; arr=arr.toNoInterlace() + if typ==ON_CELLS: + mm.write(self.__str80(self.dictMCTyp[geo])) + pass + elif typ==ON_NODES: + mm.write(self.__str80("coordinates")) + pass + else: + print "UnManaged type of field for field \"%s\" !"%(mdf.getName()) + pass + a=np.memmap(f,dtype='float32',mode='w+',offset=mm.tell(),shape=(nbCompo,end-bg)) + b=arr.toNumPyArray() ; b=b.reshape(nbCompo,end-bg) + a[:]=b + a.flush() ; mm.seek(mm.tell()+nbCompo*(end-bg)*4) + pass + pass + k="%s per %s"%(self.dictCompo[nbCompo],self.discSpatial[typ]) + if k in self._ze_top_dict: + if k1 in self._ze_top_dict[k]: + self._ze_top_dict[k][k1].append(fffn) + pass + else: + self._ze_top_dict[k][k1]=[fffn] + pass + else: + self._ze_top_dict[k]={k1:[fffn]} + pass + pass + pass + pass + headerPart="" + if len(self._ze_top_dict)!=0: + hvp=self.header_varpart[:] + for k in self._ze_top_dict: + for k1 in self._ze_top_dict[k]: + hvp+="\n%s: %s %s"%(k,k1,re.sub("([\d]{4})",4*"*",self._ze_top_dict[k][k1][0])) + pass + pass + hvp+="\n" + headerPart+=hvp + # + ddd={"NbTimeSteps":len(its),"TimeValues":TimeValues} + htp=self.header_timepart%ddd + headerPart+=htp + pass + return headerPart + + @classmethod + def __str80(cls,st): + if len(st)>79: + raise Exception("String \"%s\" is too long (>79) !"%(st)) + return st.ljust(79)+"\n" + + def __computeSizeOfGeoFile(self,listOfMeshes,nn): + sz=0 + for m in listOfMeshes: + distribTypes=m.getDistributionOfTypes() + sz+=80+4+2*80+4+nn*3*4 + i=0 + for typ2,nbelem,dummy in distribTypes: + typ=typ2 + if typ not in self.dictMCTyp: + typ=MEDCouplingMesh.GetCorrespondingPolyType() + pass + if typ!=NORM_POLYHED and typ!=NORM_POLYGON: + sz+=80+4+MEDCouplingMesh.GetNumberOfNodesOfGeometricType(typ)*nbelem*4 + pass + elif typ==NORM_POLYHED: + mplh=m[i:i+nbelem] ; delta=len(mplh.getNodalConnectivity())+nbelem + sz+=80+4+delta*4 + pass + else: + mplh=m[i:i+nbelem] ; delta=len(mplh.getNodalConnectivity()) + sz+=80+4+delta*4 + pass + i+=nbelem + pass + pass + return sz diff --git a/src/MEDLoader/Swig/MEDLoaderCommon.i b/src/MEDLoader/Swig/MEDLoaderCommon.i index ee908bcb1..b127e4c4b 100644 --- a/src/MEDLoader/Swig/MEDLoaderCommon.i +++ b/src/MEDLoader/Swig/MEDLoaderCommon.i @@ -52,6 +52,16 @@ using namespace ParaMEDMEM; $result=convertMEDFileParameter1TS($1,$owner); } +%typemap(out) ParaMEDMEM::MEDFileAnyTypeFieldMultiTS* +{ + $result=convertMEDFileFieldMultiTS($1,$owner); +} + +%typemap(out) ParaMEDMEM::MEDFileAnyTypeField1TS* +{ + $result=convertMEDFileField1TS($1,$owner); +} + %newobject MEDLoader::ReadUMeshFromFamilies; %newobject MEDLoader::ReadUMeshFromGroups; %newobject MEDLoader::ReadUMeshFromFile; @@ -61,6 +71,7 @@ using namespace ParaMEDMEM; %newobject MEDLoader::ReadFieldGauss; %newobject MEDLoader::ReadFieldGaussNE; %newobject ParaMEDMEM::MEDFileMesh::New; +%newobject ParaMEDMEM::MEDFileMesh::createNewEmpty; %newobject ParaMEDMEM::MEDFileMesh::deepCpy; %newobject ParaMEDMEM::MEDFileMesh::shallowCpy; %newobject ParaMEDMEM::MEDFileMesh::getGenMeshAtLevel; @@ -73,6 +84,7 @@ using namespace ParaMEDMEM; %newobject ParaMEDMEM::MEDFileMesh::getNodeFamilyArr; %newobject ParaMEDMEM::MEDFileMesh::getNodeFamiliesArr; %newobject ParaMEDMEM::MEDFileMesh::getAllFamiliesIdsReferenced; +%newobject ParaMEDMEM::MEDFileMesh::computeAllFamilyIdsInUse; %newobject ParaMEDMEM::MEDFileUMesh::New; %newobject ParaMEDMEM::MEDFileUMesh::getCoords; %newobject ParaMEDMEM::MEDFileUMesh::getGroup; @@ -99,29 +111,41 @@ using namespace ParaMEDMEM; %newobject ParaMEDMEM::MEDFileFields::New; %newobject ParaMEDMEM::MEDFileFields::deepCpy; +%newobject ParaMEDMEM::MEDFileFields::shallowCpy; %newobject ParaMEDMEM::MEDFileFields::getFieldWithName; %newobject ParaMEDMEM::MEDFileFields::getFieldAtPos; -%newobject ParaMEDMEM::MEDFileFields::__getitem__; +%newobject ParaMEDMEM::MEDFileFields::partOfThisLyingOnSpecifiedMeshName; +%newobject ParaMEDMEM::MEDFileFields::partOfThisLyingOnSpecifiedTimeSteps; +%newobject ParaMEDMEM::MEDFileFields::partOfThisNotLyingOnSpecifiedTimeSteps; %newobject ParaMEDMEM::MEDFileFields::__iter__; + +%newobject ParaMEDMEM::MEDFileAnyTypeFieldMultiTS::New; +%newobject ParaMEDMEM::MEDFileAnyTypeFieldMultiTS::deepCpy; +%newobject ParaMEDMEM::MEDFileAnyTypeFieldMultiTS::shallowCpy; +%newobject ParaMEDMEM::MEDFileAnyTypeFieldMultiTS::getTimeStepAtPos; +%newobject ParaMEDMEM::MEDFileAnyTypeFieldMultiTS::getTimeStep; +%newobject ParaMEDMEM::MEDFileAnyTypeFieldMultiTS::getTimeStepGivenTime; +%newobject ParaMEDMEM::MEDFileAnyTypeFieldMultiTS::__iter__; %newobject ParaMEDMEM::MEDFileFieldMultiTS::New; -%newobject ParaMEDMEM::MEDFileFieldMultiTS::deepCpy; -%newobject ParaMEDMEM::MEDFileFieldMultiTS::getTimeStepAtPos; -%newobject ParaMEDMEM::MEDFileFieldMultiTS::getTimeStep; -%newobject ParaMEDMEM::MEDFileFieldMultiTS::getTimeStepGivenTime; -%newobject ParaMEDMEM::MEDFileFieldMultiTS::__getitem__; -%newobject ParaMEDMEM::MEDFileFieldMultiTS::__iter__; %newobject ParaMEDMEM::MEDFileFieldMultiTS::getFieldAtLevel; %newobject ParaMEDMEM::MEDFileFieldMultiTS::getFieldAtTopLevel; %newobject ParaMEDMEM::MEDFileFieldMultiTS::getFieldOnMeshAtLevel; %newobject ParaMEDMEM::MEDFileFieldMultiTS::getFieldAtLevelOld; %newobject ParaMEDMEM::MEDFileFieldMultiTS::getUndergroundDataArray; +%newobject ParaMEDMEM::MEDFileIntFieldMultiTS::New; +%newobject ParaMEDMEM::MEDFileIntFieldMultiTS::getUndergroundDataArray; + +%newobject ParaMEDMEM::MEDFileAnyTypeField1TS::New; +%newobject ParaMEDMEM::MEDFileAnyTypeField1TS::shallowCpy; +%newobject ParaMEDMEM::MEDFileAnyTypeField1TS::deepCpy; %newobject ParaMEDMEM::MEDFileField1TS::New; -%newobject ParaMEDMEM::MEDFileField1TS::deepCpy; %newobject ParaMEDMEM::MEDFileField1TS::getFieldAtLevel; %newobject ParaMEDMEM::MEDFileField1TS::getFieldAtTopLevel; %newobject ParaMEDMEM::MEDFileField1TS::getFieldOnMeshAtLevel; %newobject ParaMEDMEM::MEDFileField1TS::getFieldAtLevelOld; %newobject ParaMEDMEM::MEDFileField1TS::getUndergroundDataArray; +%newobject ParaMEDMEM::MEDFileIntField1TS::New; +%newobject ParaMEDMEM::MEDFileIntField1TS::getUndergroundDataArray; %newobject ParaMEDMEM::MEDFileData::New; %newobject ParaMEDMEM::MEDFileData::deepCpy; @@ -151,8 +175,12 @@ using namespace ParaMEDMEM; %feature("unref") MEDFileMeshMultiTS "$this->decrRef();" %feature("unref") MEDFileMeshes "$this->decrRef();" %feature("unref") MEDFileFieldLoc "$this->decrRef();" +%feature("unref") MEDFileAnyTypeField1TS "$this->decrRef();" %feature("unref") MEDFileField1TS "$this->decrRef();" +%feature("unref") MEDFileIntField1TS "$this->decrRef();" +%feature("unref") MEDFileAnyTypeFieldMultiTS "$this->decrRef();" %feature("unref") MEDFileFieldMultiTS "$this->decrRef();" +%feature("unref") MEDFileIntFieldMultiTS "$this->decrRef();" %feature("unref") MEDFileFields "$this->decrRef();" %feature("unref") MEDFileParameter1TS "$this->decrRef();" %feature("unref") MEDFileParameterDouble1TSWTI "$this->decrRef();" @@ -363,9 +391,10 @@ namespace ParaMEDMEM public: static MEDFileMesh *New(const char *fileName) throw(INTERP_KERNEL::Exception); static MEDFileMesh *New(const char *fileName, const char *mName, int dt=-1, int it=-1) throw(INTERP_KERNEL::Exception); + virtual MEDFileMesh *createNewEmpty() const throw(INTERP_KERNEL::Exception); virtual MEDFileMesh *deepCpy() const throw(INTERP_KERNEL::Exception); virtual MEDFileMesh *shallowCpy() const throw(INTERP_KERNEL::Exception); - virtual void clearNonDiscrAttributes() const; + virtual void clearNonDiscrAttributes() const throw(INTERP_KERNEL::Exception); void setName(const char *name); const char *getName(); const char *getUnivName() const; @@ -383,23 +412,26 @@ namespace ParaMEDMEM void setTimeUnit(const char *unit); const char *getTimeUnit() const; virtual int getNumberOfNodes() const throw(INTERP_KERNEL::Exception); + virtual std::vector getFamArrNonEmptyLevelsExt() const throw(INTERP_KERNEL::Exception); + virtual std::vector getNumArrNonEmptyLevelsExt() const throw(INTERP_KERNEL::Exception); + virtual std::vector getNameArrNonEmptyLevelsExt() const throw(INTERP_KERNEL::Exception); std::vector getNonEmptyLevels() const throw(INTERP_KERNEL::Exception); std::vector getNonEmptyLevelsExt() const throw(INTERP_KERNEL::Exception); void write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception); int getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception); // - bool existsGroup(const char *groupName) const; - bool existsFamily(int famId) const; - bool existsFamily(const char *familyName) const; - void setFamilyId(const char *familyName, int id); + bool existsGroup(const char *groupName) const throw(INTERP_KERNEL::Exception); + bool existsFamily(int famId) const throw(INTERP_KERNEL::Exception); + bool existsFamily(const char *familyName) const throw(INTERP_KERNEL::Exception); + void setFamilyId(const char *familyName, int id) throw(INTERP_KERNEL::Exception); void setFamilyIdUnique(const char *familyName, int id) throw(INTERP_KERNEL::Exception); void addFamily(const char *familyName, int id) throw(INTERP_KERNEL::Exception); void addFamilyOnGrp(const char *grpName, const char *famName) throw(INTERP_KERNEL::Exception); virtual void createGroupOnAll(int meshDimRelToMaxExt, const char *groupName) throw(INTERP_KERNEL::Exception); virtual bool keepFamIdsOnlyOnLevs(const std::vector& famIds, const std::vector& levs) throw(INTERP_KERNEL::Exception); - void copyFamGrpMapsFrom(const MEDFileMesh& other); - const std::map& getFamilyInfo() const; - const std::map >& getGroupInfo() const; + void copyFamGrpMapsFrom(const MEDFileMesh& other) throw(INTERP_KERNEL::Exception); + const std::map& getFamilyInfo() const throw(INTERP_KERNEL::Exception); + const std::map >& getGroupInfo() const throw(INTERP_KERNEL::Exception); std::vector getFamiliesOnGroup(const char *name) const throw(INTERP_KERNEL::Exception); std::vector getFamiliesOnGroups(const std::vector& grps) const throw(INTERP_KERNEL::Exception); std::vector getFamiliesIdsOnGroup(const char *name) const throw(INTERP_KERNEL::Exception); @@ -407,11 +439,14 @@ namespace ParaMEDMEM void setFamiliesIdsOnGroup(const char *name, const std::vector& famIds) throw(INTERP_KERNEL::Exception); std::vector getGroupsOnFamily(const char *name) const throw(INTERP_KERNEL::Exception); void setGroupsOnFamily(const char *famName, const std::vector& grps) throw(INTERP_KERNEL::Exception); - std::vector getGroupsNames() const; - std::vector getFamiliesNames() const; + std::vector getGroupsNames() const throw(INTERP_KERNEL::Exception); + std::vector getFamiliesNames() const throw(INTERP_KERNEL::Exception); void assignFamilyNameWithGroupName() throw(INTERP_KERNEL::Exception); + std::vector removeEmptyGroups() throw(INTERP_KERNEL::Exception); void removeGroup(const char *name) throw(INTERP_KERNEL::Exception); void removeFamily(const char *name) throw(INTERP_KERNEL::Exception); + std::vector removeOrphanGroups() throw(INTERP_KERNEL::Exception); + std::vector removeOrphanFamilies() throw(INTERP_KERNEL::Exception); void changeGroupName(const char *oldName, const char *newName) throw(INTERP_KERNEL::Exception); void changeFamilyName(const char *oldName, const char *newName) throw(INTERP_KERNEL::Exception); void changeFamilyId(int oldId, int newId) throw(INTERP_KERNEL::Exception); @@ -419,13 +454,17 @@ namespace ParaMEDMEM void setFamilyInfo(const std::map& info); void setGroupInfo(const std::map >&info); int getFamilyId(const char *name) const throw(INTERP_KERNEL::Exception); + int getMaxAbsFamilyId() const throw(INTERP_KERNEL::Exception); int getMaxFamilyId() const throw(INTERP_KERNEL::Exception); int getMinFamilyId() const throw(INTERP_KERNEL::Exception); + int getTheMaxAbsFamilyId() const throw(INTERP_KERNEL::Exception); int getTheMaxFamilyId() const throw(INTERP_KERNEL::Exception); int getTheMinFamilyId() const throw(INTERP_KERNEL::Exception); + virtual int getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception); virtual int getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception); virtual int getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception); DataArrayInt *getAllFamiliesIdsReferenced() const throw(INTERP_KERNEL::Exception); + DataArrayInt *computeAllFamilyIdsInUse() const throw(INTERP_KERNEL::Exception); std::vector getFamiliesIds(const std::vector& famNames) const throw(INTERP_KERNEL::Exception); std::string getFamilyNameGivenId(int id) const throw(INTERP_KERNEL::Exception); bool ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception); @@ -873,6 +912,11 @@ namespace ParaMEDMEM { return self->iterator(); } + + int __len__() const throw(INTERP_KERNEL::Exception) + { + return self->getNumberOfMeshes(); + } MEDFileMesh *getMeshAtPos(int i) const throw(INTERP_KERNEL::Exception) { @@ -901,7 +945,7 @@ namespace ParaMEDMEM const std::vector& getRefCoords() const; const std::vector& getGaussCoords() const; const std::vector& getGaussWeights() const; - bool isEqual(const MEDFileFieldLoc& other, double eps) const; + bool isEqual(const MEDFileFieldLoc& other, double eps) const throw(INTERP_KERNEL::Exception); %extend { std::string __str__() const throw(INTERP_KERNEL::Exception) @@ -914,8 +958,15 @@ namespace ParaMEDMEM class MEDFileFieldGlobsReal { public: + void resetContent(); void shallowCpyGlobs(const MEDFileFieldGlobsReal& other) throw(INTERP_KERNEL::Exception); void deepCpyGlobs(const MEDFileFieldGlobsReal& other) throw(INTERP_KERNEL::Exception); + void shallowCpyOnlyUsedGlobs(const MEDFileFieldGlobsReal& other) throw(INTERP_KERNEL::Exception); + void deepCpyOnlyUsedGlobs(const MEDFileFieldGlobsReal& other) throw(INTERP_KERNEL::Exception); + void appendGlobs(const MEDFileFieldGlobsReal& other, double eps) throw(INTERP_KERNEL::Exception); + void checkGlobsCoherency() const throw(INTERP_KERNEL::Exception); + void checkGlobsPflsPartCoherency() const throw(INTERP_KERNEL::Exception); + void checkGlobsLocsPartCoherency() const throw(INTERP_KERNEL::Exception); std::vector getPfls() const throw(INTERP_KERNEL::Exception); std::vector getLocs() const throw(INTERP_KERNEL::Exception); bool existsPfl(const char *pflName) const throw(INTERP_KERNEL::Exception); @@ -1015,17 +1066,150 @@ namespace ParaMEDMEM std::vector< std::pair, std::string > > v=convertVecPairVecStFromPy(li); self->changeLocsNamesInStruct(v); } + + std::string simpleReprGlobs() const throw(INTERP_KERNEL::Exception) + { + std::ostringstream oss; + self->simpleReprGlobs(oss); + return oss.str(); + } } }; - class MEDFileField1TS : public RefCountObject, public MEDFileFieldGlobsReal, public MEDFileWritable + class MEDFileAnyTypeField1TS : public RefCountObject, public MEDFileFieldGlobsReal, public MEDFileWritable + { + public: + static MEDFileAnyTypeField1TS *New(const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileAnyTypeField1TS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + static MEDFileAnyTypeField1TS *New(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception); + void write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception); + int getDimension() const throw(INTERP_KERNEL::Exception); + int getIteration() const throw(INTERP_KERNEL::Exception); + int getOrder() const throw(INTERP_KERNEL::Exception); + std::string getName() throw(INTERP_KERNEL::Exception); + void setName(const char *name) throw(INTERP_KERNEL::Exception); + std::string getMeshName() throw(INTERP_KERNEL::Exception); + void setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception); + int getNumberOfComponents() const throw(INTERP_KERNEL::Exception); + bool isDealingTS(int iteration, int order) const throw(INTERP_KERNEL::Exception); + void setInfo(const std::vector& infos) throw(INTERP_KERNEL::Exception); + const std::vector& getInfo() const throw(INTERP_KERNEL::Exception); + void setTime(int iteration, int order, double val) throw(INTERP_KERNEL::Exception); + virtual MEDFileAnyTypeField1TS *shallowCpy() const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TS *deepCpy() const throw(INTERP_KERNEL::Exception); + std::string getDtUnit() const throw(INTERP_KERNEL::Exception); + void setDtUnit(const char *dtUnit) throw(INTERP_KERNEL::Exception); + %extend + { + PyObject *getTime() throw(INTERP_KERNEL::Exception) + { + int tmp1,tmp2; + double tmp0=self->getTime(tmp1,tmp2); + PyObject *res = PyList_New(3); + PyList_SetItem(res,0,SWIG_From_int(tmp1)); + PyList_SetItem(res,1,SWIG_From_int(tmp2)); + PyList_SetItem(res,2,SWIG_From_double(tmp0)); + return res; + } + + PyObject *getDtIt() const throw(INTERP_KERNEL::Exception) + { + std::pair res=self->getDtIt(); + PyObject *elt=PyTuple_New(2); + PyTuple_SetItem(elt,0,SWIG_From_int(res.first)); + PyTuple_SetItem(elt,1,SWIG_From_int(res.second)); + return elt; + } + + void setProfileNameOnLeaf(INTERP_KERNEL::NormalizedCellType typ, int locId, const char *newPflName, bool forceRenameOnGlob=false) throw(INTERP_KERNEL::Exception) + { + self->setProfileNameOnLeaf(0,typ,locId,newPflName,forceRenameOnGlob); + } + + void setLocNameOnLeaf(INTERP_KERNEL::NormalizedCellType typ, int locId, const char *newLocName, bool forceRenameOnGlob=false) throw(INTERP_KERNEL::Exception) + { + self->setLocNameOnLeaf(0,typ,locId,newLocName,forceRenameOnGlob); + } + + bool changeMeshNames(PyObject *li) throw(INTERP_KERNEL::Exception) + { + std::vector< std::pair > modifTab=convertVecPairStStFromPy(li); + return self->changeMeshNames(modifTab); + } + + PyObject *getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception) + { + std::vector ret=self->getTypesOfFieldAvailable(); + PyObject *ret2=PyList_New(ret.size()); + for(int i=0;i<(int)ret.size();i++) + PyList_SetItem(ret2,i,SWIG_From_int(ret[i])); + return ret2; + } + + PyObject *getNonEmptyLevels(const char *mname=0) const throw(INTERP_KERNEL::Exception) + { + std::vector ret1; + int ret0=self->getNonEmptyLevels(mname,ret1); + PyObject *elt=PyTuple_New(2); + PyTuple_SetItem(elt,0,SWIG_From_int(ret0)); + PyTuple_SetItem(elt,1,convertIntArrToPyList2(ret1)); + return elt; + } + + PyObject *getFieldSplitedByType(const char *mname=0) const throw(INTERP_KERNEL::Exception) + { + std::vector types; + std::vector< std::vector > typesF; + std::vector< std::vector > pfls; + std::vector< std::vector > locs; + std::vector< std::vector< std::pair > > ret=self->getFieldSplitedByType(mname,types,typesF,pfls,locs); + int sz=ret.size(); + PyObject *ret2=PyList_New(sz); + for(int i=0;i >& dadsI=ret[i]; + const std::vector& typesFI=typesF[i]; + const std::vector& pflsI=pfls[i]; + const std::vector& locsI=locs[i]; + PyObject *elt=PyTuple_New(2); + PyTuple_SetItem(elt,0,SWIG_From_int(types[i])); + int sz2=ret[i].size(); + PyObject *elt2=PyList_New(sz2); + for(int j=0;j > ret=self->splitComponents(); + std::size_t sz=ret.size(); + PyObject *retPy=PyList_New(sz); + for(std::size_t i=0;i& getInfo() const throw(INTERP_KERNEL::Exception); - void setTime(int iteration, int order, double val) throw(INTERP_KERNEL::Exception); %extend { MEDFileField1TS(const char *fileName) throw(INTERP_KERNEL::Exception) @@ -1071,104 +1241,28 @@ namespace ParaMEDMEM { return MEDFileField1TS::New(); } - - std::string __str__() const throw(INTERP_KERNEL::Exception) - { - return self->simpleRepr(); - } - - PyObject *getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh) const throw(INTERP_KERNEL::Exception) - { - DataArrayInt *ret1=0; - DataArrayDouble *ret0=self->getFieldWithProfile(type,meshDimRelToMax,mesh,ret1); - PyObject *ret=PyTuple_New(2); - PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__DataArrayDouble, SWIG_POINTER_OWN | 0 )); - PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); - return ret; - } - - void setProfileNameOnLeaf(INTERP_KERNEL::NormalizedCellType typ, int locId, const char *newPflName, bool forceRenameOnGlob=false) throw(INTERP_KERNEL::Exception) - { - self->setProfileNameOnLeaf(0,typ,locId,newPflName,forceRenameOnGlob); - } - - void setLocNameOnLeaf(INTERP_KERNEL::NormalizedCellType typ, int locId, const char *newLocName, bool forceRenameOnGlob=false) throw(INTERP_KERNEL::Exception) - { - self->setLocNameOnLeaf(0,typ,locId,newLocName,forceRenameOnGlob); - } - PyObject *getTime() throw(INTERP_KERNEL::Exception) - { - int tmp1,tmp2; - double tmp0=self->getTime(tmp1,tmp2); - PyObject *res = PyList_New(3); - PyList_SetItem(res,0,SWIG_From_int(tmp1)); - PyList_SetItem(res,1,SWIG_From_int(tmp2)); - PyList_SetItem(res,2,SWIG_From_double(tmp0)); - return res; - } - - PyObject *getDtIt() const throw(INTERP_KERNEL::Exception) - { - std::pair res=self->getDtIt(); - PyObject *elt=PyTuple_New(2); - PyTuple_SetItem(elt,0,SWIG_From_int(res.first)); - PyTuple_SetItem(elt,1,SWIG_From_int(res.second)); - return elt; - } - - PyObject *getTypesOfFieldAvailable() const throw(INTERP_KERNEL::Exception) + void copyTinyInfoFrom(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception) { - std::vector ret=self->getTypesOfFieldAvailable(); - PyObject *ret2=PyList_New(ret.size()); - for(int i=0;i<(int)ret.size();i++) - PyList_SetItem(ret2,i,SWIG_From_int(ret[i])); - return ret2; + const DataArrayDouble *arr=0; + if(field) + arr=field->getArray(); + self->copyTinyInfoFrom(field,arr); } - PyObject *getNonEmptyLevels(const char *mname=0) const throw(INTERP_KERNEL::Exception) + std::string __str__() const throw(INTERP_KERNEL::Exception) { - std::vector ret1; - int ret0=self->getNonEmptyLevels(mname,ret1); - PyObject *elt=PyTuple_New(2); - PyTuple_SetItem(elt,0,SWIG_From_int(ret0)); - PyTuple_SetItem(elt,1,convertIntArrToPyList2(ret1)); - return elt; + return self->simpleRepr(); } - PyObject *getFieldSplitedByType(const char *mname=0) const throw(INTERP_KERNEL::Exception) + PyObject *getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh) const throw(INTERP_KERNEL::Exception) { - std::vector types; - std::vector< std::vector > typesF; - std::vector< std::vector > pfls; - std::vector< std::vector > locs; - std::vector< std::vector< std::pair > > ret=self->getFieldSplitedByType(mname,types,typesF,pfls,locs); - int sz=ret.size(); - PyObject *ret2=PyList_New(sz); - for(int i=0;i >& dadsI=ret[i]; - const std::vector& typesFI=typesF[i]; - const std::vector& pflsI=pfls[i]; - const std::vector& locsI=locs[i]; - PyObject *elt=PyTuple_New(2); - PyTuple_SetItem(elt,0,SWIG_From_int(types[i])); - int sz2=ret[i].size(); - PyObject *elt2=PyList_New(sz2); - for(int j=0;jgetFieldWithProfile(type,meshDimRelToMax,mesh,ret1); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__DataArrayDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; } PyObject *getFieldSplitedByType2(const char *mname=0) const throw(INTERP_KERNEL::Exception) @@ -1239,25 +1333,126 @@ namespace ParaMEDMEM PyTuple_SetItem(ret,1,elt); return ret; } - - bool changeMeshNames(PyObject *li) throw(INTERP_KERNEL::Exception) - { - std::vector< std::pair > modifTab=convertVecPairStStFromPy(li); - return self->changeMeshNames(modifTab); - } } }; - class MEDFileFieldMultiTSIterator + class MEDFileIntField1TS : public MEDFileAnyTypeField1TS + { + public: + static MEDFileIntField1TS *New(); + static MEDFileIntField1TS *New(const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileIntField1TS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + static MEDFileIntField1TS *New(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception); + // + void setFieldNoProfileSBT(const MEDCouplingFieldDouble *field, const DataArrayInt *arrOfVals) throw(INTERP_KERNEL::Exception); + void setFieldProfile(const MEDCouplingFieldDouble *field, const DataArrayInt *arrOfVals, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception); + %extend + { + MEDFileIntField1TS() throw(INTERP_KERNEL::Exception) + { + return MEDFileIntField1TS::New(); + } + + MEDFileIntField1TS(const char *fileName) throw(INTERP_KERNEL::Exception) + { + return MEDFileIntField1TS::New(fileName); + } + + MEDFileIntField1TS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) + { + return MEDFileIntField1TS::New(fileName,fieldName); + } + + MEDFileIntField1TS(const char *fileName, const char *fieldName, int iteration, int order) throw(INTERP_KERNEL::Exception) + { + return MEDFileIntField1TS::New(fileName,fieldName,iteration,order); + } + + std::string __str__() const throw(INTERP_KERNEL::Exception) + { + return self->simpleRepr(); + } + + PyObject *getFieldAtLevel(TypeOfField type, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + MEDCouplingFieldDouble *ret0=self->getFieldAtLevel(type,meshDimRelToMax,ret1,renumPol); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__MEDCouplingFieldDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; + } + + PyObject *getFieldAtTopLevel(TypeOfField type, int renumPol=0) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + MEDCouplingFieldDouble *ret0=self->getFieldAtTopLevel(type,ret1,renumPol); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__MEDCouplingFieldDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; + } + + PyObject *getFieldOnMeshAtLevel(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + MEDCouplingFieldDouble *ret0=self->getFieldOnMeshAtLevel(type,meshDimRelToMax,mesh,ret1,renumPol); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__MEDCouplingFieldDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; + } + + PyObject *getFieldOnMeshAtLevel(TypeOfField type, const MEDCouplingMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + MEDCouplingFieldDouble *ret0=self->getFieldOnMeshAtLevel(type,mesh,ret1,renumPol); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__MEDCouplingFieldDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; + } + + PyObject *getFieldAtLevelOld(TypeOfField type, const char *mname, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + MEDCouplingFieldDouble *ret0=self->getFieldAtLevelOld(type,mname,meshDimRelToMax,ret1,renumPol); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__MEDCouplingFieldDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; + } + + PyObject *getFieldWithProfile(TypeOfField type, int meshDimRelToMax, const MEDFileMesh *mesh) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + DataArrayInt *ret0=self->getFieldWithProfile(type,meshDimRelToMax,mesh,ret1); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; + } + + DataArrayInt *getUndergroundDataArray() const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret=self->getUndergroundDataArray(); + if(ret) + ret->incrRef(); + return ret; + } + } + }; + + class MEDFileAnyTypeFieldMultiTSIterator { public: %extend { PyObject *next() throw(INTERP_KERNEL::Exception) { - MEDFileField1TS *ret=self->nextt(); + MEDFileAnyTypeField1TS *ret=self->nextt(); if(ret) - return SWIG_NewPointerObj(SWIG_as_voidptr(ret),SWIGTYPE_p_ParaMEDMEM__MEDFileField1TS,SWIG_POINTER_OWN | 0); + return convertMEDFileField1TS(ret, SWIG_POINTER_OWN | 0 ); else { PyErr_SetString(PyExc_StopIteration,"No more data."); @@ -1267,43 +1462,317 @@ namespace ParaMEDMEM } }; - class MEDFileFieldMultiTS : public RefCountObject, public MEDFileFieldGlobsReal, public MEDFileWritable + class MEDFileAnyTypeFieldMultiTS : public RefCountObject, public MEDFileFieldGlobsReal, public MEDFileWritable { public: - static MEDFileFieldMultiTS *New() throw(INTERP_KERNEL::Exception); - static MEDFileFieldMultiTS *New(const char *fileName) throw(INTERP_KERNEL::Exception); - static MEDFileFieldMultiTS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); - MEDFileFieldMultiTS *deepCpy() const throw(INTERP_KERNEL::Exception); - // - MEDFileField1TS *getTimeStepAtPos(int pos) const throw(INTERP_KERNEL::Exception); - MEDFileField1TS *getTimeStep(int iteration, int order) const throw(INTERP_KERNEL::Exception); - MEDFileField1TS *getTimeStepGivenTime(double time, double eps=1e-8) const throw(INTERP_KERNEL::Exception); - // - void write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldAtTopLevel(TypeOfField type, int iteration, int order, int renumPol=0) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, const MEDCouplingMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception); - MEDCouplingFieldDouble *getFieldAtLevelOld(TypeOfField type, const char *mname, int iteration, int order, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception); - // - void appendFieldNoProfileSBT(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception); - void appendFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception); - // - int getNumberOfTS() const throw(INTERP_KERNEL::Exception); - void eraseEmptyTS() throw(INTERP_KERNEL::Exception); - int getPosOfTimeStep(int iteration, int order) const throw(INTERP_KERNEL::Exception); - int getPosGivenTime(double time, double eps=1e-8) const throw(INTERP_KERNEL::Exception); + static MEDFileAnyTypeFieldMultiTS *New(const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileAnyTypeFieldMultiTS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTS *deepCpy() const throw(INTERP_KERNEL::Exception); + virtual MEDFileAnyTypeFieldMultiTS *shallowCpy() const throw(INTERP_KERNEL::Exception); std::string getName() const throw(INTERP_KERNEL::Exception); void setName(const char *name) throw(INTERP_KERNEL::Exception); + std::string getDtUnit() const throw(INTERP_KERNEL::Exception); + void setDtUnit(const char *dtUnit) throw(INTERP_KERNEL::Exception); std::string getMeshName() const throw(INTERP_KERNEL::Exception); void setMeshName(const char *newMeshName) throw(INTERP_KERNEL::Exception); const std::vector& getInfo() const throw(INTERP_KERNEL::Exception); + int getNumberOfComponents() const throw(INTERP_KERNEL::Exception); + int getNumberOfTS() const throw(INTERP_KERNEL::Exception); + void eraseEmptyTS() throw(INTERP_KERNEL::Exception); + int getPosOfTimeStep(int iteration, int order) const throw(INTERP_KERNEL::Exception); + int getPosGivenTime(double time, double eps=1e-8) const throw(INTERP_KERNEL::Exception); + void write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception); + // + virtual MEDFileAnyTypeField1TS *getTimeStepAtPos(int pos) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TS *getTimeStep(int iteration, int order) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeField1TS *getTimeStepGivenTime(double time, double eps=1e-8) const throw(INTERP_KERNEL::Exception); + void pushBackTimeStep(MEDFileAnyTypeField1TS *f1ts) throw(INTERP_KERNEL::Exception); + void synchronizeNameScope() throw(INTERP_KERNEL::Exception); %extend - { - MEDFileFieldMultiTS() - { - return MEDFileFieldMultiTS::New(); - } + { + int __len__() const throw(INTERP_KERNEL::Exception) + { + return self->getNumberOfTS(); + } + + int getTimeId(PyObject *elt0) const throw(INTERP_KERNEL::Exception) + { + if(elt0 && PyInt_Check(elt0)) + {//fmts[3] + int pos=PyInt_AS_LONG(elt0); + return pos; + } + else if(elt0 && PyTuple_Check(elt0)) + { + if(PyTuple_Size(elt0)==2) + { + PyObject *o0=PyTuple_GetItem(elt0,0); + PyObject *o1=PyTuple_GetItem(elt0,1); + if(PyInt_Check(o0) && PyInt_Check(o1)) + {//fmts(1,-1) + int iter=PyInt_AS_LONG(o0); + int order=PyInt_AS_LONG(o1); + return self->getPosOfTimeStep(iter,order); + } + else + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::__getitem__ : invalid input param ! input is a tuple of size 2 but two integers are expected in this tuple to request a time steps !"); + } + else + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::__getitem__ : invalid input param ! input is a tuple of size != 2 ! two integers are expected in this tuple to request a time steps !"); + } + else if(elt0 && PyFloat_Check(elt0)) + { + double val=PyFloat_AS_DOUBLE(elt0); + return self->getPosGivenTime(val); + } + else + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::__getitem__ : invalid input params ! expected fmts[int], fmts[int,int] or fmts[double] to request time step !"); + } + + PyObject *getIterations() const throw(INTERP_KERNEL::Exception) + { + std::vector< std::pair > res=self->getIterations(); + PyObject *ret=PyList_New(res.size()); + int rk=0; + for(std::vector< std::pair >::const_iterator iter=res.begin();iter!=res.end();iter++,rk++) + { + PyObject *elt=PyTuple_New(2); + PyTuple_SetItem(elt,0,SWIG_From_int((*iter).first)); + PyTuple_SetItem(elt,1,SWIG_From_int((*iter).second)); + PyList_SetItem(ret,rk,elt); + } + return ret; + } + + PyObject *getTimeSteps() const throw(INTERP_KERNEL::Exception) + { + std::vector ret1; + std::vector< std::pair > ret=self->getTimeSteps(ret1); + std::size_t sz=ret.size(); + PyObject *ret2=PyList_New(sz); + for(std::size_t i=0;i > ret=self->getTypesOfFieldAvailable(); + PyObject *ret2=PyList_New(ret.size()); + for(int i=0;i<(int)ret.size();i++) + { + const std::vector& rett=ret[i]; + PyObject *ret3=PyList_New(rett.size()); + for(int j=0;j<(int)rett.size();j++) + PyList_SetItem(ret3,j,SWIG_From_int(rett[j])); + PyList_SetItem(ret2,i,ret3); + } + return ret2; + } + + PyObject *getNonEmptyLevels(int iteration, int order, const char *mname=0) const throw(INTERP_KERNEL::Exception) + { + std::vector ret1; + int ret0=self->getNonEmptyLevels(iteration,order,mname,ret1); + PyObject *elt=PyTuple_New(2); + PyTuple_SetItem(elt,0,SWIG_From_int(ret0)); + PyTuple_SetItem(elt,1,convertIntArrToPyList2(ret1)); + return elt; + } + + PyObject *getFieldSplitedByType(int iteration, int order, const char *mname=0) const throw(INTERP_KERNEL::Exception) + { + std::vector types; + std::vector< std::vector > typesF; + std::vector< std::vector > pfls; + std::vector< std::vector > locs; + std::vector< std::vector< std::pair > > ret=self->getFieldSplitedByType(iteration,order,mname,types,typesF,pfls,locs); + int sz=ret.size(); + PyObject *ret2=PyList_New(sz); + for(int i=0;i >& dadsI=ret[i]; + const std::vector& typesFI=typesF[i]; + const std::vector& pflsI=pfls[i]; + const std::vector& locsI=locs[i]; + PyObject *elt=PyTuple_New(2); + PyTuple_SetItem(elt,0,SWIG_From_int(types[i])); + int sz2=ret[i].size(); + PyObject *elt2=PyList_New(sz2); + for(int j=0;j getTimeIds(PyObject *elts) const throw(INTERP_KERNEL::Exception) + { + if(PyList_Check(elts)) + { + int sz=PyList_Size(elts); + std::vector ret(sz); + for(int i=0;i ret(1); + ret[0]=ParaMEDMEM_MEDFileAnyTypeFieldMultiTS_getTimeId(self,elts); + return ret; + } + } + + void __delitem__(PyObject *elts) throw(INTERP_KERNEL::Exception) + { + if(PySlice_Check(elts)) + { + Py_ssize_t strt=2,stp=2,step=2; + PySliceObject *oC=reinterpret_cast(elts); + if(PySlice_GetIndices(oC,self->getNumberOfTS(),&strt,&stp,&step)==0) + { + self->eraseTimeStepIds2(strt,stp,step); + } + else + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS.__delitem__ : error in input slice !"); + } + else + { + std::vector idsToRemove=ParaMEDMEM_MEDFileAnyTypeFieldMultiTS_getTimeIds(self,elts); + if(!idsToRemove.empty()) + self->eraseTimeStepIds(&idsToRemove[0],&idsToRemove[0]+idsToRemove.size()); + } + } + + void eraseTimeStepIds(PyObject *li) throw(INTERP_KERNEL::Exception) + { + int sw; + int pos1; + std::vector pos2; + DataArrayInt *pos3=0; + DataArrayIntTuple *pos4=0; + convertObjToPossibleCpp1(li,sw,pos1,pos2,pos3,pos4); + switch(sw) + { + case 1: + { + self->eraseTimeStepIds(&pos1,&pos1+1); + return; + } + case 2: + { + if(pos2.empty()) + return; + self->eraseTimeStepIds(&pos2[0],&pos2[0]+pos2.size()); + return ; + } + case 3: + { + self->eraseTimeStepIds(pos3->begin(),pos3->end()); + return ; + } + default: + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::eraseTimeStepIds : unexpected input array type recognized !"); + } + } + + MEDFileAnyTypeFieldMultiTSIterator *__iter__() throw(INTERP_KERNEL::Exception) + { + return self->iterator(); + } + + PyObject *__getitem__(PyObject *elt0) const throw(INTERP_KERNEL::Exception) + { + if(elt0 && PyList_Check(elt0)) + { + int sz=PyList_Size(elt0); + MEDCouplingAutoRefCountObjectPtr da=DataArrayInt::New(); da->alloc(sz,1); + int *pt=da->getPointer(); + for(int i=0;ibuildSubPart(da->begin(),da->end()),SWIG_POINTER_OWN | 0); + } + else if(elt0 && PySlice_Check(elt0)) + { + Py_ssize_t strt=2,stp=2,step=2; + PySliceObject *oC=reinterpret_cast(elt0); + if(PySlice_GetIndices(oC,self->getNumberOfTS(),&strt,&stp,&step)==0) + return convertMEDFileFieldMultiTS(self->buildSubPartSlice(strt,stp,step),SWIG_POINTER_OWN | 0); + else + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS.__getitem__ : error in input slice !"); + } + else + return convertMEDFileField1TS(self->getTimeStepAtPos(MEDFileAnyTypeFieldMultiTSgetitemSingleTS__(self,elt0)),SWIG_POINTER_OWN | 0); + } + + bool changeMeshNames(PyObject *li) throw(INTERP_KERNEL::Exception) + { + std::vector< std::pair > modifTab=convertVecPairStStFromPy(li); + return self->changeMeshNames(modifTab); + } + + PyObject *splitComponents() const throw(INTERP_KERNEL::Exception) + { + std::vector< MEDCouplingAutoRefCountObjectPtr< MEDFileAnyTypeFieldMultiTS > > ret=self->splitComponents(); + std::size_t sz=ret.size(); + PyObject *retPy=PyList_New(sz); + for(std::size_t i=0;i tmp; + convertFromPyObjVectorOfObj(li,SWIGTYPE_p_ParaMEDMEM__MEDFileAnyTypeField1TS,"MEDFileAnyTypeField1TS",tmp); + self->pushBackTimeSteps(tmp); + } + } + }; + + class MEDFileFieldMultiTS : public MEDFileAnyTypeFieldMultiTS + { + public: + static MEDFileFieldMultiTS *New() throw(INTERP_KERNEL::Exception); + static MEDFileFieldMultiTS *New(const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileFieldMultiTS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + // + MEDCouplingFieldDouble *getFieldAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldAtTopLevel(TypeOfField type, int iteration, int order, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, const MEDCouplingMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception); + MEDCouplingFieldDouble *getFieldAtLevelOld(TypeOfField type, const char *mname, int iteration, int order, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception); + // + void appendFieldNoProfileSBT(const MEDCouplingFieldDouble *field) throw(INTERP_KERNEL::Exception); + void appendFieldProfile(const MEDCouplingFieldDouble *field, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception); + %extend + { + MEDFileFieldMultiTS() + { + return MEDFileFieldMultiTS::New(); + } MEDFileFieldMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception) { @@ -1320,152 +1789,16 @@ namespace ParaMEDMEM return self->simpleRepr(); } - int __len__() const throw(INTERP_KERNEL::Exception) - { - return self->getNumberOfTS(); - } - - MEDFileField1TS *__getitem__(PyObject *elt0) const throw(INTERP_KERNEL::Exception) - { - if(elt0 && PyInt_Check(elt0)) - {//fmts[3] - int pos=PyInt_AS_LONG(elt0); - return self->getTimeStepAtPos(pos); - } - else if(elt0 && PyTuple_Check(elt0)) - { - if(PyTuple_Size(elt0)==2) - { - PyObject *o0=PyTuple_GetItem(elt0,0); - PyObject *o1=PyTuple_GetItem(elt0,1); - if(PyInt_Check(o0) && PyInt_Check(o1)) - {//fmts(1,-1) - int iter=PyInt_AS_LONG(o0); - int order=PyInt_AS_LONG(o1); - return self->getTimeStep(iter,order); - } - else - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::__getitem__ : invalid input param ! input is a tuple of size 2 but two integers are expected in this tuple to request a time steps !"); - } - else - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::__getitem__ : invalid input param ! input is a tuple of size != 2 ! two integers are expected in this tuple to request a time steps !"); - } - else if(elt0 && PyFloat_Check(elt0)) - { - double val=PyFloat_AS_DOUBLE(elt0); - return self->getTimeStepGivenTime(val); - } - else - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::__getitem__ : invalid input params ! expected fmts[int], fmts[int,int] or fmts[double] to request time step !"); - } - - MEDFileFieldMultiTSIterator *__iter__() throw(INTERP_KERNEL::Exception) - { - return self->iterator(); - } - PyObject *getFieldWithProfile(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh) const throw(INTERP_KERNEL::Exception) - { - DataArrayInt *ret1=0; - DataArrayDouble *ret0=self->getFieldWithProfile(type,iteration,order,meshDimRelToMax,mesh,ret1); - PyObject *ret=PyTuple_New(2); - PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__DataArrayDouble, SWIG_POINTER_OWN | 0 )); - PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); - return ret; - } - - PyObject *getIterations() const { - std::vector< std::pair > res=self->getIterations(); - PyObject *ret=PyList_New(res.size()); - int rk=0; - for(std::vector< std::pair >::const_iterator iter=res.begin();iter!=res.end();iter++,rk++) - { - PyObject *elt=PyTuple_New(2); - PyTuple_SetItem(elt,0,SWIG_From_int((*iter).first)); - PyTuple_SetItem(elt,1,SWIG_From_int((*iter).second)); - PyList_SetItem(ret,rk,elt); - } + DataArrayInt *ret1=0; + DataArrayDouble *ret0=self->getFieldWithProfile(type,iteration,order,meshDimRelToMax,mesh,ret1); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__DataArrayDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); return ret; } - PyObject *getTimeSteps() const throw(INTERP_KERNEL::Exception) - { - std::vector ret1; - std::vector< std::pair > ret=self->getTimeSteps(ret1); - std::size_t sz=ret.size(); - PyObject *ret2=PyList_New(sz); - for(std::size_t i=0;i > ret=self->getTypesOfFieldAvailable(); - PyObject *ret2=PyList_New(ret.size()); - for(int i=0;i<(int)ret.size();i++) - { - const std::vector& rett=ret[i]; - PyObject *ret3=PyList_New(rett.size()); - for(int j=0;j<(int)rett.size();j++) - PyList_SetItem(ret3,j,SWIG_From_int(rett[j])); - PyList_SetItem(ret2,i,ret3); - } - return ret2; - } - - PyObject *getNonEmptyLevels(int iteration, int order, const char *mname=0) const throw(INTERP_KERNEL::Exception) - { - std::vector ret1; - int ret0=self->getNonEmptyLevels(iteration,order,mname,ret1); - PyObject *elt=PyTuple_New(2); - PyTuple_SetItem(elt,0,SWIG_From_int(ret0)); - PyTuple_SetItem(elt,1,convertIntArrToPyList2(ret1)); - return elt; - } - - PyObject *getFieldSplitedByType(int iteration, int order, const char *mname=0) const throw(INTERP_KERNEL::Exception) - { - std::vector types; - std::vector< std::vector > typesF; - std::vector< std::vector > pfls; - std::vector< std::vector > locs; - std::vector< std::vector< std::pair > > ret=self->getFieldSplitedByType(iteration,order,mname,types,typesF,pfls,locs); - int sz=ret.size(); - PyObject *ret2=PyList_New(sz); - for(int i=0;i >& dadsI=ret[i]; - const std::vector& typesFI=typesF[i]; - const std::vector& pflsI=pfls[i]; - const std::vector& locsI=locs[i]; - PyObject *elt=PyTuple_New(2); - PyTuple_SetItem(elt,0,SWIG_From_int(types[i])); - int sz2=ret[i].size(); - PyObject *elt2=PyList_New(sz2); - for(int j=0;j types; @@ -1506,6 +1839,7 @@ namespace ParaMEDMEM ret->incrRef(); return ret; } + PyObject *getUndergroundDataArrayExt(int iteration, int order) const throw(INTERP_KERNEL::Exception) { std::vector< std::pair,std::pair > > elt1Cpp; @@ -1532,106 +1866,6 @@ namespace ParaMEDMEM PyTuple_SetItem(ret,1,elt); return ret; } - - int getTimeId(PyObject *elt0) const throw(INTERP_KERNEL::Exception) - { - if(elt0 && PyInt_Check(elt0)) - {//fmts[3] - int pos=PyInt_AS_LONG(elt0); - return pos; - } - else if(elt0 && PyTuple_Check(elt0)) - { - if(PyTuple_Size(elt0)==2) - { - PyObject *o0=PyTuple_GetItem(elt0,0); - PyObject *o1=PyTuple_GetItem(elt0,1); - if(PyInt_Check(o0) && PyInt_Check(o1)) - {//fmts(1,-1) - int iter=PyInt_AS_LONG(o0); - int order=PyInt_AS_LONG(o1); - return self->getPosOfTimeStep(iter,order); - } - else - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::__getitem__ : invalid input param ! input is a tuple of size 2 but two integers are expected in this tuple to request a time steps !"); - } - else - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::__getitem__ : invalid input param ! input is a tuple of size != 2 ! two integers are expected in this tuple to request a time steps !"); - } - else if(elt0 && PyFloat_Check(elt0)) - { - double val=PyFloat_AS_DOUBLE(elt0); - return self->getPosGivenTime(val); - } - else - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::__getitem__ : invalid input params ! expected fmts[int], fmts[int,int] or fmts[double] to request time step !"); - } - - std::vector getTimeIds(PyObject *elts) const throw(INTERP_KERNEL::Exception) - { - if(PyList_Check(elts)) - { - int sz=PyList_Size(elts); - std::vector ret(sz); - for(int i=0;i ret(1); - ret[0]=ParaMEDMEM_MEDFileFieldMultiTS_getTimeId(self,elts); - return ret; - } - } - - void __delitem__(PyObject *elts) throw(INTERP_KERNEL::Exception) - { - std::vector idsToRemove=ParaMEDMEM_MEDFileFieldMultiTS_getTimeIds(self,elts); - if(!idsToRemove.empty()) - self->eraseTimeStepIds(&idsToRemove[0],&idsToRemove[0]+idsToRemove.size()); - } - - void eraseTimeStepIds(PyObject *li) throw(INTERP_KERNEL::Exception) - { - int sw; - int pos1; - std::vector pos2; - DataArrayInt *pos3=0; - DataArrayIntTuple *pos4=0; - convertObjToPossibleCpp1(li,sw,pos1,pos2,pos3,pos4); - switch(sw) - { - case 1: - { - self->eraseTimeStepIds(&pos1,&pos1+1); - return; - } - case 2: - { - if(pos2.empty()) - return; - self->eraseTimeStepIds(&pos2[0],&pos2[0]+pos2.size()); - return ; - } - case 3: - { - self->eraseTimeStepIds(pos3->begin(),pos3->end()); - return ; - } - default: - throw INTERP_KERNEL::Exception("MEDFileFieldMultiTS::eraseTimeStepIds : unexpected input array type recognized !"); - } - } - - bool changeMeshNames(PyObject *li) throw(INTERP_KERNEL::Exception) - { - std::vector< std::pair > modifTab=convertVecPairStStFromPy(li); - return self->changeMeshNames(modifTab); - } } }; @@ -1642,9 +1876,9 @@ namespace ParaMEDMEM { PyObject *next() throw(INTERP_KERNEL::Exception) { - MEDFileFieldMultiTS *ret=self->nextt(); + MEDFileAnyTypeFieldMultiTS *ret=self->nextt(); if(ret) - return SWIG_NewPointerObj(SWIG_as_voidptr(ret),SWIGTYPE_p_ParaMEDMEM__MEDFileFieldMultiTS,SWIG_POINTER_OWN | 0); + return convertMEDFileFieldMultiTS(ret, SWIG_POINTER_OWN | 0 ); else { PyErr_SetString(PyExc_StopIteration,"No more data."); @@ -1654,22 +1888,126 @@ namespace ParaMEDMEM } }; + class MEDFileIntFieldMultiTS : public MEDFileAnyTypeFieldMultiTS + { + public: + static MEDFileIntFieldMultiTS *New(); + static MEDFileIntFieldMultiTS *New(const char *fileName) throw(INTERP_KERNEL::Exception); + static MEDFileIntFieldMultiTS *New(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception); + // + void appendFieldNoProfileSBT(const MEDCouplingFieldDouble *field, const DataArrayInt *arrOfVals) throw(INTERP_KERNEL::Exception); + void appendFieldProfile(const MEDCouplingFieldDouble *field, const DataArrayInt *arrOfVals, const MEDFileMesh *mesh, int meshDimRelToMax, const DataArrayInt *profile) throw(INTERP_KERNEL::Exception); + %extend + { + MEDFileIntFieldMultiTS() + { + return MEDFileIntFieldMultiTS::New(); + } + + MEDFileIntFieldMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception) + { + return MEDFileIntFieldMultiTS::New(fileName); + } + + MEDFileIntFieldMultiTS(const char *fileName, const char *fieldName) throw(INTERP_KERNEL::Exception) + { + return MEDFileIntFieldMultiTS::New(fileName,fieldName); + } + + std::string __str__() const throw(INTERP_KERNEL::Exception) + { + return self->simpleRepr(); + } + + PyObject *getFieldAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + MEDCouplingFieldDouble *ret0=self->getFieldAtLevel(type,iteration,order,meshDimRelToMax,ret1,renumPol); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__MEDCouplingFieldDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; + } + + PyObject *getFieldAtTopLevel(TypeOfField type, int iteration, int order, int renumPol=0) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + MEDCouplingFieldDouble *ret0=self->getFieldAtTopLevel(type,iteration,order,ret1,renumPol); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__MEDCouplingFieldDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; + } + + PyObject *getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + MEDCouplingFieldDouble *ret0=self->getFieldOnMeshAtLevel(type,iteration,order,meshDimRelToMax,mesh,ret1,renumPol); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__MEDCouplingFieldDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; + } + + PyObject *getFieldOnMeshAtLevel(TypeOfField type, int iteration, int order, const MEDCouplingMesh *mesh, int renumPol=0) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + MEDCouplingFieldDouble *ret0=self->getFieldOnMeshAtLevel(type,iteration,order,mesh,ret1,renumPol); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__MEDCouplingFieldDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; + } + + PyObject *getFieldAtLevelOld(TypeOfField type, int iteration, int order, const char *mname, int meshDimRelToMax, int renumPol=0) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + MEDCouplingFieldDouble *ret0=self->getFieldAtLevelOld(type,iteration,order,mname,meshDimRelToMax,ret1,renumPol); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__MEDCouplingFieldDouble, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; + } + + PyObject *getFieldWithProfile(TypeOfField type, int iteration, int order, int meshDimRelToMax, const MEDFileMesh *mesh) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret1=0; + DataArrayInt *ret0=self->getFieldWithProfile(type,iteration,order,meshDimRelToMax,mesh,ret1); + PyObject *ret=PyTuple_New(2); + PyTuple_SetItem(ret,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + PyTuple_SetItem(ret,1,SWIG_NewPointerObj(SWIG_as_voidptr(ret1),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + return ret; + } + + DataArrayInt *getUndergroundDataArray(int iteration, int order) const throw(INTERP_KERNEL::Exception) + { + DataArrayInt *ret=self->getUndergroundDataArray(iteration,order); + if(ret) + ret->incrRef(); + return ret; + } + } + }; + class MEDFileFields : public RefCountObject, public MEDFileFieldGlobsReal, public MEDFileWritable { public: static MEDFileFields *New() throw(INTERP_KERNEL::Exception); static MEDFileFields *New(const char *fileName) throw(INTERP_KERNEL::Exception); MEDFileFields *deepCpy() const throw(INTERP_KERNEL::Exception); + MEDFileFields *shallowCpy() const throw(INTERP_KERNEL::Exception); void write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception); int getNumberOfFields() const; std::vector getFieldsNames() const throw(INTERP_KERNEL::Exception); std::vector getMeshesNames() const throw(INTERP_KERNEL::Exception); // void resize(int newSize) throw(INTERP_KERNEL::Exception); - void pushField(MEDFileFieldMultiTS *field) throw(INTERP_KERNEL::Exception); - void setFieldAtPos(int i, MEDFileFieldMultiTS *field) throw(INTERP_KERNEL::Exception); - MEDFileFieldMultiTS *getFieldAtPos(int i) const throw(INTERP_KERNEL::Exception); - MEDFileFieldMultiTS *getFieldWithName(const char *fieldName) const throw(INTERP_KERNEL::Exception); + void pushField(MEDFileAnyTypeFieldMultiTS *field) throw(INTERP_KERNEL::Exception); + void setFieldAtPos(int i, MEDFileAnyTypeFieldMultiTS *field) throw(INTERP_KERNEL::Exception); + int getPosFromFieldName(const char *fieldName) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTS *getFieldAtPos(int i) const throw(INTERP_KERNEL::Exception); + MEDFileAnyTypeFieldMultiTS *getFieldWithName(const char *fieldName) const throw(INTERP_KERNEL::Exception); + MEDFileFields *partOfThisLyingOnSpecifiedMeshName(const char *meshName) const throw(INTERP_KERNEL::Exception); void destroyFieldAtPos(int i) throw(INTERP_KERNEL::Exception); %extend { @@ -1687,19 +2025,55 @@ namespace ParaMEDMEM { return self->simpleRepr(); } - - MEDFileFieldMultiTS *__getitem__(PyObject *obj) throw(INTERP_KERNEL::Exception) + + PyObject *getCommonIterations() const throw(INTERP_KERNEL::Exception) { - if(PyInt_Check(obj)) + bool ret1; + std::vector< std::pair > ret0=self->getCommonIterations(ret1); + PyObject *ret=PyTuple_New(2); + PyObject *ret_0=PyList_New(ret0.size()); + int rk=0; + for(std::vector< std::pair >::const_iterator iter=ret0.begin();iter!=ret0.end();iter++,rk++) { - return self->getFieldAtPos((int)PyInt_AS_LONG(obj)); + PyObject *elt=PyTuple_New(2); + PyTuple_SetItem(elt,0,SWIG_From_int((*iter).first)); + PyTuple_SetItem(elt,1,SWIG_From_int((*iter).second)); + PyList_SetItem(ret_0,rk,elt); } - else if(PyString_Check(obj)) + PyTuple_SetItem(ret,0,ret_0); + PyObject *ret_1=ret1?Py_True:Py_False; Py_XINCREF(ret_1); + PyTuple_SetItem(ret,1,ret_1); + return ret; + } + + MEDFileFields *partOfThisLyingOnSpecifiedTimeSteps(PyObject *timeSteps) const throw(INTERP_KERNEL::Exception) + { + std::vector< std::pair > ts=convertTimePairIdsFromPy(timeSteps); + return self->partOfThisLyingOnSpecifiedTimeSteps(ts); + } + + MEDFileFields *partOfThisNotLyingOnSpecifiedTimeSteps(PyObject *timeSteps) const throw(INTERP_KERNEL::Exception) + { + std::vector< std::pair > ts=convertTimePairIdsFromPy(timeSteps); + return self->partOfThisNotLyingOnSpecifiedTimeSteps(ts); + } + + PyObject *__getitem__(PyObject *obj) throw(INTERP_KERNEL::Exception) + { + if(obj && PyList_Check(obj)) { - return self->getFieldWithName(PyString_AsString(obj)); + int sz=PyList_Size(obj); + MEDCouplingAutoRefCountObjectPtr da=DataArrayInt::New(); da->alloc(sz,1); + int *pt=da->getPointer(); + for(int i=0;ibuildSubPart(da->begin(),da->end())),SWIGTYPE_p_ParaMEDMEM__MEDFileFields, SWIG_POINTER_OWN | 0 ); } else - throw INTERP_KERNEL::Exception("MEDFileFields::__getitem__ : only integer or string with fieldname supported !"); + return convertMEDFileFieldMultiTS(self->getFieldAtPos(MEDFileFieldsgetitemSingleTS__(self,obj)), SWIG_POINTER_OWN | 0 ); } MEDFileFields *__setitem__(int obj, MEDFileFieldMultiTS *field) throw(INTERP_KERNEL::Exception) @@ -1708,6 +2082,11 @@ namespace ParaMEDMEM return self; } + int __len__() const throw(INTERP_KERNEL::Exception) + { + return self->getNumberOfFields(); + } + MEDFileFieldsIterator *__iter__() throw(INTERP_KERNEL::Exception) { return self->iterator(); @@ -1718,6 +2097,65 @@ namespace ParaMEDMEM std::vector< std::pair > modifTab=convertVecPairStStFromPy(li); return self->changeMeshNames(modifTab); } + + int getPosOfField(PyObject *elt0) const throw(INTERP_KERNEL::Exception) + { + if(elt0 && PyInt_Check(elt0)) + {//fmts[3] + return PyInt_AS_LONG(elt0); + } + else if(elt0 && PyString_Check(elt0)) + return self->getPosFromFieldName(PyString_AsString(elt0)); + else + throw INTERP_KERNEL::Exception("MEDFileFields::getPosOfField : invalid input params ! expected fields[int], fields[string_of_field_name] !"); + } + + std::vector getPosOfFields(PyObject *elts) const throw(INTERP_KERNEL::Exception) + { + if(PyList_Check(elts)) + { + int sz=PyList_Size(elts); + std::vector ret(sz); + for(int i=0;i ret(1); + ret[0]=ParaMEDMEM_MEDFileFields_getPosOfField(self,elts); + return ret; + } + } + + void pushFields(PyObject *fields) throw(INTERP_KERNEL::Exception) + { + std::vector tmp; + convertFromPyObjVectorOfObj(fields,SWIGTYPE_p_ParaMEDMEM__MEDFileAnyTypeFieldMultiTS,"MEDFileAnyTypeFieldMultiTS",tmp); + self->pushFields(tmp); + } + + void __delitem__(PyObject *elts) throw(INTERP_KERNEL::Exception) + { + if(elts && PySlice_Check(elts)) + { + Py_ssize_t strt=2,stp=2,step=2; + PySliceObject *oC=reinterpret_cast(elts); + if(PySlice_GetIndices(oC,self->getNumberOfFields(),&strt,&stp,&step)==0) + self->destroyFieldsAtPos2(strt,stp,step); + else + throw INTERP_KERNEL::Exception("MEDFileFields.__delitem__ : error in input slice !"); + } + else + { + std::vector idsToRemove=ParaMEDMEM_MEDFileFields_getPosOfFields(self,elts); + if(!idsToRemove.empty()) + self->destroyFieldsAtPos(&idsToRemove[0],&idsToRemove[0]+idsToRemove.size()); + } + } } }; @@ -1797,7 +2235,7 @@ namespace ParaMEDMEM return self->simpleRepr(); } - PyObject *isEqual(const MEDFileParameter1TS *other, double eps) const + PyObject *isEqual(const MEDFileParameter1TS *other, double eps) const throw(INTERP_KERNEL::Exception) { std::string what; bool ret0=self->isEqual(other,eps,what); @@ -1848,7 +2286,7 @@ namespace ParaMEDMEM return self->simpleRepr(); } - PyObject *isEqual(const MEDFileParameterMultiTS *other, double eps) const + PyObject *isEqual(const MEDFileParameterMultiTS *other, double eps) const throw(INTERP_KERNEL::Exception) { std::string what; bool ret0=self->isEqual(other,eps,what); @@ -2055,6 +2493,11 @@ namespace ParaMEDMEM else throw INTERP_KERNEL::Exception("MEDFileParameters::__getitem__ : only integer or string with meshname supported !"); } + + int __len__() const throw(INTERP_KERNEL::Exception) + { + return self->getNumberOfParams(); + } MEDFileParameterMultiTS *getParamAtPos(int i) const throw(INTERP_KERNEL::Exception) { @@ -2072,7 +2515,7 @@ namespace ParaMEDMEM return ret; } - PyObject *isEqual(const MEDFileParameters *other, double eps) const + PyObject *isEqual(const MEDFileParameters *other, double eps) const throw(INTERP_KERNEL::Exception) { std::string what; bool ret0=self->isEqual(other,eps,what); diff --git a/src/MEDLoader/Swig/MEDLoaderCouplingTrainingSession.py b/src/MEDLoader/Swig/MEDLoaderCouplingTrainingSession.py new file mode 100644 index 000000000..399e200dd --- /dev/null +++ b/src/MEDLoader/Swig/MEDLoaderCouplingTrainingSession.py @@ -0,0 +1,592 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2007-2013 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 +# +# Author Anthony GEAY (CEA/DEN/DM2S/STMF/LGLS) + +from MEDLoader import * +from MEDCouplingRemapper import * +import math + +d=DataArrayDouble.New(6,2) +d[:,0]=3. +d[:,1]=range(6) +d[:,1]*=math.pi/3. +d=d.fromPolarToCart() +d.setInfoOnComponents(["X [m]","Y [m]"]) +print d.getValues() +print d +print d.magnitude().isUniform(3.,1e-12) +# +radius=3. +translationToPerform=[[0.,0.],[3./2.*radius,-radius*math.sqrt(3.)/2],[3./2.*radius,radius*math.sqrt(3.)/2],[0.,radius*math.sqrt(3.)],[-3./2.*radius,radius*math.sqrt(3.)/2],[-3./2.*radius,-radius*math.sqrt(3.)/2],[0.,-radius*math.sqrt(3.)]] +ds=len(translationToPerform)*[None] +for pos,t in enumerate(translationToPerform): + ds[pos]=d[:] + ds[pos]+=t + pass +# +d2=DataArrayDouble.Aggregate(ds) +oldNbOfTuples=d2.getNumberOfTuples() +c,cI=d2.findCommonTuples(1e-12) +tmp=c[cI[0]:cI[0+1]] +print tmp +a=cI.deltaShiftIndex() +b=a-1 +myNewNbOfTuples=oldNbOfTuples-sum(b.getValues()) +o2n,newNbOfTuples=DataArrayInt.BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfTuples,c,cI) +print "Ai je trouve le bon resultat ? %s"%(str(myNewNbOfTuples==newNbOfTuples)) ; assert myNewNbOfTuples==newNbOfTuples +# +d3=d2.renumberAndReduce(o2n,newNbOfTuples) +n2o=o2n.invertArrayO2N2N2O(newNbOfTuples) +d3_bis=d2[n2o] +print "Ai je trouve le bon resultat (2) ? %s"%(str(d3.isEqual(d3_bis,1e-12))) ; assert d3.isEqual(d3_bis,1e-12) +# +d3+=[3.3,4.4] +# d3 contains coordinates +m=MEDCouplingUMesh.New("My7hexagons",2) +m.setCoords(d3) +m.allocateCells(7) +for i in xrange(7): + m.insertNextCell(NORM_POLYGON,o2n[6*i:6*(i+1)].getValues()) + pass +m.finishInsertingCells() +m.checkCoherency() +# +m.writeVTK("My7hexagons.vtu") + +######## + +coords=[0.,0.,0., 1.,1.,0., 1.,1.25,0., 1.,0.,0., 1.,1.5,0., 2.,0.,0., 2.,1.,0., 1.,2.,0., 0.,2.,0., 3.,1.,0., + 3.,2.,0., 0.,1.,0., 1.,3.,0., 2.,2.,0., 2.,3.,0., + 0.,0.,1., 1.,1.,1., 1.,1.25,1., 1.,0.,1., 1.,1.5,1., 2.,0.,1., 2.,1.,1., 1.,2.,1., 0.,2.,1., 3.,1.,1., + 3.,2.,1., 0.,1.,1., 1.,3.,1., 2.,2.,1., 2.,3.,1., + 0.,0.,2., 1.,1.,2., 1.,1.25,2., 1.,0.,2., 1.,1.5,2., 2.,0.,2., 2.,1.,2., 1.,2.,2., 0.,2.,2., 3.,1.,2., + 3.,2.,2., 0.,1.,2., 1.,3.,2., 2.,2.,2., 2.,3.,2., + 0.,0.,3., 1.,1.,3., 1.,1.25,3., 1.,0.,3., 1.,1.5,3., 2.,0.,3., 2.,1.,3., 1.,2.,3., 0.,2.,3., 3.,1.,3., + 3.,2.,3., 0.,1.,3., 1.,3.,3., 2.,2.,3., 2.,3.,3.] +conn=[0,11,1,3,15,26,16,18, 1,2,4,7,13,6,-1,1,16,21,6,-1,6,21,28,13,-1,13,7,22,28,-1,7,4,19,22,-1,4,2,17,19,-1,2,1,16,17,-1,16,21,28,22,19,17, + 1,6,5,3,16,21,20,18, 13,10,9,6,28,25,24,21, 11,8,7,4,2,1,-1,11,26,16,1,-1,1,16,17,2,-1,2,17,19,4,-1,4,19,22,7,-1,7,8,23,22,-1,8,11,26,23,-1,26,16,17,19,22,23, + 7,12,14,13,22,27,29,28, 15,26,16,18,30,41,31,33, 16,17,19,22,28,21,-1,16,31,36,21,-1,21,36,43,28,-1,28,22,37,43,-1,22,19,34,37,-1,19,17,32,34,-1,17,16,31,32,-1,31,36,43,37,34,32, + 16,21,20,18,31,36,35,33, 28,25,24,21,43,40,39,36, 26,23,22,19,17,16,-1,26,41,31,16,-1,16,31,32,17,-1,17,32,34,19,-1,19,34,37,22,-1,22,23,38,37,-1,23,26,41,38,-1,41,31,32,34,37,38, + 22,27,29,28,37,42,44,43, 30,41,31,33,45,56,46,48, 31,32,34,37,43,36,-1,31,46,51,36,-1,36,51,58,43,-1,43,37,52,58,-1,37,34,49,52,-1,34,32,47,49,-1,32,31,46,47,-1,46,51,58,52,49,47, + 31,36,35,33,46,51,50,48, 43,40,39,36,58,55,54,51, 41,38,37,34,32,31,-1,41,56,46,31,-1,31,46,47,32,-1,32,47,49,34,-1,34,49,52,37,-1,37,38,53,52,-1,38,41,56,53,-1,56,46,47,49,52,53, + 37,42,44,43,52,57,59,58] +mesh3D=MEDCouplingUMesh.New("mesh3D",3); +mesh3D.allocateCells(18); +mesh3D.insertNextCell(NORM_HEXA8,conn[0:8]); mesh3D.insertNextCell(NORM_POLYHED,conn[8:51]); mesh3D.insertNextCell(NORM_HEXA8,conn[51:59]); mesh3D.insertNextCell(NORM_HEXA8,conn[59:67]); mesh3D.insertNextCell(NORM_POLYHED,conn[67:110]); mesh3D.insertNextCell(NORM_HEXA8,conn[110:118]); +mesh3D.insertNextCell(NORM_HEXA8,conn[118:126]); mesh3D.insertNextCell(NORM_POLYHED,conn[126:169]); mesh3D.insertNextCell(NORM_HEXA8,conn[169:177]); mesh3D.insertNextCell(NORM_HEXA8,conn[177:185]); mesh3D.insertNextCell(NORM_POLYHED,conn[185:228]); mesh3D.insertNextCell(NORM_HEXA8,conn[228:236]); +mesh3D.insertNextCell(NORM_HEXA8,conn[236:244]); mesh3D.insertNextCell(NORM_POLYHED,conn[244:287]); mesh3D.insertNextCell(NORM_HEXA8,conn[287:295]); mesh3D.insertNextCell(NORM_HEXA8,conn[295:303]); mesh3D.insertNextCell(NORM_POLYHED,conn[303:346]); mesh3D.insertNextCell(NORM_HEXA8,conn[346:354]); +mesh3D.finishInsertingCells(); +myCoords=DataArrayDouble.New(coords,60,3); +myCoords.setInfoOnComponents(["X [m]","Y [m]","Z [m]"]) +mesh3D.setCoords(myCoords); +mesh3D.orientCorrectlyPolyhedrons() +mesh3D.sortCellsInMEDFileFrmt() +mesh3D.checkCoherency() +renum=DataArrayInt.New(60) ; renum[:15]=range(15,30) ; renum[15:30]=range(15) ; renum[30:45]=range(45,60) ; renum[45:]=range(30,45) +mesh3D.renumberNodes(renum,60) +# +mesh3D.getCoords()[:]*=100. +mesh3D.getCoords().setInfoOnComponents(["X [cm]","Y [cm]","Z [cm]"]) +# +zLev=mesh3D.getCoords()[:,2] +zLev=zLev.getDifferentValues(1e-12) +zLev.sort() +# +tmp,cellIdsSol1=mesh3D.buildSlice3D([0.,0.,(zLev[1]+zLev[2])/2],[0.,0.,1.],1e-12) +bary=mesh3D.getBarycenterAndOwner() +baryZ=bary[:,2] +cellIdsSol2=baryZ.getIdsInRange(zLev[1],zLev[2]) +nodeIds=mesh3D.findNodesOnPlane([0.,0.,zLev[0]],[0.,0.,1.],1e-10) +mesh2D=mesh3D.buildFacePartOfMySelfNode(nodeIds,True) +extMesh=MEDCouplingExtrudedMesh.New(mesh3D,mesh2D,0) +cellIdsSol3=extMesh.getMesh3DIds()[mesh2D.getNumberOfCells():2*mesh2D.getNumberOfCells()] +for i in xrange(3): + exec("print cellIdsSol%s.getValues()"%(i+1)) +# +mesh3DPart=mesh3D[cellIdsSol2] # equivalent to mesh3DPart=mesh3D.buildPartOfMySelf(cellIdsSol2,True) +mesh3DPart.zipCoords() +print mesh3DPart.checkConsecutiveCellTypesAndOrder([NORM_HEXA8,NORM_POLYHED]) ; assert mesh3DPart.checkConsecutiveCellTypesAndOrder([NORM_HEXA8,NORM_POLYHED]) +print mesh3DPart.checkConsecutiveCellTypes() ; assert mesh3DPart.checkConsecutiveCellTypes() +#print mesh3DPart.advancedRepr() +# +baryXY=bary[:,[0,1]] +baryXY-=[250.,150.] +magn=baryXY.magnitude() +cellIds2Sol1=magn.getIdsInRange(0.,1e-12) +# +bary2=mesh2D.getBarycenterAndOwner()[:,[0,1]] +bary2-=[250.,150.] +magn=bary2.magnitude() +ids=magn.getIdsInRange(0.,1e-12) +idStart=int(ids) # ids is assumed to contain only one value, if not an exception is thrown +cellIds2Sol2=extMesh.getMesh3DIds()[range(idStart,mesh3D.getNumberOfCells(),mesh2D.getNumberOfCells())] +# +mesh3DSlice2=mesh3D[cellIds2Sol1] +mesh3DSlice2.zipCoords() +# +mesh3DSlice2bis=mesh3DSlice2.deepCpy() +mesh3DSlice2bis.translate([0.,1000.,0.]) +mesh3DSlice2All=MEDCouplingUMesh.MergeUMeshes([mesh3DSlice2,mesh3DSlice2bis]) +mesh3DSlice2All.writeVTK("mesh3DSlice2All.vtu") +# +mesh3DSurf,desc,descIndx,revDesc,revDescIndx=mesh3D.buildDescendingConnectivity() +numberOf3DCellSharing=revDescIndx.deltaShiftIndex() +cellIds=numberOf3DCellSharing.getIdsNotEqual(1) +mesh3DSurfInside=mesh3DSurf[cellIds] +mesh3DSurfInside.writeVTK("mesh3DSurfInside.vtu") + +###### + +xarr=DataArrayDouble.New(11,1) +xarr.iota(0.) +cmesh=MEDCouplingCMesh.New() +cmesh.setCoords(xarr,xarr,xarr) +mesh=cmesh.buildUnstructured() +mesh.convertToPolyTypes(DataArrayInt.Range(0,mesh.getNumberOfCells(),2)) +# + +f=mesh.fillFromAnalytic(ON_CELLS,1,"(x-5.)*(x-5.)+(y-5.)*(y-5.)+(z-5.)*(z-5.)") +f.setName("MyField") +# +f2=MEDCouplingFieldDouble.New(ON_CELLS,ONE_TIME) +f2.setMesh(mesh) +f2.setName("MyField2") +f2.fillFromAnalytic(1,"(x-5.)*(x-5.)+(y-5.)*(y-5.)+(z-5.)*(z-5.)") +print "f and f2 are equal : %s"%(f.isEqualWithoutConsideringStr(f2,1e-13,1e-12)) ; assert f.isEqualWithoutConsideringStr(f2,1e-13,1e-12) +# +ids1=f.getArray().getIdsInRange(0.,5.) +fPart1=f.buildSubPart(ids1) +ids2=f.getArray().getIdsInRange(50.,1.e300) +fPart2=f.buildSubPart(ids2) +#Renumbering cells to follow MED file +fPart1Cpy=fPart1.deepCpy() +o2n=fPart1Cpy.getMesh().sortCellsInMEDFileFrmt() +fPart1Cpy.getArray().renumberInPlace(o2n) +#Check that fPart1Cpy and fPart1 are the same +fPart1Cpy.substractInPlaceDM(fPart1,12,1e-12) +fPart1Cpy.getArray().abs() +print "Fields are the same ? %s"%(fPart1Cpy.getArray().accumulate()[0]<1e-12) ; assert fPart1Cpy.getArray().accumulate()[0]<1e-12 +# +fPart12=MEDCouplingFieldDouble.MergeFields([fPart1,fPart2]) +# evaluation on points +bary=fPart12.getMesh().getBarycenterAndOwner() +arr1=fPart12.getValueOnMulti(bary) +arr2=f.getValueOnMulti(bary) +delta=arr1-arr2 +delta.abs() +print "Check OK : %s"%(delta.accumulate()[0]<1e-12) ; assert delta.accumulate()[0]<1e-12 +# +print abs(fPart12.integral(0,True)-fPart12.getArray().accumulate()[0])<1e-10 ; assert abs(fPart12.integral(0,True)-fPart12.getArray().accumulate()[0])<1e-10 +fPart12.getMesh().scale([0.,0.,0.],1.2) +print abs(fPart12.integral(0,True)-fPart12.getArray().accumulate()[0]*1.2*1.2*1.2)<1e-8 ; assert abs(fPart12.integral(0,True)-fPart12.getArray().accumulate()[0]*1.2*1.2*1.2)<1e-8 +# Explosion of field +fVec=mesh.fillFromAnalytic(ON_CELLS,3,"(x-5.)*IVec+(y-5.)*JVec+(z-5.)*KVec") +fVecPart1=fVec.buildSubPart(ids1) +fVecPart1.setName("fVecPart1") +cells=fPart1.getMesh().getNumberOfCells()*[None] +for icell,vec in enumerate(fVecPart1.getArray()): + m=fPart1.getMesh()[[icell]] + m.zipCoords() + m.translate(vec) + cells[icell]=m + pass +meshFVecPart1Exploded=MEDCouplingUMesh.MergeUMeshes(cells) +fPart1.setMesh(meshFVecPart1Exploded) + +#### + +targetCoords=[-0.3,-0.3, 0.2,-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 ]; +targetConn=[0,3,4,1, 1,4,2, 4,5,2, 6,7,4,3, 7,8,5,4]; +targetMesh=MEDCouplingUMesh.New("MyMesh",2); +targetMesh.allocateCells(5); +targetMesh.insertNextCell(NORM_TRI3,3,targetConn[4:7]); +targetMesh.insertNextCell(NORM_TRI3,3,targetConn[7:10]); +targetMesh.insertNextCell(NORM_QUAD4,4,targetConn[0:4]); +targetMesh.insertNextCell(NORM_QUAD4,4,targetConn[10:14]); +targetMesh.insertNextCell(NORM_QUAD4,4,targetConn[14:18]); +targetMesh.finishInsertingCells(); +myCoords=DataArrayDouble.New(targetCoords,9,2); +myCoords.setInfoOnComponents(["X [km]","YY [mm]"]) +targetMesh.setCoords(myCoords); +# +MEDLoader.WriteUMesh("TargetMesh.med",targetMesh,True) +# +meshRead=MEDLoader.ReadUMeshFromFile("TargetMesh.med",targetMesh.getName(),0) +print "Is the mesh read in file equals targetMesh ? %s"%(meshRead.isEqual(targetMesh,1e-12)) ; assert meshRead.isEqual(targetMesh,1e-12) +# +f=MEDCouplingFieldDouble.New(ON_CELLS,ONE_TIME) +f.setTime(5.6,7,8) +f.setArray(targetMesh.getBarycenterAndOwner()) +f.setMesh(targetMesh) +f.setName("AFieldName") +MEDLoader.WriteField("MyFirstField.med",f,True) +# +f2=MEDLoader.ReadFieldCell("MyFirstField.med",f.getMesh().getName(),0,f.getName(),7,8) +print "Is the field read in file equals f ? %s"%(f2.isEqual(f,1e-12,1e-12)) ; assert f2.isEqual(f,1e-12,1e-12) +# +MEDLoader.WriteUMesh("MySecondField.med",f.getMesh(),True) +MEDLoader.WriteFieldUsingAlreadyWrittenMesh("MySecondField.med",f) +# +f2=f.clone(True) +f2.getArray()[:]*=2.0 +f2.setTime(7.8,9,10) +MEDLoader.WriteFieldUsingAlreadyWrittenMesh("MySecondField.med",f2) +# +f3=MEDLoader.ReadFieldCell("MySecondField.med",f.getMesh().getName(),0,f.getName(),7,8) +print "Is the field read in file equals f ? %s"%(f.isEqual(f3,1e-12,1e-12)) ; assert f.isEqual(f3,1e-12,1e-12) +f4=MEDLoader.ReadFieldCell("MySecondField.med",f.getMesh().getName(),0,f.getName(),9,10) +print "Is the field read in file equals f ? %s"%(f2.isEqual(f4,1e-12,1e-12)) ; assert f2.isEqual(f4,1e-12,1e-12) + +##### + +targetCoords=[-0.3,-0.3, 0.2,-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 ]; +targetConn=[0,3,4,1, 1,4,2, 4,5,2, 6,7,4,3, 7,8,5,4]; +targetMesh=MEDCouplingUMesh.New("MyMesh",2); +targetMesh.allocateCells(5); +targetMesh.insertNextCell(NORM_TRI3,3,targetConn[4:7]); +targetMesh.insertNextCell(NORM_TRI3,3,targetConn[7:10]); +targetMesh.insertNextCell(NORM_QUAD4,4,targetConn[0:4]); +targetMesh.insertNextCell(NORM_QUAD4,4,targetConn[10:14]); +targetMesh.insertNextCell(NORM_QUAD4,4,targetConn[14:18]); +targetMesh.finishInsertingCells(); +myCoords=DataArrayDouble.New(targetCoords,9,2); +myCoords.setInfoOnComponents(["X [km]","YY [mm]"]) +targetMesh.setCoords(myCoords); +# +targetMeshConsti=targetMesh.buildDescendingConnectivity()[0] +targetMesh1=targetMeshConsti[[3,4,7,8]] +targetMesh1.setName(targetMesh.getName()) +# +meshMEDFile=MEDFileUMesh.New() +meshMEDFile.setMeshAtLevel(0,targetMesh) +meshMEDFile.setMeshAtLevel(-1,targetMesh1) +# Some groups on cells Level 0 +grp0_0=DataArrayInt.New([0,1,3]) ; grp0_0.setName("grp0_Lev0") +grp1_0=DataArrayInt.New([1,2,3,4]) ; grp1_0.setName("grp1_Lev0") +meshMEDFile.setGroupsAtLevel(0,[grp0_0,grp1_0]) +# Some groups on cells Level -1 +grp0_M1=DataArrayInt.New([0,1]) ; grp0_M1.setName("grp0_LevM1") +grp1_M1=DataArrayInt.New([0,1,2]) ; grp1_M1.setName("grp1_LevM1") +grp2_M1=DataArrayInt.New([1,2,3]) ; grp2_M1.setName("grp2_LevM1") +meshMEDFile.setGroupsAtLevel(-1,[grp0_M1,grp1_M1,grp2_M1]) +# +meshMEDFile.write("TargetMesh2.med",2) # 2 stands for write from scratch +# +meshMEDFileRead=MEDFileMesh.New("TargetMesh2.med") +meshRead0=meshMEDFileRead.getMeshAtLevel(0) +meshRead1=meshMEDFileRead.getMeshAtLevel(-1) +print "Is the mesh at level 0 read in file equals targetMesh ? %s"%(meshRead0.isEqual(targetMesh,1e-12)) ; assert meshRead0.isEqual(targetMesh,1e-12) +print "Is the mesh at level -1 read in file equals targetMesh ? %s"%(meshRead1.isEqual(targetMesh1,1e-12)) ; assert meshRead1.isEqual(targetMesh1,1e-12) +# +print meshMEDFileRead.getGrpNonEmptyLevels("grp0_Lev0") +grp0_0_read=meshMEDFileRead.getGroupArr(0,"grp0_Lev0") +print "Is group \"grp0_Lev0\" are the same ? %s"%(grp0_0_read.isEqual(grp0_0)) ; assert grp0_0_read.isEqual(grp0_0) +# +# Fields +# +f=MEDCouplingFieldDouble.New(ON_CELLS,ONE_TIME) +f.setTime(5.6,7,8) +f.setArray(targetMesh.getBarycenterAndOwner()) +f.setMesh(targetMesh) +f.setName("AFieldName") +# +fMEDFile=MEDFileField1TS.New() +fMEDFile.setFieldNoProfileSBT(f) +# +fMEDFile.write("TargetMesh2.med",0) # 0 is very important here because we want to append to TargetMesh2.med and not to scratch it +# +fMEDFileRead=MEDFileField1TS.New("TargetMesh2.med",f.getName(),7,8) +fRead1=fMEDFileRead.getFieldOnMeshAtLevel(ON_CELLS,0,meshMEDFileRead) # fastest method. No read in file. +fRead2=fMEDFileRead.getFieldAtLevel(ON_CELLS,0) # basic method like, mesh is reread in file... +print "Does the field f remains the same using fast method ? %s"%(fRead1.isEqual(f,1e-12,1e-12)) ; assert fRead1.isEqual(f,1e-12,1e-12) +print "Does the field f remains the same using slow method ? %s"%(fRead2.isEqual(f,1e-12,1e-12)) ; assert fRead2.isEqual(f,1e-12,1e-12) +# +# Writing and Reading fields on profile using MEDLoader advanced API +# +pfl=DataArrayInt.New([1,2,3]) ; pfl.setName("My1stPfl") +fPart=f.buildSubPart(pfl) +fPart.setName("fPart") +# +fMEDFile2=MEDFileField1TS.New() +fMEDFile2.setFieldProfile(fPart,meshMEDFileRead,0,pfl) +fMEDFile2.write("TargetMesh2.med",0) # 0 is very important here because we want to append to TargetMesh2.med and not to scratch it +# +fMEDFileRead2=MEDFileField1TS.New("TargetMesh2.med",fPart.getName(),7,8) +fPartRead,pflRead=fMEDFileRead2.getFieldWithProfile(ON_CELLS,0,meshMEDFileRead) +print fPartRead.isEqualWithoutConsideringStr(fPart.getArray(),1e-12) ; assert fPartRead.isEqualWithoutConsideringStr(fPart.getArray(),1e-12) +print pflRead.isEqualWithoutConsideringStr(pfl) ; assert pflRead.isEqualWithoutConsideringStr(pfl) + +##### + +m0=MEDCouplingCMesh() +arr=DataArrayDouble(31,1) ; arr.iota(0.) +m0.setCoords(arr,arr) +m0=m0.buildUnstructured() +m00=m0[::2] ; m00.simplexize(0) ; m01=m0[1::2] +m0=MEDCouplingUMesh.MergeUMeshes([m00,m01]) +m0.getCoords()[:]*=1/15. +m0.setName("mesh") +# +CellField=MEDCouplingFieldDouble(ON_CELLS,ONE_TIME) ; CellField.setTime(5.6,5,6) ; CellField.setMesh(m0) +CellField.setName("CellField") +CellField.fillFromAnalytic(1,"exp(-((x-1)*(x-1)+(y-1)*(y-1)))") ; CellField.getArray().setInfoOnComponent(0,"powercell [W]") +NodeField=MEDCouplingFieldDouble(ON_NODES,ONE_TIME) ; NodeField.setTime(5.6,5,6) ; NodeField.setMesh(m0) +NodeField.setName("NodeField") +NodeField.fillFromAnalytic(1,"exp(-((x-1)*(x-1)+(y-1)*(y-1)))") ; NodeField.getArray().setInfoOnComponent(0,"powernode [W]") +# +proc0=m0.getCellsInBoundingBox([(0.,0.4),(0.,0.4)],1e-10) +proc1=proc0.buildComplement(m0.getNumberOfCells()) +# +NodeField0=NodeField[proc0] ; NodeField0.getMesh().setName(m0.getName()) ; CellField0=CellField[proc0] ; CellField0.setMesh(NodeField0.getMesh()) +NodeField1=NodeField[proc1] ; NodeField1.getMesh().setName(m0.getName()) ; CellField1=CellField[proc1] ; CellField1.setMesh(NodeField1.getMesh()) +# +proc0_fname="proc0.med" +MEDLoader.WriteField(proc0_fname,NodeField0,True) +MEDLoader.WriteFieldUsingAlreadyWrittenMesh(proc0_fname,CellField0) +proc1_fname="proc1.med" +MEDLoader.WriteField(proc1_fname,NodeField1,True) +MEDLoader.WriteFieldUsingAlreadyWrittenMesh(proc1_fname,CellField1) +# +CellField0_read=MEDLoader.ReadFieldCell("proc0.med","mesh",0,"CellField",5,6) +CellField1_read=MEDLoader.ReadFieldCell("proc1.med","mesh",0,"CellField",5,6) +CellField_read=MEDCouplingFieldDouble.MergeFields([CellField0_read,CellField1_read]) +CellFieldCpy=CellField.deepCpy() +CellFieldCpy.substractInPlaceDM(CellField_read,10,1e-12) +CellFieldCpy.getArray().abs() +print CellFieldCpy.getArray().isUniform(0.,1e-12) +# +NodeField0_read=MEDLoader.ReadFieldNode("proc0.med","mesh",0,"NodeField",5,6) +NodeField1_read=MEDLoader.ReadFieldNode("proc1.med","mesh",0,"NodeField",5,6) +NodeField_read=MEDCouplingFieldDouble.MergeFields([NodeField0_read,NodeField1_read]) +NodeField_read.mergeNodes(1e-10) +NodeFieldCpy=NodeField.deepCpy() +NodeFieldCpy.mergeNodes(1e-10) +NodeFieldCpy.substractInPlaceDM(NodeField_read,10,1e-12) +print NodeFieldCpy.getArray().isUniform(0.,1e-12) ; assert NodeFieldCpy.getArray().isUniform(0.,1e-12) +# +fileNames=["proc0.med","proc1.med"] +msML=[MEDFileMesh.New(fname) for fname in fileNames] +fsML=[MEDFileFields.New(fname) for fname in fileNames] +mergeMLMesh=MEDFileUMesh() +mergeMLFields=MEDFileFields() +for lev in msML[0].getNonEmptyLevels(): + o2nML=len(msML[0].getNonEmptyLevels())*[None] + cs=[mML.getCoords() for mML in msML] + mergeMLMesh.setCoords(DataArrayDouble.Aggregate(cs)) + ms=[mML.getMeshAtLevel(lev) for mML in msML] + m=MEDCouplingUMesh.MergeUMeshes(ms) ; m.setCoords(mergeMLMesh.getCoords()) + o2nML[lev]=m.sortCellsInMEDFileFrmt() + mergeMLMesh.setMeshAtLevel(lev,m) + pass +# +for fieldName in fsML[0].getFieldsNames(): + fmts=[fML[fieldName] for fML in fsML] + mergeField=MEDFileFieldMultiTS() + for dt,it,tim in fmts[0].getTimeSteps(): + fts=[fmt[dt,it] for fmt in fmts] + arrs=len(fts)*[None] + for typp in fts[0].getTypesOfFieldAvailable(): + arr1s=[] + if typp==ON_CELLS: + for ft in fts: + for geoTyp,smth in ft.getFieldSplitedByType(): + if geoTyp!=NORM_ERROR: + smth1=filter(lambda x:x[0]==ON_CELLS,smth) + arr2s=[ft.getUndergroundDataArray()[elt[1][0]:elt[1][1]] for elt in smth1] + arr1s.append(DataArrayDouble.Aggregate(arr2s)) + pass + pass + pass + pass + else: + for ft in fts: + smth=filter(lambda x:x[0]==NORM_ERROR,ft.getFieldSplitedByType()) + arr2=DataArrayDouble.Aggregate([ft.getUndergroundDataArray()[elt[1][0][1][0]:elt[1][0][1][1]] for elt in smth]) + arr1s.append(arr2) + pass + pass + arr=DataArrayDouble.Aggregate(arr1s) + if typp==ON_CELLS: + arr.renumberInPlace(o2nML[lev]) + mcf=MEDCouplingFieldDouble(typp,ONE_TIME) ; mcf.setName(fieldName) ; mcf.setTime(tim,dt,it) ; mcf.setArray(arr) + mcf.setMesh(mergeMLMesh.getMeshAtLevel(lev)) ; mcf.checkCoherency() + mergeField.appendFieldNoProfileSBT(mcf) + pass + pass + mergeMLFields.pushField(mergeField) + pass +mergeMLMesh.write("merge.med",2) +mergeMLFields.write("merge.med",0) + +##### + +arr=DataArrayDouble(11) ; arr.iota(0) +trgMesh=MEDCouplingCMesh() ; trgMesh.setCoords(arr,arr) ; trgMesh=trgMesh.buildUnstructured() +# +arr=DataArrayDouble(21) ; arr.iota(0) ; arr*=0.5 +srcMesh=MEDCouplingCMesh() ; srcMesh.setCoords(arr,arr) ; srcMesh=srcMesh.buildUnstructured() +# +tmp=srcMesh[:20] ; tmp.simplexize(0) +srcMesh=MEDCouplingUMesh.MergeUMeshes([tmp,srcMesh[20:]]) +# +remap=MEDCouplingRemapper() +remap.prepare(srcMesh,trgMesh,"P0P0") +# +myMatrix=remap.getCrudeMatrix() +print myMatrix # pour voir a quoi elle ressemble +sumByRows=DataArrayDouble(len(myMatrix)) +for i,wIt in enumerate(sumByRows): + su=0. + for it in myMatrix[i]: + su+=myMatrix[i][it] + wIt[0]=su +print "Does interpolation look OK ? %s"%(str(sumByRows.isUniform(1.,1e-12))) ; assert sumByRows.isUniform(1.,1e-12) +# +srcField=MEDCouplingFieldDouble(ON_CELLS,ONE_TIME) ; srcField.setMesh(srcMesh) +srcField.fillFromAnalytic(1,"7-sqrt((x-5.)*(x-5.)+(y-5.)*(y-5.))") ; CellField.getArray().setInfoOnComponent(0,"powercell [W]") +# +#remap.transferField(srcField,1e300) +srcField.setNature(ConservativeVolumic) +trgFieldCV=remap.transferField(srcField,1e300) +# +print "ConservativeVolumic %lf == %lf"%(srcField.integral(True)[0],trgFieldCV.integral(True)[0]) ; assert abs(srcField.integral(True)[0]-trgFieldCV.integral(True)[0])<1e-6 +print "ConservativeVolumic %lf != %lf"%(srcField.getArray().accumulate()[0],trgFieldCV.getArray().accumulate()[0]) ; assert abs(srcField.getArray().accumulate()[0]-trgFieldCV.getArray().accumulate()[0])>1e-6 +# +srcField.setNature(Integral) +trgFieldI=remap.transferField(srcField,1e300) +# +print "IntegralGlobConstraint %lf != %lf"%(srcField.integral(True)[0],trgFieldI.integral(True)[0]) ; assert abs(srcField.integral(True)[0]-trgFieldI.integral(True)[0])>1e-6 +print "IntegralGlobConstraint %lf == %lf"%(srcField.getArray().accumulate()[0],trgFieldI.getArray().accumulate()[0]) ; assert abs(srcField.getArray().accumulate()[0]-trgFieldI.getArray().accumulate()[0])<1e-6 + +###### + +from numpy import * +from math import acos + +med_root_dir=os.getenv("MED_ROOT_DIR") +agitateur_file=os.path.join(os.getenv("MED_ROOT_DIR"),"share","salome","resources","med","agitateur.med") +data=MEDFileData(agitateur_file) +ts=data.getFields()[0].getTimeSteps() +print ts +# +fMts=data.getFields()["DISTANCE_INTERFACE_ELEM_BODY_ELEM_DOM"] +f1ts=fMts[(2,-1)] +fMc=f1ts.getFieldAtLevel(ON_CELLS,0) +arr=fMc.getArray() +arr.getMinMaxPerComponent() # juste pour voir la plage de variation du champ par compo +ids=arr.getIdsInRange(0.,1.) +f2Mc=fMc[ids] +# +pressMts=data.getFields()["PRESSION_ELEM_DOM"] +press1ts=pressMts[(2,-1)] +pressMc=press1ts.getFieldAtLevel(ON_CELLS,0) +pressOnAgitateurMc=pressMc[ids] +# +pressOnAgitateurMc.getMesh().zipCoords() +# +agitateurMesh3DMc=pressOnAgitateurMc.getMesh() +m3DSurf,desc,descI,revDesc,revDescI=agitateurMesh3DMc.buildDescendingConnectivity() +nbOf3DCellSharing=revDescI.deltaShiftIndex() +ids2=nbOf3DCellSharing.getIdsEqual(1) +agitateurSkinMc=m3DSurf[ids2] +OffsetsOfTupleIdsInField=revDescI[ids2] +tupleIdsInField=revDesc[OffsetsOfTupleIdsInField] +pressOnSkinAgitateurMc=pressOnAgitateurMc[tupleIdsInField] +pressOnSkinAgitateurMc.setMesh(agitateurSkinMc) +# +pressSkin=pressOnSkinAgitateurMc.getArray() +pressSkin*=1e5 +areaSkin=agitateurSkinMc.getMeasureField(True).getArray() +forceSkin=pressSkin*areaSkin +normalSkin=agitateurSkinMc.buildOrthogonalField().getArray() +forceVectSkin=forceSkin*normalSkin +# +singlePolyhedron=agitateurMesh3DMc.buildSpreadZonesWithPoly() +singlePolyhedron.orientCorrectlyPolyhedrons() +centerOfMass=singlePolyhedron.getBarycenterAndOwner() + +barySkin=agitateurSkinMc.getBarycenterAndOwner() +posSkin=barySkin-centerOfMass + +torquePerCellOnSkin=DataArrayDouble.CrossProduct(posSkin,forceVectSkin) + +zeTorque=torquePerCellOnSkin.accumulate() +print "couple = %r N.m"%(zeTorque[2]) ; assert abs(zeTorque[2]-0.37)<1e-2 + +speedMts=data.getFields()["VITESSE_ELEM_DOM"] +speed1ts=speedMts[(2,-1)] +speedMc=speed1ts.getFieldAtLevel(ON_CELLS,0) +speedOnSkin=speedMc.getArray()[tupleIdsInField] +powerSkin=DataArrayDouble.Dot(forceVectSkin,speedOnSkin) +power=powerSkin.accumulate()[0] +print "power = %r W"%(power) ; assert abs(power-4.22)<1e-2 + +x2=posSkin[:,0]*posSkin[:,0] ; x2=x2.accumulate()[0] +y2=posSkin[:,1]*posSkin[:,1] ; y2=y2.accumulate()[0] +xy=posSkin[:,0]*posSkin[:,1] ; xy=xy.accumulate()[0] +inertiaSkin=matrix([[x2,xy],[xy,y2]]) +inertiaSkinValues,inertiaSkinVects=linalg.eig(inertiaSkin) +pos=max(enumerate(inertiaSkinValues),key=lambda x: x[1])[0] +vect0=inertiaSkinVects[pos].tolist()[0] +print vect0 + +def computeAngle(locAgitateur1ts): + fMc=locAgitateur1ts.getFieldAtLevel(ON_CELLS,0) + arr=fMc.getArray() + ids=arr.getIdsInRange(0.,1.) + f2Mc=fMc[ids] + m3DSurf,desc,descI,revDesc,revDescI=f2Mc.getMesh().buildDescendingConnectivity() + nbOf3DCellSharing=revDescI.deltaShiftIndex() + ids2=nbOf3DCellSharing.getIdsEqual(1) + agitateurSkinMc=m3DSurf[ids2] + # + singlePolyhedron=agitateurMesh3DMc.buildSpreadZonesWithPoly() + singlePolyhedron.orientCorrectlyPolyhedrons() + centerOfMass=singlePolyhedron.getBarycenterAndOwner() + bary=agitateurSkinMc.getBarycenterAndOwner() + posSkin=bary-centerOfMass + x2=posSkin[:,0]*posSkin[:,0] ; x2=x2.accumulate()[0] + y2=posSkin[:,1]*posSkin[:,1] ; y2=y2.accumulate()[0] + xy=posSkin[:,0]*posSkin[:,1] ; xy=xy.accumulate()[0] + inertiaSkin=matrix([[x2,xy],[xy,y2]]) + inertiaSkinValues,inertiaSkinVects=linalg.eig(inertiaSkin) + pos=max(enumerate(inertiaSkinValues),key=lambda x: x[1])[0] + vect0=inertiaSkinVects[pos].tolist()[0] + return vect0 + +vects=len(ts)*[None] +for itts,locAgitateur1ts in zip(ts,data.getFields()["DISTANCE_INTERFACE_ELEM_BODY_ELEM_DOM"]): + angle=computeAngle(locAgitateur1ts) + vects[itts[0]]=angle + pass + +angle2=len(ts)*[0.] +for pos in xrange(2,len(vects)): + norm1=sqrt(vects[pos-1][0]*vects[pos-1][0]+vects[pos-1][1]*vects[pos-1][1]) + norm2=sqrt(vects[pos][0]*vects[pos][0]+vects[pos][1]*vects[pos][1]) + crs=vects[pos-1][0]*vects[pos][0]+vects[pos-1][1]*vects[pos][1] + crs/=norm1 ; crs/=norm2 ; crs=min(crs,1.) + angle2[pos]=acos(crs)#/(ts[pos][2]-ts[pos-1][2]) + pass + +omega=sum(angle2)/(ts[-1][2]-ts[0][2]) +print sum(angle2) ; assert abs(sum(angle2)-1.12)<1e-2 +print "Au pdt (%d,%d) a %r s le couple est de : %r N.m, power/omega=%r N.m"%(ts[2][0],ts[2][1],ts[2][2],zeTorque[2],power/omega) +assert abs(power/omega-0.37)<1e-2 diff --git a/src/MEDLoader/Swig/MEDLoaderDataForTest.py b/src/MEDLoader/Swig/MEDLoaderDataForTest.py index e93ae3303..22e8cfc28 100644 --- a/src/MEDLoader/Swig/MEDLoaderDataForTest.py +++ b/src/MEDLoader/Swig/MEDLoaderDataForTest.py @@ -561,6 +561,102 @@ class MEDLoaderDataForTest: f.setName("MyFieldOnGaussNE"); f.checkCoherency(); return f; + + def buildACompleteMEDDataStructureWithFieldsOnCells_1(cls): + coo=DataArrayDouble([0,0,1,0,2,0,0,1,1,1,2,1,0,2,1,2,2,2],9,2) + m0=MEDCouplingUMesh("mesh",2) + m0.setCoords(coo) + m0.allocateCells() + m0.insertNextCell(NORM_TRI3,[1,4,2]) + m0.insertNextCell(NORM_TRI3,[4,5,2]) + m0.insertNextCell(NORM_QUAD4,[0,3,4,1]) + m0.insertNextCell(NORM_QUAD4,[6,7,4,3]) + m0.insertNextCell(NORM_QUAD4,[7,8,5,4]) + m1=m0.computeSkin() + mm=MEDFileUMesh() + #2 levels + mm.setMeshAtLevel(0,m0) ; mm.setMeshAtLevel(-1,m1) + #some grps/families on the 2 levels + grp0=DataArrayInt([0,2,4]); grp0.setName("gr0_0_2_4") + grp1=DataArrayInt([1,2,3,4]); grp1.setName("gr0_1_2_3_4") + grp2=DataArrayInt([0,4]); grp2.setName("gr0_0_4") + mm.setGroupsAtLevel(0,[grp0,grp1,grp2]) + grp3=DataArrayInt([0,1]); grp3.setName("grM1_SegOnTri3") + grp4=DataArrayInt([2,3,4,5,6,7]); grp4.setName("grM1_SegOnQuad4") + grp5=DataArrayInt([0,3]); grp5.setName("grM1_bottom") + mm.setGroupsAtLevel(-1,[grp3,grp4,grp5]) + ms=MEDFileMeshes() + ms.pushMesh(mm) + # 3 fields + fs=MEDFileFields() + # 1st Field - fNoProfile - no profile on levels 0 + f1Name="fNoProfile" + timeStepsF1=[(0,-1,0.01),(1,-1,0.02)] + f1=MEDFileFieldMultiTS() + for i,(it,order,tim) in enumerate(timeStepsF1): + f11Tmp=MEDCouplingFieldDouble(ON_CELLS,ONE_TIME) + f11Tmp.setTime(tim,it,order) + f11Tmp.setMesh(m0) + arr=DataArrayDouble(m0.getNumberOfCells(),1) ; arr.iota() ; arr+=1+i ; arr*=0.1 + f11Tmp.setArray(arr) + f11Tmp.checkCoherency() + f11Tmp.setName(f1Name) + f1.appendFieldNoProfileSBT(f11Tmp) + pass + fs.pushField(f1) + # 2nd Field - fNoProfileMultiLevs - no profile on levels 0 and -1 + f2Name="fNoProfileMultiLevs" + timeStepsF2=[(0,-1,0.),(1,-1,0.1),(2,-1,0.2)] + f2=MEDFileFieldMultiTS() + for i,(it,order,tim) in enumerate(timeStepsF2): + f21Tmp=MEDCouplingFieldDouble(ON_CELLS,ONE_TIME) + f21Tmp.setTime(tim,it,order) + f21Tmp.setMesh(m0) + arr=DataArrayDouble(m0.getNumberOfCells(),1) ; arr.iota() ; arr+=1+i + f21Tmp.setArray(arr) + f21Tmp.checkCoherency() + f21Tmp.setName(f2Name) + f2.appendFieldNoProfileSBT(f21Tmp) + f22Tmp=MEDCouplingFieldDouble(ON_CELLS,ONE_TIME) + f22Tmp.setTime(tim,it,order) + f22Tmp.setMesh(m1) + arr=DataArrayDouble(m1.getNumberOfCells(),1) ; arr.iota() ; arr+=100+1+i + f22Tmp.setArray(arr) + f22Tmp.checkCoherency() + f22Tmp.setName(f2Name) + f2[it,order].setFieldNoProfileSBT(f22Tmp) + pass + fs.pushField(f2) + # 3rd field - fProfileMultiLevs - The most complex one + f3Name="fProfileMultiLevs" + timeStepsF3=[(0,-1,0.),(1,-1,10.),(2,-1,20.),(3,-1,30.),] + f3=MEDFileFieldMultiTS() + for i,(it,order,tim) in enumerate(timeStepsF3): + pfl1=DataArrayInt([0,1,3,4]) ; pfl1.setName("pfl1") + m0Part=m0[pfl1] + f31Tmp=MEDCouplingFieldDouble(ON_CELLS,ONE_TIME) + f31Tmp.setTime(tim,it,order) + f31Tmp.setMesh(m0Part) + arr=DataArrayDouble(m0Part.getNumberOfCells(),1) ; arr.iota() ; arr+=1000+i+1 + f31Tmp.setArray(arr) + f31Tmp.checkCoherency() + f31Tmp.setName(f3Name) + f3.appendFieldProfile(f31Tmp,mm,0,pfl1) + pfl2=DataArrayInt([0,3]) ; pfl2.setName("pfl2Bottom") + m1Part=m1[pfl2] + f32Tmp=MEDCouplingFieldDouble(ON_CELLS,ONE_TIME) + f32Tmp.setTime(tim,it,order) + f32Tmp.setMesh(m1Part) + arr=DataArrayDouble(m1Part.getNumberOfCells(),1) ; arr.iota() ; arr+=2000+1+i + f32Tmp.setArray(arr) + f32Tmp.checkCoherency() + f32Tmp.setName(f3Name) + f3[it,order].setFieldProfile(f32Tmp,mm,-1,pfl2) + pass + fs.pushField(f3) + # + data=MEDFileData() ; data.setMeshes(ms) ; data.setFields(fs) + return data build1DMesh_1=classmethod(build1DMesh_1) build2DCurveMesh_1=classmethod(build2DCurveMesh_1) @@ -578,4 +674,5 @@ class MEDLoaderDataForTest: buildVecFieldOnGauss_2=classmethod(buildVecFieldOnGauss_2) buildVecFieldOnGauss_2_Simpler=classmethod(buildVecFieldOnGauss_2_Simpler) buildVecFieldOnGaussNE_1=classmethod(buildVecFieldOnGaussNE_1) + buildACompleteMEDDataStructureWithFieldsOnCells_1=classmethod(buildACompleteMEDDataStructureWithFieldsOnCells_1) pass diff --git a/src/MEDLoader/Swig/MEDLoaderSplitter.py b/src/MEDLoader/Swig/MEDLoaderSplitter.py new file mode 100644 index 000000000..b7388b65e --- /dev/null +++ b/src/MEDLoader/Swig/MEDLoaderSplitter.py @@ -0,0 +1,115 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2007-2013 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 +# +# Author Anthony GEAY (CEA/DEN/DM2S/STMF/LGLS) + +from MEDLoader import * +import os + +class MEDLoaderSplitter: + @classmethod + def New(cls,mfd,idsLst): + """ mfd is a MEDFileData instance containing only one mesh. idsLst is a list of DataArrayInt containing each the ids per processor """ + return MEDLoaderSplitter(fileName) + pass + + def __init__(self,mfd,idsLst): + """ mfd is a MEDFileData instance containing only one mesh. idsLst is a list of DataArrayInt containing each the ids per processor """ + mfmsh=mfd.getMeshes() + mfflds=mfd.getFields() + if len(mfmsh)!=1: + raise InterpKernelException("Works only with one mesh !") + mfflds=mfflds.partOfThisLyingOnSpecifiedMeshName(mfmsh[0].getName()) + retf=self.__splitFields(mfmsh[0],mfflds,idsLst) + retm=self.__splitMesh(mfmsh[0],idsLst) + self._mfd_splitted=[MEDFileData() for i in xrange(len(idsLst))] + for a,b,c in zip(self._mfd_splitted,retf,retm): + a.setFields(b) ; a.setMeshes(c) + pass + pass + + def getSplittedInstances(self): + return self._mfd_splitted + + @classmethod + def __splitMEDFileField1TSNode(cls,f,f1ts,ids): + fRet=f[ids] + f1ts.setFieldNoProfileSBT(fRet) + pass + + @classmethod + def __splitMEDFileField1TSCell(cls,f,f1ts,ids): + fRet=f[ids] + m=fRet.getMesh() ; m.zipCoords() + o2n=m.getRenumArrForMEDFileFrmt() ; fRet.renumberCells(o2n,False) + f1ts.setFieldNoProfileSBT(fRet) + pass + + def __splitMEDFileField1TS(self,mm,f1ts,idsLst): + ret=[MEDFileField1TS() for i in xrange(len(idsLst))] + dico={ON_CELLS:self.__splitMEDFileField1TSCell, + ON_NODES:self.__splitMEDFileField1TSNode, + ON_GAUSS_PT:self.__splitMEDFileField1TSCell, + ON_GAUSS_NE:self.__splitMEDFileField1TSCell} + for t in f1ts.getTypesOfFieldAvailable(): + f=f1ts.getFieldOnMeshAtLevel(t,0,mm) + for i,f0 in enumerate(ret): + dico[t](f,f0,idsLst[i]) + pass + pass + return ret + + def __splitFields(self,mm,mfflds,idsLst): + ret0=[MEDFileFields() for i in xrange(len(idsLst))] + for fmts in mfflds: + if len(fmts.getPflsReallyUsed())!=0: + print "Field \"%s\" contains profiles ! Not supported yet ! This field will be ignored !"%(fmts.getName()) + continue + pass + ret1=[MEDFileFieldMultiTS() for i in xrange(len(idsLst))] + for f1ts in fmts: + for fmtsPart,f1tsPart in zip(ret1,self.__splitMEDFileField1TS(mm,f1ts,idsLst)): + fmtsPart.pushBackTimeStep(f1tsPart) + pass + pass + for fieldsPart,fmtsPart in zip(ret0,ret1): + fieldsPart.pushField(fmtsPart); + pass + pass + return ret0 + + def __splitMesh(self,mfm,idsLst): + ret0=[MEDFileMeshes() for i in xrange(len(idsLst))] + m=mfm.getMeshAtLevel(0) + for ret,ids in zip(ret0,idsLst): + mlPart=mfm.createNewEmpty() + mPart=m[ids] ; trad=mPart.zipCoordsTraducer() + trad=trad.invertArrayO2N2N2O(mPart.getNumberOfNodes()) + mlPart.setMeshAtLevel(0,mPart) + if 0 in mfm.getFamArrNonEmptyLevelsExt(): + mlPart.setFamilyFieldArr(0,mfm.getFamilyFieldAtLevel(0)[ids]) + pass + if 1 in mfm.getFamArrNonEmptyLevelsExt(): + mlPart.setFamilyFieldArr(1,mfm.getFamilyFieldAtLevel(1)[trad]) + pass + mlPart.copyFamGrpMapsFrom(mfm) + ret.pushMesh(mlPart) + pass + return ret0 + pass diff --git a/src/MEDLoader/Swig/MEDLoaderTest3.py b/src/MEDLoader/Swig/MEDLoaderTest3.py index 7bd354318..9e0257a94 100644 --- a/src/MEDLoader/Swig/MEDLoaderTest3.py +++ b/src/MEDLoader/Swig/MEDLoaderTest3.py @@ -271,20 +271,20 @@ class MEDLoaderTest(unittest.TestCase): res=mm.isEqual(mm2,1e-12) self.assertTrue(res[0]) l=list(mm2.getFamiliesOnGroup("G2")) ; l.sort() - self.assertEqual(['Family_10','Family_11','Family_3','Family_4','Family_7'],l) + self.assertEqual(['Family_-3','Family_-4','Family_-7','Family_10','Family_11'],l) mm2.keepFamIdsOnlyOnLevs([3],[-1]) for lev in mm.getGrpNonEmptyLevelsExt("G2"): self.assertEqual(mm.getGroupArr(lev,"G2").getValues(),mm2.getGroupArr(lev,"G2").getValues()) pass l=list(mm2.getFamiliesOnGroup("G2")) ; l.sort() - self.assertEqual(['Family_10','Family_11','Family_12','Family_3','Family_4','Family_7'],l) + self.assertEqual(['Family_-3','Family_-4','Family_-7','Family_10','Family_11'],l) # - self.assertEqual([7,7,6],mm2.getFamilyFieldAtLevel(-1).getValues()) - mm2.getFamilyFieldAtLevel(-1).setIJ(1,0,8) - self.assertEqual([7,8,6],mm2.getFamilyFieldAtLevel(-1).getValues()) - self.assertTrue(not mm2.existsFamily("Family_8")) + self.assertEqual([-7,-7,-6],mm2.getFamilyFieldAtLevel(-1).getValues()) + mm2.getFamilyFieldAtLevel(-1).setIJ(1,0,-8) + self.assertEqual([-7,-8,-6],mm2.getFamilyFieldAtLevel(-1).getValues()) + self.assertTrue(not mm2.existsFamily("Family_-8")) mm2.createGroupOnAll(-1,"GrpOnAllFace") - self.assertTrue(mm2.existsFamily("Family_8")) + self.assertTrue(mm2.existsFamily("Family_-8")) self.assertEqual(range(3),mm2.getGroupArr(-1,"GrpOnAllFace").getValues()) pass @@ -418,7 +418,7 @@ class MEDLoaderTest(unittest.TestCase): def testMEDField2(self): mm=MEDFileMesh.New("Pyfile19.med") mm.write("Pyfile19_bis.med",2) - ff=MEDFileFieldMultiTS.New("Pyfile19.med","VFieldOnNodes") + ff=MEDFileFieldMultiTS.New("Pyfile19.med") ff.write("Pyfile19_bis.med",0) self.assertEqual([('tyty','mm'),('uiop','MW')],MEDLoader.GetComponentsNamesOfField("Pyfile19_bis.med","VFieldOnNodes")) pass @@ -993,9 +993,9 @@ class MEDLoaderTest(unittest.TestCase): g3=DataArrayInt.New() ; g3.setValues([1,2,3],3,1) ; g3.setName("g3") mm.setGroupsAtLevel(0,[g1,g2],False) self.assertEqual(('g1','g2'),mm.getGroupsNames()) - self.assertEqual(('Family_2','Family_3'),mm.getFamiliesNames()) - self.assertEqual(('Family_2',),mm.getFamiliesOnGroup('g1')) - self.assertEqual(('Family_3',),mm.getFamiliesOnGroup('g2')) + self.assertEqual(('Family_-2','Family_-3'),mm.getFamiliesNames()) + self.assertEqual(('Family_-2',),mm.getFamiliesOnGroup('g1')) + self.assertEqual(('Family_-3',),mm.getFamiliesOnGroup('g2')) mm.assignFamilyNameWithGroupName() self.assertEqual(('g1','g2'),mm.getGroupsNames()) self.assertEqual(('g1','g2'),mm.getFamiliesNames()) @@ -1006,16 +1006,16 @@ class MEDLoaderTest(unittest.TestCase): mm.setMeshAtLevel(0,m) mm.setGroupsAtLevel(0,[g1,g2,g3],False) self.assertEqual(('g1','g2','g3'),mm.getGroupsNames()) - self.assertEqual(('Family_2', 'Family_4', 'Family_5'),mm.getFamiliesNames()) - self.assertEqual(('Family_2', 'Family_4'),mm.getFamiliesOnGroup('g1')) - self.assertEqual(('Family_5',),mm.getFamiliesOnGroup('g2')) - self.assertEqual(('Family_4','Family_5',),mm.getFamiliesOnGroup('g3')) + self.assertEqual(('Family_-2', 'Family_-4', 'Family_-5'),mm.getFamiliesNames()) + self.assertEqual(('Family_-2', 'Family_-4'),mm.getFamiliesOnGroup('g1')) + self.assertEqual(('Family_-5',),mm.getFamiliesOnGroup('g2')) + self.assertEqual(('Family_-4','Family_-5',),mm.getFamiliesOnGroup('g3')) mm.assignFamilyNameWithGroupName() # here it does nothing because no such group-family bijection found self.assertEqual(('g1','g2','g3'),mm.getGroupsNames()) - self.assertEqual(('Family_2', 'Family_4', 'Family_5'),mm.getFamiliesNames()) - self.assertEqual(('Family_2', 'Family_4'),mm.getFamiliesOnGroup('g1')) - self.assertEqual(('Family_5',),mm.getFamiliesOnGroup('g2')) - self.assertEqual(('Family_4','Family_5',),mm.getFamiliesOnGroup('g3')) + self.assertEqual(('Family_-2', 'Family_-4', 'Family_-5'),mm.getFamiliesNames()) + self.assertEqual(('Family_-2', 'Family_-4'),mm.getFamiliesOnGroup('g1')) + self.assertEqual(('Family_-5',),mm.getFamiliesOnGroup('g2')) + self.assertEqual(('Family_-4','Family_-5',),mm.getFamiliesOnGroup('g3')) mm.changeFamilyId(5,6) g=mm.getGroupArr(0,"g3") self.assertTrue(g.isEqual(g3)); @@ -1921,18 +1921,18 @@ class MEDLoaderTest(unittest.TestCase): daTest=DataArrayInt([1,3,4,6,9,10,12]) ; daTest.setName("grp1") mm.addGroup(0,daTest) self.assertTrue(mm.getGroupArr(0,daTest.getName()).isEqual(daTest)) - self.assertTrue(mm.getFamilyFieldAtLevel(0).isEqual(DataArrayInt([6,2,6,8,2,6,5,6,6,7,7,4,8]))) + self.assertTrue(mm.getFamilyFieldAtLevel(0).isEqual(DataArrayInt([-6,2,-6,-8,2,-6,-5,-6,-6,-7,-7,-4,-8]))) for lev,arr in [(1,da0),(-1,da1),(-2,da2)]: self.assertTrue(mm.getFamilyFieldAtLevel(lev).isEqual(arr)) pass - self.assertEqual(mm.getFamiliesNames(),('Family_4','Family_5','Family_7','Family_8','MyFam','MyOther-1','MyOtherFam')) + self.assertEqual(mm.getFamiliesNames(),('Family_-4','Family_-5','Family_-7','Family_-8','MyFam','MyOther-1','MyOtherFam')) self.assertEqual(mm.getGroupsNames(),('grp0','grp1','grpA')) self.assertEqual(mm.getFamilyNameGivenId(3),'MyOtherFam') self.assertEqual(mm.getFamilyNameGivenId(2),'MyFam') - for famName,famId in [('Family_4',4),('Family_5',5),('Family_7',7),('Family_8',8)]: + for famName,famId in [('Family_-4',-4),('Family_-5',-5),('Family_-7',-7),('Family_-8',-8)]: self.assertEqual(mm.getFamilyNameGivenId(famId),famName) pass - self.assertEqual(mm.getFamiliesOnGroup("grp0"),('MyOtherFam','Family_8')) + self.assertEqual(mm.getFamiliesOnGroup("grp0"),('MyOtherFam','Family_-8')) da=DataArrayInt([3,12]) ; da.setName("grp0") self.assertTrue(mm.getGroupArr(0,"grp0").isEqual(da)) da.setValues([1]) @@ -1940,18 +1940,18 @@ class MEDLoaderTest(unittest.TestCase): mm.write(fname,2) mm=MEDFileMesh.New(fname) self.assertTrue(mm.getGroupArr(0,daTest.getName()).isEqual(daTest)) - self.assertTrue(mm.getFamilyFieldAtLevel(0).isEqual(DataArrayInt([6,2,6,8,2,6,5,6,6,7,7,4,8]))) + self.assertTrue(mm.getFamilyFieldAtLevel(0).isEqual(DataArrayInt([-6,2,-6,-8,2,-6,-5,-6,-6,-7,-7,-4,-8]))) for lev,arr in [(1,da0),(-1,da1),(-2,da2)]: self.assertTrue(mm.getFamilyFieldAtLevel(lev).isEqual(arr)) pass - self.assertEqual(mm.getFamiliesNames(),('FAMILLE_ZERO','Family_4','Family_5','Family_7','Family_8','MyFam','MyOther-1','MyOtherFam')) + self.assertEqual(mm.getFamiliesNames(),('FAMILLE_ZERO','Family_-4','Family_-5','Family_-7','Family_-8','MyFam','MyOther-1','MyOtherFam')) self.assertEqual(mm.getGroupsNames(),('grp0','grp1','grpA')) self.assertEqual(mm.getFamilyNameGivenId(3),'MyOtherFam') self.assertEqual(mm.getFamilyNameGivenId(2),'MyFam') - for famName,famId in [('Family_4',4),('Family_5',5),('Family_7',7),('Family_8',8)]: + for famName,famId in [('Family_-4',-4),('Family_-5',-5),('Family_-7',-7),('Family_-8',-8)]: self.assertEqual(mm.getFamilyNameGivenId(famId),famName) pass - self.assertEqual(mm.getFamiliesOnGroup("grp0"),('Family_8','MyOtherFam')) + self.assertEqual(mm.getFamiliesOnGroup("grp0"),('Family_-8','MyOtherFam')) da=DataArrayInt([3,12]) ; da.setName("grp0") self.assertTrue(mm.getGroupArr(0,"grp0").isEqual(da)) da.setValues([1]) @@ -2190,6 +2190,578 @@ class MEDLoaderTest(unittest.TestCase): splitOfM1[0].isEqual(DataArrayInt([0,1,2,3,6,8,10,11,12,13])) splitOfM1[1].isEqual(DataArrayInt([4,5,7,9,14,15])) pass + + def testBugCorrection1(self): + fs=MEDFileFields() + fs.resize(3) + self.assertEqual(fs[0],None) + self.assertEqual(3,len(fs)) + pass + + def testCompareMEDFilesContainingOnlyFieldsOnCell1(self): + f1Name="Pyfile60.med" + f2Name="Pyfile61.med" + d1=MEDLoaderDataForTest.buildACompleteMEDDataStructureWithFieldsOnCells_1() + d1.write(f1Name,2) + d2=MEDLoaderDataForTest.buildACompleteMEDDataStructureWithFieldsOnCells_1() + d2.write(f2Name,2) + # reading and compare + d1=MEDFileData(f1Name) ; d2=MEDFileData(f2Name) + for mn in d1.getMeshes().getMeshesNames(): + m1=d1.getMeshes()[mn] + m2=d2.getMeshes()[mn] + for lev in m1.getNonEmptyLevels(): + grpsNames=m1.getGroupsOnSpecifiedLev(lev) + for grpName in grpsNames: + self.assertTrue(m1.getGroupArr(lev,grpName).isEqual(m2.getGroupArr(lev,grpName))) # compare groups + pass + pass + pass + for fieldn in d1.getFields().getFieldsNames(): + f1=d1.getFields()[fieldn] + f2=d2.getFields()[fieldn] + for it,order,tim in f1.getTimeSteps(): + f1t=f1[it,order] + f2t=f2[it,order] + if len(f1t.getPflsReallyUsed())!=0: + # profile case + for lev in f1t.getNonEmptyLevels()[1]: + arr1,pfl1=f1t.getFieldWithProfile(ON_CELLS,lev,m1) + arr2,pfl2=f2t.getFieldWithProfile(ON_CELLS,lev,m2) + self.assertTrue(pfl1.isEqual(pfl2)) + self.assertTrue(arr1.isEqual(arr2,1e-10)) + pass + pass + else: + # no profile case + for lev in f1t.getNonEmptyLevels()[1]: + f1mc=f1t.getFieldOnMeshAtLevel(ON_CELLS,lev,m1) + f2mc=f2t.getFieldOnMeshAtLevel(ON_CELLS,lev,m2) + self.assertTrue(f1mc.isEqual(f2mc,1e-10,1e-10)) + pass + pass + pass + pass + pass + + def testNonRegBugNormalizeFamIdsMEDFile1(self): + m=MEDCouplingCMesh() + arr=DataArrayDouble([0.,1.,2.,3.,4.]) + m.setCoords(arr,arr,arr) + m=m.buildUnstructured() + m2=m.buildDescendingConnectivity()[0] + m.setName("mesh") + g1=DataArrayInt([0,1,2,3]) ; g1.setName("g1") + g2=DataArrayInt([2,3,5,6]) ; g2.setName("g2") + g1Face=DataArrayInt([20,21,22,23]) ; g1Face.setName("g1Face") + g2Face=DataArrayInt([22,23,25,26]) ; g2Face.setName("g2Face") + g1Node=DataArrayInt([10,11,12,13]) ; g1Node.setName("g1Node") + g2Node=DataArrayInt([12,13,15,16]) ; g2Node.setName("g2Node") + mm=MEDFileUMesh() + mm.setMeshAtLevel(0,m) + mm.setGroupsAtLevel(0,[g1,g2]) + s1=set(mm.getFamiliesOnGroup("g1")) ; s2=set(mm.getFamiliesOnGroup("g2")) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g1"),(0,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g2"),(0,)) + mm.normalizeFamIdsMEDFile() + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g1"),(0,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g2"),(0,)) + self.assertTrue(mm.getGroupArr(0,"g1").isEqual(g1)) + self.assertTrue(mm.getGroupArr(0,"g2").isEqual(g2)) + self.assertEqual(s1,set(mm.getFamiliesOnGroup("g1"))) + self.assertEqual(s2,set(mm.getFamiliesOnGroup("g2"))) + for g in mm.getGroupsOnSpecifiedLev(0): + for f in mm.getFamiliesIdsOnGroup(g): + self.assertTrue(f<0) + pass + pass + # + mm=MEDFileUMesh() + mm.setMeshAtLevel(0,m) + mm.setMeshAtLevel(-1,m2) + mm.setGroupsAtLevel(0,[g1,g2]) + mm.setGroupsAtLevel(-1,[g1Face,g2Face]) + s1=set(mm.getFamiliesOnGroup("g1")) ; s2=set(mm.getFamiliesOnGroup("g2")) + s3=set(mm.getFamiliesOnGroup("g1Face")) ; s4=set(mm.getFamiliesOnGroup("g2Face")) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g1"),(0,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g2"),(0,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g1Face"),(-1,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g2Face"),(-1,)) + mm.normalizeFamIdsMEDFile() + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g1"),(0,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g2"),(0,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g1Face"),(-1,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g2Face"),(-1,)) + self.assertTrue(mm.getGroupArr(0,"g1").isEqual(g1)) + self.assertTrue(mm.getGroupArr(0,"g2").isEqual(g2)) + self.assertTrue(mm.getGroupArr(-1,"g1Face").isEqual(g1Face)) + self.assertTrue(mm.getGroupArr(-1,"g2Face").isEqual(g2Face)) + self.assertEqual(s1,set(mm.getFamiliesOnGroup("g1"))) + self.assertEqual(s2,set(mm.getFamiliesOnGroup("g2"))) + self.assertEqual(s3,set(mm.getFamiliesOnGroup("g1Face"))) + self.assertEqual(s4,set(mm.getFamiliesOnGroup("g2Face"))) + for lev in [0,-1]: + for g in mm.getGroupsOnSpecifiedLev(lev): + for f in mm.getFamiliesIdsOnGroup(g): + self.assertTrue(f<0) + pass + pass + pass + # + mm=MEDFileUMesh() + mm.setMeshAtLevel(0,m) + mm.setMeshAtLevel(-1,m2) + mm.setGroupsAtLevel(0,[g1,g2]) + mm.setGroupsAtLevel(-1,[g1Face,g2Face]) + mm.setGroupsAtLevel(1,[g1Node,g2Node]) + s1=set(mm.getFamiliesOnGroup("g1")) ; s2=set(mm.getFamiliesOnGroup("g2")) + s3=set(mm.getFamiliesOnGroup("g1Face")) ; s4=set(mm.getFamiliesOnGroup("g2Face")) + s5=set(mm.getFamiliesOnGroup("g1Node")) ; s6=set(mm.getFamiliesOnGroup("g2Node")) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g1"),(0,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g2"),(0,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g1Face"),(-1,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g2Face"),(-1,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g1Node"),(1,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g2Node"),(1,)) + mm.normalizeFamIdsMEDFile() + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g1"),(0,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g2"),(0,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g1Face"),(-1,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g2Face"),(-1,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g1Node"),(1,)) + self.assertEqual(mm.getGrpNonEmptyLevelsExt("g2Node"),(1,)) + self.assertTrue(mm.getGroupArr(0,"g1").isEqual(g1)) + self.assertTrue(mm.getGroupArr(0,"g2").isEqual(g2)) + self.assertTrue(mm.getGroupArr(-1,"g1Face").isEqual(g1Face)) + self.assertTrue(mm.getGroupArr(-1,"g2Face").isEqual(g2Face)) + self.assertTrue(mm.getGroupArr(1,"g1Node").isEqual(g1Node)) + self.assertTrue(mm.getGroupArr(1,"g2Node").isEqual(g2Node)) + self.assertEqual(s1,set(mm.getFamiliesOnGroup("g1"))) + self.assertEqual(s2,set(mm.getFamiliesOnGroup("g2"))) + self.assertEqual(s3,set(mm.getFamiliesOnGroup("g1Face"))) + self.assertEqual(s4,set(mm.getFamiliesOnGroup("g2Face"))) + self.assertEqual(s5,set(mm.getFamiliesOnGroup("g1Node"))) + self.assertEqual(s6,set(mm.getFamiliesOnGroup("g2Node"))) + for lev in [0,-1]: + for g in mm.getGroupsOnSpecifiedLev(lev): + for f in mm.getFamiliesIdsOnGroup(g): + self.assertTrue(f<0) + pass + pass + pass + for g in mm.getGroupsOnSpecifiedLev(1): + for f in mm.getFamiliesIdsOnGroup(g): + self.assertTrue(f>0) + pass + pass + pass + + def testNonRegressionMantis22212ChangeGrpName(self): + fileName="Pyfile62.med" + m2,m1,m0,f2,f1,f0,p,n2,n1,n0,fns,fids,grpns,famIdsPerGrp=MEDLoaderDataForTest.buildMultiLevelMesh_1() + m=MEDFileUMesh.New() + m.setCoords(m2.getCoords()) + m.setMeshAtLevel(0,m2) + m.setMeshAtLevel(-1,m1) + m.setMeshAtLevel(-2,m0) + m.setFamilyFieldArr(0,f2) + m.setFamilyFieldArr(-1,f1) + m.setFamilyFieldArr(-2,f0) + m.setFamilyFieldArr(1,p) + nbOfFams=len(fns) + for i in xrange(nbOfFams): + m.addFamily(fns[i],fids[i]) + pass + nbOfGrps=len(grpns) + for i in xrange(nbOfGrps): + m.setFamiliesIdsOnGroup(grpns[i],famIdsPerGrp[i]) + pass + m.setName(m2.getName()) + m.setDescription(m2.getDescription()) + m.write(fileName,2) + # + mm0=MEDFileMesh.New(fileName) + mm1=MEDFileMesh.New(fileName) + groupNamesIni=MEDLoader.GetMeshGroupsNames(fileName,"ma") + for name in groupNamesIni: + mm1.changeGroupName(name,name+'N') + pass + mm1.write(fileName,2) + del mm1 + # + mm2=MEDFileMesh.New(fileName) + for name in groupNamesIni: + for lev in mm0.getGrpNonEmptyLevelsExt(name): + arr0=mm0.getGroupArr(lev,name) + arr2=mm2.getGroupArr(lev,name+'N') + arr0.setName(name+'N') + self.assertTrue(arr0.isEqual(arr2)) + pass + pass + pass + + def testInt32InMEDFileFieldStar1(self): + fname="Pyfile63.med" + f1=MEDLoaderDataForTest.buildVecFieldOnCells_1(); + arr=f1.getArray().convertToIntArr() + f1.setArray(None) + m1=f1.getMesh() + mm1=MEDFileUMesh.New() + mm1.setCoords(m1.getCoords()) + mm1.setMeshAtLevel(0,m1) + mm1.setName(m1.getName()) + mm1.write(fname,2) + ff1=MEDFileIntField1TS() + ff1.setFieldNoProfileSBT(f1,arr) + a,b=ff1.getFieldOnMeshAtLevel(0,ON_CELLS,mm1) + self.assertEqual(b.getInfoOnComponents(),['power [MW/m^3]','density [g/cm^3]','temperature [K]']) + self.assertTrue(b.isEqual(arr)) + self.assertTrue(a.isEqual(f1,1e-12,1e-12)) + ff1.write(fname,0) + ff2=MEDFileAnyTypeField1TS.New(fname) + self.assertEqual(ff2.getName(),"VectorFieldOnCells") + self.assertEqual(ff2.getTime(),[0,1,2.0]) + self.assertTrue(isinstance(ff2,MEDFileIntField1TS)) + a,b=ff1.getFieldOnMeshAtLevel(0,ON_CELLS,mm1) + self.assertEqual(b.getInfoOnComponents(),['power [MW/m^3]','density [g/cm^3]','temperature [K]']) + self.assertTrue(b.isEqual(arr)) + self.assertTrue(a.isEqual(f1,1e-12,1e-12)) + ff2.setTime(1,2,3.) + c=ff2.getUndergroundDataArray() ; c*=2 + ff2.write(fname,0) # 2 time steps in + ffs1=MEDFileAnyTypeFieldMultiTS.New(fname,"VectorFieldOnCells") + self.assertEqual(ffs1.getTimeSteps(),[(0, 1, 2.0), (1, 2, 3.0)]) + self.assertEqual(len(ffs1),2) + self.assertTrue(isinstance(ffs1,MEDFileIntFieldMultiTS)) + a,b=ffs1[2.].getFieldOnMeshAtLevel(0,ON_CELLS,mm1) + self.assertTrue(b.isEqual(arr)) + self.assertTrue(a.isEqual(f1,1e-12,1e-12)) + a,b=ffs1[2.].getFieldOnMeshAtLevel(0,ON_CELLS,mm1) + self.assertTrue(b.isEqual(arr)) + self.assertTrue(a.isEqual(f1,1e-12,1e-12)) + it=ffs1.__iter__() ; it.next() ; ff2bis=it.next() + a,b=ff2bis.getFieldOnMeshAtLevel(0,ON_CELLS,mm1) + self.assertTrue(b.isEqual(2*arr)) + f1.setTime(3.,1,2) + self.assertTrue(a.isEqual(f1,1e-12,1e-12)) + bc=DataArrayInt(6,3) ; bc[:]=0 ; bc.setInfoOnComponents(['power [MW/m^3]','density [g/cm^3]','temperature [K]']) + for it in ffs1: + a,b=it.getFieldOnMeshAtLevel(0,ON_CELLS,mm1) + bc+=b + pass + self.assertTrue(bc.isEqual(3*arr)) + nf1=MEDCouplingFieldDouble(ON_NODES) + nf1.setTime(9.,10,-1) + nf1.setMesh(f1.getMesh()) + narr=DataArrayInt(12,2) ; narr.setInfoOnComponents(["aa [u1]","bbbvv [ppp]"]) ; narr[:,0]=range(12) ; narr[:,1]=2*narr[:,0] + nf1.setName("VectorFieldOnNodes") + nff1=MEDFileIntField1TS.New() + nff1.setFieldNoProfileSBT(nf1,narr) + self.assertEqual(nff1.getInfo(),('aa [u1]','bbbvv [ppp]')) + self.assertEqual(nff1.getTime(),[10,-1,9.0]) + nff1.write(fname,0) + # + nf2=MEDCouplingFieldDouble(ON_NODES) + nf2.setTime(19.,20,-11) + nf2.setMesh(f1.getMesh()) + narr2=DataArrayInt(8,2) ; narr.setInfoOnComponents(["aapfl [u1]","bbbvvpfl [ppp]"]) ; narr2[:,0]=range(8) ; narr2[:,0]+=10 ; narr2[:,1]=3*narr2[:,0] + nf2.setName("VectorFieldOnNodesPfl") ; narr2.setName(nf2.getName()) + nff2=MEDFileIntField1TS.New() + npfl=DataArrayInt([1,2,4,5,6,7,10,11]) ; npfl.setName("npfl") + nff2.setFieldProfile(nf2,narr2,mm1,0,npfl) + nff2.getFieldWithProfile(ON_NODES,0,mm1) + a,b=nff2.getFieldWithProfile(ON_NODES,0,mm1) ; b.setName(npfl.getName()) + self.assertTrue(b.isEqual(npfl)) + self.assertTrue(a.isEqual(narr2)) + nff2.write(fname,0) + nff2bis=MEDFileIntField1TS(fname,"VectorFieldOnNodesPfl") + a,b=nff2bis.getFieldWithProfile(ON_NODES,0,mm1) ; b.setName(npfl.getName()) + self.assertTrue(b.isEqual(npfl)) + self.assertTrue(a.isEqual(narr2)) + # + nf3=MEDCouplingFieldDouble(ON_NODES) + nf3.setName("VectorFieldOnNodesDouble") + nf3.setTime(29.,30,-21) + nf3.setMesh(f1.getMesh()) + nf3.setArray(f1.getMesh().getCoords()) + nff3=MEDFileField1TS.New() + nff3.setFieldNoProfileSBT(nf3) + nff3.write(fname,0) + fs=MEDFileFields(fname) + self.assertEqual(len(fs),4) + ffs=[it for it in fs] + self.assertTrue(isinstance(ffs[0],MEDFileIntFieldMultiTS)) + self.assertTrue(isinstance(ffs[1],MEDFileIntFieldMultiTS)) + self.assertTrue(isinstance(ffs[2],MEDFileFieldMultiTS)) + self.assertTrue(isinstance(ffs[3],MEDFileIntFieldMultiTS)) + # + self.assertTrue(fs["VectorFieldOnCells"][0].getUndergroundDataArray().isEqualWithoutConsideringStr(arr)) + self.assertTrue(fs["VectorFieldOnCells"][1,2].getUndergroundDataArray().isEqualWithoutConsideringStr(2*arr)) + self.assertTrue(fs["VectorFieldOnNodesPfl"][0].getUndergroundDataArray().isEqualWithoutConsideringStr(narr2)) + self.assertTrue(fs["VectorFieldOnNodes"][9.].getUndergroundDataArray().isEqualWithoutConsideringStr(narr)) + self.assertTrue(fs["VectorFieldOnNodesDouble"][29.].getUndergroundDataArray().isEqualWithoutConsideringStr(f1.getMesh().getCoords(),1e-12)) + # + nf3_read=MEDFileFieldMultiTS(fname,"VectorFieldOnNodesDouble") + self.assertTrue(nf3_read[29.].getUndergroundDataArray().isEqualWithoutConsideringStr(f1.getMesh().getCoords(),1e-12)) + self.assertRaises(InterpKernelException,MEDFileIntFieldMultiTS.New,fname,"VectorFieldOnNodesDouble")# exception because trying to read a double field with int instance + self.assertRaises(InterpKernelException,MEDFileFieldMultiTS.New,fname,"VectorFieldOnNodes")# exception because trying to read a int field with double instance + MEDFileField1TS.New(fname,"VectorFieldOnNodesDouble",30,-21) + self.assertRaises(InterpKernelException,MEDFileIntField1TS.New,fname,"VectorFieldOnNodesDouble",30,-21)# exception because trying to read a double field with int instance + MEDFileIntField1TS.New(fname,"VectorFieldOnNodes",10,-1) + self.assertRaises(InterpKernelException,MEDFileField1TS.New,fname,"VectorFieldOnNodes",10,-1)# exception because trying to read a double field with int instance + # + self.assertEqual(fs.getMeshesNames(),('3DSurfMesh_1','3DSurfMesh_1','3DSurfMesh_1','3DSurfMesh_1')) + self.assertTrue(fs.changeMeshNames([('3DSurfMesh_1','3DSurfMesh')])) + self.assertEqual(fs.getMeshesNames(),('3DSurfMesh','3DSurfMesh','3DSurfMesh','3DSurfMesh')) + self.assertTrue(not fs.changeMeshNames([('3DSurfMesh_1','3DSurfMesh')])) + pass + + def testMEDFileFields1(self): + fname="Pyfile64.med" + f1=MEDCouplingFieldDouble(ON_NODES) + f1.setTime(0.001,0,-1) ; f1.setTimeUnit("us") + c=DataArrayDouble(12) ; c.iota(); m=MEDCouplingCMesh() ; m.setCoordsAt(0,c) ; m.setName("mesh") + mm=MEDFileCMesh() ; mm.setMesh(m) ; mm.write(fname,2) + f1.setMesh(m) + arr=DataArrayDouble(12,2) ; arr.setInfoOnComponents(["aa [u1]","bbbvv [ppp]"]) ; arr[:,0]=range(12) ; arr[:,1]=2*arr[:,0] + f1.setArray(arr) + f1.setName("Field1") + ff1=MEDFileField1TS.New() + ff1.setFieldNoProfileSBT(f1) + self.assertEqual(ff1.getDtUnit(),"us") + ff1.write(fname,0) + f1.setTime(1.001,1,-1) ; ff1=MEDFileField1TS.New() ; ff1.setFieldNoProfileSBT(f1) ; ff1.write(fname,0) + f1.setTime(2.001,2,-1) ; ff1=MEDFileField1TS.New() ; ff1.setFieldNoProfileSBT(f1) ; ff1.write(fname,0) + # + self.assertEqual(MEDFileFields(fname).getCommonIterations(),([(0,-1),(1,-1),(2,-1)],False)) + ff1s=MEDFileFieldMultiTS(fname,"Field1") + ff1s.setName("Field2") + ff1s.write(fname,0) + self.assertEqual(MEDFileFields(fname).getCommonIterations(),([(0,-1),(1,-1),(2,-1)],False)) + f1.setTime(3.001,3,-1) ; ff1=MEDFileField1TS.New() ; ff1.setFieldNoProfileSBT(f1) ; ff1.write(fname,0) + self.assertEqual(MEDFileFields(fname).getCommonIterations(),([(0,-1),(1,-1),(2,-1)],True)) + self.assertEqual(MEDFileFields(fname).partOfThisLyingOnSpecifiedTimeSteps([(1,-1)]).getCommonIterations(),([(1,-1)],False)) + self.assertEqual(MEDFileFields(fname).partOfThisNotLyingOnSpecifiedTimeSteps([(1,-1)]).getCommonIterations(),([(0,-1),(2,-1)],True)) + f1.setName("Field2") ; f1.setTime(3.001,3,-1) ; ff1=MEDFileField1TS.New() ; ff1.setFieldNoProfileSBT(f1) ; ff1.write(fname,0) + self.assertEqual(MEDFileFields(fname).getCommonIterations(),([(0,-1),(1,-1),(2,-1),(3,-1)],False)) + self.assertEqual(MEDFileFields(fname)[1].getDtUnit(),"us") + pass + + # Multi time steps and multi fields management without Globals (profiles, locs) aspects + def testMEDFileFields2(self): + fname="Pyfile65.med" + # to check that all is initialize + MEDFileField1TS().__str__() + MEDFileFieldMultiTS().__str__() + # building a mesh containing 4 tri3 + 5 quad4 + tri=MEDCouplingUMesh("tri",2) + tri.allocateCells() ; tri.insertNextCell(NORM_TRI3,[0,1,2]) + tri.setCoords(DataArrayDouble([(0.,0.),(0.,1.),(1.,0.)])) + tris=[tri.deepCpy() for i in xrange(4)] + for i,elt in enumerate(tris): elt.translate([i,0]) + tris=MEDCouplingUMesh.MergeUMeshes(tris) + quad=MEDCouplingUMesh("quad",2) + quad.allocateCells() ; quad.insertNextCell(NORM_QUAD4,[0,1,2,3]) + quad.setCoords(DataArrayDouble([(0.,0.),(0.,1.),(1.,1.),(1.,0.)])) + quads=[quad.deepCpy() for i in xrange(5)] + for i,elt in enumerate(quads): elt.translate([5+i,0]) + quads=MEDCouplingUMesh.MergeUMeshes(quads) + m=MEDCouplingUMesh.MergeUMeshes(tris,quads) + m.setName("mesh") ; m.getCoords().setInfoOnComponents(["XX [m]","YYY [km]"]) + # + fmts0_0=MEDFileFieldMultiTS() + fmts0_1=MEDFileFieldMultiTS() + # time steps + for i in xrange(10): + infos1=["aa [bb]","ccc [ddd]"] ; name1="1stField" + d=DataArrayDouble(18) ; d.iota(i*10) ; d.rearrange(2) ; d.setInfoOnComponents(infos1) + f=MEDCouplingFieldDouble(ON_CELLS) ; f.setName(name1) ; f.setArray(d) ; f.setMesh(m) + f.setTime(float(i+1)+0.1,i+1,-i-1) + fmts0_0.appendFieldNoProfileSBT(f) + f1ts=MEDFileField1TS() ; f1ts.setFieldNoProfileSBT(f) ; fmts0_1.pushBackTimeStep(f1ts) + self.assertEqual(fmts0_1.getName(),name1) + self.assertEqual(fmts0_0.getInfo(),('aa [bb]','ccc [ddd]')) + self.assertEqual(fmts0_1.getInfo(),('aa [bb]','ccc [ddd]')) + if i>1: + # components names have been modified to generate errors + d.setInfoOnComponents(['aa [bb]','eee [dd]']) + self.assertRaises(InterpKernelException,fmts0_0.appendFieldNoProfileSBT,f) + self.assertRaises(InterpKernelException,f1ts.setInfo,['aa [bb]'])#throw because mismatch of number of components + f1ts.setInfo(['aa [bb]','eee [dd]']) + self.assertRaises(InterpKernelException,fmts0_1.pushBackTimeStep,f1ts) + pass + # add a mismatch of nb of compos + pass + fmts0_2=fmts0_0.deepCpy() + fmts0_3=fmts0_0.deepCpy() + fmts0_4=fmts0_0.deepCpy() + fmts0_5=fmts0_0.shallowCpy() + self.assertTrue(len(fmts0_0)==10 and len(fmts0_1)==10 and len(fmts0_2)==10 and len(fmts0_3)==10 and len(fmts0_4)==10 and len(fmts0_5)==10) + del fmts0_2[::2] + self.assertTrue(len(fmts0_2)==5 and fmts0_2.getIterations()==[(2,-2),(4,-4),(6,-6),(8,-8),(10,-10)]) + del fmts0_3[[1.1,(6,-6),9]] + self.assertTrue(len(fmts0_3)==7 and fmts0_3.getIterations()==[(2,-2),(3,-3),(4,-4),(5,-5),(7,-7),(8,-8),(9,-9)]) + fmts0_6=fmts0_4[[1.1,(6,-6),8]] + self.assertTrue(isinstance(fmts0_6,MEDFileFieldMultiTS)) + self.assertTrue(len(fmts0_6)==3 and fmts0_6.getIterations()==[(1,-1),(6,-6),(9,-9)]) + fmts0_7=fmts0_4[::-3] + self.assertTrue(isinstance(fmts0_7,MEDFileFieldMultiTS)) + self.assertTrue(len(fmts0_7)==4 and fmts0_7.getIterations()==[(10,-10),(7,-7),(4,-4),(1,-1)]) + # + fs0=MEDFileFields() + fs0.pushField(fmts0_0) + fmts0_2.setName("2ndField") ; fs0.pushField(fmts0_2) + fmts0_3.setName("3rdField") ; fs0.pushField(fmts0_3) + fmts0_4.setName("4thField") ; fs0.pushField(fmts0_4) + self.assertTrue(len(fs0)==4 and fs0.getFieldsNames()==('1stField','2ndField','3rdField','4thField')) + fs0.write(fname,2) + fs0=MEDFileFields(fname) + self.assertEqual(fs0.getCommonIterations(),([(2,-2),(4,-4),(8,-8)],True)) + fs1=fs0.partOfThisLyingOnSpecifiedTimeSteps(fs0.getCommonIterations()[0]) + self.assertTrue(fs1.getFieldsNames()==('1stField','2ndField','3rdField','4thField') and fs1.getCommonIterations()==([(2,-2),(4,-4),(8,-8)],False)) + del fs1[["2ndField",3]] + self.assertTrue(fs1.getFieldsNames()==('1stField','3rdField') and fs1.getCommonIterations()==([(2,-2),(4,-4),(8,-8)],False)) + fs2=fs0[[0,"4thField"]] + self.assertTrue(isinstance(fs2,MEDFileFields)) + self.assertEqual(fs2.getFieldsNames(),('1stField','4thField')) + # + mm=MEDFileUMesh() ; mm.setMeshAtLevel(0,m) ; mm.write(fname,0) + pass + + # Multi time steps and multi fields management with Globals (profiles, locs) aspects + def testMEDFileFields3(self): + fname="Pyfile66.med" + # building a mesh containing 4 tri3 + 5 quad4 + tri=MEDCouplingUMesh("tri",2) + tri.allocateCells() ; tri.insertNextCell(NORM_TRI3,[0,1,2]) + tri.setCoords(DataArrayDouble([(0.,0.),(0.,1.),(1.,0.)])) + tris=[tri.deepCpy() for i in xrange(4)] + for i,elt in enumerate(tris): elt.translate([i,0]) + tris=MEDCouplingUMesh.MergeUMeshes(tris) + quad=MEDCouplingUMesh("quad",2) + quad.allocateCells() ; quad.insertNextCell(NORM_QUAD4,[0,1,2,3]) + quad.setCoords(DataArrayDouble([(0.,0.),(0.,1.),(1.,1.),(1.,0.)])) + quads=[quad.deepCpy() for i in xrange(5)] + for i,elt in enumerate(quads): elt.translate([5+i,0]) + quads=MEDCouplingUMesh.MergeUMeshes(quads) + m=MEDCouplingUMesh.MergeUMeshes(tris,quads) + m.setName("mesh") ; m.getCoords().setInfoOnComponents(["XX [m]","YYY [km]"]) + # + mm=MEDFileUMesh() ; mm.setMeshAtLevel(0,m) ; mm.write(fname,2) + # + pfl=DataArrayInt([0,1,2,3,4,5,6]) ; pfl.setName("pfl") + pfl2=DataArrayInt([0,1,2,3,4,5,6,8]) ; pfl2.setName("pfl2") + fmts0_0=MEDFileFieldMultiTS() + fmts0_1=MEDFileFieldMultiTS() + # time steps + for i in xrange(10): + infos1=["aa [bb]","ccc [ddd]"] ; name1="1stField" + d=DataArrayDouble(14) ; d.iota(i*10) ; d.rearrange(2) ; d.setInfoOnComponents(infos1) + f=MEDCouplingFieldDouble(ON_CELLS) ; f.setName(name1) ; f.setArray(d) ; f.setMesh(m) + f.setTime(float(i+1)+0.1,i+1,-i-1) + fmts0_0.appendFieldProfile(f,mm,0,pfl) + f1ts=MEDFileField1TS() ; f1ts.setFieldProfile(f,mm,0,pfl) ; fmts0_1.pushBackTimeStep(f1ts) + self.assertEqual(fmts0_0.getInfo(),('aa [bb]','ccc [ddd]')) + self.assertEqual(fmts0_1.getInfo(),('aa [bb]','ccc [ddd]')) + pass + # + self.assertEqual(fmts0_0.getPfls(),10*('pfl_NORM_QUAD4',)) + self.assertEqual(fmts0_1.getPfls(),('pfl_NORM_QUAD4',)) + fmts0_0.zipPflsNames() + self.assertEqual(fmts0_0.getPfls(),('pfl_NORM_QUAD4',)) + self.assertTrue(fmts0_1.getProfile("pfl_NORM_QUAD4").isEqual(fmts0_0.getProfile("pfl_NORM_QUAD4"))) + fmts0_2=fmts0_0.deepCpy() + fmts0_3=fmts0_0.deepCpy() + fmts0_4=fmts0_0.deepCpy() + fs0=MEDFileFields() + fs0.pushField(fmts0_0) + fmts0_2.setName("2ndField") ; fs0.pushField(fmts0_2) + fmts0_3.setName("3rdField") ; fs0.pushField(fmts0_3) + fmts0_4.setName("4thField") ; fs0.pushField(fmts0_4) + self.assertEqual(fs0.getPfls(),('pfl_NORM_QUAD4',)) + # + fmts0_5=MEDFileFieldMultiTS() + for i in xrange(7): + infos1=["aa [bb]","ccc [ddd]"] ; name1="1stField" + d=DataArrayDouble(16) ; d.iota(i*10) ; d.rearrange(2) ; d.setInfoOnComponents(infos1) + f=MEDCouplingFieldDouble(ON_CELLS) ; f.setName(name1) ; f.setArray(d) ; f.setMesh(m) + f.setTime(float(i+1)+0.1,i+1,-i-1) + f1ts=MEDFileField1TS() ; f1ts.setFieldProfile(f,mm,0,pfl2) ; fmts0_5.pushBackTimeStep(f1ts) + pass + fmts0_5.setName("5thField") ; fs0.pushField(fmts0_5) + self.assertEqual(fs0.getPfls(),('pfl_NORM_QUAD4','pfl2_NORM_QUAD4')) + fs0.checkGlobsCoherency() + fs0.write(fname,0) + pass + + def testSplitComponents1(self): + fname="Pyfile67.med" + # building a mesh containing 4 tri3 + 5 quad4 + tri=MEDCouplingUMesh("tri",2) + tri.allocateCells() ; tri.insertNextCell(NORM_TRI3,[0,1,2]) + tri.setCoords(DataArrayDouble([(0.,0.),(0.,1.),(1.,0.)])) + tris=[tri.deepCpy() for i in xrange(4)] + for i,elt in enumerate(tris): elt.translate([i,0]) + tris=MEDCouplingUMesh.MergeUMeshes(tris) + quad=MEDCouplingUMesh("quad",2) + quad.allocateCells() ; quad.insertNextCell(NORM_QUAD4,[0,1,2,3]) + quad.setCoords(DataArrayDouble([(0.,0.),(0.,1.),(1.,1.),(1.,0.)])) + quads=[quad.deepCpy() for i in xrange(5)] + for i,elt in enumerate(quads): elt.translate([5+i,0]) + quads=MEDCouplingUMesh.MergeUMeshes(quads) + m=MEDCouplingUMesh.MergeUMeshes(tris,quads) + m.setName("mesh") ; m.getCoords().setInfoOnComponents(["XX [m]","YYY [km]"]) + # + mm=MEDFileUMesh() ; mm.setMeshAtLevel(0,m) ; mm.write(fname,2) + # + pfl=DataArrayInt([0,1,2,3,4,5,6]) ; pfl.setName("pfl") + pfl2=DataArrayInt([0,1,2,3,4,5,6,8]) ; pfl2.setName("pfl2") + fs=MEDFileFields() + fmts0_1=MEDFileFieldMultiTS() + # time steps + infos1=['aa [bb]','ccc [ddd]',"ZZZZ [MW*s]"] + for i in xrange(10): + name1="1stField" + d=DataArrayDouble(21) ; d.iota(i*10) ; d.rearrange(3) ; d.setInfoOnComponents(infos1) + f=MEDCouplingFieldDouble(ON_CELLS) ; f.setName(name1) ; f.setArray(d) ; f.setMesh(m) + f.setTime(float(i+1)+0.1,i+1,-i-1) + f1ts=MEDFileField1TS() ; f1ts.setFieldProfile(f,mm,0,pfl) ; fmts0_1.pushBackTimeStep(f1ts) + self.assertEqual(fmts0_1.getInfo(),tuple(infos1)) + pass + fs.pushField(fmts0_1) + self.assertEqual(1,len(fs)) + l=fmts0_1.splitComponents() + self.assertEqual(3,len(l)) + for elt in l: self.assertEqual(10,len(elt)) + for elt in l: self.assertTrue(isinstance(elt,MEDFileFieldMultiTS)) + for elt in l: + elt.setName("%s_%s"%(elt.getName(),DataArray.GetVarNameFromInfo(elt.getInfo()[0]))) + pass + fs.pushFields(l) + self.assertEqual(4,len(fs)) + for elt in fs: self.assertEqual(10,len(elt)) + self.assertEqual(fs.getPfls(),('pfl_NORM_QUAD4',)) + self.assertEqual(fs.getPflsReallyUsed(),('pfl_NORM_QUAD4',)) + # + fs.write(fname,0) ; del fs + # + fs1=MEDFileFields(fname) + self.assertEqual(fs1.getPfls(),('pfl_NORM_QUAD4',)) + self.assertEqual(fs1.getPflsReallyUsed(),('pfl_NORM_QUAD4',)) + self.assertEqual(4,len(fs1)) + for i in xrange(10): + for j,fieldName in enumerate(['1stField_aa','1stField_ccc','1stField_ZZZZ']): + f1ts=fs1[fieldName][i] + f=f1ts.getFieldOnMeshAtLevel(ON_CELLS,0,mm) + d=DataArrayDouble(21) ; d.iota(i*10) ; d.rearrange(3) ; d=d[:,j] ; d.setInfoOnComponent(0,infos1[j]) + self.assertTrue(d.isEqual(f.getArray(),1e-13)) + pass + f1ts=fs1["1stField"][i] + f=f1ts.getFieldOnMeshAtLevel(ON_CELLS,0,mm) + d=DataArrayDouble(21) ; d.iota(i*10) ; d.rearrange(3) ; d.setInfoOnComponents(infos1) + self.assertTrue(d.isEqual(f.getArray(),1e-13)) + pass + pass pass unittest.main() diff --git a/src/MEDLoader/Swig/MEDLoaderTypemaps.i b/src/MEDLoader/Swig/MEDLoaderTypemaps.i index 12eb0e318..ad068af70 100644 --- a/src/MEDLoader/Swig/MEDLoaderTypemaps.i +++ b/src/MEDLoader/Swig/MEDLoaderTypemaps.i @@ -23,6 +23,11 @@ static PyObject* convertMEDFileMesh(ParaMEDMEM::MEDFileMesh* mesh, int owner) throw(INTERP_KERNEL::Exception) { PyObject *ret=0; + if(!mesh) + { + Py_XINCREF(Py_None); + return Py_None; + } if(dynamic_cast(mesh)) ret=SWIG_NewPointerObj((void*)mesh,SWIGTYPE_p_ParaMEDMEM__MEDFileUMesh,owner); if(dynamic_cast(mesh)) @@ -37,6 +42,11 @@ static PyObject* convertMEDFileMesh(ParaMEDMEM::MEDFileMesh* mesh, int owner) th static PyObject* convertMEDFileParameter1TS(ParaMEDMEM::MEDFileParameter1TS* p1ts, int owner) throw(INTERP_KERNEL::Exception) { PyObject *ret=0; + if(!p1ts) + { + Py_XINCREF(Py_None); + return Py_None; + } if(dynamic_cast(p1ts)) ret=SWIG_NewPointerObj((void*)p1ts,SWIGTYPE_p_ParaMEDMEM__MEDFileParameterDouble1TS,owner); if(dynamic_cast(p1ts)) @@ -46,6 +56,40 @@ static PyObject* convertMEDFileParameter1TS(ParaMEDMEM::MEDFileParameter1TS* p1t return ret; } +static PyObject* convertMEDFileField1TS(ParaMEDMEM::MEDFileAnyTypeField1TS *p, int owner) throw(INTERP_KERNEL::Exception) +{ + PyObject *ret=0; + if(!p) + { + Py_XINCREF(Py_None); + return Py_None; + } + if(dynamic_cast(p)) + ret=SWIG_NewPointerObj((void*)p,SWIGTYPE_p_ParaMEDMEM__MEDFileField1TS,owner); + if(dynamic_cast(p)) + ret=SWIG_NewPointerObj((void*)p,SWIGTYPE_p_ParaMEDMEM__MEDFileIntField1TS,owner); + if(!ret) + throw INTERP_KERNEL::Exception("Not recognized type of MEDFileAnyTypeField1TS on downcast !"); + return ret; +} + +static PyObject* convertMEDFileFieldMultiTS(ParaMEDMEM::MEDFileAnyTypeFieldMultiTS *p, int owner) throw(INTERP_KERNEL::Exception) +{ + PyObject *ret=0; + if(!p) + { + Py_XINCREF(Py_None); + return Py_None; + } + if(dynamic_cast(p)) + ret=SWIG_NewPointerObj((void*)p,SWIGTYPE_p_ParaMEDMEM__MEDFileFieldMultiTS,owner); + if(dynamic_cast(p)) + ret=SWIG_NewPointerObj((void*)p,SWIGTYPE_p_ParaMEDMEM__MEDFileIntFieldMultiTS,owner); + if(!ret) + throw INTERP_KERNEL::Exception("Not recognized type of MEDFileAnyTypeFieldMultiTS on downcast !"); + return ret; +} + static std::vector > convertTimePairIdsFromPy(PyObject *pyLi) throw(INTERP_KERNEL::Exception) { std::vector > ret; @@ -171,7 +215,7 @@ std::vector< std::pair > convertVecPairStStFromPy(PyO throw INTERP_KERNEL::Exception(msg); PyObject *o0=PyTuple_GetItem(o,0); if(PyString_Check(o0)) - p.second=std::string(PyString_AsString(o0)); + p.first=std::string(PyString_AsString(o0)); else throw INTERP_KERNEL::Exception(msg); PyObject *o1=PyTuple_GetItem(o,1); @@ -209,9 +253,9 @@ std::vector< std::pair, std::string > > convertVecPairV PyObject *o0=PyTuple_GetItem(o,0); if(PyList_Check(o0)) { - int size2=PyList_Size(o0); - p.first.resize(size2); - for(int j=0;j, std::string > > convertVecPairV } throw INTERP_KERNEL::Exception(msg); } + +/*! + * Called by MEDFileAnyTypeFieldMultiTS::__getitem__ when \a elt0 is neither a list nor a slice. + * In this case a MEDFileAnyTypeField1TS object is returned. + */ +int MEDFileAnyTypeFieldMultiTSgetitemSingleTS__(const MEDFileAnyTypeFieldMultiTS *self, PyObject *elt0) throw(INTERP_KERNEL::Exception) +{ + if(elt0 && PyInt_Check(elt0)) + {//fmts[3] + return PyInt_AS_LONG(elt0); + } + else if(elt0 && PyTuple_Check(elt0)) + { + if(PyTuple_Size(elt0)==2) + { + PyObject *o0=PyTuple_GetItem(elt0,0); + PyObject *o1=PyTuple_GetItem(elt0,1); + if(PyInt_Check(o0) && PyInt_Check(o1)) + {//fmts(1,-1) + int iter=PyInt_AS_LONG(o0); + int order=PyInt_AS_LONG(o1); + return self->getPosOfTimeStep(iter,order); + } + else + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::__getitem__ : invalid input param ! input is a tuple of size 2 but two integers are expected in this tuple to request a time steps !"); + } + else + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::__getitem__ : invalid input param ! input is a tuple of size != 2 ! two integers are expected in this tuple to request a time steps !"); + } + else if(elt0 && PyFloat_Check(elt0)) + { + double val=PyFloat_AS_DOUBLE(elt0); + return self->getPosGivenTime(val); + } + else + throw INTERP_KERNEL::Exception("MEDFileAnyTypeFieldMultiTS::__getitem__ : invalid input params ! expected fmts[int], fmts[int,int], or fmts[double] to request one time step ! To request a series of time steps invoke fmts[slice], fmts[list of int], fmts[list of double], or fmts[list of int,int] !"); +} + +/*! + * Called by MEDFileAnyTypeFieldMultiTS::__getitem__ when \a obj is neither a list nor a slice. + * In this case a MEDFileAnyTypeField1TS object is returned. + */ +int MEDFileFieldsgetitemSingleTS__(const MEDFileFields *self, PyObject *obj) throw(INTERP_KERNEL::Exception) +{ + if(PyInt_Check(obj)) + { + return (int)PyInt_AS_LONG(obj); + } + else if(PyString_Check(obj)) + { + return self->getPosFromFieldName(PyString_AsString(obj)); + } + else + throw INTERP_KERNEL::Exception("MEDFileFields::__getitem__ : only integer or string with fieldname supported !"); +} diff --git a/src/MEDLoader/Swig/Makefile.am b/src/MEDLoader/Swig/Makefile.am index b0e14d7e6..9c6dc0c7e 100644 --- a/src/MEDLoader/Swig/Makefile.am +++ b/src/MEDLoader/Swig/Makefile.am @@ -53,9 +53,9 @@ _MEDLoader_la_LDFLAGS = -module $(MED3_LIBS_C_ONLY) $(HDF5_LIBS) $(PYTHON_LIBS) CLEANFILES = MEDLoader_wrap.cxx MEDLoader.py -dist_salomescript_SCRIPTS= med2sauv sauv2med +dist_salomescript_SCRIPTS= med2sauv sauv2med case2med med2case -dist_salomescript_DATA= MEDLoaderDataForTest.py MEDLoaderTest.py MEDLoaderTest2.py MEDLoaderTest3.py libMEDLoader_Swig.py medutilities.py +dist_salomescript_DATA= MEDLoaderDataForTest.py MEDLoaderTest.py MEDLoaderTest2.py MEDLoaderTest3.py MEDLoaderCouplingTrainingSession.py CaseIO.py CaseReader.py CaseWriter.py MEDLoaderSplitter.py libMEDLoader_Swig.py medutilities.py nodist_salomescript_DATA = MEDLoader.py UNIT_TEST_PROG = MEDLoaderTest.py MEDLoaderTest2.py diff --git a/src/MEDLoader/Swig/case2med b/src/MEDLoader/Swig/case2med new file mode 100755 index 000000000..b4281d776 --- /dev/null +++ b/src/MEDLoader/Swig/case2med @@ -0,0 +1,54 @@ +#!/usr/bin/python +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2007-2013 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 +# + +from CaseReader import CaseReader +from optparse import OptionParser +import os + +parser = OptionParser() +parser.set_usage("Convert a Case file to a MED file.\n %prog [options] case_file") +parser.add_option("-c", "--currentdir", action="store_true", dest="here", default=False, + help="Are generated MED file generated in current directory. By default not, MED file is generated in directory containing the input file (default False)") +(opts, args) = parser.parse_args() + +if len(args) != 1: + parser.print_usage() + exit(1) + pass + +fname=args[0] #"cas_test_simple.case" +if opts.here: + fOut=os.path.splitext(os.path.basename(fname))[0]+".med" + pass +else: + fOut=os.path.splitext(fname)[0]+".med" + pass +### +cr=CaseReader(fname) +try: + medfd=cr.loadInMEDFileDS() +except: + print "An error occured during the conversion!" + print "#######################################" + raise +medfd.write(fOut,2) +print "#########\nFile \"%s\" written !\n#########"%(fOut) + diff --git a/src/MEDLoader/Swig/med2case b/src/MEDLoader/Swig/med2case new file mode 100755 index 000000000..7865dd6c3 --- /dev/null +++ b/src/MEDLoader/Swig/med2case @@ -0,0 +1,63 @@ +#!/usr/bin/python +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2007-2013 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 +# +# Author Anthony GEAY (CEA/DEN/DM2S/STMF/LGLS) + +from MEDLoader import MEDFileData,InterpKernelException +from CaseWriter import CaseWriter +from optparse import OptionParser +import os + +parser = OptionParser() +parser.set_usage("Convert a MED file to a Case file.\n %prog [options] case_file") +parser.add_option("-g", "--groups", action="store_true", dest="groups", default=False, + help="Are groups in meshes stored in MEDFile exported in output case as subparts (default False)") +parser.add_option("-c", "--currentdir", action="store_true", dest="here", default=False, + help="Are generated case,geo files generated in current directory. By default not, files are generated in directory containing the input file (default False)") +(opts, args) = parser.parse_args() + +if len(args) != 1: + parser.print_usage() + exit(1) + pass + +fname=os.path.abspath(args[0]) #"cas_test_simple.case" +if opts.here: + fOut=os.path.splitext(os.path.basename(fname))[0]+".case" + pass +else: + fOut=os.path.splitext(fname)[0]+".case" + pass +### +try: + cw=CaseWriter.New() + cw.setExportingGroups(opts.groups) + mfd=MEDFileData(fname) + cw.setMEDFileDS(mfd) + listOfWrittenFileNames=cw.write(fOut) +except InterpKernelException as e: + print "An error occured during the conversion!" + print "#######################################" + raise e +print "#########" +for l in listOfWrittenFileNames: + print "File \"%s\" sucessfully written !"%(l) + pass +print "#########" diff --git a/src/MEDLoader/Test/SauvLoaderTest.cxx b/src/MEDLoader/Test/SauvLoaderTest.cxx index 084532db0..113633c73 100644 --- a/src/MEDLoader/Test/SauvLoaderTest.cxx +++ b/src/MEDLoader/Test/SauvLoaderTest.cxx @@ -135,7 +135,7 @@ void SauvLoaderTest::testSauv2MedOnA3SubsField() CPPUNIT_ASSERT_DOUBLES_EQUAL(3, length1dField->accumulate(0), 1e-12); // check field MEDCouplingAutoRefCountObjectPtr field = - d2->getFields()->getFieldWithName("CHAM1D"); + dynamic_cast(d2->getFields()->getFieldWithName("CHAM1D")); std::cout << "Number of components in field: " << field->getInfo().size() << std::endl; CPPUNIT_ASSERT_EQUAL(6,(int)field->getInfo().size()); std::vector< std::pair > timesteps = field->getIterations(); @@ -161,7 +161,6 @@ void SauvLoaderTest::testSauv2MedOnA3SubsField() for (int i=0; i < field1d->getNumberOfTuples(); i++) { - bool ok = abs(values[i]-field1d->getIJ(i, 0)) < 1e-12; CPPUNIT_ASSERT_DOUBLES_EQUAL( values[i], field1d->getIJ(i, 0), 1e-12 ); } } @@ -220,7 +219,7 @@ void SauvLoaderTest::testMed2Sauv() MEDFileFields* pointeFields = pointeMed->getFields(); for ( int i = 0; i < pointeFields->getNumberOfFields(); ++i ) { - MEDCouplingAutoRefCountObjectPtr ts = pointeFields->getFieldAtPos(i); + MEDCouplingAutoRefCountObjectPtr ts = pointeFields->getFieldAtPos(i); if ( std::string("fieldnodeint") == ts->getName()) { pointeFields->destroyFieldAtPos( i ); @@ -267,9 +266,9 @@ void SauvLoaderTest::testMed2Sauv() // check fields // fieldnodedouble MEDCouplingAutoRefCountObjectPtr fieldnodedoubleTS1 = - pointeMed->getFields()->getFieldWithName("fieldnodedouble"); + dynamic_cast(pointeMed->getFields()->getFieldWithName("fieldnodedouble")); MEDCouplingAutoRefCountObjectPtr fieldnodedoubleTS2 = - d2->getFields()->getFieldWithName("fieldnodedouble"); + dynamic_cast(d2->getFields()->getFieldWithName("fieldnodedouble")); CPPUNIT_ASSERT_EQUAL( fieldnodedoubleTS1->getInfo().size(), fieldnodedoubleTS2->getInfo().size()); for ( size_t i = 0; i < fieldnodedoubleTS1->getInfo().size(); ++i ) CPPUNIT_ASSERT_EQUAL( fieldnodedoubleTS1->getInfo()[i], fieldnodedoubleTS2->getInfo()[i]); @@ -286,9 +285,9 @@ void SauvLoaderTest::testMed2Sauv() } // fieldcelldoublevector MEDCouplingAutoRefCountObjectPtr fieldcelldoublevectorTS1 = - pointeMed->getFields()->getFieldWithName("fieldcelldoublevector"); + dynamic_cast(pointeMed->getFields()->getFieldWithName("fieldcelldoublevector")); MEDCouplingAutoRefCountObjectPtr fieldcelldoublevectorTS2 = - d2->getFields()->getFieldWithName("fieldcelldoublevector"); + dynamic_cast(d2->getFields()->getFieldWithName("fieldcelldoublevector")); CPPUNIT_ASSERT_EQUAL( fieldcelldoublevectorTS1->getInfo().size(), fieldcelldoublevectorTS2->getInfo().size()); for ( size_t i = 0; i < fieldcelldoublevectorTS1->getInfo().size(); ++i ) CPPUNIT_ASSERT_EQUAL( fieldcelldoublevectorTS1->getInfo()[i], fieldcelldoublevectorTS2->getInfo()[i]); @@ -307,7 +306,7 @@ void SauvLoaderTest::testMed2Sauv() } // "Field on 2 faces" MEDCouplingAutoRefCountObjectPtr fieldOnFaces = - d2->getFields()->getFieldWithName(f1->getName()); + dynamic_cast(d2->getFields()->getFieldWithName(f1->getName())); io1 = fieldOnFaces->getIterations(); MEDCouplingAutoRefCountObjectPtr fof = fieldOnFaces->getFieldOnMeshAtLevel(f1->getTypeOfField(),io1[0].first,io1[0].second,um1); diff --git a/src/RENUMBER/renumbering.cxx b/src/RENUMBER/renumbering.cxx index c073f1feb..ce86bde6e 100644 --- a/src/RENUMBER/renumbering.cxx +++ b/src/RENUMBER/renumbering.cxx @@ -105,12 +105,14 @@ int main(int argc, char** argv) { for(int i=0;igetNumberOfFields();i++) { - MEDFileFieldMultiTS *fmts=fs->getFieldAtPos(i); + MEDFileFieldMultiTS *fmts=dynamic_cast(fs->getFieldAtPos(i)); + if(!fmts) continue; if(fmts->getMeshName()==meshname) { for(int j=0;jgetNumberOfTS();j++) { - MEDFileField1TS *f1ts=fmts->getTimeStepAtPos(j); + MEDFileField1TS *f1ts=dynamic_cast(fmts->getTimeStepAtPos(j)); + if(!f1ts) continue; DataArrayDouble *arr=f1ts->getUndergroundDataArray(); arr->renumberInPlace(&perm[0]); } -- 2.30.2

*yD2qO@WFIKs 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%0DJnh3?F1KDLxj2weB(|>u)%*lANOn?3 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 z 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�Xje=F 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≷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