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