Salome HOME
MEDCouplingFieldInt and MEDCouplingFieldFloat are pickelized
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingFieldT.txx
1 // Copyright (C) 2016  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (EDF R&D)
20
21 #ifndef __MEDCOUPLINGFIELDT_TXX__
22 #define __MEDCOUPLINGFIELDT_TXX__
23
24 #include "MEDCouplingTimeDiscretization.hxx"
25 #include "MEDCouplingMesh.hxx"
26
27 namespace MEDCoupling
28 {
29   template<class T>
30   MEDCouplingFieldT<T>::MEDCouplingFieldT(const MEDCouplingFieldT<T>& other, bool deepCopy):MEDCouplingField(other,deepCopy),_time_discr(other._time_discr->performCopyOrIncrRef(deepCopy))
31   {
32   }
33   
34   /*!
35    * Checks if \a this field is correctly defined, else an exception is thrown.
36    *  \throw If the mesh is not set.
37    *  \throw If the data array is not set.
38    *  \throw If the spatial discretization of \a this field is NULL.
39    *  \throw If \a this->getTimeTolerance() < 0.
40    *  \throw If the temporal discretization data is incorrect.
41    *  \throw If mesh data does not correspond to field data.
42    */
43   template<class T>
44   void MEDCouplingFieldT<T>::checkConsistencyLight() const
45   {
46     MEDCouplingField::checkConsistencyLight();
47     _time_discr->checkConsistencyLight();
48     _type->checkCoherencyBetween(_mesh,getArray());
49   }
50
51   template<class T>
52   MEDCouplingFieldT<T>::MEDCouplingFieldT(const MEDCouplingField& other, MEDCouplingTimeDiscretizationTemplate<T> *timeDiscr, bool deepCopy):MEDCouplingField(other,deepCopy),_time_discr(timeDiscr)
53   {
54   }
55   
56   template<class T>
57   MEDCouplingFieldT<T>::MEDCouplingFieldT(TypeOfField type, MEDCouplingTimeDiscretizationTemplate<T> *timeDiscr):MEDCouplingField(type),_time_discr(timeDiscr)
58   {
59   }
60
61   template<class T>
62   MEDCouplingFieldT<T>::MEDCouplingFieldT(MEDCouplingFieldDiscretization *type, NatureOfField n, MEDCouplingTimeDiscretizationTemplate<T> *timeDiscr):MEDCouplingField(type,n),_time_discr(timeDiscr)
63   {
64   }
65
66   template<class T>
67   MEDCouplingFieldT<T>::~MEDCouplingFieldT()
68   {
69     delete _time_discr;
70   }
71
72   /*!
73    * This method synchronizes time information (time, iteration, order, time unit) regarding the information in \c this->_mesh.
74    * \throw If no mesh is set in this. Or if \a this is not compatible with time setting (typically NO_TIME)
75    */
76   template<class T>
77   void MEDCouplingFieldT<T>::synchronizeTimeWithMesh()
78   {
79     if(!_mesh)
80       throw INTERP_KERNEL::Exception("MEDCouplingFieldT::synchronizeTimeWithMesh : no mesh set in this !");
81     int it(-1),ordr(-1);
82     double val(_mesh->getTime(it,ordr));
83     std::string timeUnit(_mesh->getTimeUnit());
84     setTime(val,it,ordr);
85     setTimeUnit(timeUnit);
86   }
87
88   /*!
89    * Returns a new MEDCouplingFieldDouble which is a copy of \a this one. The data
90    * of \a this field is copied either deep or shallow depending on \a recDeepCpy
91    * parameter. But the underlying mesh is always deep copied.
92    * Data that can be copied either deeply or shallow are:
93    * - \ref MEDCouplingTemporalDisc "temporal discretization" data that holds array(s)
94    * of field values,
95    * - \ref MEDCouplingSpatialDisc "a spatial discretization".
96    * 
97    * This method behaves exactly like clone() except that here the underlying **mesh is
98    * always deeply duplicated**, whatever the value \a recDeepCpy parameter.
99    * The result of \c cloneWithMesh(true) is exactly the same as that of deepCopy().
100    * So the resulting field can not be used together with \a this one in the methods
101    * like operator+(), operator*() etc. To avoid deep copying the underlying mesh,
102    * the user can call clone().
103    *  \param [in] recDeepCpy - if \c true, the copy of the underlying data arrays is
104    *         deep, else all data arrays of \a this field are shared by the new field.
105    *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The
106    *         caller is to delete this field using decrRef() as it is no more needed.
107    * \sa clone()
108    */
109   template<class T>
110   typename Traits<T>::FieldType *MEDCouplingFieldT<T>::cloneWithMesh(bool recDeepCpy) const
111   {
112     MCAuto<  typename Traits<T>::FieldType > ret(clone(recDeepCpy));
113     if(_mesh)
114       {
115         MCAuto<MEDCouplingMesh> mCpy(_mesh->deepCopy());
116         ret->setMesh(mCpy);
117       }
118     return ret.retn();
119   }
120   
121   template<class T>
122   bool MEDCouplingFieldT<T>::isEqualIfNotWhy(const MEDCouplingField *other, double meshPrec, double valsPrec, std::string& reason) const
123   {
124     if(!other)
125       throw INTERP_KERNEL::Exception("MEDCouplingFieldT::isEqualIfNotWhy : other instance is NULL !");
126     const MEDCouplingFieldT<T> *otherC(dynamic_cast<const MEDCouplingFieldT<T> *>(other));
127     if(!otherC)
128       {
129         reason="field given in input is not castable in MEDCouplingFieldT !";
130         return false;
131       }
132     if(!MEDCouplingField::isEqualIfNotWhy(other,meshPrec,valsPrec,reason))
133       return false;
134     if(!_time_discr->isEqualIfNotWhy(otherC->_time_discr,T(valsPrec),reason))
135       {
136         reason.insert(0,"In FieldT time discretizations differ :");
137         return false;
138       }
139     return true;
140   }
141   
142   /*!
143    * Checks equality of \a this and \a other field. Only numeric data is considered,
144    * i.e. names, description etc are not compared.
145    *  \param [in] other - the field to compare with.
146    *  \param [in] meshPrec - a precision used to compare node coordinates of meshes.
147    *  \param [in] valsPrec - a precision used to compare data arrays of the two fields.
148    *  \return bool - \c true if the two fields are equal, \c false else.
149    *  \throw If \a other == NULL.
150    *  \throw If the spatial discretization of \a this field is NULL.
151    */
152   template<class T>
153   bool MEDCouplingFieldT<T>::isEqualWithoutConsideringStr(const MEDCouplingField *other, double meshPrec, double valsPrec) const
154   {
155     const MEDCouplingFieldT<T> *otherC(dynamic_cast<const MEDCouplingFieldT<T> *>(other));
156     if(!otherC)
157       return false;
158     if(!MEDCouplingField::isEqualWithoutConsideringStr(other,meshPrec,valsPrec))
159       return false;
160     if(!_time_discr->isEqualWithoutConsideringStr(otherC->_time_discr,T(valsPrec)))
161       return false;
162     return true;
163   }
164   
165   /*!
166    * Copies tiny info (component names, name and description) from an \a other field to
167    * \a this one.
168    * \warning The underlying mesh is not renamed (for safety reason).
169    *  \param [in] other - the field to copy the tiny info from.
170    *  \throw If \a this->getNumberOfComponents() != \a other->getNumberOfComponents()
171    */
172   template<class T>
173   void MEDCouplingFieldT<T>::copyTinyStringsFrom(const MEDCouplingField *other)
174   {
175     MEDCouplingField::copyTinyStringsFrom(other);
176     const MEDCouplingFieldT<T> *otherC(dynamic_cast<const MEDCouplingFieldT<T> *>(other));
177     if(otherC)
178       {
179         _time_discr->copyTinyStringsFrom(*otherC->_time_discr);
180       }
181   }
182
183   /*!
184    * Copies only times, order and iteration from an \a other field to
185    * \a this one. The underlying mesh is not impacted by this method.
186    * Arrays are not impacted neither.
187    *  \param [in] other - the field to tiny attributes from.
188    *  \throw If \a this->getNumberOfComponents() != \a other->getNumberOfComponents()
189    */
190   template<class T>
191   void MEDCouplingFieldT<T>::copyTinyAttrFrom(const MEDCouplingFieldT<T> *other)
192   {
193     if(other)
194       {
195         _time_discr->copyTinyAttrFrom(*other->_time_discr);
196       }
197   }
198   
199   template<class T>
200   void MEDCouplingFieldT<T>::copyAllTinyAttrFrom(const MEDCouplingFieldT<T> *other)
201   {
202     copyTinyStringsFrom(other);
203     copyTinyAttrFrom(other);
204   }
205   
206   /*!
207    * This method is more strict than MEDCouplingField::areCompatibleForMerge method.
208    * This method is used for operation on fields to operate a first check before attempting operation.
209    */
210   template<class T>
211   bool MEDCouplingFieldT<T>::areStrictlyCompatible(const MEDCouplingField *other) const
212   {
213     std::string tmp;
214     if(!MEDCouplingField::areStrictlyCompatible(other))
215       return false;
216     const MEDCouplingFieldT<T> *otherC(dynamic_cast<const MEDCouplingFieldT<T> *>(other));
217     if(!otherC)
218       return false;
219     if(!_time_discr->areStrictlyCompatible(otherC->_time_discr,tmp))
220       return false;
221     return true;
222   }
223   
224   template<class T>
225   bool MEDCouplingFieldT<T>::areStrictlyCompatibleForMulDiv(const MEDCouplingField *other) const
226   {
227     if(!MEDCouplingField::areStrictlyCompatibleForMulDiv(other))
228       return false;
229     const MEDCouplingFieldT<T> *otherC(dynamic_cast<const MEDCouplingFieldT<T> *>(other));
230     if(!otherC)
231       return false;
232     if(!_time_discr->areStrictlyCompatibleForDiv(otherC->_time_discr))
233       return false;
234     return true;
235   }
236
237   /*!
238    * Method with same principle than MEDCouplingFieldDouble::areStrictlyCompatibleForMulDiv method except that
239    * number of components between \a this and 'other' can be different here (for operator/).
240    */
241   template<class T>
242   bool MEDCouplingFieldT<T>::areCompatibleForDiv(const MEDCouplingField *other) const
243   {
244     if(!MEDCouplingField::areStrictlyCompatibleForMulDiv(other))
245       return false;
246     const MEDCouplingFieldT<T> *otherC(dynamic_cast<const MEDCouplingFieldT<T> *>(other));
247     if(!otherC)
248       return false;
249     if(!_time_discr->areStrictlyCompatibleForDiv(otherC->_time_discr))
250       return false;
251     return true;
252   }
253   
254   template<class T>
255   bool MEDCouplingFieldT<T>::areCompatibleForMul(const MEDCouplingField *other) const
256   {
257     if(!MEDCouplingField::areStrictlyCompatibleForMulDiv(other))
258       return false;
259     const MEDCouplingFieldT<T> *otherC(dynamic_cast<const MEDCouplingFieldT<T> *>(other));
260     if(!otherC)
261       return false;
262     if(!_time_discr->areStrictlyCompatibleForMul(otherC->_time_discr))
263       return false;
264     return true;
265   }
266
267   /*!
268    * Returns a string describing \a this field. This string is outputted by \c print
269    * Python command. The string includes info on
270    * - name,
271    * - description,
272    * - \ref MEDCouplingSpatialDisc "spatial discretization",
273    * - \ref MEDCouplingTemporalDisc "time discretization",
274    * - \ref NatureOfField,
275    * - components,
276    * - mesh.
277    *
278    *  \return std::string - the string describing \a this field.
279    */
280   template<class T>
281   std::string MEDCouplingFieldT<T>::simpleRepr() const
282   {
283     std::ostringstream ret;
284     ret << Traits<T>::FieldTypeName << " with name : \"" << getName() << "\"\n";
285     ret << "Description of field is : \"" << getDescription() << "\"\n";
286     if(_type)
287       { ret << Traits<T>::FieldTypeName << " space discretization is : " << _type->getStringRepr() << "\n"; }
288     else
289       { ret << Traits<T>::FieldTypeName << " has no spatial discretization !\n"; }
290     if(_time_discr)
291       { ret << Traits<T>::FieldTypeName << " time discretization is : " << _time_discr->getStringRepr() << "\n"; }
292     else
293       { ret << Traits<T>::FieldTypeName << " has no time discretization !\n"; }
294     ret << Traits<T>::FieldTypeName << " nature of field is : \"" << MEDCouplingNatureOfField::GetReprNoThrow(_nature) << "\"\n";
295     if(getArray())
296       {
297         if(getArray()->isAllocated())
298           {
299             int nbOfCompo=getArray()->getNumberOfComponents();
300             ret << Traits<T>::FieldTypeName << " default array has " << nbOfCompo << " components and " << getArray()->getNumberOfTuples() << " tuples.\n";
301             ret << Traits<T>::FieldTypeName << " default array has following info on components : ";
302             for(int i=0;i<nbOfCompo;i++)
303               ret << "\"" << getArray()->getInfoOnComponent(i) << "\" ";
304             ret << "\n";
305           }
306         else
307           {
308             ret << "Array set but not allocated !\n";
309           }
310       }
311     if(_mesh)
312       ret << "Mesh support information :\n__________________________\n" << _mesh->simpleRepr();
313     else
314       ret << "Mesh support information : No mesh set !\n";
315     return ret.str();
316   }
317   
318   template<class T>
319   void MEDCouplingFieldT<T>::reprQuickOverview(std::ostream& stream) const
320   {
321     stream << Traits<T>::FieldTypeName << " C++ instance at " << this << ". Name : \"" << _name << "\"." << std::endl;
322     const char *nat(0);
323     try
324       {
325         nat=MEDCouplingNatureOfField::GetRepr(_nature);
326         stream << "Nature of field : " << nat << ".\n";
327       }
328     catch(INTERP_KERNEL::Exception& e)
329       {  }
330     const MEDCouplingFieldDiscretization *fd(_type);
331     if(!fd)
332       stream << "No spatial discretization set !";
333     else
334       fd->reprQuickOverview(stream);
335     stream << std::endl;
336     if(!_mesh)
337       stream << "\nNo mesh support defined !";
338     else
339       {
340         std::ostringstream oss;
341         _mesh->reprQuickOverview(oss);
342         std::string tmp(oss.str());
343         stream << "\nMesh info : " << tmp.substr(0,tmp.find('\n'));
344       }
345     if(_time_discr)
346       {
347         const typename Traits<T>::ArrayType *arr(_time_discr->getArray());
348         if(arr)
349           {
350             stream << "\n\nArray info : ";
351             arr->reprQuickOverview(stream);
352           }
353         else
354           {
355             stream << "\n\nNo data array set !";
356           }
357       }
358   }
359
360   /*!
361    * Returns a type of \ref MEDCouplingTemporalDisc "time discretization" of \a this field.
362    *  \return MEDCoupling::TypeOfTimeDiscretization - an enum item describing the time
363    *          discretization type.
364    */
365   template<class T>
366   TypeOfTimeDiscretization MEDCouplingFieldT<T>::getTimeDiscretization() const
367   {
368     return _time_discr->getEnum();
369   }
370
371   /*!
372    * Builds a newly created field, that the caller will have the responsability to deal with.
373    * \n This method makes the assumption that \a this field is correctly defined when this method is called (\a this->checkConsistencyLight() returns without any exception thrown), **no check of this will be done**.
374    * \n This method returns a restriction of \a this so that only tuple ids specified in [ \a partBg , \a partEnd ) will be contained in the returned field.
375    * \n Parameter [\a partBg, \a partEnd ) specifies **cell ids whatever the spatial discretization** of \a this (
376    * \ref MEDCoupling::ON_CELLS "ON_CELLS", 
377    * \ref MEDCoupling::ON_NODES "ON_NODES",
378    * \ref MEDCoupling::ON_GAUSS_PT "ON_GAUSS_PT", 
379    * \ref MEDCoupling::ON_GAUSS_NE "ON_GAUSS_NE",
380    * \ref MEDCoupling::ON_NODES_KR "ON_NODES_KR").
381    *
382    * For example, \a this is a field on cells lying on a mesh that have 10 cells, \a partBg contains the following cell ids [3,7,6].
383    * Then the returned field will lie on mesh having 3 cells and will contain 3 tuples.
384    *- Tuple #0 of the result field will refer to the cell #0 of returned mesh. The cell #0 of returned mesh will be equal to the cell #3 of \a this->getMesh().
385    *- Tuple #1 of the result field will refer to the cell #1 of returned mesh. The cell #1 of returned mesh will be equal to the cell #7 of \a this->getMesh().
386    *- Tuple #2 of the result field will refer to the cell #2 of returned mesh. The cell #2 of returned mesh will be equal to the cell #6 of \a this->getMesh().
387    *
388    * Let, for example, \a this be a field on nodes lying on a mesh that have 10 cells and 11 nodes, and \a partBg contains following cellIds [3,7,6].
389    * Thus \a this currently contains 11 tuples. If the restriction of mesh to 3 cells leads to a mesh with 6 nodes, then the returned field
390    * will contain 6 tuples and \a this field will lie on this restricted mesh. 
391    *
392    * \param [in] partBg - start (included) of input range of cell ids to select [ \a partBg, \a partEnd )
393    * \param [in] partEnd - end (not included) of input range of cell ids to select [ \a partBg, \a partEnd )
394    * \return a newly allocated field the caller should deal with.
395    * 
396    * \throw if there is presence of an invalid cell id in [ \a partBg, \a partEnd ) regarding the number of cells of \a this->getMesh().
397    *
398    * \if ENABLE_EXAMPLES
399    * \ref cpp_mcfielddouble_subpart1 "Here a C++ example."<br>
400    * \ref py_mcfielddouble_subpart1 "Here a Python example."
401    * \endif
402    * \sa MEDCoupling::MEDCouplingFieldDouble::buildSubPart(const DataArrayInt *) const, MEDCouplingFieldDouble::buildSubPartRange
403    */
404   template<class T>
405   typename Traits<T>::FieldType *MEDCouplingFieldT<T>::buildSubPart(const int *partBg, const int *partEnd) const
406   {
407     if(_type.isNull())
408       throw INTERP_KERNEL::Exception("MEDCouplingFieldT::buildSubPart : Expecting a not NULL spatial discretization !");
409     DataArrayInt *arrSelect;
410     MCAuto<MEDCouplingMesh> m=_type->buildSubMeshData(_mesh,partBg,partEnd,arrSelect);
411     MCAuto<DataArrayInt> arrSelect2(arrSelect);
412     MCAuto< typename Traits<T>::FieldType > ret(clone(false));//quick shallow copy.
413     const MEDCouplingFieldDiscretization *disc=getDiscretization();
414     if(disc)
415       ret->setDiscretization(MCAuto<MEDCouplingFieldDiscretization>(disc->clonePart(partBg,partEnd)));
416     ret->setMesh(m);
417     std::vector<typename Traits<T>::ArrayType *> arrays;
418     timeDiscrSafe()->getArrays(arrays);
419     std::vector<typename Traits<T>::ArrayType *> arrs;
420     std::vector< MCAuto< typename Traits<T>::ArrayType > > arrsSafe;
421     const int *arrSelBg=arrSelect->begin();
422     const int *arrSelEnd=arrSelect->end();
423     for(typename std::vector<typename Traits<T>::ArrayType *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
424       {
425         typename Traits<T>::ArrayType *arr(0);
426         if(*iter)
427           arr=(*iter)->selectByTupleIdSafe(arrSelBg,arrSelEnd);
428         arrs.push_back(arr); arrsSafe.push_back(arr);
429       }
430     ret->timeDiscrSafe()->setArrays(arrs,0);
431     return ret.retn();
432   }
433
434   /*!
435    * Builds a newly created field, that the caller will have the responsability to deal with (decrRef()).
436    * This method makes the assumption that the field is correctly defined when this method is called, no check of this will be done.
437    * This method returns a restriction of \a this so that only tuples with ids specified in \a part will be contained in the returned field.
438    * Parameter \a part specifies **cell ids whatever the spatial discretization of this** (
439    * \ref MEDCoupling::ON_CELLS "ON_CELLS", 
440    * \ref MEDCoupling::ON_NODES "ON_NODES",
441    * \ref MEDCoupling::ON_GAUSS_PT "ON_GAUSS_PT", 
442    * \ref MEDCoupling::ON_GAUSS_NE "ON_GAUSS_NE",
443    * \ref MEDCoupling::ON_NODES_KR "ON_NODES_KR").
444    *
445    * For example, \a this is a field on cells lying on a mesh that have 10 cells, \a part contains following cell ids [3,7,6].
446    * Then the returned field will lie on mesh having 3 cells and the returned field will contain 3 tuples.<br>
447    * Tuple #0 of the result field will refer to the cell #0 of returned mesh. The cell #0 of returned mesh will be equal to the cell #3 of \a this->getMesh().<br>
448    * Tuple #1 of the result field will refer to the cell #1 of returned mesh. The cell #1 of returned mesh will be equal to the cell #7 of \a this->getMesh().<br>
449    * Tuple #2 of the result field will refer to the cell #2 of returned mesh. The cell #2 of returned mesh will be equal to the cell #6 of \a this->getMesh().
450    *
451    * Let, for example, \a this be a field on nodes lying on a mesh that have 10 cells and 11 nodes, and \a part contains following cellIds [3,7,6].
452    * Thus \a this currently contains 11 tuples. If the restriction of mesh to 3 cells leads to a mesh with 6 nodes, then the returned field
453    * will contain 6 tuples and \a this field will lie on this restricted mesh. 
454    *
455    *  \param [in] part - an array of cell ids to include to the result field.
456    *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The caller is to delete this field using decrRef() as it is no more needed.
457    *
458    *  \if ENABLE_EXAMPLES
459    *  \ref cpp_mcfielddouble_subpart1 "Here is a C++ example".<br>
460    *  \ref  py_mcfielddouble_subpart1 "Here is a Python example".
461    *  \endif
462    *  \sa MEDCouplingFieldDouble::buildSubPartRange
463    */
464   template<class T>
465   typename Traits<T>::FieldType *MEDCouplingFieldT<T>::buildSubPart(const DataArrayInt *part) const
466   {
467     if(part==0)
468       throw INTERP_KERNEL::Exception("MEDCouplingFieldT::buildSubPart : not empty array must be passed to this method !");
469     return buildSubPart(part->begin(),part->end());
470   }
471   
472   /*!
473    * This method is equivalent to MEDCouplingFieldDouble::buildSubPart, the only difference is that the input range of cell ids is
474    * given using a range given \a begin, \a end and \a step to optimize the part computation.
475    * 
476    * \sa MEDCouplingFieldDouble::buildSubPart
477    */
478   template<class T>
479   typename Traits<T>::FieldType *MEDCouplingFieldT<T>::buildSubPartRange(int begin, int end, int step) const
480   {
481     if(_type.isNull())
482       throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::buildSubPart : Expecting a not NULL spatial discretization !");
483     DataArrayInt *arrSelect;
484     int beginOut,endOut,stepOut;
485     MCAuto<MEDCouplingMesh> m(_type->buildSubMeshDataRange(_mesh,begin,end,step,beginOut,endOut,stepOut,arrSelect));
486     MCAuto<DataArrayInt> arrSelect2(arrSelect);
487     MCAuto< typename Traits<T>::FieldType > ret(clone(false));//quick shallow copy.
488     const MEDCouplingFieldDiscretization *disc=getDiscretization();
489     if(disc)
490       ret->setDiscretization(MCAuto<MEDCouplingFieldDiscretization>(disc->clonePartRange(begin,end,step)));
491     ret->setMesh(m);
492     std::vector<typename Traits<T>::ArrayType *> arrays;
493     timeDiscrSafe()->getArrays(arrays);
494     std::vector<typename Traits<T>::ArrayType *> arrs;
495     std::vector< MCAuto< typename Traits<T>::ArrayType > > arrsSafe;
496     for(typename std::vector<typename Traits<T>::ArrayType *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
497       {
498         typename Traits<T>::ArrayType *arr(0);
499         if(*iter)
500           {
501             if(arrSelect)
502               {
503                 const int *arrSelBg=arrSelect->begin();
504                 const int *arrSelEnd=arrSelect->end();
505                 arr=(*iter)->selectByTupleIdSafe(arrSelBg,arrSelEnd);
506               }
507             else
508               arr=(*iter)->selectByTupleIdSafeSlice(beginOut,endOut,stepOut);
509           }
510         arrs.push_back(arr); arrsSafe.push_back(arr);
511       }
512     ret->timeDiscrSafe()->setArrays(arrs,0);
513     return ret.retn();
514   }
515   
516   template<class T>
517   const MEDCouplingTimeDiscretizationTemplate<T> *MEDCouplingFieldT<T>::timeDiscrSafe() const
518   {
519     const MEDCouplingTimeDiscretizationTemplate<T> *ret(_time_discr);
520     if(!ret)
521       throw INTERP_KERNEL::Exception("const FieldT : Null type of time discr !");
522     return ret;
523   }
524   
525   template<class T>
526   MEDCouplingTimeDiscretizationTemplate<T> *MEDCouplingFieldT<T>::timeDiscrSafe()
527   {
528     MEDCouplingTimeDiscretizationTemplate<T> *ret(_time_discr);
529     if(!ret)
530       throw INTERP_KERNEL::Exception("const FieldT : Null type of time discr !");
531     return ret;
532   }
533
534   template<class T>
535   void MEDCouplingFieldT<T>::getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const
536   {
537     tinyInfo.clear();
538     timeDiscrSafe()->getTinySerializationStrInformation(tinyInfo);
539     tinyInfo.push_back(_name);
540     tinyInfo.push_back(_desc);
541     tinyInfo.push_back(getTimeUnit());
542   }
543
544   /*!
545    * This method retrieves some critical values to resize and prepare remote instance.
546    * The first two elements returned in tinyInfo correspond to the parameters to give in constructor.
547    * @param tinyInfo out parameter resized correctly after the call. The length of this vector is tiny.
548    */
549   template<class T>
550   void MEDCouplingFieldT<T>::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
551   {
552     if(_type.isNull())
553       throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform getTinySerializationIntInformation !");
554     tinyInfo.clear();
555     tinyInfo.push_back((int)_type->getEnum());
556     tinyInfo.push_back((int)timeDiscrSafe()->getEnum());
557     tinyInfo.push_back((int)_nature);
558     timeDiscrSafe()->getTinySerializationIntInformation(tinyInfo);
559     std::vector<int> tinyInfo2;
560     _type->getTinySerializationIntInformation(tinyInfo2);
561     tinyInfo.insert(tinyInfo.end(),tinyInfo2.begin(),tinyInfo2.end());
562     tinyInfo.push_back((int)tinyInfo2.size());
563   }
564
565   /*!
566    * This method retrieves some critical values to resize and prepare remote instance.
567    * @param tinyInfo out parameter resized correctly after the call. The length of this vector is tiny.
568    */
569   template<class T>
570   void MEDCouplingFieldT<T>::getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const
571   {
572     if(_type.isNull())
573       throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform getTinySerializationDbleInformation !");
574     tinyInfo.clear();
575     timeDiscrSafe()->getTinySerializationDbleInformation(tinyInfo);
576     std::vector<double> tinyInfo2;
577     _type->getTinySerializationDbleInformation(tinyInfo2);
578     tinyInfo.insert(tinyInfo.end(),tinyInfo2.begin(),tinyInfo2.end());
579     tinyInfo.push_back((int)tinyInfo2.size());//very bad, lack of time to improve it
580   }
581
582   /*!
583    * This method has to be called to the new instance filled by CORBA, MPI, File...
584    * @param tinyInfoI is the value retrieves from distant result of getTinySerializationIntInformation on source instance to be copied.
585    * @param dataInt out parameter. If not null the pointer is already owned by \a this after the call of this method. In this case no decrRef must be applied.
586    * @param arrays out parameter is a vector resized to the right size. The pointers in the vector is already owned by \a this after the call of this method.
587    *               No decrRef must be applied to every instances in returned vector.
588    * \sa checkForUnserialization
589    */
590   template<class T>
591   void MEDCouplingFieldT<T>::resizeForUnserialization(const std::vector<int>& tinyInfoI, DataArrayInt *&dataInt, std::vector<typename Traits<T>::ArrayType *>& arrays)
592   {
593     if(_type.isNull())
594       throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform resizeForUnserialization !");
595     dataInt=0;
596     std::vector<int> tinyInfoITmp(tinyInfoI);
597     int sz=tinyInfoITmp.back();
598     tinyInfoITmp.pop_back();
599     std::vector<int> tinyInfoITmp2(tinyInfoITmp.begin(),tinyInfoITmp.end()-sz);
600     std::vector<int> tinyInfoI2(tinyInfoITmp2.begin()+3,tinyInfoITmp2.end());
601     timeDiscrSafe()->resizeForUnserialization(tinyInfoI2,arrays);
602     std::vector<int> tinyInfoITmp3(tinyInfoITmp.end()-sz,tinyInfoITmp.end());
603     _type->resizeForUnserialization(tinyInfoITmp3,dataInt);
604   }
605
606   /*!
607    * This method is extremely close to resizeForUnserialization except that here the arrays in \a dataInt and in \a arrays are attached in \a this
608    * after having checked that size is correct. This method is used in python pickeling context to avoid copy of data.
609    * \sa resizeForUnserialization
610    */
611   template<class T>
612   void MEDCouplingFieldT<T>::checkForUnserialization(const std::vector<int>& tinyInfoI, const DataArrayInt *dataInt, const std::vector<typename Traits<T>::ArrayType *>& arrays)
613   {
614     if(_type.isNull())
615       throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform resizeForUnserialization !");
616     std::vector<int> tinyInfoITmp(tinyInfoI);
617     int sz=tinyInfoITmp.back();
618     tinyInfoITmp.pop_back();
619     std::vector<int> tinyInfoITmp2(tinyInfoITmp.begin(),tinyInfoITmp.end()-sz);
620     std::vector<int> tinyInfoI2(tinyInfoITmp2.begin()+3,tinyInfoITmp2.end());
621     timeDiscrSafe()->checkForUnserialization(tinyInfoI2,arrays);
622     std::vector<int> tinyInfoITmp3(tinyInfoITmp.end()-sz,tinyInfoITmp.end());
623     _type->checkForUnserialization(tinyInfoITmp3,dataInt);
624   }
625
626   template<class T>
627   void MEDCouplingFieldT<T>::finishUnserialization(const std::vector<int>& tinyInfoI, const std::vector<double>& tinyInfoD, const std::vector<std::string>& tinyInfoS)
628   {
629     if(_type.isNull())
630       throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform finishUnserialization !");
631     std::vector<int> tinyInfoI2(tinyInfoI.begin()+3,tinyInfoI.end());
632     //
633     std::vector<double> tmp(tinyInfoD);
634     int sz=(int)tinyInfoD.back();//very bad, lack of time to improve it
635     tmp.pop_back();
636     std::vector<double> tmp1(tmp.begin(),tmp.end()-sz);
637     std::vector<double> tmp2(tmp.end()-sz,tmp.end());
638     //
639     timeDiscrSafe()->finishUnserialization(tinyInfoI2,tmp1,tinyInfoS);
640     _nature=(NatureOfField)tinyInfoI[2];
641     _type->finishUnserialization(tmp2);
642     int nbOfElemS=(int)tinyInfoS.size();
643     _name=tinyInfoS[nbOfElemS-3];
644     _desc=tinyInfoS[nbOfElemS-2];
645     setTimeUnit(tinyInfoS[nbOfElemS-1]);
646   }
647
648   /*!
649    * Contrary to MEDCouplingPointSet class the returned arrays are \b not the responsabilities of the caller.
650    * The values returned must be consulted only in readonly mode.
651    */
652   template<class T>
653   void MEDCouplingFieldT<T>::serialize(DataArrayInt *&dataInt, std::vector<typename Traits<T>::ArrayType *>& arrays) const
654   {
655     if(_type.isNull())
656       throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform serialize !");
657     timeDiscrSafe()->getArrays(arrays);
658     _type->getSerializationIntArray(dataInt);
659   }
660 }
661
662 #endif