Salome HOME
Optimization and ease of usage. MEDCouplingMesh::buildPartRange returns this when...
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMesh.cxx
1 // Copyright (C) 2007-2013  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.
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 "MEDCouplingMesh.hxx"
22 #include "MEDCouplingUMesh.hxx"
23 #include "MEDCouplingMemArray.hxx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingFieldDiscretization.hxx"
26 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
27
28 #include <set>
29 #include <cmath>
30 #include <sstream>
31 #include <fstream>
32 #include <iterator>
33
34 using namespace ParaMEDMEM;
35
36 MEDCouplingMesh::MEDCouplingMesh():_time(0.),_iteration(-1),_order(-1)
37 {
38 }
39
40 MEDCouplingMesh::MEDCouplingMesh(const MEDCouplingMesh& other):_name(other._name),_description(other._description),
41                                                                _time(other._time),_iteration(other._iteration),
42                                                                _order(other._order),_time_unit(other._time_unit)
43 {
44 }
45
46 std::size_t MEDCouplingMesh::getHeapMemorySizeWithoutChildren() const
47 {
48   return _name.capacity()+_description.capacity()+_time_unit.capacity();
49 }
50
51 /*!
52  * This method is only for ParaMEDMEM in ParaFIELD constructor.
53  */
54 bool MEDCouplingMesh::isStructured() const
55 {
56   return getType()==CARTESIAN;
57 }
58
59 bool MEDCouplingMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
60 {
61   if(!other)
62     throw INTERP_KERNEL::Exception("MEDCouplingMesh::isEqualIfNotWhy : other instance is NULL !");
63   std::ostringstream oss; oss.precision(15);
64   if(_name!=other->_name)
65     {
66       oss << "Mesh names differ : this name = \"" << _name << "\" and other name = \"" << other->_name << "\" !";
67       reason=oss.str();
68       return false;
69     }
70   if(_description!=other->_description)
71     {
72       oss << "Mesh descriptions differ : this description = \"" << _description << "\" and other description = \"" << other->_description << "\" !";
73       reason=oss.str();
74       return false;
75     }
76   if(_iteration!=other->_iteration)
77     {
78       oss << "Mesh iterations differ : this iteration = \"" << _iteration << "\" and other iteration = \"" << other->_iteration << "\" !";
79       reason=oss.str();
80       return false;
81     }
82   if(_order!=other->_order)
83     {
84       oss << "Mesh orders differ : this order = \"" << _order << "\" and other order = \"" << other->_order << "\" !";
85       reason=oss.str();
86       return false;
87     }
88   if(_time_unit!=other->_time_unit)
89     {
90       oss << "Mesh time units differ : this time unit = \"" << _time_unit << "\" and other time unit = \"" << other->_time_unit << "\" !";
91       reason=oss.str();
92       return false;
93     }
94   if(fabs(_time-other->_time)>=1e-12)
95     {
96       oss << "Mesh times differ : this time = \"" << _time << "\" and other time = \"" << other->_time << "\" !";
97       reason=oss.str();
98       return false;
99     }
100   return true;
101 }
102
103 /*!
104  * Checks if \a this and another MEDCouplingMesh are fully equal.
105  *  \param [in] other - an instance of MEDCouplingMesh to compare with \a this one.
106  *  \param [in] prec - precision value used to compare node coordinates.
107  *  \return bool - \c true if the two meshes are equal, \c false else.
108  */
109 bool MEDCouplingMesh::isEqual(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
110 {
111   std::string tmp;
112   return isEqualIfNotWhy(other,prec,tmp);
113 }
114
115 /*!
116  * This method checks geo equivalence between two meshes : \a this and \a other.
117  * If no exception is thrown \a this and \a other are geometrically equivalent regarding \a levOfCheck level.
118  * This method is typically used to change the mesh of a field "safely" depending the \a levOfCheck level considered.
119  * 
120  * In case of success cell \c other[i] is equal to the cell \c this[cellCor[i]].
121  * In case of success node \c other->getCoords()[i] is equal to the node \c this->getCoords()[nodeCor[i]].
122  *
123  * If \a cellCor is null (or Py_None) it means that for all #i cell in \a other is equal to cell # i in \a this.
124  *
125  * If \a nodeCor is null (or Py_None) it means that for all #i node in \a other is equal to node # i in \a this.
126  *
127  * So null (or Py_None) returned in \a cellCor and/or \a nodeCor means identity array. This is for optimization reason to avoid to build useless arrays
128  * for some \a levOfCheck (for example 0).
129  *
130  * **Warning a not null output does not mean that it is not identity !**
131  *
132  * \param [in] other - the mesh to be compared with \a this.
133  * \param [in] levOfCheck - input that specifies the level of check specified. The possible values are listed below.
134  * \param [in] prec - input that specifies precision for double float data used for comparison in meshes.
135  * \param [out] cellCor - output array not always informed (depending \a levOfCheck param) that gives the corresponding array for cells from \a other to \a this.
136  * \param [out] nodeCor - output array not always informed (depending \a levOfCheck param) that gives the corresponding array for nodes from \a other to \a this.
137  *
138  * Possible values for levOfCheck :
139  *   - 0 for strict equality. This is the strongest level. \a cellCor and \a nodeCor params are never informed.
140  *   - 10,11,12 (10+x) for less strict equality. Two meshes are compared geometrically. In case of success \a cellCor and \a nodeCor are informed. Warning ! These equivalences are CPU/Mem costly. The 3 values correspond respectively to policy used for cell comparison (see MEDCouplingUMesh::zipConnectivityTraducer to have more details)
141  *   - 20,21,22 (20+x), for less strict equality. Two meshes are compared geometrically. The difference with the previous version is that nodes(coordinates) are expected to be the same between this and other. In case of success \a cellCor is informed. Warning ! These equivalences are CPU/Mem costly. The 3 values correspond respectively to policy used for cell comparison (see MEDCouplingUMesh::zipConnectivityTraducer to have more details)
142  *   - 1 for fast 'equality'. This is a lazy level. Just number of cells and number of nodes are considered here and 3 cells (begin,middle,end)
143  *   - 2 for deep 'equality' as 0 option except that no control is done on all strings in mesh.
144  *
145  * So the most strict level of check is 0 (equality). The least strict is 12. If the level of check 12 throws, the 2 meshes \a this and \a other are not similar enough
146  * to be compared. An interpolation using MEDCouplingRemapper class should be then used.
147  */
148 void MEDCouplingMesh::checkGeoEquivalWith(const MEDCouplingMesh *other, int levOfCheck, double prec,
149                                           DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
150 {
151   cellCor=0;
152   nodeCor=0;
153   if(this==other)
154     return ;
155   switch(levOfCheck)
156     {
157     case 0:
158       {
159         if(!isEqual(other,prec))
160           throw INTERP_KERNEL::Exception("checkGeoFitWith : Meshes are not equal !");
161         return ;
162       }
163     case 10:
164     case 11:
165     case 12:
166       {
167         checkDeepEquivalWith(other,levOfCheck-10,prec,cellCor,nodeCor);
168         return ;
169       }
170     case 20:
171     case 21:
172     case 22:
173       {
174         checkDeepEquivalOnSameNodesWith(other,levOfCheck-20,prec,cellCor);
175         return ;
176       }
177     case 1:
178       {
179         checkFastEquivalWith(other,prec);
180         return;
181       }
182     case 2:
183       {
184         if(!isEqualWithoutConsideringStr(other,prec))
185           throw INTERP_KERNEL::Exception("checkGeoFitWith : Meshes are not equal without considering strings !");
186         return ;
187       }
188     default:
189       throw INTERP_KERNEL::Exception("checkGeoFitWith : Invalid levOfCheck specified ! Value must be in 0,1,2,10,11 or 12.");
190     }
191 }
192
193 /*!
194  * Finds cells whose all nodes are in a given array of node ids.
195  *  \param [in] partBg - the array of node ids.
196  *  \param [in] partEnd - end of \a partBg, i.e. a pointer to a (last+1)-th element
197  *          of \a partBg.
198  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
199  *          cells. The caller is to delete this array using decrRef() as it is no
200  *          more needed.
201  */
202 DataArrayInt *MEDCouplingMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
203 {
204   std::vector<int> crest;
205   std::set<int> p(partBg,partEnd);
206   int nbOfCells=getNumberOfCells();
207   for(int i=0;i<nbOfCells;i++)
208     {
209       std::vector<int> conn;
210       getNodeIdsOfCell(i,conn);
211       bool cont=true;
212       for(std::vector<int>::const_iterator iter=conn.begin();iter!=conn.end() && cont;iter++)
213         if(p.find(*iter)==p.end())
214           cont=false;
215       if(cont)
216         crest.push_back(i);
217     }
218   DataArrayInt *ret=DataArrayInt::New();
219   ret->alloc((int)crest.size(),1);
220   std::copy(crest.begin(),crest.end(),ret->getPointer());
221   return ret;
222 }
223
224 /*!
225  * This method checks fastly that \a this and \a other are equal. All common checks are done here.
226  */
227 void MEDCouplingMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
228 {
229   if(!other)
230     throw INTERP_KERNEL::Exception("MEDCouplingMesh::checkFastEquivalWith : input mesh is null !");
231   if(getMeshDimension()!=other->getMeshDimension())
232     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Mesh dimensions are not equal !");
233   if(getSpaceDimension()!=other->getSpaceDimension())
234     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Space dimensions are not equal !");
235   if(getNumberOfCells()!=other->getNumberOfCells())
236     throw INTERP_KERNEL::Exception("checkFastEquivalWith : number of cells are not equal !");
237 }
238
239 /*!
240  * This method is very poor and looks only if \a this and \a other are candidate for merge of fields lying repectively on them.
241  */
242 bool MEDCouplingMesh::areCompatibleForMerge(const MEDCouplingMesh *other) const
243 {
244   if(!other)
245     throw INTERP_KERNEL::Exception("MEDCouplingMesh::areCompatibleForMerge : input mesh is null !");
246   if(getMeshDimension()!=other->getMeshDimension())
247     return false;
248   if(getSpaceDimension()!=other->getSpaceDimension())
249     return false;
250   return true;
251 }
252
253 /*!
254  * This method is equivalent to MEDCouplingMesh::buildPart method except that here the cell ids are specified using slice \a beginCellIds \a endCellIds and \a stepCellIds.
255  * \b WARNING , there is a big difference compared to MEDCouplingMesh::buildPart method.
256  * If the input range is equal all cells in \a this, \a this is returned !
257  *
258  * \return a new ref to be managed by the caller. Warning this ref can be equal to \a this if input slice is exactly equal to the whole cells in the same order.
259  *
260  * \sa MEDCouplingMesh::buildPart
261  */
262 MEDCouplingMesh *MEDCouplingMesh::buildPartRange(int beginCellIds, int endCellIds, int stepCellIds) const throw(INTERP_KERNEL::Exception)
263 {
264   if(beginCellIds==0 && endCellIds==getNumberOfCells() && stepCellIds==1)
265     {
266       MEDCouplingMesh *ret(const_cast<MEDCouplingMesh *>(this));
267       ret->incrRef();
268       return ret;
269     }
270   else
271     {
272       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=DataArrayInt::Range(beginCellIds,endCellIds,stepCellIds);
273       return buildPart(cellIds->begin(),cellIds->end());
274     }
275 }
276
277 /*!
278  * This method is equivalent to MEDCouplingMesh::buildPartAndReduceNodes method except that here the cell ids are specified using slice \a beginCellIds \a endCellIds and \a stepCellIds.
279  *
280  * \sa MEDCouplingMesh::buildPartAndReduceNodes
281  */
282 MEDCouplingMesh *MEDCouplingMesh::buildPartRangeAndReduceNodes(int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt*& arr) const throw(INTERP_KERNEL::Exception)
283 {
284   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=DataArrayInt::Range(beginCellIds,endCellIds,stepCellIds);
285   return buildPartAndReduceNodes(cellIds->begin(),cellIds->end(),arr);
286 }
287
288 /*!
289  * This method builds a field lying on \a this with 'nbOfComp' components.
290  * 'func' is a pointer that points to a function that takes 2 arrays in parameter and returns a boolean.
291  * The first array is a in-param of size this->getSpaceDimension and the second an out param of size 'nbOfComp'.
292  * The return field will have type specified by 't'. 't' is also used to determine where values of field will be
293  * evaluate.
294  * Contrary to other fillFromAnalytic methods this method requests a C++ function pointer as input.
295  * The 'func' is a callback that takes as first parameter an input array of size 'this->getSpaceDimension()',
296  * the second parameter is a pointer on a valid zone of size at least equal to 'nbOfComp' values. And too finish
297  * the returned value is a boolean that is equal to False in case of invalid evaluation (log(0) for example...)
298  * 
299  * \param t type of field returned and specifies where the evaluation of func will be done.
300  * \param nbOfComp number of components of returned field.
301  * \param func pointer to a function that should return false if the evaluation failed. (division by 0. for example)
302  * \return field with counter = 1.
303  */
304 MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic(TypeOfField t, int nbOfComp, FunctionToEvaluate func) const
305 {
306   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(t,ONE_TIME);
307   ret->setMesh(this);
308   ret->fillFromAnalytic(nbOfComp,func);
309   ret->synchronizeTimeWithSupport();
310   return ret.retn();
311 }
312
313 /*!
314  * This method copyies all tiny strings from other (name and components name).
315  * @throw if other and this have not same mesh type.
316  */
317 void MEDCouplingMesh::copyTinyStringsFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception)
318 {
319   if(!other)
320     throw INTERP_KERNEL::Exception("MEDCouplingMesh::copyTinyStringsFrom : input mesh is null !");
321   _name=other->_name;
322   _description=other->_description;
323   _time_unit=other->_time_unit;
324 }
325
326 /*!
327  * This method copies all attributes that are \b NOT arrays in this.
328  * All tiny attributes not usefully for state of \a this are ignored.
329  */
330 void MEDCouplingMesh::copyTinyInfoFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception)
331 {
332   copyTinyStringsFrom(other);
333   _time=other->_time;
334   _iteration=other->_iteration;
335   _order=other->_order;
336 }
337
338 /*!
339  * \anchor mcmesh_fillFromAnalytic
340  * Creates a new MEDCouplingFieldDouble of a given type, one time, with given number of
341  * components, lying on \a this mesh, with contents got by applying a specified
342  * function to coordinates of field location points (defined by the given field type).
343  * For example, if \a t == ParaMEDMEM::ON_CELLS, the function is applied to cell
344  * barycenters.<br>
345  * For more info on supported expressions that can be used in the function, see \ref
346  * MEDCouplingArrayApplyFuncExpr. The function can include arbitrary named variables
347  * (e.g. "x","y" or "va44") to refer to components of point coordinates. Names of
348  * variables are sorted in \b alphabetical \b order to associate a variable name with a
349  * component. For example, in the expression "2*x+z", "x" stands for the component #0
350  * and "z" stands for the component #1 (\b not #2)!<br>
351  * In a general case, a value resulting from the function evaluation is assigned to all
352  * components of the field. But there is a possibility to have its own expression for
353  * each component within one function. For this purpose, there are predefined variable
354  * names (IVec, JVec, KVec, LVec etc) each dedicated to a certain component (IVec, to
355  * the component #0 etc). A factor of such a variable is added to the
356  * corresponding component only.<br>
357  * For example, \a nbOfComp == 4, \a this->getSpaceDimension() == 3, coordinates of a
358  * point are (1.,3.,7.), then
359  *   - "2*x + z"               produces (5.,5.,5.,5.)
360  *   - "2*x + 0*y + z"         produces (9.,9.,9.,9.)
361  *   - "2*x*IVec + (x+z)*LVec" produces (2.,0.,0.,4.)
362  *   - "2*y*IVec + z*KVec + x" produces (7.,1.,1.,4.)
363  *
364  *  \param [in] t - the field type. It defines, apart from other things, points to
365  *         coordinates of which the function is applied to get field values.
366  *  \param [in] nbOfComp - the number of components in the result field.
367  *  \param [in] func - a string defining the expression which is evaluated to get
368  *         field values.
369  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The
370  *         caller is to delete this field using decrRef() as it is no more needed. 
371  *  \throw If the nodal connectivity of cells is not defined.
372  *  \throw If computing \a func fails.
373  *
374  *  \ref cpp_mcmesh_fillFromAnalytic "Here is a C++ example".<br>
375  *  \ref  py_mcmesh_fillFromAnalytic "Here is a Python example".
376  */
377 MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic(TypeOfField t, int nbOfComp, const char *func) const
378 {
379   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(t,ONE_TIME);
380   ret->setMesh(this);
381   ret->fillFromAnalytic(nbOfComp,func);
382   ret->synchronizeTimeWithSupport();
383   return ret.retn();
384 }
385
386 /*!
387  * Creates a new MEDCouplingFieldDouble of a given type, one time, with given number of
388  * components, lying on \a this mesh, with contents got by applying a specified
389  * function to coordinates of field location points (defined by the given field type).
390  * For example, if \a t == ParaMEDMEM::ON_CELLS, the function is applied to cell
391  * barycenters. This method differs from
392  * \ref MEDCouplingMesh::fillFromAnalytic(TypeOfField t, int nbOfComp, const char *func) const "fillFromAnalytic()"
393  * by the way how variable
394  * names, used in the function, are associated with components of coordinates of field
395  * location points; here, a variable name corresponding to a component is retrieved from
396  * a corresponding node coordinates array (where it is set via
397  * DataArrayDouble::setInfoOnComponent()).<br>
398  * For more info on supported expressions that can be used in the function, see \ref
399  * MEDCouplingArrayApplyFuncExpr. <br> 
400  * In a general case, a value resulting from the function evaluation is assigned to all
401  * components of a field value. But there is a possibility to have its own expression for
402  * each component within one function. For this purpose, there are predefined variable
403  * names (IVec, JVec, KVec, LVec etc) each dedicated to a certain component (IVec, to
404  * the component #0 etc). A factor of such a variable is added to the
405  * corresponding component only.<br>
406  * For example, \a nbOfComp == 4, \a this->getSpaceDimension() == 3, names of
407  * spatial components are "x", "y" and "z", coordinates of a
408  * point are (1.,3.,7.), then
409  *   - "2*x + z"               produces (9.,9.,9.,9.)
410  *   - "2*x*IVec + (x+z)*LVec" produces (2.,0.,0.,8.)
411  *   - "2*y*IVec + z*KVec + x" produces (7.,1.,1.,8.)
412  *
413  *  \param [in] t - the field type. It defines, apart from other things, the points to
414  *         coordinates of which the function is applied to get field values.
415  *  \param [in] nbOfComp - the number of components in the result field.
416  *  \param [in] func - a string defining the expression which is evaluated to get
417  *         field values.
418  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The
419  *         caller is to delete this field using decrRef() as it is no more needed. 
420  *  \throw If the node coordinates are not defined.
421  *  \throw If the nodal connectivity of cells is not defined.
422  *  \throw If computing \a func fails.
423  *
424  *  \ref cpp_mcmesh_fillFromAnalytic2 "Here is a C++ example".<br>
425  *  \ref  py_mcmesh_fillFromAnalytic2 "Here is a Python example".
426  */
427 MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic2(TypeOfField t, int nbOfComp, const char *func) const
428 {
429   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(t,ONE_TIME);
430   ret->setMesh(this);
431   ret->fillFromAnalytic2(nbOfComp,func);
432   ret->synchronizeTimeWithSupport();
433   return ret.retn();
434 }
435
436 /*!
437  * Creates a new MEDCouplingFieldDouble of a given type, one time, with given number of
438  * components, lying on \a this mesh, with contents got by applying a specified
439  * function to coordinates of field location points (defined by the given field type).
440  * For example, if \a t == ParaMEDMEM::ON_CELLS, the function is applied to cell
441  * barycenters. This method differs from \ref  \ref mcmesh_fillFromAnalytic
442  * "fillFromAnalytic()" by the way how variable
443  * names, used in the function, are associated with components of coordinates of field
444  * location points; here, a component index of a variable is defined by a
445  * rank of the variable within the input array \a varsOrder.<br>
446  * For more info on supported expressions that can be used in the function, see \ref
447  * MEDCouplingArrayApplyFuncExpr.
448  * In a general case, a value resulting from the function evaluation is assigned to all
449  * components of the field. But there is a possibility to have its own expression for
450  * each component within one function. For this purpose, there are predefined variable
451  * names (IVec, JVec, KVec, LVec etc) each dedicated to a certain component (IVec, to
452  * the component #0 etc). A factor of such a variable is added to the
453  * corresponding component only.<br>
454  * For example, \a nbOfComp == 4, \a this->getSpaceDimension() == 3, names of
455  * spatial components are given in \a varsOrder: ["x", "y","z"], coordinates of a
456  * point are (1.,3.,7.), then
457  *   - "2*x + z"               produces (9.,9.,9.,9.)
458  *   - "2*x*IVec + (x+z)*LVec" produces (2.,0.,0.,8.)
459  *   - "2*y*IVec + z*KVec + x" produces (7.,1.,1.,8.)
460  *
461  *  \param [in] t - the field type. It defines, apart from other things, the points to
462  *         coordinates of which the function is applied to get field values.
463  *  \param [in] nbOfComp - the number of components in the result field.
464  *  \param [in] varsOrder - the vector defining names of variables used to refer to
465  *         components of coordinates of field location points. A variable named
466  *         varsOrder[0] refers to the component #0 etc.
467  *  \param [in] func - a string defining the expression which is evaluated to get
468  *         field values.
469  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble. The
470  *         caller is to delete this field using decrRef() as it is no more needed. 
471  *  \throw If the node coordinates are not defined.
472  *  \throw If the nodal connectivity of cells is not defined.
473  *  \throw If computing \a func fails.
474  *
475  *  \ref cpp_mcmesh_fillFromAnalytic3 "Here is a C++ example".<br>
476  *  \ref  py_mcmesh_fillFromAnalytic3 "Here is a Python example".
477  */
478 MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic3(TypeOfField t, int nbOfComp, const std::vector<std::string>& varsOrder, const char *func) const
479 {
480   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(t,ONE_TIME);
481   ret->setMesh(this);
482   ret->fillFromAnalytic3(nbOfComp,varsOrder,func);
483   ret->synchronizeTimeWithSupport();
484   return ret.retn();
485 }
486
487 /*!
488  * Creates a new MEDCouplingMesh by concatenating two given meshes, if possible.
489  * Cells and nodes of
490  * the first mesh precede cells and nodes of the second mesh within the result mesh.
491  * The meshes must be of the same mesh type, else, an exception is thrown. The method
492  * MergeMeshes(), accepting a vector of input meshes, has no such a limitation.
493  *  \param [in] mesh1 - the first mesh.
494  *  \param [in] mesh2 - the second mesh.
495  *  \return MEDCouplingMesh * - the result mesh. It is a new instance of
496  *          MEDCouplingMesh. The caller is to delete this mesh using decrRef() as it
497  *          is no more needed.
498  *  \throw If the meshes are of different mesh type.
499  */
500 MEDCouplingMesh *MEDCouplingMesh::MergeMeshes(const MEDCouplingMesh *mesh1, const MEDCouplingMesh *mesh2) throw(INTERP_KERNEL::Exception)
501 {
502   if(!mesh1)
503     throw INTERP_KERNEL::Exception("MEDCouplingMesh::MergeMeshes : first parameter is an empty mesh !");
504   if(!mesh2)
505     throw INTERP_KERNEL::Exception("MEDCouplingMesh::MergeMeshes : second parameter is an empty mesh !");
506   return mesh1->mergeMyselfWith(mesh2);
507 }
508
509 /*!
510  * Creates a new MEDCouplingMesh by concatenating all given meshes, if possible.
511  * Cells and nodes of
512  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
513  * This method performs a systematic conversion to unstructured meshes before
514  * performing aggregation contrary to the other MergeMeshes()
515  * with two parameters that works only on the same type of meshes. So here it is possible
516  * to mix different type of meshes. 
517  *  \param [in] meshes - a vector of meshes to concatenate.
518  *  \return MEDCouplingMesh * - the result mesh. It is a new instance of
519  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
520  *          is no more needed.
521  *  \throw If \a meshes.size() == 0.
522  *  \throw If \a size[ *i* ] == NULL.
523  *  \throw If the coordinates is not set in none of the meshes.
524  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
525  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
526  */
527 MEDCouplingMesh *MEDCouplingMesh::MergeMeshes(std::vector<const MEDCouplingMesh *>& meshes) throw(INTERP_KERNEL::Exception)
528 {
529   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms1(meshes.size());
530   std::vector< const MEDCouplingUMesh * > ms2(meshes.size());
531   for(std::size_t i=0;i<meshes.size();i++)
532     {
533       if(meshes[i])
534         {
535           MEDCouplingUMesh *cur=meshes[i]->buildUnstructured();
536           ms1[i]=cur;  ms2[i]=cur;
537         }
538       else
539         {
540           std::ostringstream oss; oss << "MEDCouplingMesh::MergeMeshes(std::vector<const MEDCouplingMesh *>& meshes) : mesh at pos #" << i << " of input vector of size " << meshes.size() << " is empty !";
541           throw INTERP_KERNEL::Exception(oss.str().c_str());
542         }
543     }
544   return MEDCouplingUMesh::MergeUMeshes(ms2);
545 }
546
547 /*!
548  * For example if \a type is INTERP_KERNEL::NORM_TRI3 , INTERP_KERNEL::NORM_POLYGON is returned.
549  * If \a type is INTERP_KERNEL::NORM_HEXA8 , INTERP_KERNEL::NORM_POLYHED is returned.
550  * 
551  * \param [in] type the geometric type for which the corresponding dynamic type, is asked.
552  * \return the corresponding dynamic type, able to store the input \a type.
553  * 
554  * \throw if type is equal to \c INTERP_KERNEL::NORM_ERROR or to an unexisting geometric type.
555  */
556 INTERP_KERNEL::NormalizedCellType MEDCouplingMesh::GetCorrespondingPolyType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception)
557 {
558   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
559   return cm.getCorrespondingPolyType();
560 }
561
562 /*!
563  * \param [in] type the geometric type for which the number of nodes consituting it, is asked.
564  * \return number of nodes consituting the input geometric type \a type.
565  * 
566  * \throw if type is dynamic as \c INTERP_KERNEL::NORM_POLYHED , \c INTERP_KERNEL::NORM_POLYGON , \c INTERP_KERNEL::NORM_QPOLYG
567  * \throw if type is equal to \c INTERP_KERNEL::NORM_ERROR or to an unexisting geometric type.
568  */
569 int MEDCouplingMesh::GetNumberOfNodesOfGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception)
570 {
571   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
572   if(cm.isDynamic())
573     throw INTERP_KERNEL::Exception("MEDCouplingMesh::GetNumberOfNodesOfGeometricType : the input geometric type is dynamic ! Impossible to return a fixed number of nodes constituting it !");
574   return (int) cm.getNumberOfNodes();
575 }
576
577 /*!
578  * \param [in] type the geometric type for which the status static/dynamic is asked.
579  * \return true for static geometric type, false for dynamic geometric type.
580  * 
581  * \throw if type is equal to \c INTERP_KERNEL::NORM_ERROR or to an unexisting geometric type.
582  */
583 bool MEDCouplingMesh::IsStaticGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception)
584 {
585   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
586   return !cm.isDynamic();
587 }
588
589 bool MEDCouplingMesh::IsLinearGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception)
590 {
591   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
592   return !cm.isQuadratic();
593 }
594
595 /*!
596  * \param [in] type the geometric type for which the dimension is asked.
597  * \return the dimension associated to the input geometric type \a type.
598  * 
599  * \throw if type is equal to \c INTERP_KERNEL::NORM_ERROR or to an unexisting geometric type.
600  */
601 int MEDCouplingMesh::GetDimensionOfGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception)
602 {
603   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
604   return (int) cm.getDimension();
605 }
606
607 /*!
608  * \param [in] type the geometric type for which the representation is asked.
609  * \return the string representation corresponding to the input geometric type \a type.
610  * 
611  * \throw if type is equal to \c INTERP_KERNEL::NORM_ERROR or to an unexisting geometric type.
612  */
613 const char *MEDCouplingMesh::GetReprOfGeometricType(INTERP_KERNEL::NormalizedCellType type) throw(INTERP_KERNEL::Exception)
614 {
615   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
616   return cm.getRepr();
617 }
618
619 /*!
620  * Finds cells in contact with a ball (i.e. a point with precision).
621  * \warning This method is suitable if the caller intends to evaluate only one
622  *          point, for more points getCellsContainingPoints() is recommended as it is
623  *          faster. 
624  *  \param [in] pos - array of coordinates of the ball central point.
625  *  \param [in] eps - ball radius.
626  *  \param [in,out] elts - vector returning ids of the found cells. It is cleared
627  *         before inserting ids.
628  *
629  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
630  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
631  */
632 void MEDCouplingMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
633 {
634   int ret=getCellContainingPoint(pos,eps);
635   elts.push_back(ret);
636 }
637
638 /*!
639  * Finds cells in contact with several balls (i.e. points with precision).
640  * This method is an extension of getCellContainingPoint() and
641  * getCellsContainingPoint() for the case of multiple points.
642  *  \param [in] pos - an array of coordinates of points in full interlace mode :
643  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
644  *         this->getSpaceDimension() * \a nbOfPoints 
645  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
646  *  \param [in] eps - radius of balls (i.e. the precision).
647  *  \param [out] elts - vector returning ids of found cells.
648  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
649  *         dividing cell ids in \a elts into groups each referring to one
650  *         point. Its every element (except the last one) is an index pointing to the
651  *         first id of a group of cells. For example cells in contact with the *i*-th
652  *         point are described by following range of indices:
653  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
654  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
655  *         Number of cells in contact with the *i*-th point is
656  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
657  *
658  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
659  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
660  */
661 void MEDCouplingMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
662 {
663   eltsIndex=DataArrayInt::New(); elts=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
664   int *eltsIndexPtr(eltsIndex->getPointer());
665   int spaceDim(getSpaceDimension());
666   const double *work(pos);
667   for(int i=0;i<nbOfPoints;i++,work+=spaceDim)
668     {
669       int ret=getCellContainingPoint(work,eps);
670       if(ret>=0)
671         {
672           elts->pushBackSilent(ret);
673           eltsIndexPtr[i+1]=eltsIndexPtr[i]+1;
674         }
675       else
676         eltsIndexPtr[i+1]=eltsIndexPtr[i];
677     }
678 }
679
680 /*!
681  * Writes \a this mesh into a VTK format file named as specified.
682  *  \param [in] fileName - the name of the file to write in.
683  *  \throw If \a fileName is not a writable file.
684  */
685 void MEDCouplingMesh::writeVTK(const char *fileName, bool isBinary) const throw(INTERP_KERNEL::Exception)
686 {
687   std::string cda,pda;
688   MEDCouplingAutoRefCountObjectPtr<DataArrayByte> byteArr;
689   if(isBinary)
690     { byteArr=DataArrayByte::New(); byteArr->alloc(0,1); }
691   writeVTKAdvanced(fileName,cda,pda,byteArr);
692 }
693
694 void MEDCouplingMesh::writeVTKAdvanced(const char *fileName, const std::string& cda, const std::string& pda, DataArrayByte *byteData) const throw(INTERP_KERNEL::Exception)
695 {
696   std::ofstream ofs(fileName);
697   ofs << "<VTKFile type=\""  << getVTKDataSetType() << "\" version=\"0.1\" byte_order=\"" << MEDCouplingByteOrderStr() << "\">\n";
698   writeVTKLL(ofs,cda,pda,byteData);
699   if(byteData)
700     {
701       ofs << "<AppendedData encoding=\"raw\">\n_1234";
702       ofs << std::flush; ofs.close();
703       std::ofstream ofs2(fileName,std::ios_base::binary | std::ios_base::app);
704       ofs2.write(byteData->begin(),byteData->getNbOfElems()); ofs2 << std::flush; ofs2.close();
705       std::ofstream ofs3(fileName,std::ios_base::app); ofs3 << "\n</AppendedData>\n</VTKFile>\n"; ofs3.close();
706     }
707   else
708     {
709       ofs << "</VTKFile>\n";
710       ofs.close();
711     }
712 }