Salome HOME
Merge from V6_main 19/03/2013
[modules/med.git] / src / MEDCoupling / MEDCouplingFieldDouble.cxx
1 // Copyright (C) 2007-2012  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.
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 (CEA/DEN)
20
21 #include "MEDCouplingFieldDouble.hxx"
22 #include "MEDCouplingFieldTemplate.hxx"
23 #include "MEDCouplingUMesh.hxx"
24 #include "MEDCouplingTimeDiscretization.hxx"
25 #include "MEDCouplingFieldDiscretization.hxx"
26 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
27 #include "MEDCouplingNatureOfField.hxx"
28
29 #include "InterpKernelAutoPtr.hxx"
30
31 #include <sstream>
32 #include <limits>
33 #include <algorithm>
34 #include <functional>
35
36 using namespace ParaMEDMEM;
37
38 /*!
39  * Creates a new instance of MEDCouplingFieldDouble of given type. The caller is responsable for the returned field.
40  *
41  * \param [in] type type of spatial discretization of a created field (\ref ParaMEDMEM::ON_CELLS "ON_CELLS", \ref ParaMEDMEM::ON_NODES "ON_NODES", \ref ParaMEDMEM::ON_GAUSS_PT "ON_GAUSS_PT", \ref ParaMEDMEM::ON_GAUSS_NE "ON_GAUSS_NE", \ref ParaMEDMEM::ON_NODES_KR "ON_NODES_KR").
42  * \param [in] td type of time discretization of a created field (\ref ParaMEDMEM::NO_TIME "NO_TIME", \ref ParaMEDMEM::ONE_TIME "ONE_TIME", \ref ParaMEDMEM::LINEAR_TIME "LINEAR_TIME", \ref ParaMEDMEM::CONST_ON_TIME_INTERVAL "CONST_ON_TIME_INTERVAL").
43  
44  * \return a newly allocated field the caller should deal with.
45  */
46 MEDCouplingFieldDouble *MEDCouplingFieldDouble::New(TypeOfField type, TypeOfTimeDiscretization td)
47 {
48   return new MEDCouplingFieldDouble(type,td);
49 }
50
51 /*!
52  * Creates a new instance of MEDCouplingFieldDouble of given type. The caller is responsable for the returned field.
53  *
54  * \param [in] ft \ref MEDCouplingFieldTemplatesPage "field template" defining its spatial discretization and supporting mesh.
55  * \param [in] td type of time discretization of a created field (\ref ParaMEDMEM::NO_TIME "NO_TIME", \ref ParaMEDMEM::ONE_TIME "ONE_TIME", \ref ParaMEDMEM::LINEAR_TIME "LINEAR_TIME", \ref ParaMEDMEM::CONST_ON_TIME_INTERVAL "CONST_ON_TIME_INTERVAL")
56  
57  * \return a newly allocated field the caller should deal with.
58  */
59 MEDCouplingFieldDouble *MEDCouplingFieldDouble::New(const MEDCouplingFieldTemplate& ft, TypeOfTimeDiscretization td)
60 {
61   return new MEDCouplingFieldDouble(ft,td);
62 }
63
64 /*!
65  * Sets time \a unit of \a this field.
66  *
67  * \param [in] unit \a unit (string) in which time is measured.
68  */
69 void MEDCouplingFieldDouble::setTimeUnit(const char *unit)
70 {
71   _time_discr->setTimeUnit(unit);
72 }
73
74 /*!
75  * Returns a time unit of \a this field.
76  *
77  * \return a string describing units in which time is measured.
78  */
79 const char *MEDCouplingFieldDouble::getTimeUnit() const
80 {
81   return _time_discr->getTimeUnit();
82 }
83
84 /*!
85  * This method if possible the time information (time unit, time iteration, time unit and time value) with its support
86  * that is to say its mesh.
87  * 
88  * \throw  If \c this->_mesh is null an exception will be thrown. An exception will also be throw if the spatial discretization is
89  *         NO_TIME.
90  */
91 void MEDCouplingFieldDouble::synchronizeTimeWithSupport() throw(INTERP_KERNEL::Exception)
92 {
93   _time_discr->synchronizeTimeWith(_mesh);
94 }
95
96 /*!
97  * This method performs a copy of \a this **without any copy of the underlying mesh** ( see warning section of this method).
98  * The copy of arrays is deep if \b recDeepCpy equals to true, no copy of arrays is done if \b recDeepCpy equals to false.
99  *
100  * \c clone(false) is rather dedicated for advanced users that want to limit the amount of memory.
101  * 
102  * It allows the user to perform methods
103  * MEDCouplingFieldDouble::AddFields, MEDCouplingFieldDouble::MultiplyFields with \a this and the returned field.
104  * 
105  * \warning The \b underlying \b mesh of the returned field is \b always the same (same pointer) than \a this **whatever the value** of \a recDeepCpy parameter.
106  * If the user wants to duplicated deeply the underlying mesh he should call MEDCouplingFieldDouble::cloneWithMesh method or MEDCouplingFieldDouble::deepCpy instead.
107  *
108  * \param [in] recDeepCpy specifies if underlying arrays in \a this should be copied or only attached to the returned field.
109  * \return a newly allocated MEDCouplingFieldDouble instance that the caller should deal with.
110  * \sa ParaMEDMEM::MEDCouplingFieldDouble::cloneWithMesh(bool recDeepCpy) const
111  */
112 MEDCouplingFieldDouble *MEDCouplingFieldDouble::clone(bool recDeepCpy) const
113 {
114   return new MEDCouplingFieldDouble(*this,recDeepCpy);
115 }
116
117 /*!
118  * This method behaves exactly like MEDCouplingFieldDouble::clone method **except that here the underlying mesh is systematically **
119  * (whatever the value of the input parameter \a recDeepCpy) **deeply duplicated**.
120  *
121  * The result of \c cloneWithMesh(true) is exactly the same than calling \ref MEDCouplingFieldDouble::deepCpy "deepCpy".
122  * 
123  * So the resulting field of this call cannot be called with \a this with the following methods MEDCouplingFieldDouble::AddFields, MEDCouplingFieldDouble::MultiplyFields ...
124  * To avoid to deep copy the underlying mesh the user should call MEDCouplingFieldDouble::clone method instead.
125
126  * \param [in] recDeepCpy specifies if underlying arrays in \a this should be copied or only attached to the returned field.
127  * \return a newly allocated MEDCouplingFieldDouble instance that the caller should deal with.
128  * \sa ParaMEDMEM::MEDCouplingFieldDouble::clone(bool recDeepCpy) const
129  */
130 MEDCouplingFieldDouble *MEDCouplingFieldDouble::cloneWithMesh(bool recDeepCpy) const
131 {
132   MEDCouplingFieldDouble *ret=clone(recDeepCpy);
133   if(_mesh)
134     {
135       MEDCouplingMesh *mCpy=_mesh->deepCpy();
136       ret->setMesh(mCpy);
137       mCpy->decrRef();
138     }
139   return ret;
140 }
141
142 /*!
143  * This method performs a deepCpy of \a this (**mesh included**)!
144  * So the resulting field of this call cannot be called with \a this with following methods MEDCouplingFieldDouble::AddFields, MEDCouplingFieldDouble::MultiplyFields ...
145  * To avoid deep copying the underlying mesh the user should call MEDCouplingFieldDouble::clone method instead.
146  * This method is exactly equivalent to MEDCouplingFieldDouble::cloneWithMesh called with parameter true.
147  *
148  * \return a newly allocated MEDCouplingFieldDouble instance that the caller should deal with.
149  * \sa ParaMEDMEM::MEDCouplingFieldDouble::cloneWithMesh(bool recDeepCpy) const
150  */
151 MEDCouplingFieldDouble *MEDCouplingFieldDouble::deepCpy() const
152 {
153   return cloneWithMesh(true);
154 }
155
156 /*!
157  * TODOC
158  * 
159  * \param [in] td type of time discretization of a created field (\ref ParaMEDMEM::NO_TIME "NO_TIME", \ref ParaMEDMEM::ONE_TIME "ONE_TIME", \ref ParaMEDMEM::LINEAR_TIME "LINEAR_TIME", \ref ParaMEDMEM::CONST_ON_TIME_INTERVAL "CONST_ON_TIME_INTERVAL").
160  * \param [in] deepCopy specifies if underlying arrays in \a this should be copied or only attached to the returned field.
161  * \return a newly allocated MEDCouplingFieldDouble instance that the caller should deal with.
162  *
163  * \ref cpp_mcfielddouble_buildnewtimereprfromthis "Here a C++ example."
164  
165  * \ref py_mcfielddouble_buildnewtimereprfromthis "Here a Python example."
166  * \sa ParaMEDMEM::MEDCouplingFieldDouble::clone(bool recDeepCpy) const
167  */
168 MEDCouplingFieldDouble *MEDCouplingFieldDouble::buildNewTimeReprFromThis(TypeOfTimeDiscretization td, bool deepCopy) const
169 {
170   MEDCouplingTimeDiscretization *tdo=_time_discr->buildNewTimeReprFromThis(td,deepCopy);
171   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),tdo,_type->clone());
172   ret->setMesh(getMesh());
173   ret->setName(getName());
174   ret->setDescription(getDescription());
175   return ret;
176 }
177
178 /*!
179  * Copy tiny info (component names, name, description) but warning the underlying mesh is not renamed (for safety reason).
180  */
181 void MEDCouplingFieldDouble::copyTinyStringsFrom(const MEDCouplingField *other) throw(INTERP_KERNEL::Exception)
182 {
183   MEDCouplingField::copyTinyStringsFrom(other);
184   const MEDCouplingFieldDouble *otherC=dynamic_cast<const MEDCouplingFieldDouble *>(other);
185   if(otherC)
186     {
187       _time_discr->copyTinyStringsFrom(*otherC->_time_discr);
188     }
189 }
190
191 /*!
192  * Copy only times, order, iteration from other. The underlying mesh is not impacted by this method.
193  * Arrays are not impacted too.
194  */
195 void MEDCouplingFieldDouble::copyTinyAttrFrom(const MEDCouplingFieldDouble *other) throw(INTERP_KERNEL::Exception)
196 {
197   if(other)
198     {
199       _time_discr->copyTinyAttrFrom(*other->_time_discr);
200     }
201   
202 }
203
204 void MEDCouplingFieldDouble::copyAllTinyAttrFrom(const MEDCouplingFieldDouble *other) throw(INTERP_KERNEL::Exception)
205 {
206   copyTinyStringsFrom(other);
207   copyTinyAttrFrom(other);
208 }
209
210 std::string MEDCouplingFieldDouble::simpleRepr() const
211 {
212   std::ostringstream ret;
213   ret << "FieldDouble with name : \"" << getName() << "\"\n";
214   ret << "Description of field is : \"" << getDescription() << "\"\n";
215   ret << "FieldDouble space discretization is : " << _type->getStringRepr() << "\n";
216   ret << "FieldDouble time discretization is : " << _time_discr->getStringRepr() << "\n";
217   ret << "FieldDouble nature of field is : " << MEDCouplingNatureOfField::GetRepr(_nature) << "\n";
218   if(getArray())
219     {
220       int nbOfCompo=getArray()->getNumberOfComponents();
221       ret << "FieldDouble default array has " << nbOfCompo << " components and " << getArray()->getNumberOfTuples() << " tuples.\n";
222       ret << "FieldDouble default array has following info on components : ";
223       for(int i=0;i<nbOfCompo;i++)
224         ret << "\"" << getArray()->getInfoOnComponent(i) << "\" ";
225       ret << "\n";
226     }
227   if(_mesh)
228     ret << "Mesh support information :\n__________________________\n" << _mesh->simpleRepr();
229   else
230     ret << "Mesh support information : No mesh set !\n";
231   return ret.str();
232 }
233
234 std::string MEDCouplingFieldDouble::advancedRepr() const
235 {
236   std::ostringstream ret;
237   ret << "FieldDouble with name : \"" << getName() << "\"\n";
238   ret << "Description of field is : \"" << getDescription() << "\"\n";
239   ret << "FieldDouble space discretization is : " << _type->getStringRepr() << "\n";
240   ret << "FieldDouble time discretization is : " << _time_discr->getStringRepr() << "\n";
241   if(getArray())
242     ret << "FieldDouble default array has " << getArray()->getNumberOfComponents() << " components and " << getArray()->getNumberOfTuples() << " tuples.\n";
243   if(_mesh)
244     ret << "Mesh support information :\n__________________________\n" << _mesh->advancedRepr();
245   else
246     ret << "Mesh support information : No mesh set !\n";
247   std::vector<DataArrayDouble *> arrays;
248   _time_discr->getArrays(arrays);
249   int arrayId=0;
250   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++,arrayId++)
251     {
252       ret << "Array #" << arrayId << " :\n__________\n";
253       if(*iter)
254         (*iter)->reprWithoutNameStream(ret);
255       else
256         ret << "Array empty !";
257       ret << "\n";
258     }
259   return ret.str();
260 }
261
262 void MEDCouplingFieldDouble::writeVTK(const char *fileName) const throw(INTERP_KERNEL::Exception)
263 {
264   std::vector<const MEDCouplingFieldDouble *> fs(1,this);
265   MEDCouplingFieldDouble::WriteVTK(fileName,fs);
266 }
267
268 bool MEDCouplingFieldDouble::isEqualIfNotWhy(const MEDCouplingField *other, double meshPrec, double valsPrec, std::string& reason) const throw(INTERP_KERNEL::Exception)
269 {
270   if(!other)
271     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::isEqualIfNotWhy : other instance is NULL !");
272   const MEDCouplingFieldDouble *otherC=dynamic_cast<const MEDCouplingFieldDouble *>(other);
273   if(!otherC)
274     {
275       reason="field given in input is not castable in MEDCouplingFieldDouble !";
276       return false;
277     }
278   if(!MEDCouplingField::isEqualIfNotWhy(other,meshPrec,valsPrec,reason))
279     return false;
280   if(!_time_discr->isEqualIfNotWhy(otherC->_time_discr,valsPrec,reason))
281     {
282       reason.insert(0,"In FieldDouble time discretizations differ :");
283       return false;
284     }
285   return true;
286 }
287
288 bool MEDCouplingFieldDouble::isEqualWithoutConsideringStr(const MEDCouplingField *other, double meshPrec, double valsPrec) const
289 {
290   const MEDCouplingFieldDouble *otherC=dynamic_cast<const MEDCouplingFieldDouble *>(other);
291   if(!otherC)
292     return false;
293   if(!MEDCouplingField::isEqualWithoutConsideringStr(other,meshPrec,valsPrec))
294     return false;
295   if(!_time_discr->isEqualWithoutConsideringStr(otherC->_time_discr,valsPrec))
296     return false;
297   return true;
298 }
299
300 /*!
301  * This method states if \a this and 'other' are compatibles each other before performing any treatment.
302  * This method is good for methods like : mergeFields.
303  * This method is not very demanding compared to areStrictlyCompatible that is better for operation on fields.
304  */
305 bool MEDCouplingFieldDouble::areCompatibleForMerge(const MEDCouplingField *other) const
306 {
307   if(!MEDCouplingField::areCompatibleForMerge(other))
308     return false;
309   const MEDCouplingFieldDouble *otherC=dynamic_cast<const MEDCouplingFieldDouble *>(other);
310   if(!otherC)
311     return false;
312   if(!_time_discr->areCompatible(otherC->_time_discr))
313     return false;
314   return true;
315 }
316
317 /*!
318  * This method is more strict than MEDCouplingField::areCompatibleForMerge method.
319  * This method is used for operation on fields to operate a first check before attempting operation.
320  */
321 bool MEDCouplingFieldDouble::areStrictlyCompatible(const MEDCouplingField *other) const
322 {
323   std::string tmp;
324   if(!MEDCouplingField::areStrictlyCompatible(other))
325     return false;
326   const MEDCouplingFieldDouble *otherC=dynamic_cast<const MEDCouplingFieldDouble *>(other);
327   if(!otherC)
328     return false;
329   if(!_time_discr->areStrictlyCompatible(otherC->_time_discr,tmp))
330     return false;
331   return true;
332 }
333
334 /*!
335  * Method with same principle than MEDCouplingFieldDouble::areStrictlyCompatible method except that
336  * number of components between \a this and 'other' can be different here (for operator*).
337  */
338 bool MEDCouplingFieldDouble::areCompatibleForMul(const MEDCouplingField *other) const
339 {
340   if(!MEDCouplingField::areStrictlyCompatible(other))
341     return false;
342   const MEDCouplingFieldDouble *otherC=dynamic_cast<const MEDCouplingFieldDouble *>(other);
343   if(!otherC)
344     return false;
345   if(!_time_discr->areStrictlyCompatibleForMul(otherC->_time_discr))
346     return false;
347   return true;
348 }
349
350 /*!
351  * Method with same principle than MEDCouplingFieldDouble::areStrictlyCompatible method except that
352  * number of components between \a this and 'other' can be different here (for operator/).
353  */
354 bool MEDCouplingFieldDouble::areCompatibleForDiv(const MEDCouplingField *other) const
355 {
356   if(!MEDCouplingField::areStrictlyCompatible(other))
357     return false;
358   const MEDCouplingFieldDouble *otherC=dynamic_cast<const MEDCouplingFieldDouble *>(other);
359   if(!otherC)
360     return false;
361   if(!_time_discr->areStrictlyCompatibleForDiv(otherC->_time_discr))
362     return false;
363   return true;
364 }
365
366 /*!
367  * This method is invocated before any attempt of melding. This method is very close to areStrictlyCompatible,
368  * except that \a this and other can have different number of components.
369  */
370 bool MEDCouplingFieldDouble::areCompatibleForMeld(const MEDCouplingFieldDouble *other) const
371 {
372   if(!MEDCouplingField::areStrictlyCompatible(other))
373     return false;
374   if(!_time_discr->areCompatibleForMeld(other->_time_discr))
375     return false;
376   return true;
377 }
378
379 /*!
380  * This method performs a clone of mesh and a renumbering of underlying cells of it. The number of cells remains the same.
381  * The values of field are impacted in consequence to have the same geometrical field.
382  */
383 void MEDCouplingFieldDouble::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
384 {
385   renumberCellsWithoutMesh(old2NewBg,check);
386   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> m=_mesh->deepCpy();
387   m->renumberCells(old2NewBg,check);
388   setMesh(m);
389   updateTime();
390 }
391
392 /*!
393  * \b WARNING : use this method with lot of care !
394  * This method performs half job of MEDCouplingFieldDouble::renumberCells. That is to say no permutation of cells is done on underlying mesh.
395  * That is to say, the field content is changed by this method. The reason of this method is only for multi-field instances lying on the same mesh to
396  * avoid a systematic duplication and renumbering of _mesh attribute.
397  */
398 void MEDCouplingFieldDouble::renumberCellsWithoutMesh(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
399 {
400    if(!_mesh)
401     throw INTERP_KERNEL::Exception("Expecting a defined mesh to be able to operate a renumbering !");
402   //
403   _type->renumberCells(old2NewBg,check);
404   std::vector<DataArrayDouble *> arrays;
405   _time_discr->getArrays(arrays);
406   _type->renumberArraysForCell(_mesh,arrays,old2NewBg,check);
407   //
408   updateTime();
409 }
410
411 /*!
412  * This method performs a clone of mesh and a renumbering of underlying nodes of it. The number of nodes remains not compulsory the same as renumberCells method.
413  * The values of field are impacted in consequence to have the same geometrical field.
414  */
415 void MEDCouplingFieldDouble::renumberNodes(const int *old2NewBg) throw(INTERP_KERNEL::Exception)
416 {
417   const MEDCouplingPointSet *meshC=dynamic_cast<const MEDCouplingPointSet *>(_mesh);
418   if(!meshC)
419     throw INTERP_KERNEL::Exception("Invalid mesh to apply renumberNodes on it !");
420   int nbOfNodes=meshC->getNumberOfNodes();
421   MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> meshC2((MEDCouplingPointSet *)meshC->deepCpy());
422   int newNbOfNodes=*std::max_element(old2NewBg,old2NewBg+nbOfNodes)+1;
423   renumberNodesWithoutMesh(old2NewBg,newNbOfNodes);
424   meshC2->renumberNodes(old2NewBg,newNbOfNodes);
425   setMesh(meshC2);
426 }
427
428 /*!
429  * \b WARNING : use this method with lot of care !
430  * This method performs half job of MEDCouplingFieldDouble::renumberNodes. That is to say no permutation of cells is done on underlying mesh.
431  * That is to say, the field content is changed by this method.
432  */
433 void MEDCouplingFieldDouble::renumberNodesWithoutMesh(const int *old2NewBg, int newNbOfNodes, double eps) throw(INTERP_KERNEL::Exception)
434 {
435   std::vector<DataArrayDouble *> arrays;
436   _time_discr->getArrays(arrays);
437   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
438     if(*iter)
439       _type->renumberValuesOnNodes(eps,old2NewBg,newNbOfNodes,*iter);
440 }
441
442 /*!
443  * This method makes the assumption that the default array is set. If not an exception will be thrown.
444  * This method is usable only if the default array has exactly one component. If not an exception will be thrown too.
445  * This method returns all tuples ids that fit the range [vmin,vmax].
446  * The caller has the responsability of the returned DataArrayInt.
447  */
448 DataArrayInt *MEDCouplingFieldDouble::getIdsInRange(double vmin, double vmax) const throw(INTERP_KERNEL::Exception)
449 {
450   if(getArray()==0)
451     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getIdsInRange : no default array set !");
452   return getArray()->getIdsInRange(vmin,vmax);
453 }
454
455 /*!
456  * Builds a newly created field, that the caller will have the responsability to deal with (decrRef).
457  * This method makes the assumption that the field is correctly defined when this method is called, no check of this will be done.
458  * This method returns a restriction of \a this so that only tuples id specified in 'part' will be contained in returned field.
459  * Parameter 'part' specifies \b cell \b ids \b whatever \b the \b spatial \b discretization of \a this (ON_CELLS, ON_NODES, ON_GAUSS_PT, ON_GAUSS_NE)
460  *
461  * If \a this is a field on cell lying on a mesh that have 10 cells. If part contains following cellIds [3,7,6].
462  * In this case the returned field will lie on mesh having 3 cells and the returned field will contain 3 tuples.
463  * Tuple#0 of return field will refer to the cell#0 of returned mesh. The cell #0 of returned mesh will be equal to the cell#3 of 'this->getMesh()'
464  * Tuple#1 of return field will refer to the cell#1 of returned mesh. The cell #1 of returned mesh will be equal to the cell#7 of 'this->getMesh()'
465  * Tuple#2 of return field will refer to the cell#2 of returned mesh. The cell #2 of returned mesh will be equal to the cell#6 of 'this->getMesh()'
466  *
467  * If \a this is field on node lying on a mesh that have 10 cells and 11 nodes for example. If part contains following cellIds [3,7,6].
468  * \a this is currently contains 11 tuples. If the restriction of mesh to 3 cells leads to a mesh with 6 nodes, the returned field,
469  * will contain 6 tuples and this field will lie on this restricted mesh. 
470  */
471 MEDCouplingFieldDouble *MEDCouplingFieldDouble::buildSubPart(const DataArrayInt *part) const throw(INTERP_KERNEL::Exception)
472 {
473   if(part==0)
474     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::buildSubPart : not empty array must be passed to this method !");
475   const int *start=part->getConstPointer();
476   const int *end=start+part->getNbOfElems();
477   return buildSubPart(start,end);
478 }
479
480 /*!
481  * Builds a newly created field, that the caller will have the responsability to deal with.
482  * \n This method makes the assumption that the field \a this is correctly defined when this method is called (\c this->checkCoherency() returns without any exception thrown), **no check of this will be done**.
483  * \n This method returns a restriction of \a this so that only tuples id specified in [ \a partBg , \a partEnd ) will be contained in returned field. 
484  * \n Parameter [\a partBg, \a partEnd ) specifies \b cell \b ids \b whatever \b the \b spatial \b discretization of \a this
485  * (\ref ParaMEDMEM::ON_CELLS "ON_CELLS", \ref ParaMEDMEM::ON_NODES "ON_CELLS", \ref ParaMEDMEM::ON_GAUSS_PT "ON_GAUSS_PT", \ref ParaMEDMEM::ON_GAUSS_NE "ON_GAUSS_NE")
486  *
487  * If \a this is a field on cell lying on a mesh that have 10 cells. If part contains following cellIds [3,7,6].
488  * In this case the returned field will lie on mesh having 3 cells and the returned field will contain 3 tuples.
489  *
490  *- Tuple#0 of return field will refer to the cell#0 of returned mesh. The cell #0 of returned mesh will be equal to the cell#3 of \c this->getMesh()
491  *- Tuple#1 of return field will refer to the cell#1 of returned mesh. The cell #1 of returned mesh will be equal to the cell#7 of \c this->getMesh()
492  *- Tuple#2 of return field will refer to the cell#2 of returned mesh. The cell #2 of returned mesh will be equal to the cell#6 of \c this->getMesh()
493  *
494  * If \a this is field on node lying on a mesh that have 10 cells and 11 nodes for example. So \a this is currently contains 11 tuples.
495  * \n If part contains following cellIds [3,7,6].
496  * \n If the restriction of mesh to 3 cells leads to a mesh with 6 nodes, the returned field,
497  * will contain 6 tuples (and same number of components \c this->getArray()->getNumberOfComponents() ) and this field will lie on this restricted mesh.
498  *
499  * \param [in] partBg start (included) of input range cell ids to select [ \a partBg, \a partEnd )
500  * \param [in] partEnd end (not included) of input range cell ids to select [ \a partBg, \a partEnd )
501  * \return a newly allocated field the caller should deal with.
502  * 
503  * \throw if there is presence of an invalid cell id in [ \a partBg, \a partEnd ) regarding the number of cells of \c this->getMesh()
504  *
505  * \ref cpp_mcfielddouble_subpart1 "Here a C++ example."
506  *
507  * \ref py_mcfielddouble_subpart1 "Here a Python example."
508  * \sa ParaMEDMEM::MEDCouplingFieldDouble::buildSubPart(const DataArrayInt *) const
509  */
510 MEDCouplingFieldDouble *MEDCouplingFieldDouble::buildSubPart(const int *partBg, const int *partEnd) const throw(INTERP_KERNEL::Exception)
511 {
512   DataArrayInt *arrSelect;
513   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> m=_type->buildSubMeshData(_mesh,partBg,partEnd,arrSelect);
514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrSelect2(arrSelect);
515   MEDCouplingFieldDouble *ret=clone(false);//quick shallow copy.
516   const MEDCouplingFieldDiscretization *disc=getDiscretization();
517   if(disc)
518     ret->setDiscretization(disc->clonePart(partBg,partEnd));
519   ret->setMesh(m);
520   std::vector<DataArrayDouble *> arrays;
521   _time_discr->getArrays(arrays);
522   std::vector<DataArrayDouble *> arrs;
523   const int *arrSelBg=arrSelect->begin();
524   const int *arrSelEnd=arrSelect->end();
525   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
526     {
527       DataArrayDouble *arr=0;
528       if(*iter)
529         arr=(*iter)->selectByTupleIdSafe(arrSelBg,arrSelEnd);
530       arrs.push_back(arr);
531     }
532   ret->_time_discr->setArrays(arrs,0);
533   for(std::vector<DataArrayDouble *>::const_iterator iter=arrs.begin();iter!=arrs.end();iter++)
534     if(*iter)
535       (*iter)->decrRef();
536   return ret;
537 }
538
539 TypeOfTimeDiscretization MEDCouplingFieldDouble::getTimeDiscretization() const
540 {
541   return _time_discr->getEnum();
542 }
543
544 MEDCouplingFieldDouble::MEDCouplingFieldDouble(TypeOfField type, TypeOfTimeDiscretization td):MEDCouplingField(type),
545                                                                                               _time_discr(MEDCouplingTimeDiscretization::New(td))
546 {
547 }
548
549 MEDCouplingFieldDouble::MEDCouplingFieldDouble(const MEDCouplingFieldTemplate& ft, TypeOfTimeDiscretization td):MEDCouplingField(ft),
550                                                                                                                 _time_discr(MEDCouplingTimeDiscretization::New(td))
551 {
552 }
553
554 MEDCouplingFieldDouble::MEDCouplingFieldDouble(const MEDCouplingFieldDouble& other, bool deepCopy):MEDCouplingField(other,deepCopy),
555                                                                                                    _time_discr(other._time_discr->performCpy(deepCopy))
556 {
557 }
558
559 MEDCouplingFieldDouble::MEDCouplingFieldDouble(NatureOfField n, MEDCouplingTimeDiscretization *td, MEDCouplingFieldDiscretization *type):MEDCouplingField(type,n),_time_discr(td)
560 {
561 }
562
563 MEDCouplingFieldDouble::~MEDCouplingFieldDouble()
564 {
565   delete _time_discr;
566 }
567
568 void MEDCouplingFieldDouble::checkCoherency() const throw(INTERP_KERNEL::Exception)
569 {
570   if(!_mesh)
571     throw INTERP_KERNEL::Exception("Field invalid because no mesh specified !");
572   _time_discr->checkCoherency();
573   _type->checkCoherencyBetween(_mesh,getArray());
574 }
575
576 /*!
577  * Returns the accumulation (the sum) of comId_th component of each tuples of \b default and \b only \b default array.
578  */
579 double MEDCouplingFieldDouble::accumulate(int compId) const
580 {
581   if(getArray()==0)
582     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::accumulate : no default array defined !");
583   return getArray()->accumulate(compId);
584 }
585
586 /*!
587  * Returns the accumulation (the sum) of all tuples of \b default and \b only default array.
588  * The res is expected to be of size getNumberOfComponents().
589  */
590 void MEDCouplingFieldDouble::accumulate(double *res) const
591 {
592   if(getArray()==0)
593     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::accumulate : no default array defined !");
594   getArray()->accumulate(res);
595 }
596
597 /*!
598  * This method returns the max value in \a this. \a this is expected to be a field with exactly \b one component. If not an exception will be thrown.
599  * To getMaxValue on vector field applyFunc is needed before. This method looks only on all arrays stored in 'this->_time_discr'.
600  * If no arrays exists, an exception will be thrown.
601  */
602 double MEDCouplingFieldDouble::getMaxValue() const throw(INTERP_KERNEL::Exception)
603 {
604   std::vector<DataArrayDouble *> arrays;
605   _time_discr->getArrays(arrays);
606   double ret=-std::numeric_limits<double>::max();
607   bool isExistingArr=false;
608   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
609     {
610       if(*iter)
611         {
612           isExistingArr=true;
613           int loc;
614           ret=std::max(ret,(*iter)->getMaxValue(loc));
615         }
616     }
617   if(!isExistingArr)
618     throw INTERP_KERNEL::Exception("getMaxValue : No arrays defined !");
619   return ret;
620 }
621
622 /*!
623  * This method is an extension of ParaMEDMEM::MEDCouplingFieldDouble::getMaxValue method because the returned 
624  * value is the same but this method also returns to you a tupleIds object which the caller have the responsibility
625  * to deal with. The main difference is that the returned tupleIds is those corresponding the first set array.
626  * If you have more than one array set (in LINEAR_TIME instance for example) only the first not null array will be used
627  * to compute tupleIds.
628  */
629 double MEDCouplingFieldDouble::getMaxValue2(DataArrayInt*& tupleIds) const throw(INTERP_KERNEL::Exception)
630 {
631   std::vector<DataArrayDouble *> arrays;
632   _time_discr->getArrays(arrays);
633   double ret=-std::numeric_limits<double>::max();
634   bool isExistingArr=false;
635   tupleIds=0;
636   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
637     {
638       if(*iter)
639         {
640           isExistingArr=true;
641           DataArrayInt *tmp;
642           ret=std::max(ret,(*iter)->getMaxValue2(tmp));
643           if(!tupleIds)
644             tupleIds=tmp;
645           else
646             tmp->decrRef();
647         }
648     }
649   if(!isExistingArr)
650     throw INTERP_KERNEL::Exception("getMaxValue2 : No arrays defined !");
651   return ret;
652 }
653
654 /*!
655  * This method returns the min value in \a this. \a this is expected to be a field with exactly \b one component. If not an exception will be thrown.
656  * To getMinValue on vector field applyFunc is needed before. This method looks only on all arrays stored in 'this->_time_discr'.
657  * If no arrays exists, an exception will be thrown.
658  */
659 double MEDCouplingFieldDouble::getMinValue() const throw(INTERP_KERNEL::Exception)
660 {
661   std::vector<DataArrayDouble *> arrays;
662   _time_discr->getArrays(arrays);
663   double ret=std::numeric_limits<double>::max();
664   bool isExistingArr=false;
665   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
666     {
667       if(*iter)
668         {
669           isExistingArr=true;
670           int loc;
671           ret=std::min(ret,(*iter)->getMinValue(loc));
672         }
673     }
674   if(!isExistingArr)
675     throw INTERP_KERNEL::Exception("getMinValue : No arrays defined !");
676   return ret;
677 }
678
679 /*!
680  * This method is an extension of ParaMEDMEM::MEDCouplingFieldDouble::getMinValue method because the returned 
681  * value is the same but this method also returns to you a tupleIds object which the caller have the responsibility
682  * to deal with. The main difference is that the returned tupleIds is those corresponding the first set array.
683  * If you have more than one array set (in LINEAR_TIME instance for example) only the first not null array will be used
684  * to compute tupleIds.
685  */
686 double MEDCouplingFieldDouble::getMinValue2(DataArrayInt*& tupleIds) const throw(INTERP_KERNEL::Exception)
687 {
688   std::vector<DataArrayDouble *> arrays;
689   _time_discr->getArrays(arrays);
690   double ret=-std::numeric_limits<double>::max();
691   bool isExistingArr=false;
692   tupleIds=0;
693   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
694     {
695       if(*iter)
696         {
697           isExistingArr=true;
698           DataArrayInt *tmp;
699           ret=std::max(ret,(*iter)->getMinValue2(tmp));
700           if(!tupleIds)
701             tupleIds=tmp;
702           else
703             tmp->decrRef();
704         }
705     }
706   if(!isExistingArr)
707     throw INTERP_KERNEL::Exception("getMinValue2 : No arrays defined !");
708   return ret;
709 }
710
711 /*!
712  * This method returns the average value in \a this. \a this is expected to be a field with exactly \b one component. If not an exception will be thrown.
713  * To getAverageValue on vector field applyFunc is needed before. This method looks only \b default array \b and \b only \b default.
714  * If default array does not exist, an exception will be thrown.
715  */
716 double MEDCouplingFieldDouble::getAverageValue() const throw(INTERP_KERNEL::Exception)
717 {
718   if(getArray()==0)
719     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getAverageValue : no default array defined !");
720   return getArray()->getAverageValue();
721 }
722
723 /*!
724  * This method returns the euclidean norm of \a this.
725  * \f[
726  * \sqrt{\sum_{0 \leq i < nbOfEntity}val[i]*val[i]}
727  * \f]
728  * If default array does not exist, an exception will be thrown.
729  */
730 double MEDCouplingFieldDouble::norm2() const throw(INTERP_KERNEL::Exception)
731 {
732   if(getArray()==0)
733     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::norm2 : no default array defined !");
734   return getArray()->norm2();
735 }
736
737 /*!
738  * This method returns the max norm of \a this.
739  * \f[
740  * \max_{0 \leq i < nbOfEntity}{abs(val[i])}
741  * \f]
742  * If default array does not exist, an exception will be thrown.
743  */
744 double MEDCouplingFieldDouble::normMax() const throw(INTERP_KERNEL::Exception)
745 {
746   if(getArray()==0)
747     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::normMax : no default array defined !");
748   return getArray()->normMax();
749 }
750
751 /*!
752  * This method returns the average value in \a this weighted by ParaMEDMEM::MEDCouplingField::buildMeasureField.
753  * \a this is expected to be a field with exactly \b one component. If not an exception will be thrown.
754  * To getAverageValue on vector field applyFunc is needed before. This method looks only \b default array \b and \b only \b default.
755  * If default array does not exist, an exception will be thrown.
756  * 
757  * \param [out] res the location where the result will be stored. \a res is expected to be a location with \c this->getNumberOfComponents() places available.
758  * \param [in] isWAbs specifies if abs is applied on measure on underlying mesh before performing computation. For a user already sure that all cells of its underlying mesh
759  *                    are all well oriented this parameter can be set to false to be 'faster'. By default this parameter is true.
760  */
761 void MEDCouplingFieldDouble::getWeightedAverageValue(double *res, bool isWAbs) const throw(INTERP_KERNEL::Exception)
762 {
763   if(getArray()==0)
764     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getWeightedAverageValue : no default array defined !");
765   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> w=buildMeasureField(isWAbs);
766   double deno=w->getArray()->accumulate(0);
767   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=getArray()->deepCpy();
768   arr->multiplyEqual(w->getArray());
769   std::transform(arr->begin(),arr->end(),arr->getPointer(),std::bind2nd(std::multiplies<double>(),1./deno));
770   arr->accumulate(res);
771 }
772
773 /*!
774  * This method returns the average value in \a this weighted by ParaMEDMEM::MEDCouplingField::buildMeasureField.
775  * \a this is expected to be a field with exactly \b one component. If not an exception will be thrown.
776  * To getAverageValue on vector field applyFunc is needed before. This method looks only \b default array \b and \b only \b default.
777  * If default array does not exist, an exception will be thrown.
778  * 
779  * \param [in] compId The component id that should be in [0, \c this->getNumberOfComponents() ). If not an INTERP_KERNEL::Exception will be thrown.
780  * \param [in] isWAbs specifies if abs is applied on measure on underlying mesh before performing computation. For a user already sure that all cells of its underlying mesh
781  *                    are all well oriented this parameter can be set to false to be 'faster'. By default this parameter is true in C++ not in python (overloading confusion).
782  */
783 double MEDCouplingFieldDouble::getWeightedAverageValue(int compId, bool isWAbs) const throw(INTERP_KERNEL::Exception)
784 {
785   int nbComps=getArray()->getNumberOfComponents();
786   if(compId<0 || compId>=nbComps)
787     {
788       std::ostringstream oss; oss << "MEDCouplingFieldDouble::getWeightedAverageValue : Invalid compId specified : No such nb of components ! Should be in [0," << nbComps << ") !";
789       throw INTERP_KERNEL::Exception(oss.str().c_str());
790     }
791   INTERP_KERNEL::AutoPtr<double> res=new double[nbComps];
792   getWeightedAverageValue(res,isWAbs);
793   return res[compId];
794 }
795
796 /*!
797  * Returns the normL1 of current field on compId component :
798  * \f[
799  * \frac{\sum_{0 \leq i < nbOfEntity}|val[i]*Vol[i]|}{\sum_{0 \leq i < nbOfEntity}|Vol[i]|}
800  * \f]
801  * If compId>=nbOfComponent an exception is thrown.
802  */
803 double MEDCouplingFieldDouble::normL1(int compId) const throw(INTERP_KERNEL::Exception)
804 {
805   if(!_mesh)
806     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform normL1");
807   int nbComps=getArray()->getNumberOfComponents();
808   if(compId<0 || compId>=nbComps)
809     {
810       std::ostringstream oss; oss << "MEDCouplingFieldDouble::normL1 : Invalid compId specified : No such nb of components ! Should be in [0," << nbComps << ") !";
811       throw INTERP_KERNEL::Exception(oss.str().c_str());
812     }
813   INTERP_KERNEL::AutoPtr<double> res=new double[nbComps];
814   _type->normL1(_mesh,getArray(),res);
815   return res[compId];
816 }
817
818 /*!
819  * Returns the normL1 of current field on each components :
820  * \f[
821  * \frac{\sum_{0 \leq i < nbOfEntity}|val[i]*Vol[i]|}{\sum_{0 \leq i < nbOfEntity}|Vol[i]|}
822  * \f]
823  * The res is expected to be of size getNumberOfComponents().
824  */
825 void MEDCouplingFieldDouble::normL1(double *res) const throw(INTERP_KERNEL::Exception)
826 {
827   if(!_mesh)
828     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform normL1");
829   _type->normL1(_mesh,getArray(),res);
830 }
831
832 /*!
833  * Returns the normL2 of current field on compId component :
834  * \f[
835  * \sqrt{\frac{\sum_{0 \leq i < nbOfEntity}|val[i]^{2}*Vol[i]|}{\sum_{0 \leq i < nbOfEntity}|Vol[i]|}}
836  * \f]
837  * If compId>=nbOfComponent an exception is thrown.
838  */
839 double MEDCouplingFieldDouble::normL2(int compId) const throw(INTERP_KERNEL::Exception)
840 {
841   if(!_mesh)
842     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform normL2");
843   int nbComps=getArray()->getNumberOfComponents();
844   if(compId<0 || compId>=nbComps)
845     {
846       std::ostringstream oss; oss << "MEDCouplingFieldDouble::normL2 : Invalid compId specified : No such nb of components ! Should be in [0," << nbComps << ") !";
847       throw INTERP_KERNEL::Exception(oss.str().c_str());
848     }
849   INTERP_KERNEL::AutoPtr<double> res=new double[nbComps];
850   _type->normL2(_mesh,getArray(),res);
851   return res[compId];
852 }
853
854 /*!
855  * Returns the normL2 of current field on each components :
856  * \f[
857  * \sqrt{\frac{\sum_{0 \leq i < nbOfEntity}|val[i]^{2}*Vol[i]|}{\sum_{0 \leq i < nbOfEntity}|Vol[i]|}}
858  * \f]
859  * The res is expected to be of size getNumberOfComponents().
860  */
861 void MEDCouplingFieldDouble::normL2(double *res) const throw(INTERP_KERNEL::Exception)
862 {
863   if(!_mesh)
864     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform normL2");
865   _type->normL2(_mesh,getArray(),res);
866 }
867
868 /*!
869  * Returns the accumulation (the sum) of comId_th component of each tuples weigthed by the field
870  * returns by getWeightingField relative of the _type of field of default array.
871  * This method is useful to check the conservativity of interpolation method.
872  */
873 double MEDCouplingFieldDouble::integral(int compId, bool isWAbs) const throw(INTERP_KERNEL::Exception)
874 {
875   if(!_mesh)
876     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform integral");
877   int nbComps=getArray()->getNumberOfComponents();
878   if(compId<0 || compId>=nbComps)
879     {
880       std::ostringstream oss; oss << "MEDCouplingFieldDouble::integral : Invalid compId specified : No such nb of components ! Should be in [0," << nbComps << ") !";
881       throw INTERP_KERNEL::Exception(oss.str().c_str());
882     }
883   INTERP_KERNEL::AutoPtr<double> res=new double[nbComps];
884   _type->integral(_mesh,getArray(),isWAbs,res);
885   return res[compId];
886 }
887
888 /*!
889  * Returns the accumulation (the sum) of each tuples weigthed by the field
890  * returns by getWeightingField relative of the _type of field of default array.
891  * This method is useful to check the conservativity of interpolation method.
892  */
893 void MEDCouplingFieldDouble::integral(bool isWAbs, double *res) const throw(INTERP_KERNEL::Exception)
894 {
895   if(!_mesh)
896     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform integral2");
897   _type->integral(_mesh,getArray(),isWAbs,res);
898 }
899
900 /*!
901  * This method is reserved for field lying on structured mesh spatial support. It returns the value of cell localized by (i,j,k)
902  * If spatial support is not structured mesh an exception will be thrown.
903  * @param res out array expected to be equal to size getNumberOfComponents()
904  */
905 void MEDCouplingFieldDouble::getValueOnPos(int i, int j, int k, double *res) const throw(INTERP_KERNEL::Exception)
906 {
907   const DataArrayDouble *arr=_time_discr->getArray();
908   if(!_mesh)
909     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform getValueOnPos");
910   _type->getValueOnPos(arr,_mesh,i,j,k,res);
911 }
912
913 /*!
914  * Returns value of \a this on default time of point 'spaceLoc' using spatial discretization.
915  * If 'point' is outside the spatial discretization of this an exception will be thrown.
916  */
917 void MEDCouplingFieldDouble::getValueOn(const double *spaceLoc, double *res) const throw(INTERP_KERNEL::Exception)
918 {
919   const DataArrayDouble *arr=_time_discr->getArray();
920   if(!_mesh)
921     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform getValueOn");
922   _type->getValueOn(arr,_mesh,spaceLoc,res);
923 }
924
925 /*!
926  * Returns a newly allocated array with 'nbOfPoints' tuples and nb of components equal to 'this->getNumberOfComponents()'.
927  */
928 DataArrayDouble *MEDCouplingFieldDouble::getValueOnMulti(const double *spaceLoc, int nbOfPoints) const throw(INTERP_KERNEL::Exception)
929 {
930   const DataArrayDouble *arr=_time_discr->getArray();
931   if(!_mesh)
932     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform getValueOnMulti");
933   return _type->getValueOnMulti(arr,_mesh,spaceLoc,nbOfPoints);
934 }
935
936 /*!
937  * Returns value of \a this on time 'time' of point 'spaceLoc' using spatial discretization.
938  * If 'time' is not covered by this->_time_discr an exception will be thrown.
939  * If 'point' is outside the spatial discretization of this an exception will be thrown.
940  */
941 void MEDCouplingFieldDouble::getValueOn(const double *spaceLoc, double time, double *res) const throw(INTERP_KERNEL::Exception)
942 {
943   std::vector< const DataArrayDouble *> arrs=_time_discr->getArraysForTime(time);
944   if(!_mesh)
945     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform getValueOn");
946   std::vector<double> res2;
947   for(std::vector< const DataArrayDouble *>::const_iterator iter=arrs.begin();iter!=arrs.end();iter++)
948     {
949       int sz=(int)res2.size();
950       res2.resize(sz+(*iter)->getNumberOfComponents());
951       _type->getValueOn(*iter,_mesh,spaceLoc,&res2[sz]);
952     }
953   _time_discr->getValueForTime(time,res2,res);
954 }
955
956 /*!
957  * Applies a*x+b on 'compoId'th component of each cell.
958  */
959 void MEDCouplingFieldDouble::applyLin(double a, double b, int compoId)
960 {
961   _time_discr->applyLin(a,b,compoId);
962 }
963
964 /*!
965  * This method sets \a this to a uniform scalar field with one component.
966  * All tuples will have the same value 'value'.
967  * An exception is thrown if no underlying mesh is defined.
968  */
969 MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator=(double value) throw(INTERP_KERNEL::Exception)
970 {
971   if(!_mesh)
972     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::operator= : no mesh defined !");
973   int nbOfTuple=_type->getNumberOfTuples(_mesh);
974   _time_discr->setUniformValue(nbOfTuple,1,value);
975   return *this;
976 }
977
978 /*!
979  * This method is very similar to this one MEDCouplingMesh::fillFromAnalytic.
980  * See MEDCouplingMesh::fillFromAnalytic method doc to have more details.
981  * The main difference is that the field as been started to be constructed here.
982  * An exception is thrown if no underlying mesh is set before the call of this method.
983  */
984 void MEDCouplingFieldDouble::fillFromAnalytic(int nbOfComp, FunctionToEvaluate func) throw(INTERP_KERNEL::Exception)
985 {
986   if(!_mesh)
987     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::fillFromAnalytic : no mesh defined !");
988   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=_type->getLocalizationOfDiscValues(_mesh);
989   _time_discr->fillFromAnalytic(loc,nbOfComp,func);
990 }
991
992 /*!
993  * This method is very similar to this one MEDCouplingMesh::fillFromAnalytic.
994  * See MEDCouplingMesh::fillFromAnalytic method doc to have more details.
995  * The main difference is that the field as been started to be constructed here.
996  * An exception is thrown if no underlying mesh is set before the call of this method.
997  */
998 void MEDCouplingFieldDouble::fillFromAnalytic(int nbOfComp, const char *func) throw(INTERP_KERNEL::Exception)
999 {
1000   if(!_mesh)
1001     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::fillFromAnalytic : no mesh defined !");
1002   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=_type->getLocalizationOfDiscValues(_mesh);
1003   _time_discr->fillFromAnalytic(loc,nbOfComp,func);
1004 }
1005
1006 /*!
1007  * This method is very similar to this one MEDCouplingMesh::fillFromAnalytic2.
1008  * See MEDCouplingMesh::fillFromAnalytic method doc to have more details.
1009  * The main difference is that the field as been started to be constructed here.
1010  * An exception is throw if no underlying mesh is set before the call of this method.
1011  */
1012 void MEDCouplingFieldDouble::fillFromAnalytic2(int nbOfComp, const char *func) throw(INTERP_KERNEL::Exception)
1013 {
1014   if(!_mesh)
1015     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::fillFromAnalytic2 : no mesh defined !");
1016   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=_type->getLocalizationOfDiscValues(_mesh);
1017   _time_discr->fillFromAnalytic2(loc,nbOfComp,func);
1018 }
1019
1020 /*!
1021  * This method is very similar to this one MEDCouplingMesh::fillFromAnalytic3.
1022  * See MEDCouplingMesh::fillFromAnalytic method doc to have more details.
1023  * The main difference is that the field as been started to be constructed here.
1024  * An exception is thrown if no underlying mesh is set before the call of this method.
1025  */
1026 void MEDCouplingFieldDouble::fillFromAnalytic3(int nbOfComp, const std::vector<std::string>& varsOrder, const char *func) throw(INTERP_KERNEL::Exception)
1027 {
1028   if(!_mesh)
1029     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::fillFromAnalytic2 : no mesh defined !");
1030   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=_type->getLocalizationOfDiscValues(_mesh);
1031   _time_discr->fillFromAnalytic3(loc,nbOfComp,varsOrder,func);
1032 }
1033
1034 /*!
1035  * Applyies the function specified by pointer 'func' on each tuples on all arrays contained in _time_discr.
1036  * If '*func' returns false during one evaluation an exception will be thrown.
1037  */
1038 void MEDCouplingFieldDouble::applyFunc(int nbOfComp, FunctionToEvaluate func)
1039 {
1040   _time_discr->applyFunc(nbOfComp,func);
1041 }
1042
1043 /*!
1044  * This method is a specialization of other overloaded methods. When 'nbOfComp' equals 1 this method is equivalent to
1045  * ParaMEDMEM::MEDCouplingFieldDouble::operator=.
1046  */
1047 void MEDCouplingFieldDouble::applyFunc(int nbOfComp, double val)
1048 {
1049   if(!_mesh)
1050     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::applyFunc : no mesh defined !");
1051   int nbOfTuple=_type->getNumberOfTuples(_mesh);
1052   _time_discr->setUniformValue(nbOfTuple,nbOfComp,val);
1053 }
1054
1055 /*!
1056  * Applyies the function specified by the string repr 'func' on each tuples on all arrays contained in _time_discr.
1057  * If '*func' fails in evaluation during one evaluation an exception will be thrown.
1058  * The field will contain 'nbOfComp' components after the call.
1059  */
1060 void MEDCouplingFieldDouble::applyFunc(int nbOfComp, const char *func) throw(INTERP_KERNEL::Exception)
1061 {
1062   _time_discr->applyFunc(nbOfComp,func);
1063 }
1064
1065 /*!
1066  * This method is equivalent to MEDCouplingFieldDouble::applyFunc, except that here components info are used to determine variables position in 'func'.
1067  * If there is vars detected in 'func' that is not in an info on components an exception will be thrown.
1068  */
1069 void MEDCouplingFieldDouble::applyFunc2(int nbOfComp, const char *func) throw(INTERP_KERNEL::Exception)
1070 {
1071   _time_discr->applyFunc2(nbOfComp,func);
1072 }
1073
1074 /*!
1075  * This method is equivalent to MEDCouplingFieldDouble::applyFunc, except that here 'varsOrder' is used to determine variables position in 'func'.
1076  * If there is vars detected in 'func' that is not in 'varsOrder' an exception will be thrown.
1077  */
1078 void MEDCouplingFieldDouble::applyFunc3(int nbOfComp, const std::vector<std::string>& varsOrder, const char *func) throw(INTERP_KERNEL::Exception)
1079 {
1080   _time_discr->applyFunc3(nbOfComp,varsOrder,func);
1081 }
1082
1083 /*!
1084  * Applyies the function specified by the string repr 'func' on each tuples on all arrays contained in _time_discr.
1085  * If '*func' fails in evaluation during one evaluation an exception will be thrown.
1086  * The field will contain exactly the same number of components after the call.
1087  */
1088 void MEDCouplingFieldDouble::applyFunc(const char *func) throw(INTERP_KERNEL::Exception)
1089 {
1090   _time_discr->applyFunc(func);
1091 }
1092
1093 /*!
1094  * Applyies the function specified by the string repr 'func' on each tuples on all arrays contained in _time_discr.
1095  * The field will contain exactly the same number of components after the call.
1096  * Use is not warranted for the moment !
1097  */
1098 void MEDCouplingFieldDouble::applyFuncFast32(const char *func) throw(INTERP_KERNEL::Exception)
1099 {
1100   _time_discr->applyFuncFast32(func);
1101 }
1102
1103 /*!
1104  * Applyies the function specified by the string repr 'func' on each tuples on all arrays contained in _time_discr.
1105  * The field will contain exactly the same number of components after the call.
1106  * Use is not warranted for the moment !
1107  */
1108 void MEDCouplingFieldDouble::applyFuncFast64(const char *func) throw(INTERP_KERNEL::Exception)
1109 {
1110   _time_discr->applyFuncFast64(func);
1111 }
1112
1113 /*!
1114  * This method makes the assumption that the default array has been set before.
1115  * If not an exception will be sent.
1116  * If default array set, the number of components will be sent.
1117  */
1118 int MEDCouplingFieldDouble::getNumberOfComponents() const throw(INTERP_KERNEL::Exception)
1119 {
1120   if(getArray()==0)
1121     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getNumberOfComponents : No array specified !");
1122   return getArray()->getNumberOfComponents();
1123 }
1124
1125 /*!
1126  * This method makes the assumption that _mesh has be set before the call of this method and description of gauss
1127  * localizations in case of Gauss field. If not an exception will sent.
1128  * \b Contrary to MEDCouplingFieldDouble::getNumberOfComponents and MEDCouplingFieldDouble::getNumberOfValues is
1129  * \b not aware of the presence of the default array.
1130  * \b WARNING \b no coherency check is done here. MEDCouplingFieldDouble::checkCoherency method should be called to check that !
1131  */
1132 int MEDCouplingFieldDouble::getNumberOfTuples() const throw(INTERP_KERNEL::Exception)
1133 {
1134   if(!_mesh)
1135     throw INTERP_KERNEL::Exception("Impossible to retrieve number of tuples because no mesh specified !");
1136   return _type->getNumberOfTuples(_mesh);
1137 }
1138
1139 /*!
1140  * This method makes the assumption that the default array has been set before.
1141  * If not an exception will be sent.
1142  * If default array set, the number of values present in the default array will be sent.
1143  */
1144 int MEDCouplingFieldDouble::getNumberOfValues() const throw(INTERP_KERNEL::Exception)
1145 {
1146   if(getArray()==0)
1147     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getNumberOfValues : No array specified !");
1148   return getArray()->getNbOfElems();
1149 }
1150
1151 void MEDCouplingFieldDouble::updateTime() const
1152 {
1153   MEDCouplingField::updateTime();
1154   updateTimeWith(*_time_discr);
1155 }
1156
1157 std::size_t MEDCouplingFieldDouble::getHeapMemorySize() const
1158 {
1159   std::size_t ret=0;
1160   if(_time_discr)
1161     ret+=_time_discr->getHeapMemorySize();
1162   return MEDCouplingField::getHeapMemorySize()+ret;
1163 }
1164
1165 void MEDCouplingFieldDouble::setNature(NatureOfField nat) throw(INTERP_KERNEL::Exception)
1166 {
1167   MEDCouplingField::setNature(nat);
1168   _type->checkCompatibilityWithNature(nat);
1169 }
1170
1171 /*!
1172  * This method synchronizes time information (time, iteration, order, time unit) regarding the information in \c this->_mesh.
1173  * \throw If no mesh is set in this. Or if \a this is not compatible with time setting (typically NO_TIME)
1174  */
1175 void MEDCouplingFieldDouble::synchronizeTimeWithMesh() throw(INTERP_KERNEL::Exception)
1176 {
1177   if(!_mesh)
1178     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::synchronizeTimeWithMesh : no mesh set in this !");
1179   int it=-1,ordr=-1;
1180   double val=_mesh->getTime(it,ordr);
1181   std::string timeUnit(_mesh->getTimeUnit());
1182   setTime(val,it,ordr);
1183   setTimeUnit(timeUnit.c_str());
1184 }
1185
1186 double MEDCouplingFieldDouble::getIJK(int cellId, int nodeIdInCell, int compoId) const
1187 {
1188   return _type->getIJK(_mesh,getArray(),cellId,nodeIdInCell,compoId);
1189 }
1190
1191 void MEDCouplingFieldDouble::setArray(DataArrayDouble *array)
1192 {
1193   _time_discr->setArray(array,this);
1194 }
1195
1196 void MEDCouplingFieldDouble::setEndArray(DataArrayDouble *array)
1197 {
1198   _time_discr->setEndArray(array,this);
1199 }
1200
1201 void MEDCouplingFieldDouble::setArrays(const std::vector<DataArrayDouble *>& arrs) throw(INTERP_KERNEL::Exception)
1202 {
1203   _time_discr->setArrays(arrs,this);
1204 }
1205
1206 void MEDCouplingFieldDouble::getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const
1207 {
1208   tinyInfo.clear();
1209   _time_discr->getTinySerializationStrInformation(tinyInfo);
1210   tinyInfo.push_back(_name);
1211   tinyInfo.push_back(_desc);
1212   tinyInfo.push_back(getTimeUnit());
1213 }
1214
1215 /*!
1216  * This method retrieves some critical values to resize and prepare remote instance.
1217  * The first two elements returned in tinyInfo correspond to the parameters to give in constructor.
1218  * @param tinyInfo out parameter resized correctly after the call. The length of this vector is tiny.
1219  */
1220 void MEDCouplingFieldDouble::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
1221 {
1222   tinyInfo.clear();
1223   tinyInfo.push_back((int)_type->getEnum());
1224   tinyInfo.push_back((int)_time_discr->getEnum());
1225   tinyInfo.push_back((int)_nature);
1226   _time_discr->getTinySerializationIntInformation(tinyInfo);
1227   std::vector<int> tinyInfo2;
1228   _type->getTinySerializationIntInformation(tinyInfo2);
1229   tinyInfo.insert(tinyInfo.end(),tinyInfo2.begin(),tinyInfo2.end());
1230   tinyInfo.push_back((int)tinyInfo2.size());
1231 }
1232
1233 /*!
1234  * This method retrieves some critical values to resize and prepare remote instance.
1235  * @param tinyInfo out parameter resized correctly after the call. The length of this vector is tiny.
1236  */
1237 void MEDCouplingFieldDouble::getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const
1238 {
1239   tinyInfo.clear();
1240   _time_discr->getTinySerializationDbleInformation(tinyInfo);
1241   std::vector<double> tinyInfo2;
1242   _type->getTinySerializationDbleInformation(tinyInfo2);
1243   tinyInfo.insert(tinyInfo.end(),tinyInfo2.begin(),tinyInfo2.end());
1244   tinyInfo.push_back((int)tinyInfo2.size());//very bad, lack of time to improve it
1245 }
1246
1247 /*!
1248  * This method has to be called to the new instance filled by CORBA, MPI, File...
1249  * @param tinyInfoI is the value retrieves from distant result of getTinySerializationIntInformation on source instance to be copied.
1250  * @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.
1251  * @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.
1252  *               No decrRef must be applied to every instances in returned vector.
1253  */
1254 void MEDCouplingFieldDouble::resizeForUnserialization(const std::vector<int>& tinyInfoI, DataArrayInt *&dataInt, std::vector<DataArrayDouble *>& arrays)
1255 {
1256   dataInt=0;
1257   std::vector<int> tinyInfoITmp(tinyInfoI);
1258   int sz=tinyInfoITmp.back();
1259   tinyInfoITmp.pop_back();
1260   std::vector<int> tinyInfoITmp2(tinyInfoITmp.begin(),tinyInfoITmp.end()-sz);
1261   std::vector<int> tinyInfoI2(tinyInfoITmp2.begin()+3,tinyInfoITmp2.end());
1262   _time_discr->resizeForUnserialization(tinyInfoI2,arrays);
1263   std::vector<int> tinyInfoITmp3(tinyInfoITmp.end()-sz,tinyInfoITmp.end());
1264   _type->resizeForUnserialization(tinyInfoITmp3,dataInt);
1265 }
1266
1267 void MEDCouplingFieldDouble::finishUnserialization(const std::vector<int>& tinyInfoI, const std::vector<double>& tinyInfoD, const std::vector<std::string>& tinyInfoS)
1268 {
1269   std::vector<int> tinyInfoI2(tinyInfoI.begin()+3,tinyInfoI.end());
1270   //
1271   std::vector<double> tmp(tinyInfoD);
1272   int sz=(int)tinyInfoD.back();//very bad, lack of time to improve it
1273   tmp.pop_back();
1274   std::vector<double> tmp1(tmp.begin(),tmp.end()-sz);
1275   std::vector<double> tmp2(tmp.end()-sz,tmp.end());
1276   //
1277   _time_discr->finishUnserialization(tinyInfoI2,tmp1,tinyInfoS);
1278   _nature=(NatureOfField)tinyInfoI[2];
1279   _type->finishUnserialization(tmp2);
1280   int nbOfElemS=(int)tinyInfoS.size();
1281   _name=tinyInfoS[nbOfElemS-3];
1282   _desc=tinyInfoS[nbOfElemS-2];
1283   setTimeUnit(tinyInfoS[nbOfElemS-1].c_str());
1284 }
1285
1286 /*!
1287  * Contrary to MEDCouplingPointSet class the returned arrays are \b not the responsabilities of the caller.
1288  * The values returned must be consulted only in readonly mode.
1289  */
1290 void MEDCouplingFieldDouble::serialize(DataArrayInt *&dataInt, std::vector<DataArrayDouble *>& arrays) const
1291 {
1292   _time_discr->getArrays(arrays);
1293   _type->getSerializationIntArray(dataInt);
1294 }
1295
1296 /*!
1297  * This method tries to to change the mesh support of \a this following the parameter 'levOfCheck' and 'prec'.
1298  * Semantic of 'levOfCheck' is explained in MEDCouplingMesh::checkGeoEquivalWith method. This method is used to perform the job.
1299  * If this->_mesh is not defined or other an exeption will be throw.
1300  */
1301 void MEDCouplingFieldDouble::changeUnderlyingMesh(const MEDCouplingMesh *other, int levOfCheck, double prec) throw(INTERP_KERNEL::Exception)
1302 {
1303   if(_mesh==0 || other==0)
1304     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::changeUnderlyingMesh : is expected to operate on not null meshes !");
1305   DataArrayInt *cellCor=0,*nodeCor=0;
1306   other->checkGeoEquivalWith(_mesh,levOfCheck,prec,cellCor,nodeCor);
1307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2(cellCor),nodeCor2(nodeCor);
1308   if(cellCor)
1309     renumberCellsWithoutMesh(cellCor->getConstPointer(),false);
1310   if(nodeCor)
1311     renumberNodesWithoutMesh(nodeCor->getConstPointer(),_mesh->getNumberOfNodes());
1312   setMesh(const_cast<MEDCouplingMesh *>(other));
1313 }
1314
1315 /*!
1316  * This method is an extension of MEDCouplingFieldDouble::operator-=. It allows a user to operate a difference of 2 fields (\a this and 'f') even if they do not share same meshes.
1317  * No interpolation will be done here only an analyze of two underlying mesh will be done to see if the meshes are geometrically equivalent. If yes, the eventual renumbering will be done and operator-= applyed after.
1318  * This method requires that 'f' and \a this are coherent (check coherency) and that 'f' and \a this would be coherent for a merge.
1319  * Semantic of 'levOfCheck' is explained in MEDCouplingMesh::checkGeoEquivalWith method.
1320  */
1321 void MEDCouplingFieldDouble::substractInPlaceDM(const MEDCouplingFieldDouble *f, int levOfCheck, double prec) throw(INTERP_KERNEL::Exception)
1322 {
1323   checkCoherency();
1324   f->checkCoherency();
1325   if(!areCompatibleForMerge(f))
1326     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::diffWith : Fields are not compatible ; unable to apply mergeFields on them !");
1327   changeUnderlyingMesh(f->getMesh(),levOfCheck,prec);
1328   operator-=(*f);
1329 }
1330
1331 /*!
1332  * Merge nodes of underlying mesh. In case of some node will be merged the underlying mesh instance will change.
1333  * The first 'eps' stands for geometric approximation. The second 'epsOnVals' is for epsilon on values in case of node merging.
1334  * If 2 nodes distant from less than 'eps' and with value different with more than 'epsOnVals' an exception will be thrown.
1335  */
1336 bool MEDCouplingFieldDouble::mergeNodes(double eps, double epsOnVals) throw(INTERP_KERNEL::Exception)
1337 {
1338   const MEDCouplingPointSet *meshC=dynamic_cast<const MEDCouplingPointSet *>(_mesh);
1339   if(!meshC)
1340     throw INTERP_KERNEL::Exception("Invalid support mesh to apply mergeNodes on it : must be a MEDCouplingPointSet one !");
1341   MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> meshC2((MEDCouplingPointSet *)meshC->deepCpy());
1342   bool ret;
1343   int ret2;
1344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=meshC2->mergeNodes(eps,ret,ret2);
1345   if(!ret)//no nodes have been merged.
1346     return ret;
1347   std::vector<DataArrayDouble *> arrays;
1348   _time_discr->getArrays(arrays);
1349   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
1350     if(*iter)
1351       _type->renumberValuesOnNodes(epsOnVals,arr->getConstPointer(),meshC2->getNumberOfNodes(),*iter);
1352   setMesh(meshC2);
1353   return true;
1354 }
1355
1356 /*!
1357  * Merge nodes with (barycenter computation) of underlying mesh. In case of some node will be merged the underlying mesh instance will change.
1358  * The first 'eps' stands for geometric approximation. The second 'epsOnVals' is for epsilon on values in case of node merging.
1359  * If 2 nodes distant from less than 'eps' and with value different with more than 'epsOnVals' an exception will be thrown.
1360  */
1361 bool MEDCouplingFieldDouble::mergeNodes2(double eps, double epsOnVals) throw(INTERP_KERNEL::Exception)
1362 {
1363   const MEDCouplingPointSet *meshC=dynamic_cast<const MEDCouplingPointSet *>(_mesh);
1364   if(!meshC)
1365     throw INTERP_KERNEL::Exception("Invalid support mesh to apply mergeNodes on it : must be a MEDCouplingPointSet one !");
1366   MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> meshC2((MEDCouplingPointSet *)meshC->deepCpy());
1367   bool ret;
1368   int ret2;
1369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=meshC2->mergeNodes2(eps,ret,ret2);
1370   if(!ret)//no nodes have been merged.
1371     return ret;
1372   std::vector<DataArrayDouble *> arrays;
1373   _time_discr->getArrays(arrays);
1374   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
1375     if(*iter)
1376       _type->renumberValuesOnNodes(epsOnVals,arr->getConstPointer(),meshC2->getNumberOfNodes(),*iter);
1377   setMesh(meshC2);
1378   return true;
1379 }
1380
1381 /*!
1382  * This method applyies ParaMEDMEM::MEDCouplingPointSet::zipCoords method on 'this->_mesh' that should be set and of type ParaMEDMEM::MEDCouplingPointSet.
1383  * If some nodes have disappeared true is returned.
1384  * 'epsOnVals' stands for epsilon in case of merge of cells. This value is used as tolerance in case the corresponding values differ.
1385  */
1386 bool MEDCouplingFieldDouble::zipCoords(double epsOnVals) throw(INTERP_KERNEL::Exception)
1387 {
1388   const MEDCouplingPointSet *meshC=dynamic_cast<const MEDCouplingPointSet *>(_mesh);
1389   if(!meshC)
1390     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::zipCoords : Invalid support mesh to apply zipCoords on it : must be a MEDCouplingPointSet one !");
1391   MEDCouplingAutoRefCountObjectPtr<MEDCouplingPointSet> meshC2((MEDCouplingPointSet *)meshC->deepCpy());
1392   int oldNbOfNodes=meshC2->getNumberOfNodes();
1393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=meshC2->zipCoordsTraducer();
1394   if(meshC2->getNumberOfNodes()!=oldNbOfNodes)
1395     {
1396       std::vector<DataArrayDouble *> arrays;
1397       _time_discr->getArrays(arrays);
1398       for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
1399         if(*iter)
1400           _type->renumberValuesOnNodes(epsOnVals,arr->getConstPointer(),meshC2->getNumberOfNodes(),*iter);
1401       setMesh(meshC2);
1402       return true;
1403     }
1404   return false;
1405 }
1406
1407 /*!
1408  * This method applyies ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer on 'this->_mesh' that should be set and of type ParaMEDMEM::MEDCouplingUMesh.
1409  * The semantic of 'compType' is given in ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer method.
1410  * 'epsOnVals' stands for epsilon in case of merge of cells. This value is used as tolerance in case the corresponding values differ.
1411  */
1412 bool MEDCouplingFieldDouble::zipConnectivity(int compType, double epsOnVals) throw(INTERP_KERNEL::Exception)
1413 {
1414   const MEDCouplingUMesh *meshC=dynamic_cast<const MEDCouplingUMesh *>(_mesh);
1415   if(!meshC)
1416     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::zipCoords : Invalid support mesh to apply zipCoords on it : must be a MEDCouplingPointSet one !");
1417   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshC2((MEDCouplingUMesh *)meshC->deepCpy());
1418   int oldNbOfCells=meshC2->getNumberOfCells();
1419   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=meshC2->zipConnectivityTraducer(compType);
1420   if(meshC2->getNumberOfCells()!=oldNbOfCells)
1421     {
1422       std::vector<DataArrayDouble *> arrays;
1423       _time_discr->getArrays(arrays);
1424       for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
1425         if(*iter)
1426           _type->renumberValuesOnCells(epsOnVals,meshC,arr->getConstPointer(),meshC2->getNumberOfCells(),*iter);
1427       setMesh(meshC2);
1428       return true;
1429     }
1430   return false;
1431 }
1432
1433 /*!
1434  * This method calls MEDCouplingUMesh::buildSlice3D method. So this method makes the assumption that underlying mesh exists.
1435  * For the moment, this method is implemented for fields on cells.
1436  * 
1437  * \return a newly allocated field double containing the result that the user should deallocate.
1438  */
1439 MEDCouplingFieldDouble *MEDCouplingFieldDouble::extractSlice3D(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
1440 {
1441   const MEDCouplingMesh *mesh=getMesh();
1442   if(!mesh)
1443     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::extractSlice3D : underlying mesh is null !");
1444   if(getTypeOfField()!=ON_CELLS)
1445     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::extractSlice3D : only implemented for fields on cells !");
1446   const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> umesh(mesh->buildUnstructured());
1447   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=clone(false);
1448   ret->setMesh(umesh);
1449   DataArrayInt *cellIds=0;
1450   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh2=umesh->buildSlice3D(origin,vec,eps,cellIds);
1451   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds2=cellIds;
1452   ret->setMesh(mesh2);
1453   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tupleIds=computeTupleIdsToSelectFromCellIds(cellIds->begin(),cellIds->end());
1454   std::vector<DataArrayDouble *> arrays;
1455   _time_discr->getArrays(arrays);
1456   int i=0;
1457   std::vector<DataArrayDouble *> newArr(arrays.size());
1458   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > newArr2(arrays.size());
1459   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++,i++)
1460     {
1461       if(*iter)
1462         {
1463           newArr2[i]=(*iter)->selectByTupleIdSafe(cellIds->begin(),cellIds->end());
1464           newArr[i]=newArr2[i];
1465         }
1466     }
1467   ret->setArrays(newArr);
1468   return ret.retn();
1469 }
1470
1471 /*!
1472  * This method applyies ParaMEDMEM::MEDCouplingUMesh::simplexize on 'this->_mesh'.
1473  * The semantic of 'policy' is given in ParaMEDMEM::MEDCouplingUMesh::simplexize method.
1474  */
1475 bool MEDCouplingFieldDouble::simplexize(int policy) throw(INTERP_KERNEL::Exception)
1476 {
1477   int oldNbOfCells=_mesh->getNumberOfCells();
1478   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> meshC2(_mesh->deepCpy());
1479   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr=meshC2->simplexize(policy);
1480   int newNbOfCells=meshC2->getNumberOfCells();
1481   if(oldNbOfCells==newNbOfCells)
1482     return false;
1483   std::vector<DataArrayDouble *> arrays;
1484   _time_discr->getArrays(arrays);
1485   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
1486     if(*iter)
1487       _type->renumberValuesOnCellsR(_mesh,arr->getConstPointer(),arr->getNbOfElems(),*iter);
1488   setMesh(meshC2);
1489   return true;
1490 }
1491
1492 MEDCouplingFieldDouble *MEDCouplingFieldDouble::doublyContractedProduct() const throw(INTERP_KERNEL::Exception)
1493 {
1494   MEDCouplingTimeDiscretization *td=_time_discr->doublyContractedProduct();
1495   td->copyTinyAttrFrom(*_time_discr);
1496   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
1497   ret->setName("DoublyContractedProduct");
1498   ret->setMesh(getMesh());
1499   return ret;
1500 }
1501
1502 MEDCouplingFieldDouble *MEDCouplingFieldDouble::determinant() const throw(INTERP_KERNEL::Exception)
1503 {
1504   MEDCouplingTimeDiscretization *td=_time_discr->determinant();
1505   td->copyTinyAttrFrom(*_time_discr);
1506   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
1507   ret->setName("Determinant");
1508   ret->setMesh(getMesh());
1509   return ret;
1510 }
1511
1512 MEDCouplingFieldDouble *MEDCouplingFieldDouble::eigenValues() const throw(INTERP_KERNEL::Exception)
1513 {
1514   MEDCouplingTimeDiscretization *td=_time_discr->eigenValues();
1515   td->copyTinyAttrFrom(*_time_discr);
1516   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
1517   ret->setName("EigenValues");
1518   ret->setMesh(getMesh());
1519   return ret;
1520 }
1521
1522 MEDCouplingFieldDouble *MEDCouplingFieldDouble::eigenVectors() const throw(INTERP_KERNEL::Exception)
1523 {
1524   MEDCouplingTimeDiscretization *td=_time_discr->eigenVectors();
1525   td->copyTinyAttrFrom(*_time_discr);
1526   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
1527   ret->setName("EigenVectors");
1528   ret->setMesh(getMesh());
1529   return ret;
1530 }
1531
1532 MEDCouplingFieldDouble *MEDCouplingFieldDouble::inverse() const throw(INTERP_KERNEL::Exception)
1533 {
1534   MEDCouplingTimeDiscretization *td=_time_discr->inverse();
1535   td->copyTinyAttrFrom(*_time_discr);
1536   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
1537   ret->setName("Inversion");
1538   ret->setMesh(getMesh());
1539   return ret;
1540 }
1541
1542 MEDCouplingFieldDouble *MEDCouplingFieldDouble::trace() const throw(INTERP_KERNEL::Exception)
1543 {
1544   MEDCouplingTimeDiscretization *td=_time_discr->trace();
1545   td->copyTinyAttrFrom(*_time_discr);
1546   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
1547   ret->setName("Trace");
1548   ret->setMesh(getMesh());
1549   return ret;
1550 }
1551
1552 MEDCouplingFieldDouble *MEDCouplingFieldDouble::deviator() const throw(INTERP_KERNEL::Exception)
1553 {
1554   MEDCouplingTimeDiscretization *td=_time_discr->deviator();
1555   td->copyTinyAttrFrom(*_time_discr);
1556   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
1557   ret->setName("Trace");
1558   ret->setMesh(getMesh());
1559   return ret;
1560 }
1561
1562 MEDCouplingFieldDouble *MEDCouplingFieldDouble::magnitude() const throw(INTERP_KERNEL::Exception)
1563 {
1564   MEDCouplingTimeDiscretization *td=_time_discr->magnitude();
1565   td->copyTinyAttrFrom(*_time_discr);
1566   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
1567   ret->setName("Magnitude");
1568   ret->setMesh(getMesh());
1569   return ret;
1570 }
1571
1572 MEDCouplingFieldDouble *MEDCouplingFieldDouble::maxPerTuple() const throw(INTERP_KERNEL::Exception)
1573 {
1574   MEDCouplingTimeDiscretization *td=_time_discr->maxPerTuple();
1575   td->copyTinyAttrFrom(*_time_discr);
1576   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
1577   std::ostringstream oss;
1578   oss << "Max_" << getName();
1579   ret->setName(oss.str().c_str());
1580   ret->setMesh(getMesh());
1581   return ret;
1582 }
1583
1584 void MEDCouplingFieldDouble::changeNbOfComponents(int newNbOfComp, double dftValue) throw(INTERP_KERNEL::Exception)
1585 {
1586   _time_discr->changeNbOfComponents(newNbOfComp,dftValue);
1587 }
1588
1589 MEDCouplingFieldDouble *MEDCouplingFieldDouble::keepSelectedComponents(const std::vector<int>& compoIds) const throw(INTERP_KERNEL::Exception)
1590 {
1591   MEDCouplingTimeDiscretization *td=_time_discr->keepSelectedComponents(compoIds);
1592   td->copyTinyAttrFrom(*_time_discr);
1593   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(getNature(),td,_type->clone());
1594   ret->setName(getName());
1595   ret->setMesh(getMesh());
1596   return ret;
1597 }
1598
1599 void MEDCouplingFieldDouble::setSelectedComponents(const MEDCouplingFieldDouble *f, const std::vector<int>& compoIds) throw(INTERP_KERNEL::Exception)
1600 {
1601   _time_discr->setSelectedComponents(f->_time_discr,compoIds);
1602 }
1603
1604 void MEDCouplingFieldDouble::sortPerTuple(bool asc) throw(INTERP_KERNEL::Exception)
1605 {
1606   _time_discr->sortPerTuple(asc);
1607 }
1608
1609 MEDCouplingFieldDouble *MEDCouplingFieldDouble::MergeFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2) throw(INTERP_KERNEL::Exception)
1610 {
1611   if(!f1->areCompatibleForMerge(f2))
1612     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply MergeFields on them !");
1613   const MEDCouplingMesh *m1=f1->getMesh();
1614   const MEDCouplingMesh *m2=f2->getMesh();
1615   MEDCouplingMesh *m=m1->mergeMyselfWith(m2);
1616   MEDCouplingTimeDiscretization *td=f1->_time_discr->aggregate(f2->_time_discr);
1617   td->copyTinyAttrFrom(*f1->_time_discr);
1618   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
1619   ret->setMesh(m);
1620   m->decrRef();
1621   ret->setName(f1->getName());
1622   ret->setDescription(f1->getDescription());
1623   return ret;
1624 }
1625
1626 /*!
1627  * This method returns a newly created field that is the union of all fields in input array 'a'.
1628  * This method expects that 'a' is non empty. If not an exception will be thrown.
1629  * If there is only one field in 'a' a deepCopy (except time information of mesh and field) of the unique field instance in 'a' will be returned.
1630  * Generally speaking the first instance field in 'a' will be used to assign tiny attributes of returned field.
1631  */
1632 MEDCouplingFieldDouble *MEDCouplingFieldDouble::MergeFields(const std::vector<const MEDCouplingFieldDouble *>& a) throw(INTERP_KERNEL::Exception)
1633 {
1634   if(a.size()<1)
1635     throw INTERP_KERNEL::Exception("FieldDouble::MergeFields : size of array must be >= 1 !");
1636   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms(a.size());
1637   std::vector< const MEDCouplingUMesh *> ms2(a.size());
1638   std::vector< const MEDCouplingTimeDiscretization *> tds(a.size());
1639   std::vector<const MEDCouplingFieldDouble *>::const_iterator it=a.begin();
1640   const MEDCouplingFieldDouble *ref=(*it++);
1641   for(;it!=a.end();it++)
1642     if(!ref->areCompatibleForMerge(*it))
1643       throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply MergeFields on them !");
1644   for(int i=0;i<(int)a.size();i++)
1645     {
1646       if(!a[i]->getMesh())
1647         throw INTERP_KERNEL::Exception("MergeFields : A field as no underlying mesh !");
1648       ms[i]=a[i]->getMesh()->buildUnstructured();
1649       ms2[i]=ms[i];
1650       tds[i]=a[i]->_time_discr;
1651     }
1652   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MEDCouplingUMesh::MergeUMeshes(ms2);
1653   m->setName(ms2[0]->getName()); m->setDescription(ms2[0]->getDescription());
1654   MEDCouplingTimeDiscretization *td=tds[0]->aggregate(tds);
1655   td->copyTinyAttrFrom(*(a[0]->_time_discr));
1656   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(a[0]->getNature(),td,a[0]->_type->clone());
1657   ret->setMesh(m);
1658   ret->setName(a[0]->getName());
1659   ret->setDescription(a[0]->getDescription());
1660   return ret;
1661 }
1662
1663 MEDCouplingFieldDouble *MEDCouplingFieldDouble::MeldFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2) throw(INTERP_KERNEL::Exception)
1664 {
1665   if(!f1->areCompatibleForMeld(f2))
1666     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply MeldFields on them !");
1667   MEDCouplingTimeDiscretization *td=f1->_time_discr->meld(f2->_time_discr);
1668   td->copyTinyAttrFrom(*f1->_time_discr);
1669   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
1670   ret->setMesh(f1->getMesh());
1671   return ret;
1672 }
1673
1674 MEDCouplingFieldDouble *MEDCouplingFieldDouble::DotFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2) throw(INTERP_KERNEL::Exception)
1675 {
1676   if(!f1->areStrictlyCompatible(f2))
1677     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply DotFields on them !");
1678   MEDCouplingTimeDiscretization *td=f1->_time_discr->dot(f2->_time_discr);
1679   td->copyTinyAttrFrom(*f1->_time_discr);
1680   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
1681   ret->setMesh(f1->getMesh());
1682   return ret;
1683 }
1684
1685 MEDCouplingFieldDouble *MEDCouplingFieldDouble::CrossProductFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2) throw(INTERP_KERNEL::Exception)
1686 {
1687   if(!f1->areStrictlyCompatible(f2))
1688     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply CrossProductFields on them !");
1689   MEDCouplingTimeDiscretization *td=f1->_time_discr->crossProduct(f2->_time_discr);
1690   td->copyTinyAttrFrom(*f1->_time_discr);
1691   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
1692   ret->setMesh(f1->getMesh());
1693   return ret;
1694 }
1695
1696 MEDCouplingFieldDouble *MEDCouplingFieldDouble::MaxFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2) throw(INTERP_KERNEL::Exception)
1697 {
1698   if(!f1->areStrictlyCompatible(f2))
1699     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply MaxFields on them !");
1700   MEDCouplingTimeDiscretization *td=f1->_time_discr->max(f2->_time_discr);
1701   td->copyTinyAttrFrom(*f1->_time_discr);
1702   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
1703   ret->setMesh(f1->getMesh());
1704   return ret;
1705 }
1706
1707 MEDCouplingFieldDouble *MEDCouplingFieldDouble::MinFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2) throw(INTERP_KERNEL::Exception)
1708 {
1709   if(!f1->areStrictlyCompatible(f2))
1710     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply MinFields on them !");
1711   MEDCouplingTimeDiscretization *td=f1->_time_discr->min(f2->_time_discr);
1712   td->copyTinyAttrFrom(*f1->_time_discr);
1713   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
1714   ret->setMesh(f1->getMesh());
1715   return ret;
1716 }
1717
1718 MEDCouplingFieldDouble *MEDCouplingFieldDouble::AddFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2) throw(INTERP_KERNEL::Exception)
1719 {
1720   if(!f1->areStrictlyCompatible(f2))
1721     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply AddFields on them !");
1722   MEDCouplingTimeDiscretization *td=f1->_time_discr->add(f2->_time_discr);
1723   td->copyTinyAttrFrom(*f1->_time_discr);
1724   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
1725   ret->setMesh(f1->getMesh());
1726   return ret;
1727 }
1728
1729 const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator+=(const MEDCouplingFieldDouble& other) throw(INTERP_KERNEL::Exception)
1730 {
1731   if(!areStrictlyCompatible(&other))
1732     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply += on them !");
1733   _time_discr->addEqual(other._time_discr);
1734   return *this;
1735 }
1736
1737 MEDCouplingFieldDouble *MEDCouplingFieldDouble::SubstractFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2) throw(INTERP_KERNEL::Exception)
1738 {
1739   if(!f1->areStrictlyCompatible(f2))
1740     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply SubstractFields on them !");
1741   MEDCouplingTimeDiscretization *td=f1->_time_discr->substract(f2->_time_discr);
1742   td->copyTinyAttrFrom(*f1->_time_discr);
1743   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
1744   ret->setMesh(f1->getMesh());
1745   return ret;
1746 }
1747
1748 const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator-=(const MEDCouplingFieldDouble& other) throw(INTERP_KERNEL::Exception)
1749 {
1750   if(!areStrictlyCompatible(&other))
1751     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply -= on them !");
1752   _time_discr->substractEqual(other._time_discr);
1753   return *this;
1754 }
1755
1756 MEDCouplingFieldDouble *MEDCouplingFieldDouble::MultiplyFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2) throw(INTERP_KERNEL::Exception)
1757 {
1758   if(!f1->areCompatibleForMul(f2))
1759     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply MultiplyFields on them !");
1760   MEDCouplingTimeDiscretization *td=f1->_time_discr->multiply(f2->_time_discr);
1761   td->copyTinyAttrFrom(*f1->_time_discr);
1762   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
1763   ret->setMesh(f1->getMesh());
1764   return ret;
1765 }
1766
1767 const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator*=(const MEDCouplingFieldDouble& other) throw(INTERP_KERNEL::Exception)
1768 {
1769   if(!areCompatibleForMul(&other))
1770     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply *= on them !");
1771   _time_discr->multiplyEqual(other._time_discr);
1772   return *this;
1773 }
1774
1775 MEDCouplingFieldDouble *MEDCouplingFieldDouble::DivideFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2) throw(INTERP_KERNEL::Exception)
1776 {
1777   if(!f1->areCompatibleForDiv(f2))
1778     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply DivideFields on them !");
1779   MEDCouplingTimeDiscretization *td=f1->_time_discr->divide(f2->_time_discr);
1780   td->copyTinyAttrFrom(*f1->_time_discr);
1781   MEDCouplingFieldDouble *ret=new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone());
1782   ret->setMesh(f1->getMesh());
1783   return ret;
1784 }
1785
1786 const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator/=(const MEDCouplingFieldDouble& other) throw(INTERP_KERNEL::Exception)
1787 {
1788   if(!areCompatibleForDiv(&other))
1789     throw INTERP_KERNEL::Exception("Fields are not compatible ; unable to apply /= on them !");
1790   _time_discr->divideEqual(other._time_discr);
1791   return *this;
1792 }
1793
1794 /*!
1795  * This method writes the field series 'fs' in the VTK file 'fileName'.
1796  * If 'fs' is empty no file is written. If fields lies on more than one mesh an exception will be thrown and no file will be written too.
1797  * If the single mesh is empty an exception will be thrown.
1798  * Finally there is a field in 'fs' with no name an exception will be thrown too.
1799  */
1800 void MEDCouplingFieldDouble::WriteVTK(const char *fileName, const std::vector<const MEDCouplingFieldDouble *>& fs) throw(INTERP_KERNEL::Exception)
1801 {
1802   if(fs.empty())
1803     return;
1804   std::size_t nfs=fs.size();
1805   const MEDCouplingMesh *m=fs[0]->getMesh();
1806   for(std::size_t i=1;i<nfs;i++)
1807     if(fs[i]->getMesh()!=m)
1808       throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::WriteVTK : Fields are not lying on a same mesh ! Expected by VTK ! MEDCouplingFieldDouble::setMesh or MEDCouplingFieldDouble::changeUnderlyingMesh can help to that.");
1809   if(!m)
1810     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::WriteVTK : Fields are lying on a same mesh but it is empty !");
1811   std::ostringstream coss,noss;
1812   for(std::size_t i=0;i<nfs;i++)
1813     {
1814       const MEDCouplingFieldDouble *cur=fs[i];
1815       std::string name(cur->getName());
1816       if(name.empty())
1817         {
1818           std::ostringstream oss; oss << "MEDCouplingFieldDouble::WriteVTK : Field in pos #" << i << " has no name !";
1819           throw INTERP_KERNEL::Exception(oss.str().c_str());
1820         }
1821       TypeOfField typ=cur->getTypeOfField();
1822       if(typ==ON_CELLS)
1823         cur->getArray()->writeVTK(coss,8,cur->getName());
1824       else if(typ==ON_NODES)
1825         cur->getArray()->writeVTK(noss,8,cur->getName());
1826     }
1827   m->writeVTKAdvanced(fileName,coss.str(),noss.str());
1828 }