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