Salome HOME
Management of 3D in MEDCouplingFieldDouble::voronoize method
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingFieldDouble.cxx
1 // Copyright (C) 2007-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 (CEA/DEN)
20
21 #include "MEDCouplingFieldDouble.hxx"
22 #include "MEDCouplingFieldTemplate.hxx"
23 #include "MEDCouplingFieldT.txx"
24 #include "MEDCouplingFieldInt.hxx"
25 #include "MEDCouplingUMesh.hxx"
26 #include "MEDCouplingTimeDiscretization.hxx"
27 #include "MEDCouplingFieldDiscretization.hxx"
28 #include "MCAuto.txx"
29 #include "MEDCouplingVoronoi.hxx"
30 #include "MEDCouplingNatureOfField.hxx"
31
32 #include "InterpKernelAutoPtr.hxx"
33
34 #include <sstream>
35 #include <limits>
36 #include <algorithm>
37 #include <functional>
38
39 using namespace MEDCoupling;
40
41 template class MEDCouplingFieldT<double>;
42
43 /*!
44  * Creates a new MEDCouplingFieldDouble, of given spatial type and time discretization.
45  * For more info, see \ref MEDCouplingFirstSteps3.
46  * \param [in] type - the type of spatial discretization of the created field, one of
47  *        (\ref MEDCoupling::ON_CELLS "ON_CELLS", 
48  *         \ref MEDCoupling::ON_NODES "ON_NODES",
49  *         \ref MEDCoupling::ON_GAUSS_PT "ON_GAUSS_PT", 
50  *         \ref MEDCoupling::ON_GAUSS_NE "ON_GAUSS_NE",
51  *         \ref MEDCoupling::ON_NODES_KR "ON_NODES_KR").
52  * \param [in] td - the type of time discretization of the created field, one of
53  *        (\ref MEDCoupling::NO_TIME "NO_TIME", 
54  *         \ref MEDCoupling::ONE_TIME "ONE_TIME", 
55  *         \ref MEDCoupling::LINEAR_TIME "LINEAR_TIME", 
56  *         \ref MEDCoupling::CONST_ON_TIME_INTERVAL "CONST_ON_TIME_INTERVAL").
57  * \return MEDCouplingFieldDouble* - a new instance of MEDCouplingFieldDouble. The
58  *         caller is to delete this field using decrRef() as it is no more needed. 
59  */
60 MEDCouplingFieldDouble* MEDCouplingFieldDouble::New(TypeOfField type, TypeOfTimeDiscretization td)
61 {
62   return new MEDCouplingFieldDouble(type,td);
63 }
64
65 /*!
66  * Creates a new MEDCouplingFieldDouble, of a given time discretization and with a
67  * spatial type and supporting mesh copied from a given 
68  * \ref MEDCouplingFieldTemplatesPage "field template".
69  * For more info, see \ref MEDCouplingFirstSteps3.
70  * \warning This method does not deeply copy neither the mesh nor the spatial
71  * discretization. Only a shallow copy (reference) is done for the mesh and the spatial
72  * discretization!
73  * \param [in] ft - the \ref MEDCouplingFieldTemplatesPage "field template" defining
74  *        the spatial discretization and the supporting mesh.
75  * \param [in] td - the type of time discretization of the created field, one of
76  *        (\ref MEDCoupling::NO_TIME "NO_TIME", 
77  *         \ref MEDCoupling::ONE_TIME "ONE_TIME", 
78  *         \ref MEDCoupling::LINEAR_TIME "LINEAR_TIME", 
79  *         \ref MEDCoupling::CONST_ON_TIME_INTERVAL "CONST_ON_TIME_INTERVAL").
80  * \return MEDCouplingFieldDouble* - a new instance of MEDCouplingFieldDouble. The
81  *         caller is to delete this field using decrRef() as it is no more needed. 
82  */
83 MEDCouplingFieldDouble *MEDCouplingFieldDouble::New(const MEDCouplingFieldTemplate& ft, TypeOfTimeDiscretization td)
84 {
85   return new MEDCouplingFieldDouble(ft,td);
86 }
87
88 /*!
89  * Sets a time \a unit of \a this field. For more info, see \ref MEDCouplingFirstSteps3.
90  * \param [in] unit \a unit (string) in which time is measured.
91  */
92 //void MEDCouplingFieldDouble::setTimeUnit(const std::string& unit)
93
94 /*!
95  * Returns a time unit of \a this field.
96  * \return a string describing units in which time is measured.
97  */
98 //std::string MEDCouplingFieldDouble::getTimeUnit() const
99
100
101 /*!
102  * This method if possible the time information (time unit, time iteration, time unit and time value) with its support
103  * that is to say its mesh.
104  * 
105  * \throw  If \c this->_mesh is null an exception will be thrown. An exception will also be throw if the spatial discretization is
106  *         NO_TIME.
107  */
108 void MEDCouplingFieldDouble::synchronizeTimeWithSupport()
109 {
110   timeDiscr()->synchronizeTimeWith(_mesh);
111 }
112
113 /*!
114  * Returns a new MEDCouplingFieldDouble which is a copy of \a this one. The data
115  * of \a this field is copied either deep or shallow depending on \a recDeepCpy
116  * parameter. But the underlying mesh is always shallow copied.
117  * Data that can be copied either deeply or shallow are:
118  * - \ref MEDCouplingTemporalDisc "temporal discretization" data that holds array(s)
119  * of field values,
120  * - \ref MEDCouplingSpatialDisc "a spatial discretization".
121  * 
122  * \c clone(false) is rather dedicated for advanced users that want to limit the amount
123  * of memory. It allows the user to perform methods like operator+(), operator*()
124  * etc. with \a this and the returned field. If the user wants to duplicate deeply the
125  * underlying mesh he should call cloneWithMesh() method or deepCopy() instead. 
126  * \warning The underlying \b mesh of the returned field is **always the same**
127  *         (pointer) as \a this one **whatever the value** of \a recDeepCpy parameter.
128  *  \param [in] recDeepCpy - if \c true, the copy of the underlying data arrays is
129  *         deep, else all data arrays of \a this field are shared by the new field.
130  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The
131  *         caller is to delete this field using decrRef() as it is no more needed.
132  * \sa cloneWithMesh()
133  */
134 MEDCouplingFieldDouble *MEDCouplingFieldDouble::clone(bool recDeepCpy) const
135 {
136   return new MEDCouplingFieldDouble(*this,recDeepCpy);
137 }
138
139 /*!
140  * Returns a new MEDCouplingFieldDouble which is a deep copy of \a this one **including
141  * the mesh**.
142  * The result of this method is exactly the same as that of \c cloneWithMesh(true).
143  * So the resulting field can not be used together with \a this one in the methods
144  * like operator+(), operator*() etc. To avoid deep copying the underlying mesh,
145  * the user can call clone().
146  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The
147  *         caller is to delete this field using decrRef() as it is no more needed.
148  * \sa cloneWithMesh()
149  */
150 MEDCouplingFieldDouble *MEDCouplingFieldDouble::deepCopy() const
151 {
152   return cloneWithMesh(true);
153 }
154
155 /*!
156  * Creates a new MEDCouplingFieldDouble of given
157  * \ref MEDCouplingTemporalDisc "temporal discretization". The result field either
158  * shares the data array(s) with \a this field, or holds a deep copy of it, depending on
159  * \a deepCopy parameter. But the underlying \b mesh is always **shallow copied**.
160  * \param [in] td - the type of time discretization of the created field, one of
161  *        (\ref MEDCoupling::NO_TIME "NO_TIME", 
162  *         \ref MEDCoupling::ONE_TIME "ONE_TIME", 
163  *         \ref MEDCoupling::LINEAR_TIME "LINEAR_TIME", 
164  *         \ref MEDCoupling::CONST_ON_TIME_INTERVAL "CONST_ON_TIME_INTERVAL").
165  * \param [in] deepCopy - if \c true, the copy of the underlying data arrays is
166  *         deep, else all data arrays of \a this field are shared by the new field.
167  * \return MEDCouplingFieldDouble* - a new instance of MEDCouplingFieldDouble. The
168  *         caller is to delete this field using decrRef() as it is no more needed. 
169  * 
170  * \if ENABLE_EXAMPLES
171  * \ref cpp_mcfielddouble_buildNewTimeReprFromThis "Here is a C++ example."<br>
172  * \ref py_mcfielddouble_buildNewTimeReprFromThis "Here is a Python example."
173  * \endif
174  * \sa clone()
175  */
176 MEDCouplingFieldDouble *MEDCouplingFieldDouble::buildNewTimeReprFromThis(TypeOfTimeDiscretization td, bool deepCopy) const
177 {
178   MEDCouplingTimeDiscretization *tdo=timeDiscr()->buildNewTimeReprFromThis(td,deepCopy);
179   MCAuto<MEDCouplingFieldDiscretization> disc;
180   if(_type)
181     disc=_type->clone();
182   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(getNature(),tdo,disc.retn()));
183   ret->setMesh(getMesh());
184   ret->setName(getName());
185   ret->setDescription(getDescription());
186   return ret.retn();
187 }
188
189 /*!
190  * This method converts a field on nodes (\a this) to a cell field (returned field). The convertion is a \b non \b conservative remapping !
191  * This method is useful only for users that need a fast convertion from node to cell spatial discretization. The algorithm applied is simply to attach
192  * to each cell the average of values on nodes constituting this cell.
193  *
194  * \return MEDCouplingFieldDouble* - a new instance of MEDCouplingFieldDouble. The
195  *         caller is to delete this field using decrRef() as it is no more needed. The returned field will share the same mesh object object than those in \a this.
196  * \throw If \a this spatial discretization is empty or not ON_NODES.
197  * \throw If \a this is not coherent (see MEDCouplingFieldDouble::checkConsistencyLight).
198  * 
199  * \warning This method is a \b non \b conservative method of remapping from node spatial discretization to cell spatial discretization.
200  * If a conservative method of interpolation is required MEDCoupling::MEDCouplingRemapper class should be used instead with "P1P0" method.
201  */
202 MEDCouplingFieldDouble *MEDCouplingFieldDouble::nodeToCellDiscretization() const
203 {
204   checkConsistencyLight();
205   TypeOfField tf(getTypeOfField());
206   if(tf!=ON_NODES)
207     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::nodeToCellDiscretization : this field is expected to be on ON_NODES !");
208   MCAuto<MEDCouplingFieldDouble> ret(clone(false));
209   MCAuto<MEDCouplingFieldDiscretizationP0> nsp(new MEDCouplingFieldDiscretizationP0);
210   ret->setDiscretization(nsp);
211   const MEDCouplingMesh *m(getMesh());//m is non empty thanks to checkConsistencyLight call
212   int nbCells(m->getNumberOfCells());
213   std::vector<DataArrayDouble *> arrs(getArrays());
214   std::size_t sz(arrs.size());
215   std::vector< MCAuto<DataArrayDouble> > outArrsSafe(sz); std::vector<DataArrayDouble *> outArrs(sz);
216   for(std::size_t j=0;j<sz;j++)
217     {
218       int nbCompo(arrs[j]->getNumberOfComponents());
219       outArrsSafe[j]=DataArrayDouble::New(); outArrsSafe[j]->alloc(nbCells,nbCompo);
220       outArrsSafe[j]->copyStringInfoFrom(*arrs[j]);
221       outArrs[j]=outArrsSafe[j];
222       double *pt(outArrsSafe[j]->getPointer());
223       const double *srcPt(arrs[j]->begin());
224       for(int i=0;i<nbCells;i++,pt+=nbCompo)
225         {
226           std::vector<int> nodeIds;
227           m->getNodeIdsOfCell(i,nodeIds);
228           std::fill(pt,pt+nbCompo,0.);
229           std::size_t nbNodesInCell(nodeIds.size());
230           for(std::size_t k=0;k<nbNodesInCell;k++)
231             std::transform(srcPt+nodeIds[k]*nbCompo,srcPt+(nodeIds[k]+1)*nbCompo,pt,pt,std::plus<double>());
232           if(nbNodesInCell!=0)
233             std::transform(pt,pt+nbCompo,pt,std::bind2nd(std::multiplies<double>(),1./((double)nbNodesInCell)));
234           else
235             {
236               std::ostringstream oss; oss << "MEDCouplingFieldDouble::nodeToCellDiscretization : Cell id #" << i << " has been detected to have no nodes !";
237               throw INTERP_KERNEL::Exception(oss.str());
238             }
239         }
240     }
241   ret->setArrays(outArrs);
242   return ret.retn();
243 }
244
245 /*!
246  * This method converts a field on cell (\a this) to a node field (returned field). The convertion is a \b non \b conservative remapping !
247  * This method is useful only for users that need a fast convertion from cell to node spatial discretization. The algorithm applied is simply to attach
248  * to each node the average of values on cell sharing this node. If \a this lies on a mesh having orphan nodes the values applied on them will be NaN (division by 0.).
249  *
250  * \return MEDCouplingFieldDouble* - a new instance of MEDCouplingFieldDouble. The
251  *         caller is to delete this field using decrRef() as it is no more needed. The returned field will share the same mesh object object than those in \a this.
252  * \throw If \a this spatial discretization is empty or not ON_CELLS.
253  * \throw If \a this is not coherent (see MEDCouplingFieldDouble::checkConsistencyLight).
254  *
255  * \warning This method is a \b non \b conservative method of remapping from cell spatial discretization to node spatial discretization.
256  * If a conservative method of interpolation is required MEDCoupling::MEDCouplingRemapper class should be used instead with "P0P1" method.
257  */
258 MEDCouplingFieldDouble *MEDCouplingFieldDouble::cellToNodeDiscretization() const
259 {
260   checkConsistencyLight();
261   TypeOfField tf(getTypeOfField());
262   if(tf!=ON_CELLS)
263     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::cellToNodeDiscretization : this field is expected to be on ON_CELLS !");
264   MCAuto<MEDCouplingFieldDouble> ret(clone(false));
265   MCAuto<MEDCouplingFieldDiscretizationP1> nsp(new MEDCouplingFieldDiscretizationP1);
266   ret->setDiscretization(nsp);
267   const MEDCouplingMesh *m(getMesh());//m is non empty thanks to checkConsistencyLight call
268   MCAuto<DataArrayInt> rn(DataArrayInt::New()),rni(DataArrayInt::New());
269   m->getReverseNodalConnectivity(rn,rni);
270   MCAuto<DataArrayInt> rni2(rni->deltaShiftIndex());
271   MCAuto<DataArrayDouble> rni3(rni2->convertToDblArr()); rni2=0;
272   std::vector<DataArrayDouble *> arrs(getArrays());
273   std::size_t sz(arrs.size());
274   std::vector< MCAuto<DataArrayDouble> > outArrsSafe(sz); std::vector<DataArrayDouble *> outArrs(sz);
275   for(std::size_t j=0;j<sz;j++)
276     {
277       MCAuto<DataArrayDouble> tmp(arrs[j]->selectByTupleIdSafe(rn->begin(),rn->end()));
278       outArrsSafe[j]=(tmp->accumulatePerChunck(rni->begin(),rni->end())); tmp=0;
279       outArrsSafe[j]->divideEqual(rni3);
280       outArrsSafe[j]->copyStringInfoFrom(*arrs[j]);
281       outArrs[j]=outArrsSafe[j];
282     }
283   ret->setArrays(outArrs);
284   return ret.retn();
285 }
286
287 /*!
288  * Returns a string describing \a this field. The string includes info on
289  * - name,
290  * - description,
291  * - \ref MEDCouplingSpatialDisc "spatial discretization",
292  * - \ref MEDCouplingTemporalDisc "time discretization",
293  * - components,
294  * - mesh,
295  * - contents of data arrays.
296  *
297  *  \return std::string - the string describing \a this field.
298  */
299 std::string MEDCouplingFieldDouble::advancedRepr() const
300 {
301   std::ostringstream ret;
302   ret << "FieldDouble with name : \"" << getName() << "\"\n";
303   ret << "Description of field is : \"" << getDescription() << "\"\n";
304   if(_type)
305     { ret << "FieldDouble space discretization is : " << _type->getStringRepr() << "\n"; }
306   else
307     { ret << "FieldDouble has no space discretization set !\n"; }
308   if(timeDiscr())
309     { ret << "FieldDouble time discretization is : " << timeDiscr()->getStringRepr() << "\n"; }
310   else
311     { ret << "FieldDouble has no time discretization set !\n"; }
312   if(getArray())
313     ret << "FieldDouble default array has " << getArray()->getNumberOfComponents() << " components and " << getArray()->getNumberOfTuples() << " tuples.\n";
314   if(_mesh)
315     ret << "Mesh support information :\n__________________________\n" << _mesh->advancedRepr();
316   else
317     ret << "Mesh support information : No mesh set !\n";
318   std::vector<DataArrayDouble *> arrays;
319   timeDiscr()->getArrays(arrays);
320   int arrayId=0;
321   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++,arrayId++)
322     {
323       ret << "Array #" << arrayId << " :\n__________\n";
324       if(*iter)
325         (*iter)->reprWithoutNameStream(ret);
326       else
327         ret << "Array empty !";
328       ret << "\n";
329     }
330   return ret.str();
331 }
332
333 std::string MEDCouplingFieldDouble::writeVTK(const std::string& fileName, bool isBinary) const
334 {
335   std::vector<const MEDCouplingFieldDouble *> fs(1,this);
336   return MEDCouplingFieldDouble::WriteVTK(fileName,fs,isBinary);
337 }
338
339 /*!
340  * This method states if \a this and 'other' are compatibles each other before performing any treatment.
341  * This method is good for methods like : mergeFields.
342  * This method is not very demanding compared to areStrictlyCompatible that is better for operation on fields.
343  */
344 bool MEDCouplingFieldDouble::areCompatibleForMerge(const MEDCouplingField *other) const
345 {
346   if(!MEDCouplingField::areCompatibleForMerge(other))
347     return false;
348   const MEDCouplingFieldDouble *otherC(dynamic_cast<const MEDCouplingFieldDouble *>(other));
349   if(!otherC)
350     return false;
351   if(!timeDiscr()->areCompatible(otherC->timeDiscr()))
352     return false;
353   return true;
354 }
355
356 /*!
357  * This method is invocated before any attempt of melding. This method is very close to areStrictlyCompatible,
358  * except that \a this and other can have different number of components.
359  */
360 bool MEDCouplingFieldDouble::areCompatibleForMeld(const MEDCouplingFieldDouble *other) const
361 {
362   if(!MEDCouplingField::areStrictlyCompatible(other))
363     return false;
364   if(!timeDiscr()->areCompatibleForMeld(other->timeDiscr()))
365     return false;
366   return true;
367 }
368
369 /*!
370  * Permutes values of \a this field according to a given permutation array for cells
371  * renumbering. The underlying mesh is deeply copied and its cells are also permuted. 
372  * The number of cells remains the same; for that the permutation array \a old2NewBg
373  * should not contain equal ids.
374  * ** Warning, this method modifies the mesh aggreagated by \a this (by performing a deep copy ) **.
375  *
376  *  \param [in] old2NewBg - the permutation array in "Old to New" mode. Its length is
377  *         to be equal to \a this->getMesh()->getNumberOfCells().
378  *  \param [in] check - if \c true, \a old2NewBg is transformed to a new permutation
379  *         array, so that its maximal cell id to correspond to (be less than) the number
380  *         of cells in mesh. This new array is then used for the renumbering. If \a 
381  *         check == \c false, \a old2NewBg is used as is, that is less secure as validity 
382  *         of ids in \a old2NewBg is not checked.
383  *  \throw If the mesh is not set.
384  *  \throw If the spatial discretization of \a this field is NULL.
385  *  \throw If \a check == \c true and \a old2NewBg contains equal ids.
386  *  \throw If mesh nature does not allow renumbering (e.g. structured mesh).
387  * 
388  *  \if ENABLE_EXAMPLES
389  *  \ref cpp_mcfielddouble_renumberCells "Here is a C++ example".<br>
390  *  \ref  py_mcfielddouble_renumberCells "Here is a Python example".
391  *  \endif
392  */
393 void MEDCouplingFieldDouble::renumberCells(const int *old2NewBg, bool check)
394 {
395   renumberCellsWithoutMesh(old2NewBg,check);
396   MCAuto<MEDCouplingMesh> m=_mesh->deepCopy();
397   m->renumberCells(old2NewBg,check);
398   setMesh(m);
399   updateTime();
400 }
401
402 /*!
403  * Permutes values of \a this field according to a given permutation array for cells
404  * renumbering. The underlying mesh is \b not permuted. 
405  * The number of cells remains the same; for that the permutation array \a old2NewBg
406  * should not contain equal ids.
407  * This method performs a part of job of renumberCells(). The reasonable use of this
408  * method is only for multi-field instances lying on the same mesh to avoid a
409  * systematic duplication and renumbering of _mesh attribute. 
410  * \warning Use this method with a lot of care!
411  *  \param [in] old2NewBg - the permutation array in "Old to New" mode. Its length is
412  *         to be equal to \a this->getMesh()->getNumberOfCells().
413  *  \param [in] check - if \c true, \a old2NewBg is transformed to a new permutation
414  *         array, so that its maximal cell id to correspond to (be less than) the number
415  *         of cells in mesh. This new array is then used for the renumbering. If \a 
416  *         check == \c false, \a old2NewBg is used as is, that is less secure as validity 
417  *         of ids in \a old2NewBg is not checked.
418  *  \throw If the mesh is not set.
419  *  \throw If the spatial discretization of \a this field is NULL.
420  *  \throw If \a check == \c true and \a old2NewBg contains equal ids.
421  *  \throw If mesh nature does not allow renumbering (e.g. structured mesh).
422  */
423 void MEDCouplingFieldDouble::renumberCellsWithoutMesh(const int *old2NewBg, bool check)
424 {
425   if(!_mesh)
426     throw INTERP_KERNEL::Exception("Expecting a defined mesh to be able to operate a renumbering !");
427   if(_type.isNull())
428     throw INTERP_KERNEL::Exception("Expecting a spatial discretization to be able to operate a renumbering !");
429   //
430   _type->renumberCells(old2NewBg,check);
431   std::vector<DataArrayDouble *> arrays;
432   timeDiscr()->getArrays(arrays);
433   std::vector<DataArray *> arrays2(arrays.size()); std::copy(arrays.begin(),arrays.end(),arrays2.begin());
434   _type->renumberArraysForCell(_mesh,arrays2,old2NewBg,check);
435   //
436   updateTime();
437 }
438
439 /*!
440  * Permutes values of \a this field according to a given permutation array for node
441  * renumbering. The underlying mesh is deeply copied and its nodes are also permuted. 
442  * The number of nodes can change, contrary to renumberCells().
443  *  \param [in] old2NewBg - the permutation array in "Old to New" mode. Its length is
444  *         to be equal to \a this->getMesh()->getNumberOfNodes().
445  *  \param [in] eps - a precision used to compare field values at merged nodes. If
446  *         the values differ more than \a eps, an exception is thrown.
447  *  \throw If the mesh is not set.
448  *  \throw If the spatial discretization of \a this field is NULL.
449  *  \throw If \a check == \c true and \a old2NewBg contains equal ids.
450  *  \throw If mesh nature does not allow renumbering (e.g. structured mesh).
451  *  \throw If values at merged nodes deffer more than \a eps.
452  * 
453  *  \if ENABLE_EXAMPLES
454  *  \ref cpp_mcfielddouble_renumberNodes "Here is a C++ example".<br>
455  *  \ref  py_mcfielddouble_renumberNodes "Here is a Python example".
456  *  \endif
457  */
458 void MEDCouplingFieldDouble::renumberNodes(const int *old2NewBg, double eps)
459 {
460   const MEDCouplingPointSet *meshC=dynamic_cast<const MEDCouplingPointSet *>(_mesh);
461   if(!meshC)
462     throw INTERP_KERNEL::Exception("Invalid mesh to apply renumberNodes on it !");
463   int nbOfNodes=meshC->getNumberOfNodes();
464   MCAuto<MEDCouplingPointSet> meshC2((MEDCouplingPointSet *)meshC->deepCopy());
465   int newNbOfNodes=*std::max_element(old2NewBg,old2NewBg+nbOfNodes)+1;
466   renumberNodesWithoutMesh(old2NewBg,newNbOfNodes,eps);
467   meshC2->renumberNodes(old2NewBg,newNbOfNodes);
468   setMesh(meshC2);
469 }
470
471 /*!
472  * Permutes values of \a this field according to a given permutation array for nodes
473  * renumbering. The underlying mesh is \b not permuted. 
474  * The number of nodes can change, contrary to renumberCells().
475  * A given epsilon specifies a threshold of error in case of two nodes are merged but
476  * the difference of values on these nodes are higher than \a eps.
477  * This method performs a part of job of renumberNodes(), excluding node renumbering
478  * in mesh. The reasonable use of this
479  * method is only for multi-field instances lying on the same mesh to avoid a
480  * systematic duplication and renumbering of _mesh attribute. 
481  * \warning Use this method with a lot of care!
482  * \warning In case of an exception thrown, the contents of the data array can be
483  *         partially modified until the exception occurs. 
484  *  \param [in] old2NewBg - the permutation array in "Old to New" mode. Its length is
485  *         to be equal to \a this->getMesh()->getNumberOfNodes().
486  *  \param [in] newNbOfNodes - a number of nodes in the mesh after renumbering.
487  *  \param [in] eps - a precision used to compare field values at merged nodes. If
488  *         the values differ more than \a eps, an exception is thrown.
489  *  \throw If the mesh is not set.
490  *  \throw If the spatial discretization of \a this field is NULL.
491  *  \throw If values at merged nodes deffer more than \a eps.
492  */
493 void MEDCouplingFieldDouble::renumberNodesWithoutMesh(const int *old2NewBg, int newNbOfNodes, double eps)
494 {
495   if(_type.isNull())
496     throw INTERP_KERNEL::Exception("Expecting a spatial discretization to be able to operate a renumbering !");
497   std::vector<DataArrayDouble *> arrays;
498   timeDiscr()->getArrays(arrays);
499   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
500     if(*iter)
501       _type->renumberValuesOnNodes(eps,old2NewBg,newNbOfNodes,*iter);
502 }
503
504 /*!
505  * Returns all tuple ids of \a this scalar field that fit the range [\a vmin,
506  * \a vmax]. This method calls DataArrayDouble::findIdsInRange().
507  *  \param [in] vmin - a lower boundary of the range. Tuples with values less than \a
508  *         vmin are not included in the result array.
509  *  \param [in] vmax - an upper boundary of the range. Tuples with values more than \a
510  *         vmax are not included in the result array.
511  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of selected
512  *          tuples. The caller is to delete this array using decrRef() as it is no
513  *          more needed.
514  *  \throw If the data array is not set.
515  *  \throw If \a this->getNumberOfComponents() != 1.
516  */
517 DataArrayInt *MEDCouplingFieldDouble::findIdsInRange(double vmin, double vmax) const
518 {
519   if(getArray()==0)
520     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::findIdsInRange : no default array set !");
521   return getArray()->findIdsInRange(vmin,vmax);
522 }
523
524 /*!
525  * Builds a newly created field, that the caller will have the responsability to deal with (decrRef()).
526  * This method makes the assumption that the field is correctly defined when this method is called, no check of this will be done.
527  * 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.
528  * Parameter \a part specifies **cell ids whatever the spatial discretization of this** (
529  * \ref MEDCoupling::ON_CELLS "ON_CELLS", 
530  * \ref MEDCoupling::ON_NODES "ON_NODES",
531  * \ref MEDCoupling::ON_GAUSS_PT "ON_GAUSS_PT", 
532  * \ref MEDCoupling::ON_GAUSS_NE "ON_GAUSS_NE",
533  * \ref MEDCoupling::ON_NODES_KR "ON_NODES_KR").
534  *
535  * 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].
536  * Then the returned field will lie on mesh having 3 cells and the returned field will contain 3 tuples.<br>
537  * 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>
538  * 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>
539  * 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().
540  *
541  * 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].
542  * 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
543  * will contain 6 tuples and \a this field will lie on this restricted mesh. 
544  *
545  *  \param [in] part - an array of cell ids to include to the result field.
546  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The caller is to delete this field using decrRef() as it is no more needed.
547  *
548  *  \if ENABLE_EXAMPLES
549  *  \ref cpp_mcfielddouble_subpart1 "Here is a C++ example".<br>
550  *  \ref  py_mcfielddouble_subpart1 "Here is a Python example".
551  *  \endif
552  *  \sa MEDCouplingFieldDouble::buildSubPartRange
553  */
554
555 MEDCouplingFieldDouble *MEDCouplingFieldDouble::buildSubPart(const DataArrayInt *part) const
556 {
557   if(part==0)
558     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::buildSubPart : not empty array must be passed to this method !");
559   return buildSubPart(part->begin(),part->end());
560 }
561
562 /*!
563  * Builds a newly created field, that the caller will have the responsability to deal with.
564  * \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**.
565  * \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.
566  * \n Parameter [\a partBg, \a partEnd ) specifies **cell ids whatever the spatial discretization** of \a this (
567  * \ref MEDCoupling::ON_CELLS "ON_CELLS", 
568  * \ref MEDCoupling::ON_NODES "ON_NODES",
569  * \ref MEDCoupling::ON_GAUSS_PT "ON_GAUSS_PT", 
570  * \ref MEDCoupling::ON_GAUSS_NE "ON_GAUSS_NE",
571  * \ref MEDCoupling::ON_NODES_KR "ON_NODES_KR").
572  *
573  * 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].
574  * Then the returned field will lie on mesh having 3 cells and will contain 3 tuples.
575  *- 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().
576  *- 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().
577  *- 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().
578  *
579  * 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].
580  * 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
581  * will contain 6 tuples and \a this field will lie on this restricted mesh. 
582  *
583  * \param [in] partBg - start (included) of input range of cell ids to select [ \a partBg, \a partEnd )
584  * \param [in] partEnd - end (not included) of input range of cell ids to select [ \a partBg, \a partEnd )
585  * \return a newly allocated field the caller should deal with.
586  * 
587  * \throw if there is presence of an invalid cell id in [ \a partBg, \a partEnd ) regarding the number of cells of \a this->getMesh().
588  *
589  * \if ENABLE_EXAMPLES
590  * \ref cpp_mcfielddouble_subpart1 "Here a C++ example."<br>
591  * \ref py_mcfielddouble_subpart1 "Here a Python example."
592  * \endif
593  * \sa MEDCoupling::MEDCouplingFieldDouble::buildSubPart(const DataArrayInt *) const, MEDCouplingFieldDouble::buildSubPartRange
594  */
595 MEDCouplingFieldDouble *MEDCouplingFieldDouble::buildSubPart(const int *partBg, const int *partEnd) const
596 {
597   if(_type.isNull())
598     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::buildSubPart : Expecting a not NULL spatial discretization !");
599   DataArrayInt *arrSelect;
600   MCAuto<MEDCouplingMesh> m=_type->buildSubMeshData(_mesh,partBg,partEnd,arrSelect);
601   MCAuto<DataArrayInt> arrSelect2(arrSelect);
602   MCAuto<MEDCouplingFieldDouble> ret(clone(false));//quick shallow copy.
603   const MEDCouplingFieldDiscretization *disc=getDiscretization();
604   if(disc)
605     ret->setDiscretization(MCAuto<MEDCouplingFieldDiscretization>(disc->clonePart(partBg,partEnd)));
606   ret->setMesh(m);
607   std::vector<DataArrayDouble *> arrays;
608   timeDiscr()->getArrays(arrays);
609   std::vector<DataArrayDouble *> arrs;
610   std::vector< MCAuto<DataArrayDouble> > arrsSafe;
611   const int *arrSelBg=arrSelect->begin();
612   const int *arrSelEnd=arrSelect->end();
613   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
614     {
615       DataArrayDouble *arr=0;
616       if(*iter)
617         arr=(*iter)->selectByTupleIdSafe(arrSelBg,arrSelEnd);
618       arrs.push_back(arr); arrsSafe.push_back(arr);
619     }
620   ret->timeDiscr()->setArrays(arrs,0);
621   return ret.retn();
622 }
623
624 /*!
625  * This method is equivalent to MEDCouplingFieldDouble::buildSubPart, the only difference is that the input range of cell ids is
626  * given using a range given \a begin, \a end and \a step to optimize the part computation.
627  * 
628  * \sa MEDCouplingFieldDouble::buildSubPart
629  */
630 MEDCouplingFieldDouble *MEDCouplingFieldDouble::buildSubPartRange(int begin, int end, int step) const
631 {
632   if(_type.isNull())
633     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::buildSubPart : Expecting a not NULL spatial discretization !");
634   DataArrayInt *arrSelect;
635   int beginOut,endOut,stepOut;
636   MCAuto<MEDCouplingMesh> m(_type->buildSubMeshDataRange(_mesh,begin,end,step,beginOut,endOut,stepOut,arrSelect));
637   MCAuto<DataArrayInt> arrSelect2(arrSelect);
638   MCAuto<MEDCouplingFieldDouble> ret(clone(false));//quick shallow copy.
639   const MEDCouplingFieldDiscretization *disc=getDiscretization();
640   if(disc)
641     ret->setDiscretization(MCAuto<MEDCouplingFieldDiscretization>(disc->clonePartRange(begin,end,step)));
642   ret->setMesh(m);
643   std::vector<DataArrayDouble *> arrays;
644   timeDiscr()->getArrays(arrays);
645   std::vector<DataArrayDouble *> arrs;
646   std::vector< MCAuto<DataArrayDouble> > arrsSafe;
647   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
648     {
649       DataArrayDouble *arr=0;
650       if(*iter)
651         {
652           if(arrSelect)
653             {
654               const int *arrSelBg=arrSelect->begin();
655               const int *arrSelEnd=arrSelect->end();
656               arr=(*iter)->selectByTupleIdSafe(arrSelBg,arrSelEnd);
657             }
658           else
659             arr=(*iter)->selectByTupleIdSafeSlice(beginOut,endOut,stepOut);
660         }
661       arrs.push_back(arr); arrsSafe.push_back(arr);
662     }
663   ret->timeDiscr()->setArrays(arrs,0);
664   return ret.retn();
665 }
666
667 MEDCouplingFieldInt *MEDCouplingFieldDouble::convertToIntField() const
668 {
669   MCAuto<MEDCouplingFieldTemplate> tmp(MEDCouplingFieldTemplate::New(*this));
670   int t1,t2;
671   double t0(getTime(t1,t2));
672   MCAuto<MEDCouplingFieldInt> ret(MEDCouplingFieldInt::New(*tmp,getTimeDiscretization()));
673   ret->setTime(t0,t1,t2);
674   if(getArray())
675     {
676       MCAuto<DataArrayInt> arr(getArray()->convertToIntArr());
677       ret->setArray(arr);
678     }
679   return ret.retn();
680 }
681
682 MEDCouplingFieldDouble::MEDCouplingFieldDouble(TypeOfField type, TypeOfTimeDiscretization td):MEDCouplingFieldT<double>(type,MEDCouplingTimeDiscretization::New(td))
683 {
684 }
685
686 /*!
687  * ** WARINING : This method do not deeply copy neither mesh nor spatial discretization. Only a shallow copy (reference) is done for mesh and spatial discretization ! **
688  */
689 MEDCouplingFieldDouble::MEDCouplingFieldDouble(const MEDCouplingFieldTemplate& ft, TypeOfTimeDiscretization td):MEDCouplingFieldT<double>(ft,MEDCouplingTimeDiscretization::New(td),false)
690 {
691 }
692
693 MEDCouplingFieldDouble::MEDCouplingFieldDouble(const MEDCouplingFieldDouble& other, bool deepCopy):MEDCouplingFieldT<double>(other,deepCopy)
694 {
695 }
696
697 MEDCouplingFieldDouble::MEDCouplingFieldDouble(NatureOfField n, MEDCouplingTimeDiscretization *td, MEDCouplingFieldDiscretization *type):MEDCouplingFieldT<double>(type,n,td)
698 {
699 }
700
701 /*!
702  * Accumulate values of a given component of \a this field.
703  *  \param [in] compId - the index of the component of interest.
704  *  \return double - a sum value of *compId*-th component.
705  *  \throw If the data array is not set.
706  *  \throw If \a the condition ( 0 <= \a compId < \a this->getNumberOfComponents() ) is
707  *         not respected.
708  */
709 double MEDCouplingFieldDouble::accumulate(int compId) const
710 {
711   if(getArray()==0)
712     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::accumulate : no default array defined !");
713   return getArray()->accumulate(compId);
714 }
715
716 /*!
717  * Accumulates values of each component of \a this array.
718  *  \param [out] res - an array of length \a this->getNumberOfComponents(), allocated 
719  *         by the caller, that is filled by this method with sum value for each
720  *         component.
721  *  \throw If the data array is not set.
722  */
723 void MEDCouplingFieldDouble::accumulate(double *res) const
724 {
725   if(getArray()==0)
726     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::accumulate : no default array defined !");
727   getArray()->accumulate(res);
728 }
729
730 /*!
731  * Returns the maximal value within \a this scalar field. Values of all arrays stored
732  * in \a this->_time_discr are checked.
733  *  \return double - the maximal value among all values of \a this field.
734  *  \throw If \a this->getNumberOfComponents() != 1
735  *  \throw If the data array is not set.
736  *  \throw If there is an empty data array in \a this field.
737  */
738 double MEDCouplingFieldDouble::getMaxValue() const
739 {
740   std::vector<DataArrayDouble *> arrays;
741   timeDiscr()->getArrays(arrays);
742   double ret(-std::numeric_limits<double>::max());
743   bool isExistingArr=false;
744   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
745     {
746       if(*iter)
747         {
748           isExistingArr=true;
749           int loc;
750           ret=std::max(ret,(*iter)->getMaxValue(loc));
751         }
752     }
753   if(!isExistingArr)
754     throw INTERP_KERNEL::Exception("getMaxValue : No arrays defined !");
755   return ret;
756 }
757
758 /*!
759  * Returns the maximal value and all its locations within \a this scalar field.
760  * Only the first of available data arrays is checked.
761  *  \param [out] tupleIds - a new instance of DataArrayInt containg indices of
762  *               tuples holding the maximal value. The caller is to delete it using
763  *               decrRef() as it is no more needed.
764  *  \return double - the maximal value among all values of the first array of \a this filed.
765  *  \throw If \a this->getNumberOfComponents() != 1.
766  *  \throw If there is an empty data array in \a this field.
767  */
768 double MEDCouplingFieldDouble::getMaxValue2(DataArrayInt*& tupleIds) const
769 {
770   std::vector<DataArrayDouble *> arrays;
771   timeDiscr()->getArrays(arrays);
772   double ret(-std::numeric_limits<double>::max());
773   bool isExistingArr=false;
774   tupleIds=0;
775   MCAuto<DataArrayInt> ret1;
776   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
777     {
778       if(*iter)
779         {
780           isExistingArr=true;
781           DataArrayInt *tmp;
782           ret=std::max(ret,(*iter)->getMaxValue2(tmp));
783           MCAuto<DataArrayInt> tmpSafe(tmp);
784           if(!((const DataArrayInt *)ret1))
785             ret1=tmpSafe;
786         }
787     }
788   if(!isExistingArr)
789     throw INTERP_KERNEL::Exception("getMaxValue2 : No arrays defined !");
790   tupleIds=ret1.retn();
791   return ret;
792 }
793
794 /*!
795  * Returns the minimal value within \a this scalar field. Values of all arrays stored
796  * in \a this->_time_discr are checked.
797  *  \return double - the minimal value among all values of \a this field.
798  *  \throw If \a this->getNumberOfComponents() != 1
799  *  \throw If the data array is not set.
800  *  \throw If there is an empty data array in \a this field.
801  */
802 double MEDCouplingFieldDouble::getMinValue() const
803 {
804   std::vector<DataArrayDouble *> arrays;
805   timeDiscr()->getArrays(arrays);
806   double ret(std::numeric_limits<double>::max());
807   bool isExistingArr=false;
808   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
809     {
810       if(*iter)
811         {
812           isExistingArr=true;
813           int loc;
814           ret=std::min(ret,(*iter)->getMinValue(loc));
815         }
816     }
817   if(!isExistingArr)
818     throw INTERP_KERNEL::Exception("getMinValue : No arrays defined !");
819   return ret;
820 }
821
822 /*!
823  * Returns the minimal value and all its locations within \a this scalar field.
824  * Only the first of available data arrays is checked.
825  *  \param [out] tupleIds - a new instance of DataArrayInt containg indices of
826  *               tuples holding the minimal value. The caller is to delete it using
827  *               decrRef() as it is no more needed.
828  *  \return double - the minimal value among all values of the first array of \a this filed.
829  *  \throw If \a this->getNumberOfComponents() != 1.
830  *  \throw If there is an empty data array in \a this field.
831  */
832 double MEDCouplingFieldDouble::getMinValue2(DataArrayInt*& tupleIds) const
833 {
834   std::vector<DataArrayDouble *> arrays;
835   timeDiscr()->getArrays(arrays);
836   double ret(-std::numeric_limits<double>::max());
837   bool isExistingArr=false;
838   tupleIds=0;
839   MCAuto<DataArrayInt> ret1;
840   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
841     {
842       if(*iter)
843         {
844           isExistingArr=true;
845           DataArrayInt *tmp;
846           ret=std::max(ret,(*iter)->getMinValue2(tmp));
847           MCAuto<DataArrayInt> tmpSafe(tmp);
848           if(!((const DataArrayInt *)ret1))
849             ret1=tmpSafe;
850         }
851     }
852   if(!isExistingArr)
853     throw INTERP_KERNEL::Exception("getMinValue2 : No arrays defined !");
854   tupleIds=ret1.retn();
855   return ret;
856 }
857
858 /*!
859  * Returns the average value of \a this scalar field.
860  *  \return double - the average value over all values of the data array.
861  *  \throw If \a this->getNumberOfComponents() != 1
862  *  \throw If the data array is not set or it is empty.
863  */
864 double MEDCouplingFieldDouble::getAverageValue() const
865 {
866   if(getArray()==0)
867     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getAverageValue : no default array defined !");
868   return getArray()->getAverageValue();
869 }
870
871 /*!
872  * This method returns the euclidean norm of \a this field.
873  * \f[
874  * \sqrt{\sum_{0 \leq i < nbOfEntity}val[i]*val[i]}
875  * \f]
876  *  \throw If the data array is not set.
877  */
878 double MEDCouplingFieldDouble::norm2() const
879 {
880   if(getArray()==0)
881     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::norm2 : no default array defined !");
882   return getArray()->norm2();
883 }
884
885 /*!
886  * This method returns the max norm of \a this field.
887  * \f[
888  * \max_{0 \leq i < nbOfEntity}{abs(val[i])}
889  * \f]
890  *  \throw If the data array is not set.
891  */
892 double MEDCouplingFieldDouble::normMax() const
893 {
894   if(getArray()==0)
895     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::normMax : no default array defined !");
896   return getArray()->normMax();
897 }
898
899 /*!
900  * Computes the weighted average of values of each component of \a this field, the weights being the
901  * values returned by buildMeasureField().  
902  *  \param [out] res - pointer to an array of result sum values, of size at least \a
903  *         this->getNumberOfComponents(), that is to be allocated by the caller.
904  *  \param [in] isWAbs - if \c true (default), \c abs() is applied to the weights computed by
905  *         buildMeasureField(). It makes this method slower. If you are sure that all
906  *         the cells of the underlying mesh have a correct orientation (no negative volume), you can put \a isWAbs ==
907  *         \c false to speed up the method.
908  *  \throw If the mesh is not set.
909  *  \throw If the data array is not set.
910  */
911 void MEDCouplingFieldDouble::getWeightedAverageValue(double *res, bool isWAbs) const
912 {
913   if(getArray()==0)
914     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getWeightedAverageValue : no default array defined !");
915   MCAuto<MEDCouplingFieldDouble> w=buildMeasureField(isWAbs);
916   double deno=w->getArray()->accumulate(0);
917   MCAuto<DataArrayDouble> arr=getArray()->deepCopy();
918   arr->multiplyEqual(w->getArray());
919   arr->accumulate(res);
920   int nCompo = getArray()->getNumberOfComponents();
921   std::transform(res,res+nCompo,res,std::bind2nd(std::multiplies<double>(),1./deno));
922 }
923
924 /*!
925  * Computes the weighted average of values of a given component of \a this field, the weights being the
926  * values returned by buildMeasureField().
927  *  \param [in] compId - an index of the component of interest.
928  *  \param [in] isWAbs - if \c true (default), \c abs() is applied to the weights computed by
929  *         buildMeasureField(). It makes this method slower. If you are sure that all
930  *         the cells of the underlying mesh have a correct orientation (no negative volume), you can put \a isWAbs ==
931  *         \c false to speed up the method.
932  *  \throw If the mesh is not set.
933  *  \throw If the data array is not set.
934  *  \throw If \a compId is not valid.
935            A valid range is ( 0 <= \a compId < \a this->getNumberOfComponents() ).
936  */
937 double MEDCouplingFieldDouble::getWeightedAverageValue(int compId, bool isWAbs) const
938 {
939   int nbComps=getArray()->getNumberOfComponents();
940   if(compId<0 || compId>=nbComps)
941     {
942       std::ostringstream oss; oss << "MEDCouplingFieldDouble::getWeightedAverageValue : Invalid compId specified : No such nb of components ! Should be in [0," << nbComps << ") !";
943       throw INTERP_KERNEL::Exception(oss.str());
944     }
945   INTERP_KERNEL::AutoPtr<double> res=new double[nbComps];
946   getWeightedAverageValue(res,isWAbs);
947   return res[compId];
948 }
949
950 /*!
951  * Returns the \c normL1 of values of a given component of \a this field:
952  * \f[
953  * \frac{\sum_{0 \leq i < nbOfEntity}|val[i]*Vol[i]|}{\sum_{0 \leq i < nbOfEntity}|Vol[i]|}
954  * \f]
955  *  \param [in] compId - an index of the component of interest.
956  *  \throw If the mesh is not set.
957  *  \throw If the spatial discretization of \a this field is NULL.
958  *  \throw If \a compId is not valid.
959            A valid range is ( 0 <= \a compId < \a this->getNumberOfComponents() ).
960  */
961 double MEDCouplingFieldDouble::normL1(int compId) const
962 {
963   if(!_mesh)
964     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform normL1 !");
965   if(_type.isNull())
966     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform normL1 !");
967   int nbComps=getArray()->getNumberOfComponents();
968   if(compId<0 || compId>=nbComps)
969     {
970       std::ostringstream oss; oss << "MEDCouplingFieldDouble::normL1 : Invalid compId specified : No such nb of components ! Should be in [0," << nbComps << ") !";
971       throw INTERP_KERNEL::Exception(oss.str());
972     }
973   INTERP_KERNEL::AutoPtr<double> res=new double[nbComps];
974   _type->normL1(_mesh,getArray(),res);
975   return res[compId];
976 }
977
978 /*!
979  * Returns the \c normL1 of values of each component of \a this field:
980  * \f[
981  * \frac{\sum_{0 \leq i < nbOfEntity}|val[i]*Vol[i]|}{\sum_{0 \leq i < nbOfEntity}|Vol[i]|}
982  * \f]
983  *  \param [out] res - pointer to an array of result values, of size at least \a
984  *         this->getNumberOfComponents(), that is to be allocated by the caller.
985  *  \throw If the mesh is not set.
986  *  \throw If the spatial discretization of \a this field is NULL.
987  */
988 void MEDCouplingFieldDouble::normL1(double *res) const
989 {
990   if(!_mesh)
991     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform normL1");
992   if(_type.isNull())
993     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform normL1 !");
994   _type->normL1(_mesh,getArray(),res);
995 }
996
997 /*!
998  * Returns the \c normL2 of values of a given component of \a this field:
999  * \f[
1000  * \sqrt{\frac{\sum_{0 \leq i < nbOfEntity}|val[i]^{2}*Vol[i]|}{\sum_{0 \leq i < nbOfEntity}|Vol[i]|}}
1001  * \f]
1002  *  \param [in] compId - an index of the component of interest.
1003  *  \throw If the mesh is not set.
1004  *  \throw If the spatial discretization of \a this field is NULL.
1005  *  \throw If \a compId is not valid.
1006            A valid range is ( 0 <= \a compId < \a this->getNumberOfComponents() ).
1007  */
1008 double MEDCouplingFieldDouble::normL2(int compId) const
1009 {
1010   if(!_mesh)
1011     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform normL2");
1012   if(_type.isNull())
1013     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform normL2 !");
1014   int nbComps=getArray()->getNumberOfComponents();
1015   if(compId<0 || compId>=nbComps)
1016     {
1017       std::ostringstream oss; oss << "MEDCouplingFieldDouble::normL2 : Invalid compId specified : No such nb of components ! Should be in [0," << nbComps << ") !";
1018       throw INTERP_KERNEL::Exception(oss.str());
1019     }
1020   INTERP_KERNEL::AutoPtr<double> res=new double[nbComps];
1021   _type->normL2(_mesh,getArray(),res);
1022   return res[compId];
1023 }
1024
1025 /*!
1026  * Returns the \c normL2 of values of each component of \a this field:
1027  * \f[
1028  * \sqrt{\frac{\sum_{0 \leq i < nbOfEntity}|val[i]^{2}*Vol[i]|}{\sum_{0 \leq i < nbOfEntity}|Vol[i]|}}
1029  * \f]
1030  *  \param [out] res - pointer to an array of result values, of size at least \a
1031  *         this->getNumberOfComponents(), that is to be allocated by the caller.
1032  *  \throw If the mesh is not set.
1033  *  \throw If the spatial discretization of \a this field is NULL.
1034  */
1035 void MEDCouplingFieldDouble::normL2(double *res) const
1036 {
1037   if(!_mesh)
1038     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform normL2");
1039   if(_type.isNull())
1040     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform normL2 !");
1041   _type->normL2(_mesh,getArray(),res);
1042 }
1043
1044 /*!
1045  * Computes a sum of values of a given component of \a this field multiplied by
1046  * values returned by buildMeasureField().
1047  * This method is useful to check the conservativity of interpolation method.
1048  *  \param [in] compId - an index of the component of interest.
1049  *  \param [in] isWAbs - if \c true (default), \c abs() is applied to the weighs computed by
1050  *         buildMeasureField() that makes this method slower. If a user is sure that all
1051  *         cells of the underlying mesh have correct orientation, he can put \a isWAbs ==
1052  *         \c false that speeds up this method.
1053  *  \throw If the mesh is not set.
1054  *  \throw If the data array is not set.
1055  *  \throw If \a compId is not valid.
1056            A valid range is ( 0 <= \a compId < \a this->getNumberOfComponents() ).
1057  */
1058 double MEDCouplingFieldDouble::integral(int compId, bool isWAbs) const
1059 {
1060   if(!_mesh)
1061     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform integral");
1062   if(_type.isNull())
1063     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform integral !");
1064   int nbComps=getArray()->getNumberOfComponents();
1065   if(compId<0 || compId>=nbComps)
1066     {
1067       std::ostringstream oss; oss << "MEDCouplingFieldDouble::integral : Invalid compId specified : No such nb of components ! Should be in [0," << nbComps << ") !";
1068       throw INTERP_KERNEL::Exception(oss.str());
1069     }
1070   INTERP_KERNEL::AutoPtr<double> res=new double[nbComps];
1071   _type->integral(_mesh,getArray(),isWAbs,res);
1072   return res[compId];
1073 }
1074
1075 /*!
1076  * Computes a sum of values of each component of \a this field multiplied by
1077  * values returned by buildMeasureField().
1078  * This method is useful to check the conservativity of interpolation method.
1079  *  \param [in] isWAbs - if \c true (default), \c abs() is applied to the weighs computed by
1080  *         buildMeasureField() that makes this method slower. If a user is sure that all
1081  *         cells of the underlying mesh have correct orientation, he can put \a isWAbs ==
1082  *         \c false that speeds up this method.
1083  *  \param [out] res - pointer to an array of result sum values, of size at least \a
1084  *         this->getNumberOfComponents(), that is to be allocated by the caller.
1085  *  \throw If the mesh is not set.
1086  *  \throw If the data array is not set.
1087  *  \throw If the spatial discretization of \a this field is NULL.
1088  */
1089 void MEDCouplingFieldDouble::integral(bool isWAbs, double *res) const
1090 {
1091   if(!_mesh)
1092     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform integral2");
1093   if(_type.isNull())
1094     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform integral2 !");
1095   _type->integral(_mesh,getArray(),isWAbs,res);
1096 }
1097
1098 /*!
1099  * Returns a value at a given cell of a structured mesh. The cell is specified by its
1100  * (i,j,k) index.
1101  *  \param [in] i - a index of node coordinates array along X axis. The cell is
1102  *         located between the i-th and ( i + 1 )-th nodes along X axis.
1103  *  \param [in] j - a index of node coordinates array along Y axis. The cell is
1104  *         located between the j-th and ( j + 1 )-th nodes along Y axis.
1105  *  \param [in] k - a index of node coordinates array along Z axis. The cell is
1106  *         located between the k-th and ( k + 1 )-th nodes along Z axis.
1107  *  \param [out] res - pointer to an array returning a feild value, of size at least
1108  *         \a this->getNumberOfComponents(), that is to be allocated by the caller.
1109  *  \throw If the spatial discretization of \a this field is NULL.
1110  *  \throw If the mesh is not set.
1111  *  \throw If the mesh is not a structured one.
1112  *
1113  *  \if ENABLE_EXAMPLES
1114  *  \ref cpp_mcfielddouble_getValueOnPos "Here is a C++ example".<br>
1115  *  \ref  py_mcfielddouble_getValueOnPos "Here is a Python example".
1116  *  \endif
1117  */
1118 void MEDCouplingFieldDouble::getValueOnPos(int i, int j, int k, double *res) const
1119 {
1120   const DataArrayDouble *arr=timeDiscr()->getArray();
1121   if(!_mesh)
1122     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform getValueOnPos");
1123   if(_type.isNull())
1124     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform getValueOnPos !");
1125   _type->getValueOnPos(arr,_mesh,i,j,k,res);
1126 }
1127
1128 /*!
1129  * Returns a value of \a this at a given point using spatial discretization.
1130  *  \param [in] spaceLoc - the point of interest.
1131  *  \param [out] res - pointer to an array returning a feild value, of size at least
1132  *         \a this->getNumberOfComponents(), that is to be allocated by the caller.
1133  *  \throw If the spatial discretization of \a this field is NULL.
1134  *  \throw If the mesh is not set.
1135  *  \throw If \a spaceLoc is out of the spatial discretization.
1136  *
1137  *  \if ENABLE_EXAMPLES
1138  *  \ref cpp_mcfielddouble_getValueOn "Here is a C++ example".<br>
1139  *  \ref  py_mcfielddouble_getValueOn "Here is a Python example".
1140  *  \endif
1141  */
1142 void MEDCouplingFieldDouble::getValueOn(const double *spaceLoc, double *res) const
1143 {
1144   const DataArrayDouble *arr=timeDiscr()->getArray();
1145   if(!_mesh)
1146     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform getValueOn");
1147   if(_type.isNull())
1148     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform getValueOnPos !");
1149   _type->getValueOn(arr,_mesh,spaceLoc,res);
1150 }
1151
1152 /*!
1153  * Returns values of \a this at given points using spatial discretization.
1154  *  \param [in] spaceLoc - coordinates of points of interest in full-interlace
1155  *          mode. This array is to be of size ( \a nbOfPoints * \a this->getNumberOfComponents() ).
1156  *  \param [in] nbOfPoints - number of points of interest.
1157  *  \return DataArrayDouble * - a new instance of DataArrayDouble holding field
1158  *         values relating to the input points. This array is of size \a nbOfPoints
1159  *         tuples per \a this->getNumberOfComponents() components. The caller is to 
1160  *         delete this array using decrRef() as it is no more needed.
1161  *  \throw If the spatial discretization of \a this field is NULL.
1162  *  \throw If the mesh is not set.
1163  *  \throw If any point in \a spaceLoc is out of the spatial discretization.
1164  *
1165  *  \if ENABLE_EXAMPLES
1166  *  \ref cpp_mcfielddouble_getValueOnMulti "Here is a C++ example".<br>
1167  *  \ref  py_mcfielddouble_getValueOnMulti "Here is a Python example".
1168  *  \endif
1169  */
1170 DataArrayDouble *MEDCouplingFieldDouble::getValueOnMulti(const double *spaceLoc, int nbOfPoints) const
1171 {
1172   const DataArrayDouble *arr=timeDiscr()->getArray();
1173   if(!_mesh)
1174     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform getValueOnMulti");
1175   if(_type.isNull())
1176     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform getValueOnMulti !");
1177   return _type->getValueOnMulti(arr,_mesh,spaceLoc,nbOfPoints);
1178 }
1179
1180 /*!
1181  * Returns a value of \a this field at a given point at a given time using spatial discretization.
1182  * If the time is not covered by \a this->_time_discr, an exception is thrown.
1183  *  \param [in] spaceLoc - the point of interest.
1184  *  \param [in] time - the time of interest.
1185  *  \param [out] res - pointer to an array returning a feild value, of size at least
1186  *         \a this->getNumberOfComponents(), that is to be allocated by the caller.
1187  *  \throw If the spatial discretization of \a this field is NULL.
1188  *  \throw If the mesh is not set.
1189  *  \throw If \a spaceLoc is out of the spatial discretization.
1190  *  \throw If \a time is not covered by \a this->_time_discr.
1191  *
1192  *  \if ENABLE_EXAMPLES
1193  *  \ref cpp_mcfielddouble_getValueOn_time "Here is a C++ example".<br>
1194  *  \ref  py_mcfielddouble_getValueOn_time "Here is a Python example".
1195  *  \endif
1196  */
1197 void MEDCouplingFieldDouble::getValueOn(const double *spaceLoc, double time, double *res) const
1198 {
1199   std::vector< const DataArrayDouble *> arrs=timeDiscr()->getArraysForTime(time);
1200   if(!_mesh)
1201     throw INTERP_KERNEL::Exception("No mesh underlying this field to perform getValueOn");
1202   if(_type.isNull())
1203     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform getValueOn !");
1204   std::vector<double> res2;
1205   for(std::vector< const DataArrayDouble *>::const_iterator iter=arrs.begin();iter!=arrs.end();iter++)
1206     {
1207       int sz=(int)res2.size();
1208       res2.resize(sz+(*iter)->getNumberOfComponents());
1209       _type->getValueOn(*iter,_mesh,spaceLoc,&res2[sz]);
1210     }
1211   timeDiscr()->getValueForTime(time,res2,res);
1212 }
1213
1214 /*!
1215  * Apply a linear function to a given component of \a this field, so that
1216  * a component value <em>(x)</em> becomes \f$ a * x + b \f$.
1217  *  \param [in] a - the first coefficient of the function.
1218  *  \param [in] b - the second coefficient of the function.
1219  *  \param [in] compoId - the index of component to modify.
1220  *  \throw If the data array(s) is(are) not set.
1221  */
1222 void MEDCouplingFieldDouble::applyLin(double a, double b, int compoId)
1223 {
1224   timeDiscr()->applyLin(a,b,compoId);
1225 }
1226
1227 /*!
1228  * Apply a linear function to all components of \a this field, so that
1229  * values <em>(x)</em> becomes \f$ a * x + b \f$.
1230  *  \param [in] a - the first coefficient of the function.
1231  *  \param [in] b - the second coefficient of the function.
1232  *  \throw If the data array(s) is(are) not set.
1233  */
1234 void MEDCouplingFieldDouble::applyLin(double a, double b)
1235 {
1236   timeDiscr()->applyLin(a,b);
1237 }
1238
1239 /*!
1240  * This method sets \a this to a uniform scalar field with one component.
1241  * All tuples will have the same value 'value'.
1242  * An exception is thrown if no underlying mesh is defined.
1243  */
1244 MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator=(double value)
1245 {
1246   if(!_mesh)
1247     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::operator= : no mesh defined !");
1248   if(_type.isNull())
1249     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform operator = !");
1250   int nbOfTuple=_type->getNumberOfTuples(_mesh);
1251   timeDiscr()->setOrCreateUniformValueOnAllComponents(nbOfTuple,value);
1252   return *this;
1253 }
1254
1255 /*!
1256  * Creates data array(s) of \a this field by using a C function for value generation.
1257  *  \param [in] nbOfComp - the number of components for \a this field to have.
1258  *  \param [in] func - the function used to compute values of \a this field.
1259  *         This function is to compute a field value basing on coordinates of value
1260  *         location point.
1261  *  \throw If the mesh is not set.
1262  *  \throw If \a func returns \c false.
1263  *  \throw If the spatial discretization of \a this field is NULL.
1264  *
1265  *  \if ENABLE_EXAMPLES
1266  *  \ref cpp_mcfielddouble_fillFromAnalytic_c_func "Here is a C++ example".
1267  *  \endif
1268  */
1269 void MEDCouplingFieldDouble::fillFromAnalytic(int nbOfComp, FunctionToEvaluate func)
1270 {
1271   if(!_mesh)
1272     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::fillFromAnalytic : no mesh defined !");
1273   if(_type.isNull())
1274     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform fillFromAnalytic !");
1275   MCAuto<DataArrayDouble> loc=_type->getLocalizationOfDiscValues(_mesh);
1276   timeDiscr()->fillFromAnalytic(loc,nbOfComp,func);
1277 }
1278
1279 /*!
1280  * Creates data array(s) of \a this field by using a function for value generation.<br>
1281  * The function is applied to coordinates of value location points. For example, if
1282  * \a this field is on cells, the function is applied to cell barycenters.
1283  * For more info on supported expressions that can be used in the function, see \ref
1284  * MEDCouplingArrayApplyFuncExpr. <br>
1285  * The function can include arbitrary named variables
1286  * (e.g. "x","y" or "va44") to refer to components of point coordinates. Names of
1287  * variables are sorted in \b alphabetical \b order to associate a variable name with a
1288  * component. For example, in the expression "2*x+z", "x" stands for the component #0
1289  * and "z" stands for the component #1 (\b not #2)!<br>
1290  * In a general case, a value resulting from the function evaluation is assigned to all
1291  * components of a field value. But there is a possibility to have its own expression for
1292  * each component within one function. For this purpose, there are predefined variable
1293  * names (IVec, JVec, KVec, LVec etc) each dedicated to a certain component (IVec, to
1294  * the component #0 etc). A factor of such a variable is added to the
1295  * corresponding component only.<br>
1296  * For example, \a nbOfComp == 4, coordinates of a 3D point are (1.,3.,7.), then
1297  *   - "2*x + z"               produces (5.,5.,5.,5.)
1298  *   - "2*x + 0*y + z"         produces (9.,9.,9.,9.)
1299  *   - "2*x*IVec + (x+z)*LVec" produces (2.,0.,0.,4.)
1300  *   - "2*y*IVec + z*KVec + x" produces (7.,1.,1.,4.)
1301  *
1302  *  \param [in] nbOfComp - the number of components for \a this field to have.
1303  *  \param [in] func - the function used to compute values of \a this field.
1304  *         This function is used to compute a field value basing on coordinates of value
1305  *         location point. For example, if \a this field is on cells, the function
1306  *         is applied to cell barycenters.
1307  *  \throw If the mesh is not set.
1308  *  \throw If the spatial discretization of \a this field is NULL.
1309  *  \throw If computing \a func fails.
1310  *
1311  *  \if ENABLE_EXAMPLES
1312  *  \ref cpp_mcfielddouble_fillFromAnalytic "Here is a C++ example".<br>
1313  *  \ref  py_mcfielddouble_fillFromAnalytic "Here is a Python example".
1314  *  \endif
1315  */
1316 void MEDCouplingFieldDouble::fillFromAnalytic(int nbOfComp, const std::string& func)
1317 {
1318   if(!_mesh)
1319     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::fillFromAnalytic : no mesh defined !");
1320   if(_type.isNull())
1321     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform fillFromAnalytic !");
1322   MCAuto<DataArrayDouble> loc=_type->getLocalizationOfDiscValues(_mesh);
1323   timeDiscr()->fillFromAnalytic(loc,nbOfComp,func);
1324 }
1325
1326 /*!
1327  * Creates data array(s) of \a this field by using a function for value generation.<br>
1328  * The function is applied to coordinates of value location points. For example, if
1329  * \a this field is on cells, the function is applied to cell barycenters.<br>
1330  * This method differs from
1331  * \ref MEDCoupling::MEDCouplingFieldDouble::fillFromAnalytic(int nbOfComp, const std::string& func) "fillFromAnalytic()"
1332  * by the way how variable
1333  * names, used in the function, are associated with components of coordinates of field
1334  * location points; here, a variable name corresponding to a component is retrieved from
1335  * a corresponding node coordinates array (where it is set via
1336  * DataArrayDouble::setInfoOnComponent()).<br>
1337  * For more info on supported expressions that can be used in the function, see \ref
1338  * MEDCouplingArrayApplyFuncExpr. <br> 
1339  * In a general case, a value resulting from the function evaluation is assigned to all
1340  * components of a field value. But there is a possibility to have its own expression for
1341  * each component within one function. For this purpose, there are predefined variable
1342  * names (IVec, JVec, KVec, LVec etc) each dedicated to a certain component (IVec, to
1343  * the component #0 etc). A factor of such a variable is added to the
1344  * corresponding component only.<br>
1345  * For example, \a nbOfComp == 4, names of spatial components are "x", "y" and "z",
1346  * coordinates of a 3D point are (1.,3.,7.), then
1347  *   - "2*x + z"               produces (9.,9.,9.,9.)
1348  *   - "2*x*IVec + (x+z)*LVec" produces (2.,0.,0.,8.)
1349  *   - "2*y*IVec + z*KVec + x" produces (7.,1.,1.,8.)
1350  *
1351  *  \param [in] nbOfComp - the number of components for \a this field to have.
1352  *  \param [in] func - the function used to compute values of \a this field.
1353  *         This function is used to compute a field value basing on coordinates of value
1354  *         location point. For example, if \a this field is on cells, the function
1355  *         is applied to cell barycenters.
1356  *  \throw If the mesh is not set.
1357  *  \throw If the spatial discretization of \a this field is NULL.
1358  *  \throw If computing \a func fails.
1359  *
1360  *  \if ENABLE_EXAMPLES
1361  *  \ref cpp_mcfielddouble_fillFromAnalytic2 "Here is a C++ example".<br>
1362  *  \ref  py_mcfielddouble_fillFromAnalytic2 "Here is a Python example".
1363  *  \endif
1364  */
1365 void MEDCouplingFieldDouble::fillFromAnalyticCompo(int nbOfComp, const std::string& func)
1366 {
1367   if(!_mesh)
1368     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::fillFromAnalyticCompo : no mesh defined !");
1369   if(_type.isNull())
1370     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform fillFromAnalyticCompo !");
1371   MCAuto<DataArrayDouble> loc=_type->getLocalizationOfDiscValues(_mesh);
1372   timeDiscr()->fillFromAnalyticCompo(loc,nbOfComp,func);
1373 }
1374
1375 /*!
1376  * Creates data array(s) of \a this field by using a function for value generation.<br>
1377  * The function is applied to coordinates of value location points. For example, if
1378  * \a this field is on cells, the function is applied to cell barycenters.<br>
1379  * This method differs from
1380  * \ref MEDCoupling::MEDCouplingFieldDouble::fillFromAnalytic(int nbOfComp, const std::string& func) "fillFromAnalytic()"
1381  * by the way how variable
1382  * names, used in the function, are associated with components of coordinates of field
1383  * location points; here, a component index of a variable is defined by a
1384  * rank of the variable within the input array \a varsOrder.<br>
1385  * For more info on supported expressions that can be used in the function, see \ref
1386  * MEDCouplingArrayApplyFuncExpr.
1387  * In a general case, a value resulting from the function evaluation is assigned to all
1388  * components of a field value. But there is a possibility to have its own expression for
1389  * each component within one function. For this purpose, there are predefined variable
1390  * names (IVec, JVec, KVec, LVec etc) each dedicated to a certain component (IVec, to
1391  * the component #0 etc). A factor of such a variable is added to the
1392  * corresponding component only.<br>
1393  * For example, \a nbOfComp == 4, names of
1394  * spatial components are given in \a varsOrder: ["x", "y","z"], coordinates of a
1395  * 3D point are (1.,3.,7.), then
1396  *   - "2*x + z"               produces (9.,9.,9.,9.)
1397  *   - "2*x*IVec + (x+z)*LVec" produces (2.,0.,0.,8.)
1398  *   - "2*y*IVec + z*KVec + x" produces (7.,1.,1.,8.)
1399  *
1400  *  \param [in] nbOfComp - the number of components for \a this field to have.
1401  *  \param [in] func - the function used to compute values of \a this field.
1402  *         This function is used to compute a field value basing on coordinates of value
1403  *         location point. For example, if \a this field is on cells, the function
1404  *         is applied to cell barycenters.
1405  *  \throw If the mesh is not set.
1406  *  \throw If the spatial discretization of \a this field is NULL.
1407  *  \throw If computing \a func fails.
1408  *
1409  *  \if ENABLE_EXAMPLES
1410  *  \ref cpp_mcfielddouble_fillFromAnalytic3 "Here is a C++ example".<br>
1411  *  \ref  py_mcfielddouble_fillFromAnalytic3 "Here is a Python example".
1412  *  \endif
1413  */
1414 void MEDCouplingFieldDouble::fillFromAnalyticNamedCompo(int nbOfComp, const std::vector<std::string>& varsOrder, const std::string& func)
1415 {
1416   if(!_mesh)
1417     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::fillFromAnalyticCompo : no mesh defined !");
1418   if(_type.isNull())
1419     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform fillFromAnalyticNamedCompo !");
1420   MCAuto<DataArrayDouble> loc=_type->getLocalizationOfDiscValues(_mesh);
1421   timeDiscr()->fillFromAnalyticNamedCompo(loc,nbOfComp,varsOrder,func);
1422 }
1423
1424 /*!
1425  * Modifies values of \a this field by applying a C function to each tuple of all
1426  * data arrays.
1427  *  \param [in] nbOfComp - the number of components for \a this field to have.
1428  *  \param [in] func - the function used to compute values of \a this field.
1429  *         This function is to compute a field value basing on a current field value.
1430  *  \throw If \a func returns \c false.
1431  *
1432  *  \if ENABLE_EXAMPLES
1433  *  \ref cpp_mcfielddouble_applyFunc_c_func "Here is a C++ example".
1434  *  \endif
1435  */
1436 void MEDCouplingFieldDouble::applyFunc(int nbOfComp, FunctionToEvaluate func)
1437 {
1438   timeDiscr()->applyFunc(nbOfComp,func);
1439 }
1440
1441 /*!
1442  * Fill \a this field with a given value.<br>
1443  * This method is a specialization of other overloaded methods. When \a nbOfComp == 1
1444  * this method is equivalent to MEDCoupling::MEDCouplingFieldDouble::operator=().
1445  *  \param [in] nbOfComp - the number of components for \a this field to have.
1446  *  \param [in] val - the value to assign to every atomic value of \a this field.
1447  *  \throw If the spatial discretization of \a this field is NULL.
1448  *  \throw If the mesh is not set.
1449  *
1450  *  \if ENABLE_EXAMPLES
1451  *  \ref cpp_mcfielddouble_applyFunc_val "Here is a C++ example".<br>
1452  *  \ref  py_mcfielddouble_applyFunc_val "Here is a Python example".
1453  *  \endif
1454  */
1455 void MEDCouplingFieldDouble::applyFunc(int nbOfComp, double val)
1456 {
1457   if(!_mesh)
1458     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::applyFunc : no mesh defined !");
1459   if(_type.isNull())
1460     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform applyFunc !");
1461   int nbOfTuple=_type->getNumberOfTuples(_mesh);
1462   timeDiscr()->setUniformValue(nbOfTuple,nbOfComp,val);
1463 }
1464
1465 /*!
1466  * Modifies values of \a this field by applying a function to each tuple of all
1467  * data arrays.
1468  * For more info on supported expressions that can be used in the function, see \ref
1469  * MEDCouplingArrayApplyFuncExpr. <br>
1470  * The function can include arbitrary named variables
1471  * (e.g. "x","y" or "va44") to refer to components of a field value. Names of
1472  * variables are sorted in \b alphabetical \b order to associate a variable name with a
1473  * component. For example, in the expression "2*x+z", "x" stands for the component #0
1474  * and "z" stands for the component #1 (\b not #2)!<br>
1475  * In a general case, a value resulting from the function evaluation is assigned to all
1476  * components of a field value. But there is a possibility to have its own expression for
1477  * each component within one function. For this purpose, there are predefined variable
1478  * names (IVec, JVec, KVec, LVec etc) each dedicated to a certain component (IVec, to
1479  * the component #0 etc). A factor of such a variable is added to the
1480  * corresponding component only.<br>
1481  * For example, \a nbOfComp == 4, components of a field value are (1.,3.,7.), then
1482  *   - "2*x + z"               produces (5.,5.,5.,5.)
1483  *   - "2*x + 0*y + z"         produces (9.,9.,9.,9.)
1484  *   - "2*x*IVec + (x+z)*LVec" produces (2.,0.,0.,4.)
1485  *   - "2*y*IVec + z*KVec + x" produces (7.,1.,1.,4.)
1486  *
1487  *  \param [in] nbOfComp - the number of components for \a this field to have.
1488  *  \param [in] func - the function used to compute values of \a this field.
1489  *         This function is to compute a field value basing on a current field value.
1490  *  \throw If computing \a func fails.
1491  *
1492  *  \if ENABLE_EXAMPLES
1493  *  \ref cpp_mcfielddouble_applyFunc "Here is a C++ example".<br>
1494  *  \ref  py_mcfielddouble_applyFunc "Here is a Python example".
1495  *  \endif
1496  */
1497 void MEDCouplingFieldDouble::applyFunc(int nbOfComp, const std::string& func)
1498 {
1499   timeDiscr()->applyFunc(nbOfComp,func);
1500 }
1501
1502
1503 /*!
1504  * Modifies values of \a this field by applying a function to each tuple of all
1505  * data arrays.
1506  * For more info on supported expressions that can be used in the function, see \ref
1507  * MEDCouplingArrayApplyFuncExpr. <br>
1508  * This method differs from
1509  * \ref MEDCoupling::MEDCouplingFieldDouble::applyFunc(int nbOfComp, const std::string& func) "applyFunc()"
1510  * by the way how variable
1511  * names, used in the function, are associated with components of field values;
1512  * here, a variable name corresponding to a component is retrieved from
1513  * component information of an array (where it is set via
1514  * DataArrayDouble::setInfoOnComponent()).<br>
1515  * In a general case, a value resulting from the function evaluation is assigned to all
1516  * components of a field value. But there is a possibility to have its own expression for
1517  * each component within one function. For this purpose, there are predefined variable
1518  * names (IVec, JVec, KVec, LVec etc) each dedicated to a certain component (IVec, to
1519  * the component #0 etc). A factor of such a variable is added to the
1520  * corresponding component only.<br>
1521  * For example, \a nbOfComp == 4, components of a field value are (1.,3.,7.), then
1522  *   - "2*x + z"               produces (5.,5.,5.,5.)
1523  *   - "2*x + 0*y + z"         produces (9.,9.,9.,9.)
1524  *   - "2*x*IVec + (x+z)*LVec" produces (2.,0.,0.,4.)
1525  *   - "2*y*IVec + z*KVec + x" produces (7.,1.,1.,4.)
1526  *
1527  *  \param [in] nbOfComp - the number of components for \a this field to have.
1528  *  \param [in] func - the function used to compute values of \a this field.
1529  *         This function is to compute a new field value basing on a current field value.
1530  *  \throw If computing \a func fails.
1531  *
1532  *  \if ENABLE_EXAMPLES
1533  *  \ref cpp_mcfielddouble_applyFunc2 "Here is a C++ example".<br>
1534  *  \ref  py_mcfielddouble_applyFunc2 "Here is a Python example".
1535  *  \endif
1536  */
1537 void MEDCouplingFieldDouble::applyFuncCompo(int nbOfComp, const std::string& func)
1538 {
1539   timeDiscr()->applyFuncCompo(nbOfComp,func);
1540 }
1541
1542 /*!
1543  * Modifies values of \a this field by applying a function to each tuple of all
1544  * data arrays.
1545  * This method differs from
1546  * \ref MEDCoupling::MEDCouplingFieldDouble::applyFunc(int nbOfComp, const std::string& func) "applyFunc()"
1547  * by the way how variable
1548  * names, used in the function, are associated with components of field values;
1549  * here, a component index of a variable is defined by a
1550  * rank of the variable within the input array \a varsOrder.<br>
1551  * For more info on supported expressions that can be used in the function, see \ref
1552  * MEDCouplingArrayApplyFuncExpr.
1553  * In a general case, a value resulting from the function evaluation is assigned to all
1554  * components of a field value. But there is a possibility to have its own expression for
1555  * each component within one function. For this purpose, there are predefined variable
1556  * names (IVec, JVec, KVec, LVec etc) each dedicated to a certain component (IVec, to
1557  * the component #0 etc). A factor of such a variable is added to the
1558  * corresponding component only.<br>
1559  * For example, \a nbOfComp == 4, names of
1560  * components are given in \a varsOrder: ["x", "y","z"], components of a
1561  * 3D vector are (1.,3.,7.), then
1562  *   - "2*x + z"               produces (9.,9.,9.,9.)
1563  *   - "2*x*IVec + (x+z)*LVec" produces (2.,0.,0.,8.)
1564  *   - "2*y*IVec + z*KVec + x" produces (7.,1.,1.,8.)
1565  *
1566  *  \param [in] nbOfComp - the number of components for \a this field to have.
1567  *  \param [in] func - the function used to compute values of \a this field.
1568  *         This function is to compute a new field value basing on a current field value.
1569  *  \throw If computing \a func fails.
1570  *
1571  *  \if ENABLE_EXAMPLES
1572  *  \ref cpp_mcfielddouble_applyFunc3 "Here is a C++ example".<br>
1573  *  \ref  py_mcfielddouble_applyFunc3 "Here is a Python example".
1574  *  \endif
1575  */
1576 void MEDCouplingFieldDouble::applyFuncNamedCompo(int nbOfComp, const std::vector<std::string>& varsOrder, const std::string& func)
1577 {
1578   timeDiscr()->applyFuncNamedCompo(nbOfComp,varsOrder,func);
1579 }
1580
1581 /*!
1582  * Modifies values of \a this field by applying a function to each atomic value of all
1583  * data arrays. The function computes a new single value basing on an old single value.
1584  * For more info on supported expressions that can be used in the function, see \ref
1585  * MEDCouplingArrayApplyFuncExpr. <br>
1586  * The function can include **only one** arbitrary named variable
1587  * (e.g. "x","y" or "va44") to refer to a field atomic value. <br>
1588  * In a general case, a value resulting from the function evaluation is assigned to 
1589  * a single field value. But there is a possibility to have its own expression for
1590  * each component within one function. For this purpose, there are predefined variable
1591  * names (IVec, JVec, KVec, LVec etc) each dedicated to a certain component (IVec, to
1592  * the component #0 etc). A factor of such a variable is added to the
1593  * corresponding component only.<br>
1594  * For example, components of a field value are (1.,3.,7.), then
1595  *   - "2*x - 1"               produces (1.,5.,13.)
1596  *   - "2*x*IVec + (x+3)*KVec" produces (2.,0.,10.)
1597  *   - "2*x*IVec + (x+3)*KVec + 1" produces (3.,1.,11.)
1598  *
1599  *  \param [in] func - the function used to compute values of \a this field.
1600  *         This function is to compute a field value basing on a current field value.
1601  *  \throw If computing \a func fails.
1602  *
1603  *  \if ENABLE_EXAMPLES
1604  *  \ref cpp_mcfielddouble_applyFunc_same_nb_comp "Here is a C++ example".<br>
1605  *  \ref  py_mcfielddouble_applyFunc_same_nb_comp "Here is a Python example".
1606  *  \endif
1607  */
1608 void MEDCouplingFieldDouble::applyFunc(const std::string& func)
1609 {
1610   timeDiscr()->applyFunc(func);
1611 }
1612
1613 /*!
1614  * Applyies the function specified by the string repr 'func' on each tuples on all arrays contained in _time_discr.
1615  * The field will contain exactly the same number of components after the call.
1616  * Use is not warranted for the moment !
1617  */
1618 void MEDCouplingFieldDouble::applyFuncFast32(const std::string& func)
1619 {
1620   timeDiscr()->applyFuncFast32(func);
1621 }
1622
1623 /*!
1624  * Applyies the function specified by the string repr 'func' on each tuples on all arrays contained in _time_discr.
1625  * The field will contain exactly the same number of components after the call.
1626  * Use is not warranted for the moment !
1627  */
1628 void MEDCouplingFieldDouble::applyFuncFast64(const std::string& func)
1629 {
1630   timeDiscr()->applyFuncFast64(func);
1631 }
1632
1633 /*!
1634  * Returns number of components in the data array. For more info on the data arrays,
1635  * see \ref arrays.
1636  *  \return int - the number of components in the data array.
1637  *  \throw If the data array is not set.
1638  */
1639 std::size_t MEDCouplingFieldDouble::getNumberOfComponents() const
1640 {
1641   if(getArray()==0)
1642     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getNumberOfComponents : No array specified !");
1643   return getArray()->getNumberOfComponents();
1644 }
1645
1646 /*!
1647  * Use MEDCouplingField::getNumberOfTuplesExpected instead of this method. This method will be removed soon, because it is
1648  * confusing compared to getNumberOfComponents() and getNumberOfValues() behaviour.
1649  *
1650  * Returns number of tuples in \a this field, that depends on 
1651  * - the number of entities in the underlying mesh
1652  * - \ref MEDCouplingSpatialDisc "spatial discretization" of \a this field (e.g. number
1653  * of Gauss points if \a this->getTypeOfField() == 
1654  * \ref MEDCoupling::ON_GAUSS_PT "ON_GAUSS_PT").
1655  *
1656  * The returned value does \b not \b depend on the number of tuples in the data array
1657  * (which has to be equal to the returned value), \b contrary to
1658  * getNumberOfComponents() and getNumberOfValues() that retrieve information from the
1659  * data array (Sorry, it is confusing !).
1660  * So \b this \b method \b behaves \b exactly \b as MEDCouplingField::getNumberOfTuplesExpected \b method.
1661  *
1662  * \warning No checkConsistencyLight() is done here.
1663  * For more info on the data arrays, see \ref arrays.
1664  *  \return int - the number of tuples.
1665  *  \throw If the mesh is not set.
1666  *  \throw If the spatial discretization of \a this field is NULL.
1667  *  \throw If the spatial discretization is not fully defined.
1668  *  \sa MEDCouplingField::getNumberOfTuplesExpected
1669  */
1670 std::size_t MEDCouplingFieldDouble::getNumberOfTuples() const
1671 {
1672   if(!_mesh)
1673     throw INTERP_KERNEL::Exception("Impossible to retrieve number of tuples because no mesh specified !");
1674   if(_type.isNull())
1675     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform getNumberOfTuples !");
1676   return _type->getNumberOfTuples(_mesh);
1677 }
1678
1679 /*!
1680  * Returns number of atomic double values in the data array of \a this field.
1681  * For more info on the data arrays, see \ref arrays.
1682  *  \return int - (number of tuples) * (number of components) of the
1683  *  data array.
1684  *  \throw If the data array is not set.
1685  */
1686 std::size_t MEDCouplingFieldDouble::getNumberOfValues() const
1687 {
1688   if(getArray()==0)
1689     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::getNumberOfValues : No array specified !");
1690   return getArray()->getNbOfElems();
1691 }
1692
1693 /*!
1694  * Sets own modification time by the most recently modified element of data (the mesh,
1695  * the data array etc). For more info, see \ref MEDCouplingTimeLabelPage.
1696  */
1697 void MEDCouplingFieldDouble::updateTime() const
1698 {
1699   MEDCouplingField::updateTime();
1700   updateTimeWith(*timeDiscr());
1701 }
1702
1703 std::size_t MEDCouplingFieldDouble::getHeapMemorySizeWithoutChildren() const
1704 {
1705   return MEDCouplingField::getHeapMemorySizeWithoutChildren();
1706 }
1707
1708 std::vector<const BigMemoryObject *> MEDCouplingFieldDouble::getDirectChildrenWithNull() const
1709 {
1710   std::vector<const BigMemoryObject *> ret(MEDCouplingField::getDirectChildrenWithNull());
1711   if(timeDiscr())
1712     {
1713       std::vector<const BigMemoryObject *> ret2(timeDiscr()->getDirectChildrenWithNull());
1714       ret.insert(ret.end(),ret2.begin(),ret2.end());
1715     }
1716   return ret;
1717 }
1718
1719 /*!
1720  * Returns a value of \a this field of type either
1721  * \ref MEDCoupling::ON_GAUSS_PT "ON_GAUSS_PT" or
1722  * \ref MEDCoupling::ON_GAUSS_NE "ON_GAUSS_NE".
1723  *  \param [in] cellId - an id of cell of interest.
1724  *  \param [in] nodeIdInCell - a node index within the cell.
1725  *  \param [in] compoId - an index of component.
1726  *  \return double - the field value corresponding to the specified parameters.
1727  *  \throw If the data array is not set.
1728  *  \throw If the mesh is not set.
1729  *  \throw If the spatial discretization of \a this field is NULL.
1730  *  \throw If \a this field if of type other than 
1731  *         \ref MEDCoupling::ON_GAUSS_PT "ON_GAUSS_PT" or
1732  *         \ref MEDCoupling::ON_GAUSS_NE "ON_GAUSS_NE".
1733  */
1734 double MEDCouplingFieldDouble::getIJK(int cellId, int nodeIdInCell, int compoId) const
1735 {
1736   if(_type.isNull())
1737     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform getIJK !");
1738   return _type->getIJK(_mesh,getArray(),cellId,nodeIdInCell,compoId);
1739 }
1740
1741 /*!
1742  * Sets the data array. 
1743  *  \param [in] array - the data array holding values of \a this field. It's size
1744  *         should correspond to the mesh and
1745  *         \ref MEDCouplingSpatialDisc "spatial discretization" of \a this field
1746  *         (see getNumberOfTuples()), but this size is not checked here.
1747  */
1748 //void MEDCouplingFieldDouble::setArray(DataArrayDouble *array)
1749
1750 /*!
1751  * Sets the data array holding values corresponding to an end of a time interval
1752  * for which \a this field is defined.
1753  *  \param [in] array - the data array holding values of \a this field. It's size
1754  *         should correspond to the mesh and
1755  *         \ref MEDCouplingSpatialDisc "spatial discretization" of \a this field
1756  *         (see getNumberOfTuples()), but this size is not checked here.
1757  */
1758 //void MEDCouplingFieldDouble::setEndArray(DataArrayDouble *array)
1759
1760 /*!
1761  * Sets all data arrays needed to define the field values.
1762  *  \param [in] arrs - a vector of DataArrayDouble's holding values of \a this
1763  *         field. Size of each array should correspond to the mesh and
1764  *         \ref MEDCouplingSpatialDisc "spatial discretization" of \a this field
1765  *         (see getNumberOfTuples()), but this size is not checked here.
1766  *  \throw If number of arrays in \a arrs does not correspond to type of
1767  *         \ref MEDCouplingTemporalDisc "temporal discretization" of \a this field.
1768  */
1769 //void MEDCouplingFieldDouble::setArrays(const std::vector<DataArrayDouble *>& arrs)
1770
1771 void MEDCouplingFieldDouble::getTinySerializationStrInformation(std::vector<std::string>& tinyInfo) const
1772 {
1773   tinyInfo.clear();
1774   timeDiscr()->getTinySerializationStrInformation(tinyInfo);
1775   tinyInfo.push_back(_name);
1776   tinyInfo.push_back(_desc);
1777   tinyInfo.push_back(getTimeUnit());
1778 }
1779
1780 /*!
1781  * This method retrieves some critical values to resize and prepare remote instance.
1782  * The first two elements returned in tinyInfo correspond to the parameters to give in constructor.
1783  * @param tinyInfo out parameter resized correctly after the call. The length of this vector is tiny.
1784  */
1785 void MEDCouplingFieldDouble::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
1786 {
1787   if(_type.isNull())
1788     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform getTinySerializationIntInformation !");
1789   tinyInfo.clear();
1790   tinyInfo.push_back((int)_type->getEnum());
1791   tinyInfo.push_back((int)timeDiscr()->getEnum());
1792   tinyInfo.push_back((int)_nature);
1793   timeDiscr()->getTinySerializationIntInformation(tinyInfo);
1794   std::vector<int> tinyInfo2;
1795   _type->getTinySerializationIntInformation(tinyInfo2);
1796   tinyInfo.insert(tinyInfo.end(),tinyInfo2.begin(),tinyInfo2.end());
1797   tinyInfo.push_back((int)tinyInfo2.size());
1798 }
1799
1800 /*!
1801  * This method retrieves some critical values to resize and prepare remote instance.
1802  * @param tinyInfo out parameter resized correctly after the call. The length of this vector is tiny.
1803  */
1804 void MEDCouplingFieldDouble::getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const
1805 {
1806   if(_type.isNull())
1807     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform getTinySerializationDbleInformation !");
1808   tinyInfo.clear();
1809   timeDiscr()->getTinySerializationDbleInformation(tinyInfo);
1810   std::vector<double> tinyInfo2;
1811   _type->getTinySerializationDbleInformation(tinyInfo2);
1812   tinyInfo.insert(tinyInfo.end(),tinyInfo2.begin(),tinyInfo2.end());
1813   tinyInfo.push_back((int)tinyInfo2.size());//very bad, lack of time to improve it
1814 }
1815
1816 /*!
1817  * This method has to be called to the new instance filled by CORBA, MPI, File...
1818  * @param tinyInfoI is the value retrieves from distant result of getTinySerializationIntInformation on source instance to be copied.
1819  * @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.
1820  * @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.
1821  *               No decrRef must be applied to every instances in returned vector.
1822  * \sa checkForUnserialization
1823  */
1824 void MEDCouplingFieldDouble::resizeForUnserialization(const std::vector<int>& tinyInfoI, DataArrayInt *&dataInt, std::vector<DataArrayDouble *>& arrays)
1825 {
1826   if(_type.isNull())
1827     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform resizeForUnserialization !");
1828   dataInt=0;
1829   std::vector<int> tinyInfoITmp(tinyInfoI);
1830   int sz=tinyInfoITmp.back();
1831   tinyInfoITmp.pop_back();
1832   std::vector<int> tinyInfoITmp2(tinyInfoITmp.begin(),tinyInfoITmp.end()-sz);
1833   std::vector<int> tinyInfoI2(tinyInfoITmp2.begin()+3,tinyInfoITmp2.end());
1834   timeDiscr()->resizeForUnserialization(tinyInfoI2,arrays);
1835   std::vector<int> tinyInfoITmp3(tinyInfoITmp.end()-sz,tinyInfoITmp.end());
1836   _type->resizeForUnserialization(tinyInfoITmp3,dataInt);
1837 }
1838
1839 /*!
1840  * This method is extremely close to resizeForUnserialization except that here the arrays in \a dataInt and in \a arrays are attached in \a this
1841  * after having checked that size is correct. This method is used in python pickeling context to avoid copy of data.
1842  * \sa resizeForUnserialization
1843  */
1844 void MEDCouplingFieldDouble::checkForUnserialization(const std::vector<int>& tinyInfoI, const DataArrayInt *dataInt, const std::vector<DataArrayDouble *>& arrays)
1845 {
1846   if(_type.isNull())
1847     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform resizeForUnserialization !");
1848   std::vector<int> tinyInfoITmp(tinyInfoI);
1849   int sz=tinyInfoITmp.back();
1850   tinyInfoITmp.pop_back();
1851   std::vector<int> tinyInfoITmp2(tinyInfoITmp.begin(),tinyInfoITmp.end()-sz);
1852   std::vector<int> tinyInfoI2(tinyInfoITmp2.begin()+3,tinyInfoITmp2.end());
1853   timeDiscr()->checkForUnserialization(tinyInfoI2,arrays);
1854   std::vector<int> tinyInfoITmp3(tinyInfoITmp.end()-sz,tinyInfoITmp.end());
1855   _type->checkForUnserialization(tinyInfoITmp3,dataInt);
1856 }
1857
1858 void MEDCouplingFieldDouble::finishUnserialization(const std::vector<int>& tinyInfoI, const std::vector<double>& tinyInfoD, const std::vector<std::string>& tinyInfoS)
1859 {
1860   if(_type.isNull())
1861     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform finishUnserialization !");
1862   std::vector<int> tinyInfoI2(tinyInfoI.begin()+3,tinyInfoI.end());
1863   //
1864   std::vector<double> tmp(tinyInfoD);
1865   int sz=(int)tinyInfoD.back();//very bad, lack of time to improve it
1866   tmp.pop_back();
1867   std::vector<double> tmp1(tmp.begin(),tmp.end()-sz);
1868   std::vector<double> tmp2(tmp.end()-sz,tmp.end());
1869   //
1870   timeDiscr()->finishUnserialization(tinyInfoI2,tmp1,tinyInfoS);
1871   _nature=(NatureOfField)tinyInfoI[2];
1872   _type->finishUnserialization(tmp2);
1873   int nbOfElemS=(int)tinyInfoS.size();
1874   _name=tinyInfoS[nbOfElemS-3];
1875   _desc=tinyInfoS[nbOfElemS-2];
1876   setTimeUnit(tinyInfoS[nbOfElemS-1]);
1877 }
1878
1879 /*!
1880  * Contrary to MEDCouplingPointSet class the returned arrays are \b not the responsabilities of the caller.
1881  * The values returned must be consulted only in readonly mode.
1882  */
1883 void MEDCouplingFieldDouble::serialize(DataArrayInt *&dataInt, std::vector<DataArrayDouble *>& arrays) const
1884 {
1885   if(_type.isNull())
1886     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform serialize !");
1887   timeDiscr()->getArrays(arrays);
1888   _type->getSerializationIntArray(dataInt);
1889 }
1890
1891 /*!
1892  * Tries to set an \a other mesh as the support of \a this field. An attempt fails, if
1893  * a current and the \a other meshes are different with use of specified equality
1894  * criteria, and then an exception is thrown.
1895  *  \param [in] other - the mesh to use as the field support if this mesh can be
1896  *         considered equal to the current mesh.
1897  *  \param [in] levOfCheck - defines equality criteria used for mesh comparison. For
1898  *         it's meaning explanation, see MEDCouplingMesh::checkGeoEquivalWith() which
1899  *         is used for mesh comparison.
1900  *  \param [in] precOnMesh - a precision used to compare nodes of the two meshes.
1901  *         It is used as \a prec parameter of MEDCouplingMesh::checkGeoEquivalWith().
1902  *  \param [in] eps - a precision used at node renumbering (if needed) to compare field
1903  *         values at merged nodes. If the values differ more than \a eps, an
1904  *         exception is thrown.
1905  *  \throw If the mesh is not set.
1906  *  \throw If \a other == NULL.
1907  *  \throw If any of the meshes is not well defined.
1908  *  \throw If the two meshes do not match.
1909  *  \throw If field values at merged nodes (if any) deffer more than \a eps.
1910  *
1911  *  \if ENABLE_EXAMPLES
1912  *  \ref cpp_mcfielddouble_changeUnderlyingMesh "Here is a C++ example".<br>
1913  *  \ref  py_mcfielddouble_changeUnderlyingMesh "Here is a Python example".
1914  *  \endif
1915  */
1916 void MEDCouplingFieldDouble::changeUnderlyingMesh(const MEDCouplingMesh *other, int levOfCheck, double precOnMesh, double eps)
1917 {
1918   if(_mesh==0 || other==0)
1919     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::changeUnderlyingMesh : is expected to operate on not null meshes !");
1920   DataArrayInt *cellCor=0,*nodeCor=0;
1921   other->checkGeoEquivalWith(_mesh,levOfCheck,precOnMesh,cellCor,nodeCor);
1922   MCAuto<DataArrayInt> cellCor2(cellCor),nodeCor2(nodeCor);
1923   if(cellCor)
1924     renumberCellsWithoutMesh(cellCor->getConstPointer(),false);
1925   if(nodeCor)
1926     renumberNodesWithoutMesh(nodeCor->getConstPointer(),nodeCor->getMaxValueInArray()+1,eps);
1927   setMesh(other);
1928 }
1929
1930 /*!
1931  * Subtracts another field from \a this one in case when the two fields have different
1932  * supporting meshes. The subtraction is performed provided that the tho meshes can be
1933  * considered equal with use of specified equality criteria, else an exception is thrown.
1934  * If the meshes match, the mesh of \a f is set to \a this field (\a this is permuted if 
1935  * necessary) and field values are subtracted. No interpolation is done here, only an
1936  * analysis of two underlying mesh is done to see if the meshes are geometrically
1937  * equivalent.<br>
1938  * The job of this method consists in calling
1939  * \a this->changeUnderlyingMesh() with \a f->getMesh() as the first parameter, and then
1940  * \a this -= \a f.<br>
1941  * This method requires that \a f and \a this are coherent (checkConsistencyLight()) and that \a f
1942  * and \a this are coherent for a merge.<br>
1943  * "DM" in the method name stands for "different meshes".
1944  *  \param [in] f - the field to subtract from this.
1945  *  \param [in] levOfCheck - defines equality criteria used for mesh comparison. For
1946  *         it's meaning explanation, see MEDCouplingMesh::checkGeoEquivalWith() which
1947  *         is used for mesh comparison.
1948  *  \param [in] precOnMesh - a precision used to compare nodes of the two meshes.
1949  *         It is used as \a prec parameter of MEDCouplingMesh::checkGeoEquivalWith().
1950  *  \param [in] eps - a precision used at node renumbering (if needed) to compare field
1951  *         values at merged nodes. If the values differ more than \a eps, an
1952  *         exception is thrown.
1953  *  \throw If \a f == NULL.
1954  *  \throw If any of the meshes is not set or is not well defined.
1955  *  \throw If the two meshes do not match.
1956  *  \throw If the two fields are not coherent for merge.
1957  *  \throw If field values at merged nodes (if any) deffer more than \a eps.
1958  *
1959  *  \if ENABLE_EXAMPLES
1960  *  \ref cpp_mcfielddouble_substractInPlaceDM "Here is a C++ example".<br>
1961  *  \ref  py_mcfielddouble_substractInPlaceDM "Here is a Python example".
1962  *  \endif
1963  *  \sa changeUnderlyingMesh().
1964  */
1965 void MEDCouplingFieldDouble::substractInPlaceDM(const MEDCouplingFieldDouble *f, int levOfCheck, double precOnMesh, double eps)
1966 {
1967   checkConsistencyLight();
1968   if(!f)
1969     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::substractInPlaceDM : input field is NULL !");
1970   f->checkConsistencyLight();
1971   if(!areCompatibleForMerge(f))
1972     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::substractInPlaceDM : Fields are not compatible ; unable to apply mergeFields on them !");
1973   changeUnderlyingMesh(f->getMesh(),levOfCheck,precOnMesh,eps);
1974   operator-=(*f);
1975 }
1976
1977 /*!
1978  * Merges coincident nodes of the underlying mesh. If some nodes are coincident, the
1979  * underlying mesh is replaced by a new mesh instance where the coincident nodes are merged.
1980  *  \param [in] eps - a precision used to compare nodes of the two meshes.
1981  *  \param [in] epsOnVals - a precision used to compare field
1982  *         values at merged nodes. If the values differ more than \a epsOnVals, an
1983  *         exception is thrown.
1984  *  \return bool - \c true if some nodes have been merged and hence \a this field lies
1985  *         on another mesh.
1986  *  \throw If the mesh is of type not inheriting from MEDCouplingPointSet.
1987  *  \throw If the mesh is not well defined.
1988  *  \throw If the spatial discretization of \a this field is NULL.
1989  *  \throw If the data array is not set.
1990  *  \throw If field values at merged nodes (if any) deffer more than \a epsOnVals.
1991  */
1992 bool MEDCouplingFieldDouble::mergeNodes(double eps, double epsOnVals)
1993 {
1994   const MEDCouplingPointSet *meshC=dynamic_cast<const MEDCouplingPointSet *>(_mesh);
1995   if(!meshC)
1996     throw INTERP_KERNEL::Exception("Invalid support mesh to apply mergeNodes on it : must be a MEDCouplingPointSet one !");
1997   if(_type.isNull())
1998     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform mergeNodes !");
1999   MCAuto<MEDCouplingPointSet> meshC2((MEDCouplingPointSet *)meshC->deepCopy());
2000   bool ret;
2001   int ret2;
2002   MCAuto<DataArrayInt> arr=meshC2->mergeNodes(eps,ret,ret2);
2003   if(!ret)//no nodes have been merged.
2004     return ret;
2005   std::vector<DataArrayDouble *> arrays;
2006   timeDiscr()->getArrays(arrays);
2007   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
2008     if(*iter)
2009       _type->renumberValuesOnNodes(epsOnVals,arr->getConstPointer(),meshC2->getNumberOfNodes(),*iter);
2010   setMesh(meshC2);
2011   return true;
2012 }
2013
2014 /*!
2015  * Merges coincident nodes of the underlying mesh. If some nodes are coincident, the
2016  * underlying mesh is replaced by a new mesh instance where the coincident nodes are
2017  * merged.<br>
2018  * In contrast to mergeNodes(), location of merged nodes is changed to be at their barycenter.
2019  *  \param [in] eps - a precision used to compare nodes of the two meshes.
2020  *  \param [in] epsOnVals - a precision used to compare field
2021  *         values at merged nodes. If the values differ more than \a epsOnVals, an
2022  *         exception is thrown.
2023  *  \return bool - \c true if some nodes have been merged and hence \a this field lies
2024  *         on another mesh.
2025  *  \throw If the mesh is of type not inheriting from MEDCouplingPointSet.
2026  *  \throw If the mesh is not well defined.
2027  *  \throw If the spatial discretization of \a this field is NULL.
2028  *  \throw If the data array is not set.
2029  *  \throw If field values at merged nodes (if any) deffer more than \a epsOnVals.
2030  */
2031 bool MEDCouplingFieldDouble::mergeNodesCenter(double eps, double epsOnVals)
2032 {
2033   const MEDCouplingPointSet *meshC=dynamic_cast<const MEDCouplingPointSet *>(_mesh);
2034   if(!meshC)
2035     throw INTERP_KERNEL::Exception("Invalid support mesh to apply mergeNodes on it : must be a MEDCouplingPointSet one !");
2036   if(_type.isNull())
2037     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform mergeNodesCenter !");
2038   MCAuto<MEDCouplingPointSet> meshC2((MEDCouplingPointSet *)meshC->deepCopy());
2039   bool ret;
2040   int ret2;
2041   MCAuto<DataArrayInt> arr=meshC2->mergeNodesCenter(eps,ret,ret2);
2042   if(!ret)//no nodes have been merged.
2043     return ret;
2044   std::vector<DataArrayDouble *> arrays;
2045   timeDiscr()->getArrays(arrays);
2046   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
2047     if(*iter)
2048       _type->renumberValuesOnNodes(epsOnVals,arr->getConstPointer(),meshC2->getNumberOfNodes(),*iter);
2049   setMesh(meshC2);
2050   return true;
2051 }
2052
2053 /*!
2054  * Removes from the underlying mesh nodes not used in any cell. If some nodes are
2055  * removed, the underlying mesh is replaced by a new mesh instance where the unused
2056  * nodes are removed.<br>
2057  *  \param [in] epsOnVals - a precision used to compare field
2058  *         values at merged nodes. If the values differ more than \a epsOnVals, an
2059  *         exception is thrown.
2060  *  \return bool - \c true if some nodes have been removed and hence \a this field lies
2061  *         on another mesh.
2062  *  \throw If the mesh is of type not inheriting from MEDCouplingPointSet.
2063  *  \throw If the mesh is not well defined.
2064  *  \throw If the spatial discretization of \a this field is NULL.
2065  *  \throw If the data array is not set.
2066  *  \throw If field values at merged nodes (if any) deffer more than \a epsOnVals.
2067  */
2068 bool MEDCouplingFieldDouble::zipCoords(double epsOnVals)
2069 {
2070   const MEDCouplingPointSet *meshC=dynamic_cast<const MEDCouplingPointSet *>(_mesh);
2071   if(!meshC)
2072     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::zipCoords : Invalid support mesh to apply zipCoords on it : must be a MEDCouplingPointSet one !");
2073   if(_type.isNull())
2074     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform zipCoords !");
2075   MCAuto<MEDCouplingPointSet> meshC2((MEDCouplingPointSet *)meshC->deepCopy());
2076   int oldNbOfNodes=meshC2->getNumberOfNodes();
2077   MCAuto<DataArrayInt> arr=meshC2->zipCoordsTraducer();
2078   if(meshC2->getNumberOfNodes()!=oldNbOfNodes)
2079     {
2080       std::vector<DataArrayDouble *> arrays;
2081       timeDiscr()->getArrays(arrays);
2082       for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
2083         if(*iter)
2084           _type->renumberValuesOnNodes(epsOnVals,arr->getConstPointer(),meshC2->getNumberOfNodes(),*iter);
2085       setMesh(meshC2);
2086       return true;
2087     }
2088   return false;
2089 }
2090
2091 /*!
2092  * Removes duplicates of cells from the understanding mesh. If some cells are
2093  * removed, the underlying mesh is replaced by a new mesh instance where the cells
2094  * duplicates are removed.<br>
2095  *  \param [in] compType - specifies a cell comparison technique. Meaning of its
2096  *          valid values [0,1,2] is explained in the description of
2097  *          MEDCouplingPointSet::zipConnectivityTraducer() which is called by this method.
2098  *  \param [in] epsOnVals - a precision used to compare field
2099  *         values at merged cells. If the values differ more than \a epsOnVals, an
2100  *         exception is thrown.
2101  *  \return bool - \c true if some cells have been removed and hence \a this field lies
2102  *         on another mesh.
2103  *  \throw If the mesh is not an instance of MEDCouplingUMesh.
2104  *  \throw If the mesh is not well defined.
2105  *  \throw If the spatial discretization of \a this field is NULL.
2106  *  \throw If the data array is not set.
2107  *  \throw If field values at merged cells (if any) deffer more than \a epsOnVals.
2108  */
2109 bool MEDCouplingFieldDouble::zipConnectivity(int compType, double epsOnVals)
2110 {
2111   const MEDCouplingUMesh *meshC=dynamic_cast<const MEDCouplingUMesh *>(_mesh);
2112   if(!meshC)
2113     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::zipConnectivity : Invalid support mesh to apply zipCoords on it : must be a MEDCouplingPointSet one !");
2114   if(_type.isNull())
2115     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform zipConnectivity !");
2116   MCAuto<MEDCouplingUMesh> meshC2((MEDCouplingUMesh *)meshC->deepCopy());
2117   int oldNbOfCells=meshC2->getNumberOfCells();
2118   MCAuto<DataArrayInt> arr=meshC2->zipConnectivityTraducer(compType);
2119   if(meshC2->getNumberOfCells()!=oldNbOfCells)
2120     {
2121       std::vector<DataArrayDouble *> arrays;
2122       timeDiscr()->getArrays(arrays);
2123       for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
2124         if(*iter)
2125           _type->renumberValuesOnCells(epsOnVals,meshC,arr->getConstPointer(),meshC2->getNumberOfCells(),*iter);
2126       setMesh(meshC2);
2127       return true;
2128     }
2129   return false;
2130 }
2131
2132 /*!
2133  * This method calls MEDCouplingUMesh::buildSlice3D method. So this method makes the assumption that underlying mesh exists.
2134  * For the moment, this method is implemented for fields on cells.
2135  * 
2136  * \return a newly allocated field double containing the result that the user should deallocate.
2137  */
2138 MEDCouplingFieldDouble *MEDCouplingFieldDouble::extractSlice3D(const double *origin, const double *vec, double eps) const
2139 {
2140   const MEDCouplingMesh *mesh=getMesh();
2141   if(!mesh)
2142     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::extractSlice3D : underlying mesh is null !");
2143   if(getTypeOfField()!=ON_CELLS)
2144     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::extractSlice3D : only implemented for fields on cells !");
2145   const MCAuto<MEDCouplingUMesh> umesh(mesh->buildUnstructured());
2146   MCAuto<MEDCouplingFieldDouble> ret(clone(false));
2147   ret->setMesh(umesh);
2148   DataArrayInt *cellIds=0;
2149   MCAuto<MEDCouplingUMesh> mesh2=umesh->buildSlice3D(origin,vec,eps,cellIds);
2150   MCAuto<DataArrayInt> cellIds2=cellIds;
2151   ret->setMesh(mesh2);
2152   MCAuto<DataArrayInt> tupleIds=computeTupleIdsToSelectFromCellIds(cellIds->begin(),cellIds->end());
2153   std::vector<DataArrayDouble *> arrays;
2154   timeDiscr()->getArrays(arrays);
2155   int i=0;
2156   std::vector<DataArrayDouble *> newArr(arrays.size());
2157   std::vector< MCAuto<DataArrayDouble> > newArr2(arrays.size());
2158   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++,i++)
2159     {
2160       if(*iter)
2161         {
2162           newArr2[i]=(*iter)->selectByTupleIdSafe(cellIds->begin(),cellIds->end());
2163           newArr[i]=newArr2[i];
2164         }
2165     }
2166   ret->setArrays(newArr);
2167   return ret.retn();
2168 }
2169
2170 /*!
2171  * Divides every cell of the underlying mesh into simplices (triangles in 2D and
2172  * tetrahedra in 3D). If some cells are divided, the underlying mesh is replaced by a new
2173  * mesh instance containing the simplices.<br> 
2174  *  \param [in] policy - specifies a pattern used for splitting. For its description, see
2175  *          MEDCouplingUMesh::simplexize().
2176  *  \return bool - \c true if some cells have been divided and hence \a this field lies
2177  *         on another mesh.
2178  *  \throw If \a policy has an invalid value. For valid values, see the description of 
2179  *         MEDCouplingUMesh::simplexize().
2180  *  \throw If MEDCouplingMesh::simplexize() is not applicable to the underlying mesh.
2181  *  \throw If the mesh is not well defined.
2182  *  \throw If the spatial discretization of \a this field is NULL.
2183  *  \throw If the data array is not set.
2184  */
2185 bool MEDCouplingFieldDouble::simplexize(int policy)
2186 {
2187   if(!_mesh)
2188     throw INTERP_KERNEL::Exception("No underlying mesh on this field to perform simplexize !");
2189   if(_type.isNull())
2190     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform simplexize !");
2191   int oldNbOfCells=_mesh->getNumberOfCells();
2192   MCAuto<MEDCouplingMesh> meshC2(_mesh->deepCopy());
2193   MCAuto<DataArrayInt> arr=meshC2->simplexize(policy);
2194   int newNbOfCells=meshC2->getNumberOfCells();
2195   if(oldNbOfCells==newNbOfCells)
2196     return false;
2197   std::vector<DataArrayDouble *> arrays;
2198   timeDiscr()->getArrays(arrays);
2199   for(std::vector<DataArrayDouble *>::const_iterator iter=arrays.begin();iter!=arrays.end();iter++)
2200     if(*iter)
2201       _type->renumberValuesOnCellsR(_mesh,arr->getConstPointer(),arr->getNbOfElems(),*iter);
2202   setMesh(meshC2);
2203   return true;
2204 }
2205
2206 /*!
2207  * This method makes the hypothesis that \a this is a Gauss field. This method returns a newly created field on cells with same number of tuples than \a this.
2208  * Each Gauss points in \a this is replaced by a polygon or polyhedron cell with associated region following Voronoi algorithm.
2209  */
2210 MCAuto<MEDCouplingFieldDouble> MEDCouplingFieldDouble::voronoize(double eps) const
2211 {
2212   checkConsistencyLight();
2213   const MEDCouplingMesh *mesh(getMesh());
2214   INTERP_KERNEL::AutoCppPtr<Voronizer> vor;
2215   if(mesh->getSpaceDimension()==2 && mesh->getSpaceDimension()==2)
2216     {
2217       vor=new Voronizer2D;
2218     }
2219   else if(mesh->getSpaceDimension()==3 && mesh->getSpaceDimension()==3)
2220     {
2221       vor=new Voronizer3D;
2222     }
2223   else
2224     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::voronoize : only 2D and 3D are supported for the moment !");
2225   return voronoizeGen(vor,eps);
2226 }
2227
2228 /*!
2229  * This is expected to be a 3 components vector field on nodes (if not an exception will be thrown). \a this is also expected to lie on a MEDCouplingPointSet mesh.
2230  * Finaly \a this is also expected to be consistent.
2231  * In these conditions this method returns a newly created field (to be dealed by the caller).
2232  * The returned field will also 3 compo vector field be on nodes lying on the same mesh than \a this.
2233  * 
2234  * For each 3 compo tuple \a tup in \a this the returned tuple is the result of the transformation of \a tup in the new referential. This referential is defined by \a Ur, \a Uteta, \a Uz.
2235  * \a Ur is the vector between \a center point and the associated node with \a tuple. \a Uz is \a vect normalized. And Uteta is the cross product of \a Uz with \a Ur.
2236  *
2237  * \sa DataArrayDouble::fromCartToCylGiven
2238  */
2239 MEDCouplingFieldDouble *MEDCouplingFieldDouble::computeVectorFieldCyl(const double center[3], const double vect[3]) const
2240 {
2241   checkConsistencyLight();
2242   const DataArrayDouble *coo(getMesh()->getDirectAccessOfCoordsArrIfInStructure());
2243   MEDCouplingTimeDiscretization *td(timeDiscr()->computeVectorFieldCyl(coo,center,vect));
2244   td->copyTinyAttrFrom(*timeDiscr());
2245   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(getNature(),td,_type->clone()));
2246   ret->setMesh(getMesh());
2247   ret->setName(getName());
2248   return ret.retn();
2249 }
2250
2251 /*!
2252  * Creates a new MEDCouplingFieldDouble filled with the doubly contracted product of
2253  * every tensor of \a this 6-componental field.
2254  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, whose
2255  *          each tuple is calculated from the tuple <em>(t)</em> of \a this field as
2256  *          follows: \f$ t[0]^2+t[1]^2+t[2]^2+2*t[3]^2+2*t[4]^2+2*t[5]^2\f$. 
2257  *          This new field lies on the same mesh as \a this one. The caller is to delete
2258  *          this field using decrRef() as it is no more needed.
2259  *  \throw If \a this->getNumberOfComponents() != 6.
2260  *  \throw If the spatial discretization of \a this field is NULL.
2261  */
2262 MEDCouplingFieldDouble *MEDCouplingFieldDouble::doublyContractedProduct() const
2263 {
2264   if(_type.isNull())
2265     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform doublyContractedProduct !");
2266   MEDCouplingTimeDiscretization *td(timeDiscr()->doublyContractedProduct());
2267   td->copyTinyAttrFrom(*timeDiscr());
2268   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(getNature(),td,_type->clone()));
2269   ret->setName("DoublyContractedProduct");
2270   ret->setMesh(getMesh());
2271   return ret.retn();
2272 }
2273
2274 /*!
2275  * Creates a new MEDCouplingFieldDouble filled with the determinant of a square
2276  * matrix defined by every tuple of \a this field, having either 4, 6 or 9 components.
2277  * The case of 6 components corresponds to that of the upper triangular matrix. 
2278  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, whose
2279  *          each tuple is the determinant of matrix of the corresponding tuple of \a this 
2280  *          field. This new field lies on the same mesh as \a this one. The caller is to 
2281  *          delete this field using decrRef() as it is no more needed.
2282  *  \throw If \a this->getNumberOfComponents() is not in [4,6,9].
2283  *  \throw If the spatial discretization of \a this field is NULL.
2284  */
2285 MEDCouplingFieldDouble *MEDCouplingFieldDouble::determinant() const
2286 {
2287   if(_type.isNull())
2288     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform determinant !");
2289   MEDCouplingTimeDiscretization *td(timeDiscr()->determinant());
2290   td->copyTinyAttrFrom(*timeDiscr());
2291   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(getNature(),td,_type->clone()));
2292   ret->setName("Determinant");
2293   ret->setMesh(getMesh());
2294   return ret.retn();
2295 }
2296
2297
2298 /*!
2299  * Creates a new MEDCouplingFieldDouble with 3 components filled with 3 eigenvalues of
2300  * an upper triangular matrix defined by every tuple of \a this 6-componental field.
2301  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, 
2302  *          having 3 components, whose each tuple contains the eigenvalues of the matrix of
2303  *          corresponding tuple of \a this field. This new field lies on the same mesh as
2304  *          \a this one. The caller is to delete this field using decrRef() as it is no
2305  *          more needed.  
2306  *  \throw If \a this->getNumberOfComponents() != 6.
2307  *  \throw If the spatial discretization of \a this field is NULL.
2308  */
2309 MEDCouplingFieldDouble *MEDCouplingFieldDouble::eigenValues() const
2310 {
2311   if(_type.isNull())
2312     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform eigenValues !");
2313   MEDCouplingTimeDiscretization *td(timeDiscr()->eigenValues());
2314   td->copyTinyAttrFrom(*timeDiscr());
2315   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(getNature(),td,_type->clone()));
2316   ret->setName("EigenValues");
2317   ret->setMesh(getMesh());
2318   return ret.retn();
2319 }
2320
2321 /*!
2322  * Creates a new MEDCouplingFieldDouble with 9 components filled with 3 eigenvectors of
2323  * an upper triangular matrix defined by every tuple of \a this 6-componental field.
2324  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, 
2325  *          having 9 components, whose each tuple contains the eigenvectors of the matrix of
2326  *          corresponding tuple of \a this field. This new field lies on the same mesh as
2327  *          \a this one. The caller is to delete this field using decrRef() as it is no
2328  *          more needed.  
2329  *  \throw If \a this->getNumberOfComponents() != 6.
2330  *  \throw If the spatial discretization of \a this field is NULL.
2331  */
2332 MEDCouplingFieldDouble *MEDCouplingFieldDouble::eigenVectors() const
2333 {
2334   if(_type.isNull())
2335     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform eigenVectors !");
2336   MEDCouplingTimeDiscretization *td(timeDiscr()->eigenVectors());
2337   td->copyTinyAttrFrom(*timeDiscr());
2338   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(getNature(),td,_type->clone()));
2339   ret->setName("EigenVectors");
2340   ret->setMesh(getMesh());
2341   return ret.retn();
2342 }
2343
2344 /*!
2345  * Creates a new MEDCouplingFieldDouble filled with the inverse matrix of
2346  * a matrix defined by every tuple of \a this field having either 4, 6 or 9
2347  * components. The case of 6 components corresponds to that of the upper triangular
2348  * matrix.
2349  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, 
2350  *          having the same number of components as \a this one, whose each tuple
2351  *          contains the inverse matrix of the matrix of corresponding tuple of \a this
2352  *          field. This new field lies on the same mesh as \a this one. The caller is to
2353  *          delete this field using decrRef() as it is no more needed.  
2354  *  \throw If \a this->getNumberOfComponents() is not in [4,6,9].
2355  *  \throw If the spatial discretization of \a this field is NULL.
2356  */
2357 MEDCouplingFieldDouble *MEDCouplingFieldDouble::inverse() const
2358 {
2359   if(_type.isNull())
2360     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform inverse !");
2361   MEDCouplingTimeDiscretization *td(timeDiscr()->inverse());
2362   td->copyTinyAttrFrom(*timeDiscr());
2363   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(getNature(),td,_type->clone()));
2364   ret->setName("Inversion");
2365   ret->setMesh(getMesh());
2366   return ret.retn();
2367 }
2368
2369 /*!
2370  * Creates a new MEDCouplingFieldDouble filled with the trace of
2371  * a matrix defined by every tuple of \a this field having either 4, 6 or 9
2372  * components. The case of 6 components corresponds to that of the upper triangular
2373  * matrix.
2374  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, 
2375  *          having 1 component, whose each tuple is the trace of the matrix of
2376  *          corresponding tuple of \a this field.
2377  *          This new field lies on the same mesh as \a this one. The caller is to
2378  *          delete this field using decrRef() as it is no more needed.  
2379  *  \throw If \a this->getNumberOfComponents() is not in [4,6,9].
2380  *  \throw If the spatial discretization of \a this field is NULL.
2381  */
2382 MEDCouplingFieldDouble *MEDCouplingFieldDouble::trace() const
2383 {
2384   if(_type.isNull())
2385     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform trace !");
2386   MEDCouplingTimeDiscretization *td(timeDiscr()->trace());
2387   td->copyTinyAttrFrom(*timeDiscr());
2388   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(getNature(),td,_type->clone()));
2389   ret->setName("Trace");
2390   ret->setMesh(getMesh());
2391   return ret.retn();
2392 }
2393
2394 /*!
2395  * Creates a new MEDCouplingFieldDouble filled with the stress deviator tensor of
2396  * a stress tensor defined by every tuple of \a this 6-componental field.
2397  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, 
2398  *          having same number of components and tuples as \a this field,
2399  *          whose each tuple contains the stress deviator tensor of the stress tensor of
2400  *          corresponding tuple of \a this field. This new field lies on the same mesh as
2401  *          \a this one. The caller is to delete this field using decrRef() as it is no
2402  *          more needed.  
2403  *  \throw If \a this->getNumberOfComponents() != 6.
2404  *  \throw If the spatial discretization of \a this field is NULL.
2405  */
2406 MEDCouplingFieldDouble *MEDCouplingFieldDouble::deviator() const
2407 {
2408   if(_type.isNull())
2409     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform deviator !");
2410   MEDCouplingTimeDiscretization *td(timeDiscr()->deviator());
2411   td->copyTinyAttrFrom(*timeDiscr());
2412   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(getNature(),td,_type->clone()));
2413   ret->setName("Deviator");
2414   ret->setMesh(getMesh());
2415   return ret.retn();
2416 }
2417
2418 /*!
2419  * Creates a new MEDCouplingFieldDouble filled with the magnitude of
2420  * every vector of \a this field.
2421  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, 
2422  *          having one component, whose each tuple is the magnitude of the vector
2423  *          of corresponding tuple of \a this field. This new field lies on the
2424  *          same mesh as \a this one. The caller is to
2425  *          delete this field using decrRef() as it is no more needed.  
2426  *  \throw If the spatial discretization of \a this field is NULL.
2427  */
2428 MEDCouplingFieldDouble *MEDCouplingFieldDouble::magnitude() const
2429 {
2430   if(_type.isNull())
2431     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform magnitude !");
2432   MEDCouplingTimeDiscretization *td(timeDiscr()->magnitude());
2433   td->copyTinyAttrFrom(*timeDiscr());
2434   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(getNature(),td,_type->clone()));
2435   ret->setName("Magnitude");
2436   ret->setMesh(getMesh());
2437   return ret.retn();
2438 }
2439
2440 /*!
2441  * Creates a new scalar MEDCouplingFieldDouble filled with the maximal value among
2442  * values of every tuple of \a this field.
2443  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble.
2444  *          This new field lies on the same mesh as \a this one. The caller is to
2445  *          delete this field using decrRef() as it is no more needed.  
2446  *  \throw If the spatial discretization of \a this field is NULL.
2447  */
2448 MEDCouplingFieldDouble *MEDCouplingFieldDouble::maxPerTuple() const
2449 {
2450   if(_type.isNull())
2451     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform maxPerTuple !");
2452   MEDCouplingTimeDiscretization *td(timeDiscr()->maxPerTuple());
2453   td->copyTinyAttrFrom(*timeDiscr());
2454   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(getNature(),td,_type->clone()));
2455   std::ostringstream oss;
2456   oss << "Max_" << getName();
2457   ret->setName(oss.str());
2458   ret->setMesh(getMesh());
2459   return ret.retn();
2460 }
2461
2462 /*!
2463  * Changes number of components in \a this field. If \a newNbOfComp is less
2464  * than \a this->getNumberOfComponents() then each tuple
2465  * is truncated to have \a newNbOfComp components, keeping first components. If \a
2466  * newNbOfComp is more than \a this->getNumberOfComponents() then 
2467  * each tuple is populated with \a dftValue to have \a newNbOfComp components.  
2468  *  \param [in] newNbOfComp - number of components for the new field to have.
2469  *  \param [in] dftValue - value assigned to new values added to \a this field.
2470  *  \throw If \a this is not allocated.
2471  */
2472 void MEDCouplingFieldDouble::changeNbOfComponents(int newNbOfComp, double dftValue)
2473 {
2474   timeDiscr()->changeNbOfComponents(newNbOfComp,dftValue);
2475 }
2476
2477 /*!
2478  * Creates a new MEDCouplingFieldDouble composed of selected components of \a this field.
2479  * The new MEDCouplingFieldDouble has the same number of tuples but includes components
2480  * specified by \a compoIds parameter. So that getNbOfElems() of the result field
2481  * can be either less, same or more than \a this->getNumberOfValues().
2482  *  \param [in] compoIds - sequence of zero based indices of components to include
2483  *              into the new field.
2484  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble that the caller
2485  *          is to delete using decrRef() as it is no more needed.
2486  *  \throw If a component index (\a i) is not valid: 
2487  *         \a i < 0 || \a i >= \a this->getNumberOfComponents().
2488  */
2489 MEDCouplingFieldDouble *MEDCouplingFieldDouble::keepSelectedComponents(const std::vector<int>& compoIds) const
2490 {
2491   if(_type.isNull())
2492     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform keepSelectedComponents !");
2493   MEDCouplingTimeDiscretization *td(timeDiscr()->keepSelectedComponents(compoIds));
2494   td->copyTinyAttrFrom(*timeDiscr());
2495   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(getNature(),td,_type->clone()));
2496   ret->setName(getName());
2497   ret->setMesh(getMesh());
2498   return ret.retn();
2499 }
2500
2501
2502 /*!
2503  * Copy all components in a specified order from another field.
2504  * The number of tuples in \a this and the other field can be different.
2505  *  \param [in] f - the field to copy data from.
2506  *  \param [in] compoIds - sequence of zero based indices of components, data of which is
2507  *              to be copied.
2508  *  \throw If the two fields have different number of data arrays.
2509  *  \throw If a data array is set in one of fields and is not set in the other.
2510  *  \throw If \a compoIds.size() != \a a->getNumberOfComponents().
2511  *  \throw If \a compoIds[i] < 0 or \a compoIds[i] > \a this->getNumberOfComponents().
2512  */
2513 void MEDCouplingFieldDouble::setSelectedComponents(const MEDCouplingFieldDouble *f, const std::vector<int>& compoIds)
2514 {
2515   timeDiscr()->setSelectedComponents(f->timeDiscr(),compoIds);
2516 }
2517
2518 /*!
2519  * Sorts value within every tuple of \a this field.
2520  *  \param [in] asc - if \a true, the values are sorted in ascending order, else,
2521  *              in descending order.
2522  *  \throw If a data array is not allocated.
2523  */
2524 void MEDCouplingFieldDouble::sortPerTuple(bool asc)
2525 {
2526   timeDiscr()->sortPerTuple(asc);
2527 }
2528
2529 /*!
2530  * Creates a new MEDCouplingFieldDouble by concatenating two given fields.
2531  * Values of
2532  * the first field precede values of the second field within the result field.
2533  *  \param [in] f1 - the first field.
2534  *  \param [in] f2 - the second field.
2535  *  \return MEDCouplingFieldDouble * - the result field. It is a new instance of
2536  *          MEDCouplingFieldDouble. The caller is to delete this mesh using decrRef() 
2537  *          as it is no more needed.
2538  *  \throw If the fields are not compatible for the merge.
2539  *  \throw If the spatial discretization of \a f1 is NULL.
2540  *  \throw If the time discretization of \a f1 is NULL.
2541  *
2542  *  \if ENABLE_EXAMPLES
2543  *  \ref cpp_mcfielddouble_MergeFields "Here is a C++ example".<br>
2544  *  \ref  py_mcfielddouble_MergeFields "Here is a Python example".
2545  *  \endif
2546  */
2547 MEDCouplingFieldDouble *MEDCouplingFieldDouble::MergeFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
2548 {
2549   if(!f1->areCompatibleForMerge(f2))
2550     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply MergeFields on them ! Check support mesh, field nature, and spatial and time discretisation.");
2551   const MEDCouplingMesh *m1(f1->getMesh()),*m2(f2->getMesh());
2552   if(!f1->timeDiscr())
2553     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::MergeFields : no time discr of f1 !");
2554   if(!f1->_type)
2555     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::MergeFields : no spatial discr of f1 !");
2556   MEDCouplingTimeDiscretization *td(f1->timeDiscr()->aggregate(f2->timeDiscr()));
2557   td->copyTinyAttrFrom(*f1->timeDiscr());
2558   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()));
2559   ret->setName(f1->getName());
2560   ret->setDescription(f1->getDescription());
2561   if(m1)
2562     {
2563       MCAuto<MEDCouplingMesh> m=m1->mergeMyselfWith(m2);
2564       ret->setMesh(m);
2565     }
2566   return ret.retn();
2567 }
2568
2569 /*!
2570  * Creates a new MEDCouplingFieldDouble by concatenating all given fields.
2571  * Values of the *i*-th field precede values of the (*i*+1)-th field within the result.
2572  * If there is only one field in \a a, a deepCopy() (except time information of mesh and
2573  * field) of the field is returned. 
2574  * Generally speaking the first field in \a a is used to assign tiny attributes of the
2575  * returned field. 
2576  *  \param [in] a - a vector of fields (MEDCouplingFieldDouble) to concatenate.
2577  *  \return MEDCouplingFieldDouble * - the result field. It is a new instance of
2578  *          MEDCouplingFieldDouble. The caller is to delete this mesh using decrRef() 
2579  *          as it is no more needed.
2580  *  \throw If \a a is empty.
2581  *  \throw If the fields are not compatible for the merge.
2582  *
2583  *  \if ENABLE_EXAMPLES
2584  *  \ref cpp_mcfielddouble_MergeFields "Here is a C++ example".<br>
2585  *  \ref  py_mcfielddouble_MergeFields "Here is a Python example".
2586  *  \endif
2587  */
2588 MEDCouplingFieldDouble *MEDCouplingFieldDouble::MergeFields(const std::vector<const MEDCouplingFieldDouble *>& a)
2589 {
2590   if(a.size()<1)
2591     throw INTERP_KERNEL::Exception("FieldDouble::MergeFields : size of array must be >= 1 !");
2592   std::vector< MCAuto<MEDCouplingUMesh> > ms(a.size());
2593   std::vector< const MEDCouplingUMesh *> ms2(a.size());
2594   std::vector< const MEDCouplingTimeDiscretization *> tds(a.size());
2595   std::vector<const MEDCouplingFieldDouble *>::const_iterator it=a.begin();
2596   const MEDCouplingFieldDouble *ref=(*it++);
2597   if(!ref)
2598     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::MergeFields : presence of NULL instance in first place of input vector !");
2599   for(;it!=a.end();it++)
2600     if(!ref->areCompatibleForMerge(*it))
2601       throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply MergeFields on them! Check support mesh, field nature, and spatial and time discretisation.");
2602   for(int i=0;i<(int)a.size();i++)
2603     {
2604       if(a[i]->getMesh())
2605         { ms[i]=a[i]->getMesh()->buildUnstructured(); ms2[i]=ms[i]; }
2606       else
2607         { ms[i]=0; ms2[i]=0; }
2608       tds[i]=a[i]->timeDiscr();
2609     }
2610   MEDCouplingTimeDiscretization *td(tds[0]->aggregate(tds));
2611   td->copyTinyAttrFrom(*(a[0]->timeDiscr()));
2612   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(a[0]->getNature(),td,a[0]->_type->clone()));
2613   ret->setName(a[0]->getName());
2614   ret->setDescription(a[0]->getDescription());
2615   if(ms2[0])
2616     {
2617       MCAuto<MEDCouplingUMesh> m(MEDCouplingUMesh::MergeUMeshes(ms2));
2618       m->copyTinyInfoFrom(ms2[0]);
2619       ret->setMesh(m);
2620     }
2621   return ret.retn();
2622 }
2623
2624 /*!
2625  * Creates a new MEDCouplingFieldDouble by concatenating components of two given fields.
2626  * The number of components in the result field is a sum of the number of components of
2627  * given fields. The number of tuples in the result field is same as that of each of given
2628  * arrays.
2629  * Number of tuples in the given fields must be the same.
2630  *  \param [in] f1 - a field to include in the result field.
2631  *  \param [in] f2 - another field to include in the result field.
2632  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble.
2633  *          The caller is to delete this result field using decrRef() as it is no more
2634  *          needed.
2635  *  \throw If the fields are not compatible for a meld (areCompatibleForMeld()).
2636  *  \throw If any of data arrays is not allocated.
2637  *  \throw If \a f1->getNumberOfTuples() != \a f2->getNumberOfTuples()
2638  */
2639 MEDCouplingFieldDouble *MEDCouplingFieldDouble::MeldFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
2640 {
2641   if(!f1 || !f2)
2642     throw INTERP_KERNEL::Exception("MeldFields : null input pointer !");
2643   if(!f1->areCompatibleForMeld(f2))
2644     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply MeldFields on them ! Check support mesh, field nature, and spatial and time discretisation.");
2645   MEDCouplingTimeDiscretization *td(f1->timeDiscr()->meld(f2->timeDiscr()));
2646   td->copyTinyAttrFrom(*f1->timeDiscr());
2647   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()));
2648   ret->setMesh(f1->getMesh());
2649   return ret.retn();
2650 }
2651
2652 /*!
2653  * Returns a new MEDCouplingFieldDouble containing a dot product of two given fields, 
2654  * so that the i-th tuple of the result field is a sum of products of j-th components of
2655  * i-th tuples of given fields (\f$ f_i = \sum_{j=1}^n f1_j * f2_j \f$). 
2656  * Number of tuples and components in the given fields must be the same.
2657  *  \param [in] f1 - a given field.
2658  *  \param [in] f2 - another given field.
2659  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble.
2660  *          The caller is to delete this result field using decrRef() as it is no more
2661  *          needed.
2662  *  \throw If either \a f1 or \a f2 is NULL.
2663  *  \throw If the fields are not strictly compatible (areStrictlyCompatible()), i.e. they
2664  *         differ not only in values.
2665  */
2666 MEDCouplingFieldDouble *MEDCouplingFieldDouble::DotFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
2667 {
2668   if(!f1)
2669     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::DotFields : input field is NULL !");
2670   if(!f1->areStrictlyCompatibleForMulDiv(f2))
2671     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply DotFields on them!  Check support mesh, and spatial and time discretisation.");
2672   MEDCouplingTimeDiscretization *td(f1->timeDiscr()->dot(f2->timeDiscr()));
2673   td->copyTinyAttrFrom(*f1->timeDiscr());
2674   MEDCouplingFieldDouble *ret(new MEDCouplingFieldDouble(NoNature,td,f1->_type->clone()));
2675   ret->setMesh(f1->getMesh());
2676   return ret;
2677 }
2678
2679 /*!
2680  * Returns a new MEDCouplingFieldDouble containing a cross product of two given fields, 
2681  * so that
2682  * the i-th tuple of the result field is a 3D vector which is a cross
2683  * product of two vectors defined by the i-th tuples of given fields.
2684  * Number of tuples in the given fields must be the same.
2685  * Number of components in the given fields must be 3.
2686  *  \param [in] f1 - a given field.
2687  *  \param [in] f2 - another given field.
2688  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble.
2689  *          The caller is to delete this result field using decrRef() as it is no more
2690  *          needed.
2691  *  \throw If either \a f1 or \a f2 is NULL.
2692  *  \throw If \a f1->getNumberOfComponents() != 3
2693  *  \throw If \a f2->getNumberOfComponents() != 3
2694  *  \throw If the fields are not strictly compatible (areStrictlyCompatible()), i.e. they
2695  *         differ not only in values.
2696  */
2697 MEDCouplingFieldDouble *MEDCouplingFieldDouble::CrossProductFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
2698 {
2699   if(!f1)
2700     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::CrossProductFields : input field is NULL !");
2701   if(!f1->areStrictlyCompatibleForMulDiv(f2))
2702     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply CrossProductFields on them! Check support mesh, and spatial and time discretisation.");
2703   MEDCouplingTimeDiscretization *td(f1->timeDiscr()->crossProduct(f2->timeDiscr()));
2704   td->copyTinyAttrFrom(*f1->timeDiscr());
2705   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(NoNature,td,f1->_type->clone()));
2706   ret->setMesh(f1->getMesh());
2707   return ret.retn();
2708 }
2709
2710 /*!
2711  * Returns a new MEDCouplingFieldDouble containing maximal values of two given fields.
2712  * Number of tuples and components in the given fields must be the same.
2713  *  \param [in] f1 - a field to compare values with another one.
2714  *  \param [in] f2 - another field to compare values with the first one.
2715  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble.
2716  *          The caller is to delete this result field using decrRef() as it is no more
2717  *          needed.
2718  *  \throw If either \a f1 or \a f2 is NULL.
2719  *  \throw If the fields are not strictly compatible (areStrictlyCompatible()), i.e. they
2720  *         differ not only in values.
2721  *
2722  *  \if ENABLE_EXAMPLES
2723  *  \ref cpp_mcfielddouble_MaxFields "Here is a C++ example".<br>
2724  *  \ref  py_mcfielddouble_MaxFields "Here is a Python example".
2725  *  \endif
2726  */
2727 MEDCouplingFieldDouble *MEDCouplingFieldDouble::MaxFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
2728 {
2729   if(!f1)
2730     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::MaxFields : input field is NULL !");
2731   if(!f1->areStrictlyCompatible(f2))
2732     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply MaxFields on them! Check support mesh, field nature, and spatial and time discretisation.");
2733   MEDCouplingTimeDiscretization *td(f1->timeDiscr()->max(f2->timeDiscr()));
2734   td->copyTinyAttrFrom(*f1->timeDiscr());
2735   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()));
2736   ret->setMesh(f1->getMesh());
2737   return ret.retn();
2738 }
2739
2740 /*!
2741  * Returns a new MEDCouplingFieldDouble containing minimal values of two given fields.
2742  * Number of tuples and components in the given fields must be the same.
2743  *  \param [in] f1 - a field to compare values with another one.
2744  *  \param [in] f2 - another field to compare values with the first one.
2745  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble.
2746  *          The caller is to delete this result field using decrRef() as it is no more
2747  *          needed.
2748  *  \throw If either \a f1 or \a f2 is NULL.
2749  *  \throw If the fields are not strictly compatible (areStrictlyCompatible()), i.e. they
2750  *         differ not only in values.
2751  *
2752  *  \if ENABLE_EXAMPLES
2753  *  \ref cpp_mcfielddouble_MaxFields "Here is a C++ example".<br>
2754  *  \ref  py_mcfielddouble_MaxFields "Here is a Python example".
2755  *  \endif
2756  */
2757 MEDCouplingFieldDouble *MEDCouplingFieldDouble::MinFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
2758 {
2759   if(!f1)
2760     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::MinFields : input field is NULL !");
2761   if(!f1->areStrictlyCompatible(f2))
2762     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply MinFields on them! Check support mesh, field nature, and spatial and time discretisation.");
2763   MEDCouplingTimeDiscretization *td(f1->timeDiscr()->min(f2->timeDiscr()));
2764   td->copyTinyAttrFrom(*f1->timeDiscr());
2765   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()));
2766   ret->setMesh(f1->getMesh());
2767   return ret.retn();
2768 }
2769
2770 /*!
2771  * Returns a copy of \a this field in which sign of all values is reversed.
2772  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble
2773  *         containing the same number of tuples and components as \a this field. 
2774  *         The caller is to delete this result field using decrRef() as it is no more
2775  *         needed. 
2776  *  \throw If the spatial discretization of \a this field is NULL.
2777  *  \throw If a data array is not allocated.
2778  */
2779 MEDCouplingFieldDouble *MEDCouplingFieldDouble::negate() const
2780 {
2781   if(_type.isNull())
2782     throw INTERP_KERNEL::Exception("No spatial discretization underlying this field to perform negate !");
2783   MEDCouplingTimeDiscretization *td(timeDiscr()->negate());
2784   td->copyTinyAttrFrom(*timeDiscr());
2785   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(getNature(),td,_type->clone()));
2786   ret->setMesh(getMesh());
2787   return ret.retn();
2788 }
2789
2790 /*!
2791  * Returns a new MEDCouplingFieldDouble containing sum values of corresponding values of
2792  * two given fields ( _f_ [ i, j ] = _f1_ [ i, j ] + _f2_ [ i, j ] ).
2793  * Number of tuples and components in the given fields must be the same.
2794  *  \param [in] f1 - a field to sum up.
2795  *  \param [in] f2 - another field to sum up.
2796  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble.
2797  *          The caller is to delete this result field using decrRef() as it is no more
2798  *          needed.
2799  *  \throw If either \a f1 or \a f2 is NULL.
2800  *  \throw If the fields are not strictly compatible (areStrictlyCompatible()), i.e. they
2801  *         differ not only in values.
2802  */
2803 MEDCouplingFieldDouble *MEDCouplingFieldDouble::AddFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
2804 {
2805   if(!f1)
2806     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::AddFields : input field is NULL !");
2807   if(!f1->areStrictlyCompatible(f2))
2808     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply AddFields on them! Check support mesh, field nature, and spatial and time discretisation.");
2809   MEDCouplingTimeDiscretization *td(f1->timeDiscr()->add(f2->timeDiscr()));
2810   td->copyTinyAttrFrom(*f1->timeDiscr());
2811   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()));
2812   ret->setMesh(f1->getMesh());
2813   return ret.retn();
2814 }
2815
2816 /*!
2817  * Adds values of another MEDCouplingFieldDouble to values of \a this one
2818  * ( _this_ [ i, j ] += _other_ [ i, j ] ) using DataArrayDouble::addEqual().
2819  * The two fields must have same number of tuples, components and same underlying mesh.
2820  *  \param [in] other - the field to add to \a this one.
2821  *  \return const MEDCouplingFieldDouble & - a reference to \a this field.
2822  *  \throw If \a other is NULL.
2823  *  \throw If the fields are not strictly compatible (areStrictlyCompatible()), i.e. they
2824  *         differ not only in values.
2825  */
2826 const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator+=(const MEDCouplingFieldDouble& other)
2827 {
2828   if(!areStrictlyCompatible(&other))
2829     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply += on them! Check support mesh, field nature, and spatial and time discretisation.");
2830   timeDiscr()->addEqual(other.timeDiscr());
2831   return *this;
2832 }
2833
2834 /*!
2835  * Returns a new MEDCouplingFieldDouble containing subtraction of corresponding values of
2836  * two given fields ( _f_ [ i, j ] = _f1_ [ i, j ] - _f2_ [ i, j ] ).
2837  * Number of tuples and components in the given fields must be the same.
2838  *  \param [in] f1 - a field to subtract from.
2839  *  \param [in] f2 - a field to subtract.
2840  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble.
2841  *          The caller is to delete this result field using decrRef() as it is no more
2842  *          needed.
2843  *  \throw If either \a f1 or \a f2 is NULL.
2844  *  \throw If the fields are not strictly compatible (areStrictlyCompatible()), i.e. they
2845  *         differ not only in values.
2846  */
2847 MEDCouplingFieldDouble *MEDCouplingFieldDouble::SubstractFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
2848 {
2849   if(!f1)
2850     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::SubstractFields : input field is NULL !");
2851   if(!f1->areStrictlyCompatible(f2))
2852     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply SubstractFields on them! Check support mesh, field nature, and spatial and time discretisation.");
2853   MEDCouplingTimeDiscretization *td(f1->timeDiscr()->substract(f2->timeDiscr()));
2854   td->copyTinyAttrFrom(*f1->timeDiscr());
2855   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(f1->getNature(),td,f1->_type->clone()));
2856   ret->setMesh(f1->getMesh());
2857   return ret.retn();
2858 }
2859
2860 /*!
2861  * Subtract values of another MEDCouplingFieldDouble from values of \a this one
2862  * ( _this_ [ i, j ] -= _other_ [ i, j ] ) using DataArrayDouble::substractEqual().
2863  * The two fields must have same number of tuples, components and same underlying mesh.
2864  *  \param [in] other - the field to subtract from \a this one.
2865  *  \return const MEDCouplingFieldDouble & - a reference to \a this field.
2866  *  \throw If \a other is NULL.
2867  *  \throw If the fields are not strictly compatible (areStrictlyCompatible()), i.e. they
2868  *         differ not only in values.
2869  */
2870 const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator-=(const MEDCouplingFieldDouble& other)
2871 {
2872   if(!areStrictlyCompatible(&other))
2873     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply -= on them! Check support mesh, field nature, and spatial and time discretisation.");
2874   timeDiscr()->substractEqual(other.timeDiscr());
2875   return *this;
2876 }
2877
2878 /*!
2879  * Returns a new MEDCouplingFieldDouble containing product values of
2880  * two given fields. There are 2 valid cases.
2881  * 1.  The fields have same number of tuples and components. Then each value of
2882  *   the result field (_f_) is a product of the corresponding values of _f1_ and
2883  *   _f2_, i.e. _f_ [ i, j ] = _f1_ [ i, j ] * _f2_ [ i, j ].
2884  * 2.  The fields have same number of tuples and one field, say _f2_, has one
2885  *   component. Then
2886  *   _f_ [ i, j ] = _f1_ [ i, j ] * _f2_ [ i, 0 ].
2887  *
2888  * The two fields must have same number of tuples and same underlying mesh.
2889  *  \param [in] f1 - a factor field.
2890  *  \param [in] f2 - another factor field.
2891  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, with no nature set.
2892  *          The caller is to delete this result field using decrRef() as it is no more
2893  *          needed.
2894  *  \throw If either \a f1 or \a f2 is NULL.
2895  *  \throw If the fields are not compatible for multiplication (areCompatibleForMul()),
2896  *         i.e. they differ not only in values and possibly number of components.
2897  */
2898 MEDCouplingFieldDouble *MEDCouplingFieldDouble::MultiplyFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
2899 {
2900   if(!f1)
2901     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::MultiplyFields : input field is NULL !");
2902   if(!f1->areCompatibleForMul(f2))
2903     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply MultiplyFields on them! Check support mesh, and spatial and time discretisation.");
2904   MEDCouplingTimeDiscretization *td(f1->timeDiscr()->multiply(f2->timeDiscr()));
2905   td->copyTinyAttrFrom(*f1->timeDiscr());
2906   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(NoNature,td,f1->_type->clone()));
2907   ret->setMesh(f1->getMesh());
2908   return ret.retn();
2909 }
2910
2911 /*!
2912  * Multiply values of another MEDCouplingFieldDouble to values of \a this one
2913  * using DataArrayDouble::multiplyEqual().
2914  * The two fields must have same number of tuples and same underlying mesh.
2915  * There are 2 valid cases.
2916  * 1.  The fields have same number of components. Then each value of
2917  *   \a other is multiplied to the corresponding value of \a this field, i.e.
2918  *   _this_ [ i, j ] *= _other_ [ i, j ].
2919  * 2. The _other_ field has one component. Then
2920  *   _this_ [ i, j ] *= _other_ [ i, 0 ].
2921  *
2922  * The two fields must have same number of tuples and same underlying mesh.
2923  *  \param [in] other - an field to multiply to \a this one.
2924  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, with no nature set.
2925  *          The caller is to delete this result field using decrRef() as it is no more
2926  *          needed.
2927  *  \throw If \a other is NULL.
2928  *  \throw If the fields are not strictly compatible for multiplication
2929  *         (areCompatibleForMul()),
2930  *         i.e. they differ not only in values and possibly in number of components.
2931  */
2932 const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator*=(const MEDCouplingFieldDouble& other)
2933 {
2934   if(!areCompatibleForMul(&other))
2935     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply *= on them! Check support mesh, and spatial and time discretisation.");
2936   timeDiscr()->multiplyEqual(other.timeDiscr());
2937   _nature = NoNature;
2938   return *this;
2939 }
2940
2941 /*!
2942  * Returns a new MEDCouplingFieldDouble containing division of two given fields.
2943  * There are 2 valid cases.
2944  * 1.  The fields have same number of tuples and components. Then each value of
2945  *   the result field (_f_) is a division of the corresponding values of \a f1 and
2946  *   \a f2, i.e. _f_ [ i, j ] = _f1_ [ i, j ] / _f2_ [ i, j ].
2947  * 2.  The fields have same number of tuples and _f2_ has one component. Then
2948  *   _f_ [ i, j ] = _f1_ [ i, j ] / _f2_ [ i, 0 ].
2949  *
2950  *  \param [in] f1 - a numerator field.
2951  *  \param [in] f2 - a denominator field.
2952  *  \return MEDCouplingFieldDouble * - the new instance of MEDCouplingFieldDouble, with no nature set.
2953  *          The caller is to delete this result field using decrRef() as it is no more
2954  *          needed.
2955  *  \throw If either \a f1 or \a f2 is NULL.
2956  *  \throw If the fields are not compatible for division (areCompatibleForDiv()),
2957  *         i.e. they differ not only in values and possibly in number of components.
2958  */
2959 MEDCouplingFieldDouble *MEDCouplingFieldDouble::DivideFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
2960 {
2961   if(!f1)
2962     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::DivideFields : input field is NULL !");
2963   if(!f1->areCompatibleForDiv(f2))
2964     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply DivideFields on them! Check support mesh, and spatial and time discretisation.");
2965   MEDCouplingTimeDiscretization *td(f1->timeDiscr()->divide(f2->timeDiscr()));
2966   td->copyTinyAttrFrom(*f1->timeDiscr());
2967   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(NoNature,td,f1->_type->clone()));
2968   ret->setMesh(f1->getMesh());
2969   return ret.retn();
2970 }
2971
2972 /*!
2973  * Divide values of \a this field by values of another MEDCouplingFieldDouble
2974  * using DataArrayDouble::divideEqual().
2975  * The two fields must have same number of tuples and same underlying mesh.
2976  * There are 2 valid cases.
2977  * 1.  The fields have same number of components. Then each value of
2978  *    \a this field is divided by the corresponding value of \a other one, i.e.
2979  *   _this_ [ i, j ] /= _other_ [ i, j ].
2980  * 2.  The \a other field has one component. Then
2981  *   _this_ [ i, j ] /= _other_ [ i, 0 ].
2982  *
2983  *  \warning No check of division by zero is performed!
2984  *  \param [in] other - an field to divide \a this one by.
2985  *  \throw If \a other is NULL.
2986  *  \throw If the fields are not compatible for division (areCompatibleForDiv()),
2987  *         i.e. they differ not only in values and possibly in number of components.
2988  */
2989 const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator/=(const MEDCouplingFieldDouble& other)
2990 {
2991   if(!areCompatibleForDiv(&other))
2992     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply /= on them! Check support mesh, and spatial and time discretisation.");
2993   timeDiscr()->divideEqual(other.timeDiscr());
2994   _nature = NoNature;
2995   return *this;
2996 }
2997
2998 /*!
2999  * Directly called by MEDCouplingFieldDouble::operator^.
3000  * 
3001  * \sa MEDCouplingFieldDouble::operator^
3002  */
3003 MEDCouplingFieldDouble *MEDCouplingFieldDouble::PowFields(const MEDCouplingFieldDouble *f1, const MEDCouplingFieldDouble *f2)
3004 {
3005   if(!f1)
3006     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::PowFields : input field is NULL !");
3007   if(!f1->areCompatibleForMul(f2))
3008     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply PowFields on them! Check support mesh, and spatial and time discretisation.");
3009   MEDCouplingTimeDiscretization *td(f1->timeDiscr()->pow(f2->timeDiscr()));
3010   td->copyTinyAttrFrom(*f1->timeDiscr());
3011   MCAuto<MEDCouplingFieldDouble> ret(new MEDCouplingFieldDouble(NoNature,td,f1->_type->clone()));
3012   ret->setMesh(f1->getMesh());
3013   return ret.retn();
3014 }
3015
3016 /*!
3017  * Directly call MEDCouplingFieldDouble::PowFields static method.
3018  * 
3019  * \sa MEDCouplingFieldDouble::PowFields
3020  */
3021 MEDCouplingFieldDouble *MEDCouplingFieldDouble::operator^(const MEDCouplingFieldDouble& other) const
3022 {
3023   return PowFields(this,&other);
3024 }
3025
3026 const MEDCouplingFieldDouble &MEDCouplingFieldDouble::operator^=(const MEDCouplingFieldDouble& other)
3027 {
3028   if(!areCompatibleForDiv(&other))
3029     throw INTERP_KERNEL::Exception("Fields are not compatible. Unable to apply ^= on them!  Check support mesh, and spatial and time discretisation.");
3030   timeDiscr()->powEqual(other.timeDiscr());
3031   _nature = NoNature;
3032   return *this;
3033 }
3034
3035 /*!
3036  * Writes the field series \a fs and the mesh the fields lie on in the VTK file \a fileName.
3037  * If \a fs is empty no file is written.
3038  * The result file is valid provided that no exception is thrown.
3039  * \warning All the fields must be named and lie on the same non NULL mesh.
3040  *  \param [in] fileName - the name of a VTK file to write in.
3041  *  \param [in] fs - the fields to write.
3042  *  \param [in] isBinary - specifies the VTK format of the written file. By default true (Binary mode)
3043  *  \throw If \a fs[ 0 ] == NULL.
3044  *  \throw If the fields lie not on the same mesh.
3045  *  \throw If the mesh is not set.
3046  *  \throw If any of the fields has no name.
3047  *
3048  *  \if ENABLE_EXAMPLES
3049  *  \ref cpp_mcfielddouble_WriteVTK "Here is a C++ example".<br>
3050  *  \ref  py_mcfielddouble_WriteVTK "Here is a Python example".
3051  *  \endif
3052  */
3053 std::string MEDCouplingFieldDouble::WriteVTK(const std::string& fileName, const std::vector<const MEDCouplingFieldDouble *>& fs, bool isBinary)
3054 {
3055   if(fs.empty())
3056     return std::string();
3057   std::size_t nfs=fs.size();
3058   if(!fs[0])
3059     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::WriteVTK : 1st instance of field is NULL !");
3060   const MEDCouplingMesh *m=fs[0]->getMesh();
3061   if(!m)
3062     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::WriteVTK : 1st instance of field lies on NULL mesh !");
3063   for(std::size_t i=1;i<nfs;i++)
3064     if(fs[i]->getMesh()!=m)
3065       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.");
3066   if(!m)
3067     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::WriteVTK : Fields are lying on a same mesh but it is empty !");
3068   std::string ret(m->getVTKFileNameOf(fileName));
3069   MCAuto<DataArrayByte> byteArr;
3070   if(isBinary)
3071     { byteArr=DataArrayByte::New(); byteArr->alloc(0,1); }
3072   std::ostringstream coss,noss;
3073   for(std::size_t i=0;i<nfs;i++)
3074     {
3075       const MEDCouplingFieldDouble *cur=fs[i];
3076       std::string name(cur->getName());
3077       if(name.empty())
3078         {
3079           std::ostringstream oss; oss << "MEDCouplingFieldDouble::WriteVTK : Field in pos #" << i << " has no name !";
3080           throw INTERP_KERNEL::Exception(oss.str());
3081         }
3082       TypeOfField typ=cur->getTypeOfField();
3083       if(typ==ON_CELLS)
3084         cur->getArray()->writeVTK(coss,8,cur->getName(),byteArr);
3085       else if(typ==ON_NODES)
3086         cur->getArray()->writeVTK(noss,8,cur->getName(),byteArr);
3087       else
3088         throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::WriteVTK : only node and cell fields supported for the moment !");
3089     }
3090   m->writeVTKAdvanced(ret,coss.str(),noss.str(),byteArr);
3091   return ret;
3092 }
3093
3094 MCAuto<MEDCouplingFieldDouble> MEDCouplingFieldDouble::voronoizeGen(const Voronizer *vor, double eps) const
3095 {
3096   checkConsistencyLight();
3097   if(!vor)
3098     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::voronoizeGen : null pointer !");
3099   const MEDCouplingMesh *inpMesh(getMesh());
3100   int nbCells(inpMesh->getNumberOfCells());
3101   const MEDCouplingFieldDiscretization *disc(getDiscretization());
3102   const MEDCouplingFieldDiscretizationGauss *disc2(dynamic_cast<const MEDCouplingFieldDiscretizationGauss *>(disc));
3103   if(!disc2)
3104     throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::voronoize2D : Not a ON_GAUSS_PT field");
3105   int nbLocs(disc2->getNbOfGaussLocalization());
3106   std::vector< MCAuto<MEDCouplingUMesh> > cells(nbCells);
3107   for(int i=0;i<nbLocs;i++)
3108     {
3109       const MEDCouplingGaussLocalization& gl(disc2->getGaussLocalization(i));
3110       if(gl.getDimension()!=vor->getDimension())
3111         throw INTERP_KERNEL::Exception("MEDCouplingFieldDouble::voronoize2D : not a 2D one !");
3112       MCAuto<MEDCouplingUMesh> mesh(gl.buildRefCell());
3113       const std::vector<double>& coo(gl.getGaussCoords());
3114       MCAuto<DataArrayDouble> coo2(DataArrayDouble::NewFromStdVector(coo));
3115       coo2->rearrange(vor->getDimension());
3116       //
3117       MCAuto<MEDCouplingUMesh> coo3(MEDCouplingUMesh::Build0DMeshFromCoords(coo2));
3118       //
3119       MCAuto<MEDCouplingUMesh> vorCellsForCurDisc(vor->doIt(mesh,coo2,eps));
3120       std::vector<int> ids;
3121       MCAuto<DataArrayDouble> ptsInReal;
3122       disc2->getCellIdsHavingGaussLocalization(i,ids);
3123       {
3124         MCAuto<MEDCouplingUMesh> tmp4(inpMesh->buildUnstructured());
3125         MCAuto<MEDCouplingUMesh> subMesh(tmp4->buildPartOfMySelf(&ids[0],&ids[0]+ids.size()));
3126         ptsInReal=gl.localizePtsInRefCooForEachCell(vorCellsForCurDisc->getCoords(),subMesh);
3127       }
3128       int nbPtsPerCell(vorCellsForCurDisc->getNumberOfNodes());
3129       for(std::size_t i=0;i<ids.size();i++)
3130         {
3131           MCAuto<MEDCouplingUMesh> elt(vorCellsForCurDisc->clone(false));
3132           MCAuto<DataArrayDouble> coo(ptsInReal->selectByTupleIdSafeSlice(i*nbPtsPerCell,(i+1)*nbPtsPerCell,1));
3133           elt->setCoords(coo);
3134           cells[ids[i]]=elt;
3135         }
3136     }
3137   std::vector< const MEDCouplingUMesh * > cellsPtr(VecAutoToVecOfCstPt(cells));
3138   MCAuto<MEDCouplingUMesh> outMesh(MEDCouplingUMesh::MergeUMeshes(cellsPtr));
3139   MCAuto<MEDCouplingFieldDouble> onCells(MEDCouplingFieldDouble::New(ON_CELLS));
3140   onCells->setMesh(outMesh);
3141   {
3142     MCAuto<DataArrayDouble> arr(getArray()->deepCopy());
3143     onCells->setArray(arr);
3144   }
3145   onCells->setTimeUnit(getTimeUnit());
3146   {
3147     int b,c;
3148     double a(getTime(b,c));
3149     onCells->setTime(a,b,c);
3150   }
3151   onCells->setName(getName());
3152   return onCells;
3153 }
3154
3155 MEDCouplingTimeDiscretization *MEDCouplingFieldDouble::timeDiscr()
3156 {
3157   MEDCouplingTimeDiscretizationTemplate<double> *ret(_time_discr);
3158   if(!ret)
3159     return 0;
3160   MEDCouplingTimeDiscretization *retc(dynamic_cast<MEDCouplingTimeDiscretization *>(ret));
3161   if(!retc)
3162     throw INTERP_KERNEL::Exception("Field Double Null invalid type of time discr !");
3163   return retc;
3164 }
3165
3166 const MEDCouplingTimeDiscretization *MEDCouplingFieldDouble::timeDiscr() const
3167 {
3168   const MEDCouplingTimeDiscretizationTemplate<double> *ret(_time_discr);
3169   if(!ret)
3170     return 0;
3171   const MEDCouplingTimeDiscretization *retc(dynamic_cast<const MEDCouplingTimeDiscretization *>(ret));
3172   if(!retc)
3173     throw INTERP_KERNEL::Exception("Field Double Null invalid type of time discr !");
3174   return retc;
3175 }
3176