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