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