Salome HOME
Rollback modif in tests dans SauvLoader.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingFieldDiscretization.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 "MEDCouplingFieldDiscretization.hxx"
22 #include "MEDCouplingCMesh.hxx"
23 #include "MEDCouplingUMesh.hxx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
26
27 #include "CellModel.hxx"
28 #include "InterpolationUtils.hxx"
29 #include "InterpKernelAutoPtr.hxx"
30 #include "InterpKernelGaussCoords.hxx"
31 #include "InterpKernelMatrixTools.hxx"
32
33 #include <set>
34 #include <list>
35 #include <limits>
36 #include <sstream>
37 #include <numeric>
38 #include <algorithm>
39 #include <functional>
40
41 using namespace ParaMEDMEM;
42
43 const double MEDCouplingFieldDiscretization::DFLT_PRECISION=1.e-12;
44
45 const char MEDCouplingFieldDiscretizationP0::REPR[]="P0";
46
47 const TypeOfField MEDCouplingFieldDiscretizationP0::TYPE=ON_CELLS;
48
49 const char MEDCouplingFieldDiscretizationP1::REPR[]="P1";
50
51 const TypeOfField MEDCouplingFieldDiscretizationP1::TYPE=ON_NODES;
52
53 const int MEDCouplingFieldDiscretizationPerCell::DFT_INVALID_LOCID_VALUE=-1;
54
55 const char MEDCouplingFieldDiscretizationGauss::REPR[]="GAUSS";
56
57 const TypeOfField MEDCouplingFieldDiscretizationGauss::TYPE=ON_GAUSS_PT;
58
59 const char MEDCouplingFieldDiscretizationGaussNE::REPR[]="GSSNE";
60
61 const TypeOfField MEDCouplingFieldDiscretizationGaussNE::TYPE=ON_GAUSS_NE;
62
63 const char MEDCouplingFieldDiscretizationKriging::REPR[]="KRIGING";
64
65 const TypeOfField MEDCouplingFieldDiscretizationKriging::TYPE=ON_NODES_KR;
66
67 // doc is here http://www.code-aster.org/V2/doc/default/fr/man_r/r3/r3.01.01.pdf
68 const double MEDCouplingFieldDiscretizationGaussNE::FGP_SEG2[2]={1.,1.};
69 const double MEDCouplingFieldDiscretizationGaussNE::FGP_SEG3[3]={0.5555555555555556,0.5555555555555556,0.8888888888888888};
70 const double MEDCouplingFieldDiscretizationGaussNE::FGP_SEG4[4]={0.347854845137454,0.347854845137454,0.652145154862546,0.652145154862546};
71 const double MEDCouplingFieldDiscretizationGaussNE::FGP_TRI3[3]={0.16666666666666666,0.16666666666666666,0.16666666666666666};
72 const double MEDCouplingFieldDiscretizationGaussNE::FGP_TRI6[6]={0.0549758718227661,0.0549758718227661,0.0549758718227661,0.11169079483905,0.11169079483905,0.11169079483905};
73 const double MEDCouplingFieldDiscretizationGaussNE::FGP_TRI7[7]={0.062969590272413,0.062969590272413,0.062969590272413,0.066197076394253,0.066197076394253,0.066197076394253,0.1125};
74 const double MEDCouplingFieldDiscretizationGaussNE::FGP_QUAD4[4]={1.,1.,1.,1.};
75 const double MEDCouplingFieldDiscretizationGaussNE::FGP_QUAD9[9]={0.30864197530864196,0.30864197530864196,0.30864197530864196,0.30864197530864196,0.49382716049382713,0.49382716049382713,0.49382716049382713,0.49382716049382713,0.7901234567901234};
76 const double MEDCouplingFieldDiscretizationGaussNE::FGP_TETRA4[4]={0.041666666666666664,0.041666666666666664,0.041666666666666664,0.041666666666666664};
77 const double MEDCouplingFieldDiscretizationGaussNE::FGP_PENTA6[6]={0.16666666666666666,0.16666666666666666,0.16666666666666666,0.16666666666666666,0.16666666666666666,0.16666666666666666};
78 const double MEDCouplingFieldDiscretizationGaussNE::FGP_HEXA8[8]={1.,1.,1.,1.,1.,1.,1.,1.};
79 const double MEDCouplingFieldDiscretizationGaussNE::FGP_HEXA27[27]={0.1714677640603567,0.1714677640603567,0.1714677640603567,0.1714677640603567,0.1714677640603567,0.1714677640603567,0.1714677640603567,0.1714677640603567,0.27434842249657065,0.27434842249657065,0.27434842249657065,0.27434842249657065,0.27434842249657065,0.27434842249657065,0.27434842249657065,0.27434842249657065,0.27434842249657065,0.27434842249657065,0.27434842249657065,0.27434842249657065,0.43895747599451296,0.43895747599451296,0.43895747599451296,0.43895747599451296,0.43895747599451296,0.43895747599451296,0.7023319615912208};
80 const double MEDCouplingFieldDiscretizationGaussNE::FGP_PYRA5[5]={0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333,0.13333333333333333};
81 const double MEDCouplingFieldDiscretizationGaussNE::REF_SEG2[2]={-1.,1.};
82 const double MEDCouplingFieldDiscretizationGaussNE::REF_SEG3[3]={-1.,0.,1.};
83 const double MEDCouplingFieldDiscretizationGaussNE::REF_SEG4[4]={-1.,1.,-0.3333333333333333,0.3333333333333333};
84 const double MEDCouplingFieldDiscretizationGaussNE::REF_TRI3[6]={0.,0.,1.,0.,0.,1.};
85 const double MEDCouplingFieldDiscretizationGaussNE::REF_TRI6[12]={0.,0.,1.,0.,0.,1.,0.5,0.,0.5,0.5,0.,0.5};
86 const double MEDCouplingFieldDiscretizationGaussNE::REF_TRI7[14]={0.,0.,1.,0.,0.,1.,0.5,0.,0.5,0.5,0.,0.5,0.3333333333333333,0.3333333333333333};
87 const double MEDCouplingFieldDiscretizationGaussNE::REF_QUAD4[8]={-1.,-1.,1.,-1.,1.,1.,-1.,1.};
88 const double MEDCouplingFieldDiscretizationGaussNE::REF_QUAD8[16]={-1.,-1.,1.,-1.,1.,1.,-1.,1.,0.,-1.,1.,0.,0.,1.,-1.,0.};
89 const double MEDCouplingFieldDiscretizationGaussNE::REF_QUAD9[18]={-1.,-1.,1.,-1.,1.,1.,-1.,1.,0.,-1.,1.,0.,0.,1.,-1.,0.,0.,0.};
90 const double MEDCouplingFieldDiscretizationGaussNE::REF_TETRA4[12]={0.,1.,0.,0.,0.,1.,0.,0.,0.,1.,0.,0.};
91 const double MEDCouplingFieldDiscretizationGaussNE::REF_TETRA10[30]={0.,1.,0.,0.,0.,1.,0.,0.,0.,1.,0.,0.,0.,0.5,0.5,0.,0.,0.5,0.,0.5,0.,0.5,0.5,0.,0.5,0.,0.5,0.5,0.,0.};
92 const double MEDCouplingFieldDiscretizationGaussNE::REF_PENTA6[18]={-1.,1.,0.,-1.,0.,1.,-1.,0.,0.,1.,1.,0.,1.,0.,1.,1.,0.,0.};
93 const double MEDCouplingFieldDiscretizationGaussNE::REF_PENTA15[45]={-1.,1.,0.,-1.,0.,1.,-1.,0.,0.,1.,1.,0.,1.,0.,1.,1.,0.,0.,-1.,0.5,0.5,-1.,0.,0.5,-1.,0.5,0.,0.,1.,0.,0.,0.,1.,0.,0.,0.,1.,0.5,0.5,1.,0.,0.5,1.,0.5,0.};
94 const double MEDCouplingFieldDiscretizationGaussNE::REF_HEXA8[24]={-1.,-1.,-1.,1.,-1.,-1.,1.,1.,-1.,-1.,1.,-1.,-1.,-1.,1.,1.,-1.,1.,1.,1.,1.,-1.,1.,1.};
95 const double MEDCouplingFieldDiscretizationGaussNE::REF_HEXA20[60]={-1.,-1.,-1.,1.,-1.,-1.,1.,1.,-1.,-1.,1.,-1.,-1.,-1.,1.,1.,-1.,1.,1.,1.,1.,-1.,1.,1.,0.,-1.,-1.,1.,0.,-1.,0.,1.,-1.,-1.,0.,-1.,-1.,-1.,0.,1.,-1.,0.,1.,1.,0.,-1.,1.,0.,0.,-1.,1.,1.,0.,1.,0.,1.,1.,-1.,0.,1.};
96 const double MEDCouplingFieldDiscretizationGaussNE::REF_HEXA27[81]={-1.,-1.,-1.,1.,-1.,-1.,1.,1.,-1.,-1.,1.,-1.,-1.,-1.,1.,1.,-1.,1.,1.,1.,1.,-1.,1.,1.,0.,-1.,-1.,1.,0.,-1.,0.,1.,-1.,-1.,0.,-1.,-1.,-1.,0.,1.,-1.,0.,1.,1.,0.,-1.,1.,0.,0.,-1.,1.,1.,0.,1.,0.,1.,1.,-1.,0.,1.,0.,0.,-1.,0.,-1.,0.,1.,0.,0.,0.,1.,0.,-1.,0.,0.,0.,0.,1.,0.,0.,0.};
97 const double MEDCouplingFieldDiscretizationGaussNE::REF_PYRA5[15]={1.,0.,0.,0.,1.,0.,-1.,0.,0.,0.,-1.,0.,0.,0.,1.};
98 const double MEDCouplingFieldDiscretizationGaussNE::REF_PYRA13[39]={1.,0.,0.,0.,1.,0.,-1.,0.,0.,0.,-1.,0.,0.,0.,1.,0.5,0.5,0.,-0.5,0.5,0.,-0.5,-0.5,0.,0.5,-0.5,0.,0.5,0.,0.5,0.,0.5,0.5,-0.5,0.,0.5,0.,-0.5,0.5};
99
100 MEDCouplingFieldDiscretization::MEDCouplingFieldDiscretization():_precision(DFLT_PRECISION)
101 {
102 }
103
104 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretization::New(TypeOfField type)
105 {
106   switch(type)
107     {
108     case MEDCouplingFieldDiscretizationP0::TYPE:
109       return new MEDCouplingFieldDiscretizationP0;
110     case MEDCouplingFieldDiscretizationP1::TYPE:
111       return new MEDCouplingFieldDiscretizationP1;
112     case MEDCouplingFieldDiscretizationGauss::TYPE:
113       return new MEDCouplingFieldDiscretizationGauss;
114     case MEDCouplingFieldDiscretizationGaussNE::TYPE:
115       return new MEDCouplingFieldDiscretizationGaussNE;
116     case MEDCouplingFieldDiscretizationKriging::TYPE:
117       return new MEDCouplingFieldDiscretizationKriging;
118     default:
119       throw INTERP_KERNEL::Exception("Choosen discretization is not implemented yet.");
120     }
121 }
122
123 TypeOfField MEDCouplingFieldDiscretization::GetTypeOfFieldFromStringRepr(const char *repr) throw(INTERP_KERNEL::Exception)
124 {
125   std::string reprCpp(repr);
126   if(reprCpp==MEDCouplingFieldDiscretizationP0::REPR)
127     return MEDCouplingFieldDiscretizationP0::TYPE;
128   if(reprCpp==MEDCouplingFieldDiscretizationP1::REPR)
129     return MEDCouplingFieldDiscretizationP1::TYPE;
130   if(reprCpp==MEDCouplingFieldDiscretizationGauss::REPR)
131     return MEDCouplingFieldDiscretizationGauss::TYPE;
132   if(reprCpp==MEDCouplingFieldDiscretizationGaussNE::REPR)
133     return MEDCouplingFieldDiscretizationGaussNE::TYPE;
134   if(reprCpp==MEDCouplingFieldDiscretizationKriging::REPR)
135     return MEDCouplingFieldDiscretizationKriging::TYPE;
136   throw INTERP_KERNEL::Exception("Representation does not match with any field discretization !");
137 }
138
139 bool MEDCouplingFieldDiscretization::isEqual(const MEDCouplingFieldDiscretization *other, double eps) const
140 {
141   std::string reason;
142   return isEqualIfNotWhy(other,eps,reason);
143 }
144
145 bool MEDCouplingFieldDiscretization::isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const
146 {
147   return isEqual(other,eps);
148 }
149
150 /*!
151  * This method is an alias of MEDCouplingFieldDiscretization::clone. It is only here for coherency with all the remaining of MEDCoupling.
152  * \sa MEDCouplingFieldDiscretization::clone.
153  */
154 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretization::deepCpy() const
155 {
156   return clone();
157 }
158
159 /*!
160  * For all field discretization excepted GaussPts the [ \a startCellIds, \a endCellIds ) has no impact on the cloned instance.
161  */
162 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretization::clonePart(const int *startCellIds, const int *endCellIds) const
163 {
164   return clone();
165 }
166
167 /*!
168  * For all field discretization excepted GaussPts the slice( \a beginCellId, \a endCellIds, \a stepCellId ) has no impact on the cloned instance.
169  */
170 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretization::clonePartRange(int beginCellIds, int endCellIds, int stepCellIds) const
171 {
172   return clone();
173 }
174
175 /*!
176  * Excepted for MEDCouplingFieldDiscretizationPerCell no underlying TimeLabel object : nothing to do in generally.
177  */
178 void MEDCouplingFieldDiscretization::updateTime() const
179 {
180 }
181
182 std::size_t MEDCouplingFieldDiscretization::getHeapMemorySize() const
183 {
184   return 0;
185 }
186
187 /*!
188  * Computes normL1 of DataArrayDouble instance arr.
189  * @param res output parameter expected to be of size arr->getNumberOfComponents();
190  * @throw when the field discretization fails on getMeasure fields (gauss points for example)
191  */
192 void MEDCouplingFieldDiscretization::normL1(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, double *res) const throw(INTERP_KERNEL::Exception)
193 {
194   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> vol=getMeasureField(mesh,true);
195   int nbOfCompo=arr->getNumberOfComponents();
196   int nbOfElems=getNumberOfTuples(mesh);
197   std::fill(res,res+nbOfCompo,0.);
198   const double *arrPtr=arr->getConstPointer();
199   const double *volPtr=vol->getArray()->getConstPointer();
200   double deno=0.;
201   for(int i=0;i<nbOfElems;i++)
202     {
203       double v=fabs(volPtr[i]);
204       for(int j=0;j<nbOfCompo;j++)
205         res[j]+=fabs(arrPtr[i*nbOfCompo+j])*v;
206       deno+=v;
207     }
208   std::transform(res,res+nbOfCompo,res,std::bind2nd(std::multiplies<double>(),1./deno));
209 }
210
211 /*!
212  * Computes normL2 of DataArrayDouble instance arr.
213  * @param res output parameter expected to be of size arr->getNumberOfComponents();
214  * @throw when the field discretization fails on getMeasure fields (gauss points for example)
215  */
216 void MEDCouplingFieldDiscretization::normL2(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, double *res) const throw(INTERP_KERNEL::Exception)
217 {
218   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> vol=getMeasureField(mesh,true);
219   int nbOfCompo=arr->getNumberOfComponents();
220   int nbOfElems=getNumberOfTuples(mesh);
221   std::fill(res,res+nbOfCompo,0.);
222   const double *arrPtr=arr->getConstPointer();
223   const double *volPtr=vol->getArray()->getConstPointer();
224   double deno=0.;
225   for(int i=0;i<nbOfElems;i++)
226     {
227       double v=fabs(volPtr[i]);
228       for(int j=0;j<nbOfCompo;j++)
229         res[j]+=arrPtr[i*nbOfCompo+j]*arrPtr[i*nbOfCompo+j]*v;
230       deno+=v;
231     }
232   std::transform(res,res+nbOfCompo,res,std::bind2nd(std::multiplies<double>(),1./deno));
233   std::transform(res,res+nbOfCompo,res,std::ptr_fun<double,double>(std::sqrt));
234 }
235
236 /*!
237  * Computes integral of DataArrayDouble instance arr.
238  * @param res output parameter expected to be of size arr->getNumberOfComponents();
239  * @throw when the field discretization fails on getMeasure fields (gauss points for example)
240  */
241 void MEDCouplingFieldDiscretization::integral(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, bool isWAbs, double *res) const throw(INTERP_KERNEL::Exception)
242 {
243   if(!mesh)
244     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretization::integral : mesh is NULL !");
245   if(!arr)
246     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretization::integral : input array is NULL !");
247   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> vol=getMeasureField(mesh,isWAbs);
248   int nbOfCompo=arr->getNumberOfComponents();
249   int nbOfElems=getNumberOfTuples(mesh);
250   if(nbOfElems!=arr->getNumberOfTuples())
251     {
252       std::ostringstream oss; oss << "MEDCouplingFieldDiscretization::integral : field is not correct ! number of tuples in array is " << arr->getNumberOfTuples();
253       oss << " whereas number of tuples expected is " << nbOfElems << " !";
254       throw INTERP_KERNEL::Exception(oss.str().c_str());
255     }
256   std::fill(res,res+nbOfCompo,0.);
257   const double *arrPtr=arr->getConstPointer();
258   const double *volPtr=vol->getArray()->getConstPointer();
259   INTERP_KERNEL::AutoPtr<double> tmp=new double[nbOfCompo];
260   for (int i=0;i<nbOfElems;i++)
261     {
262       std::transform(arrPtr+i*nbOfCompo,arrPtr+(i+1)*nbOfCompo,(double *)tmp,std::bind2nd(std::multiplies<double>(),volPtr[i]));
263       std::transform((double *)tmp,(double *)tmp+nbOfCompo,res,res,std::plus<double>());
264     }
265 }
266
267 /*!
268  * This method is strictly equivalent to MEDCouplingFieldDiscretization::buildSubMeshData except that it is optimized for input defined as a range of cell ids.
269  * 
270  * \param [out] beginOut Valid only if \a di is NULL
271  * \param [out] endOut Valid only if \a di is NULL
272  * \param [out] stepOut Valid only if \a di is NULL
273  * \param [out] di is an array returned that specifies entity ids (nodes, cells, Gauss points... ) in array if no output range is foundable.
274  *
275  * \sa MEDCouplingFieldDiscretization::buildSubMeshData
276  */
277 MEDCouplingMesh *MEDCouplingFieldDiscretization::buildSubMeshDataRange(const MEDCouplingMesh *mesh, int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt *&di) const
278 {
279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::Range(beginCellIds,endCellIds,stepCellIds);
280   return buildSubMeshData(mesh,da->begin(),da->end(),di);
281 }
282
283 void MEDCouplingFieldDiscretization::getSerializationIntArray(DataArrayInt *& arr) const
284 {
285   arr=0;
286 }
287
288 /*!
289  * Empty : Not a bug
290  */
291 void MEDCouplingFieldDiscretization::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
292 {
293 }
294
295 /*!
296  * Empty : Not a bug
297  */
298 void MEDCouplingFieldDiscretization::getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const
299 {
300 }
301
302 void MEDCouplingFieldDiscretization::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *& arr)
303 {
304   arr=0;
305 }
306
307 /*!
308  * Empty : Not a bug
309  */
310 void MEDCouplingFieldDiscretization::finishUnserialization(const std::vector<double>& tinyInfo)
311 {
312 }
313
314 /*!
315  * This method is typically the first step of renumbering. The implementation is empty it is not a bug only gauss is impacted
316  * virtualy by this method.
317  */
318 void MEDCouplingFieldDiscretization::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
319 {
320 }
321
322 double MEDCouplingFieldDiscretization::getIJK(const MEDCouplingMesh *mesh, const DataArrayDouble *da,
323                                               int cellId, int nodeIdInCell, int compoId) const throw(INTERP_KERNEL::Exception)
324 {
325   throw INTERP_KERNEL::Exception("getIJK Invalid ! only for GaussPoint and GaussNE discretizations !");
326 }
327
328 void MEDCouplingFieldDiscretization::setGaussLocalizationOnType(const MEDCouplingMesh *m, INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
329                                                                 const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
330 {
331   throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
332 }
333
334 void MEDCouplingFieldDiscretization::setGaussLocalizationOnCells(const MEDCouplingMesh *m, const int *begin, const int *end, const std::vector<double>& refCoo,
335                                                                  const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
336 {
337   throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
338 }
339
340 void MEDCouplingFieldDiscretization::clearGaussLocalizations() throw(INTERP_KERNEL::Exception)
341 {
342   throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
343 }
344
345 MEDCouplingGaussLocalization& MEDCouplingFieldDiscretization::getGaussLocalization(int locId) throw(INTERP_KERNEL::Exception)
346 {
347   throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
348 }
349
350 const MEDCouplingGaussLocalization& MEDCouplingFieldDiscretization::getGaussLocalization(int locId) const throw(INTERP_KERNEL::Exception)
351 {
352   throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
353 }
354
355 int MEDCouplingFieldDiscretization::getNbOfGaussLocalization() const throw(INTERP_KERNEL::Exception)
356 {
357   throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
358 }
359
360 int MEDCouplingFieldDiscretization::getGaussLocalizationIdOfOneCell(int cellId) const throw(INTERP_KERNEL::Exception)
361 {
362   throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
363 }
364
365 int MEDCouplingFieldDiscretization::getGaussLocalizationIdOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
366 {
367   throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
368 }
369
370 std::set<int> MEDCouplingFieldDiscretization::getGaussLocalizationIdsOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
371 {
372   throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
373 }
374
375 void MEDCouplingFieldDiscretization::getCellIdsHavingGaussLocalization(int locId, std::vector<int>& cellIds) const throw(INTERP_KERNEL::Exception)
376 {
377   throw INTERP_KERNEL::Exception("Invalid method for the corresponding field discretization : available only for GaussPoint discretization !");
378 }
379
380 void MEDCouplingFieldDiscretization::RenumberEntitiesFromO2NArr(double eps, const int *old2NewPtr, int newNbOfEntity, DataArrayDouble *arr, const char *msg)
381 {
382   if(!arr)
383     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretization::RenumberEntitiesFromO2NArr : input array is NULL !");
384   int oldNbOfElems=arr->getNumberOfTuples();
385   int nbOfComp=arr->getNumberOfComponents();
386   int newNbOfTuples=newNbOfEntity;
387   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arrCpy=arr->deepCpy();
388   const double *ptSrc=arrCpy->getConstPointer();
389   arr->reAlloc(newNbOfTuples);
390   double *ptToFill=arr->getPointer();
391   std::fill(ptToFill,ptToFill+nbOfComp*newNbOfTuples,std::numeric_limits<double>::max());
392   INTERP_KERNEL::AutoPtr<double> tmp=new double[nbOfComp];
393   for(int i=0;i<oldNbOfElems;i++)
394     {
395       int newNb=old2NewPtr[i];
396       if(newNb>=0)//if newNb<0 the node is considered as out.
397         {
398           if(std::find_if(ptToFill+newNb*nbOfComp,ptToFill+(newNb+1)*nbOfComp,std::bind2nd(std::not_equal_to<double>(),std::numeric_limits<double>::max()))
399              ==ptToFill+(newNb+1)*nbOfComp)
400             std::copy(ptSrc+i*nbOfComp,ptSrc+(i+1)*nbOfComp,ptToFill+newNb*nbOfComp);
401           else
402             {
403               std::transform(ptSrc+i*nbOfComp,ptSrc+(i+1)*nbOfComp,ptToFill+newNb*nbOfComp,(double *)tmp,std::minus<double>());
404               std::transform((double *)tmp,((double *)tmp)+nbOfComp,(double *)tmp,std::ptr_fun<double,double>(fabs));
405               //if(!std::equal(ptSrc+i*nbOfComp,ptSrc+(i+1)*nbOfComp,ptToFill+newNb*nbOfComp))
406               if(*std::max_element((double *)tmp,((double *)tmp)+nbOfComp)>eps)
407                 {
408                   std::ostringstream oss;
409                   oss << msg << " " << i << " and " << std::find(old2NewPtr,old2NewPtr+i,newNb)-old2NewPtr
410                       << " have been merged and " << msg << " field on them are different !";
411                   throw INTERP_KERNEL::Exception(oss.str().c_str());
412                 }
413             }
414         }
415     }
416 }
417
418 void MEDCouplingFieldDiscretization::RenumberEntitiesFromN2OArr(const int *new2OldPtr, int new2OldSz, DataArrayDouble *arr, const char *msg)
419 {
420   int nbOfComp=arr->getNumberOfComponents();
421   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arrCpy=arr->deepCpy();
422   const double *ptSrc=arrCpy->getConstPointer();
423   arr->reAlloc(new2OldSz);
424   double *ptToFill=arr->getPointer();
425   for(int i=0;i<new2OldSz;i++)
426     {
427       int oldNb=new2OldPtr[i];
428       std::copy(ptSrc+oldNb*nbOfComp,ptSrc+(oldNb+1)*nbOfComp,ptToFill+i*nbOfComp);
429     }
430 }
431
432 MEDCouplingFieldDiscretization::~MEDCouplingFieldDiscretization()
433 {
434 }
435
436 TypeOfField MEDCouplingFieldDiscretizationP0::getEnum() const
437 {
438   return TYPE;
439 }
440
441 /*!
442  * This method is simply called by MEDCouplingFieldDiscretization::deepCpy. It performs the deep copy of \a this.
443  *
444  * \sa MEDCouplingFieldDiscretization::deepCpy.
445  */
446 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationP0::clone() const
447 {
448   return new MEDCouplingFieldDiscretizationP0;
449 }
450
451 std::string MEDCouplingFieldDiscretizationP0::getStringRepr() const
452 {
453   return std::string(REPR);
454 }
455
456 const char *MEDCouplingFieldDiscretizationP0::getRepr() const
457 {
458   return REPR;
459 }
460
461 bool MEDCouplingFieldDiscretizationP0::isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const
462 {
463   if(!other)
464     {
465       reason="other spatial discretization is NULL, and this spatial discretization (P0) is defined.";
466       return false;
467     }
468   const MEDCouplingFieldDiscretizationP0 *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationP0 *>(other);
469   bool ret=otherC!=0;
470   if(!ret)
471     reason="Spatial discrtization of this is ON_CELLS, which is not the case of other.";
472   return ret;
473 }
474
475 int MEDCouplingFieldDiscretizationP0::getNumberOfTuples(const MEDCouplingMesh *mesh) const throw(INTERP_KERNEL::Exception)
476 {
477   if(!mesh)
478     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::getNumberOfTuples : NULL input mesh !");
479   return mesh->getNumberOfCells();
480 }
481
482 /*!
483  * mesh is not used here. It is not a bug !
484  */
485 int MEDCouplingFieldDiscretizationP0::getNumberOfTuplesExpectedRegardingCode(const MEDCouplingMesh *mesh, const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
486 {
487   if(code.size()%3!=0)
488     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::getNumberOfTuplesExpectedRegardingCode : invalid input code !");
489   int nbOfSplit=(int)idsPerType.size();
490   int nbOfTypes=(int)code.size()/3;
491   int ret=0;
492   for(int i=0;i<nbOfTypes;i++)
493     {
494       int nbOfEltInChunk=code[3*i+1];
495       if(nbOfEltInChunk<0)
496         throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::getNumberOfTuplesExpectedRegardingCode : invalid input code ! presence of negative value in a type !");
497       int pos=code[3*i+2];
498       if(pos!=-1)
499         {
500           if(pos<0 || pos>=nbOfSplit)
501             {
502               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationP0::getNumberOfTuplesExpectedRegardingCode : input code points to pos " << pos << " in typeid " << i << " ! Should be in [0," << nbOfSplit << ") !";
503               throw INTERP_KERNEL::Exception(oss.str().c_str());
504             }
505           const DataArrayInt *ids(idsPerType[pos]);
506           if(!ids || !ids->isAllocated() || ids->getNumberOfComponents()!=1 || ids->getNumberOfTuples()!=nbOfEltInChunk || ids->getMinValueInArray()<0)
507             {
508               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationP0::getNumberOfTuplesExpectedRegardingCode : input pfl chunck at pos " << pos << " should have " << i << " tuples and one component and with ids all >=0 !";
509               throw INTERP_KERNEL::Exception(oss.str().c_str());
510             }
511         }
512       ret+=nbOfEltInChunk;
513     }
514   return ret;
515 }
516
517 int MEDCouplingFieldDiscretizationP0::getNumberOfMeshPlaces(const MEDCouplingMesh *mesh) const
518 {
519   if(!mesh)
520     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::getNumberOfMeshPlaces : NULL input mesh !");
521   return mesh->getNumberOfCells();
522 }
523
524 DataArrayInt *MEDCouplingFieldDiscretizationP0::getOffsetArr(const MEDCouplingMesh *mesh) const
525 {
526   if(!mesh)
527     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::getOffsetArr : NULL input mesh !");
528   int nbOfTuples=mesh->getNumberOfCells();
529   DataArrayInt *ret=DataArrayInt::New();
530   ret->alloc(nbOfTuples+1,1);
531   ret->iota(0);
532   return ret;
533 }
534
535 void MEDCouplingFieldDiscretizationP0::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArray *>& arrays,
536                                                              const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
537 {
538   if(!mesh)
539     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::renumberArraysForCell : NULL input mesh !");
540   const int *array=old2NewBg;
541   if(check)
542     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+mesh->getNumberOfCells());
543   for(std::vector<DataArray *>::const_iterator it=arrays.begin();it!=arrays.end();it++)
544     {
545       if(*it)
546         (*it)->renumberInPlace(array);
547     }
548   if(check)
549     free(const_cast<int *>(array));
550 }
551
552 DataArrayDouble *MEDCouplingFieldDiscretizationP0::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const
553 {
554   if(!mesh)
555     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::getLocalizationOfDiscValues : NULL input mesh !");
556   return mesh->getBarycenterAndOwner();
557 }
558
559 void MEDCouplingFieldDiscretizationP0::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *tupleIdsBg, const int *tupleIdsEnd,
560                                                                           DataArrayInt *&cellRestriction, DataArrayInt *&trueTupleRestriction) const throw(INTERP_KERNEL::Exception)
561 {
562   if(!mesh)
563     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::computeMeshRestrictionFromTupleIds : NULL input mesh !");
564   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=DataArrayInt::New();
565   tmp->alloc((int)std::distance(tupleIdsBg,tupleIdsEnd),1);
566   std::copy(tupleIdsBg,tupleIdsEnd,tmp->getPointer());
567   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2(tmp->deepCpy());
568   cellRestriction=tmp.retn();
569   trueTupleRestriction=tmp2.retn();
570 }
571
572 void MEDCouplingFieldDiscretizationP0::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
573 {
574   stream << "P0 spatial discretization.";
575 }
576
577 void MEDCouplingFieldDiscretizationP0::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
578 {
579 }
580
581 void MEDCouplingFieldDiscretizationP0::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception)
582 {
583   if(!mesh || !da)
584     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::checkCoherencyBetween : NULL input mesh or DataArray !");
585   if(mesh->getNumberOfCells()!=da->getNumberOfTuples())
586     {
587       std::ostringstream message;
588       message << "Field on cells invalid because there are " << mesh->getNumberOfCells();
589       message << " cells in mesh and " << da->getNumberOfTuples() << " tuples in field !";
590       throw INTERP_KERNEL::Exception(message.str().c_str());
591     }
592 }
593
594 MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationP0::getMeasureField(const MEDCouplingMesh *mesh, bool isAbs) const
595 {
596   if(!mesh)
597     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::getMeasureField : mesh instance specified is NULL !");
598   return mesh->getMeasureField(isAbs);
599 }
600
601 void MEDCouplingFieldDiscretizationP0::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
602 {
603   if(!mesh)
604     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::getValueOn : NULL input mesh !");
605   int id=mesh->getCellContainingPoint(loc,_precision);
606   if(id==-1)
607     throw INTERP_KERNEL::Exception("Specified point is detected outside of mesh : unable to apply P0::getValueOn !");
608   arr->getTuple(id,res);
609 }
610
611 void MEDCouplingFieldDiscretizationP0::getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const
612 {
613   const MEDCouplingCMesh *meshC=dynamic_cast<const MEDCouplingCMesh *>(mesh);
614   if(!meshC)
615     throw INTERP_KERNEL::Exception("P0::getValueOnPos is only accessible for structured meshes !");
616   int id=meshC->getCellIdFromPos(i,j,k);
617   arr->getTuple(id,res);
618 }
619
620 DataArrayDouble *MEDCouplingFieldDiscretizationP0::getValueOnMulti(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, int nbOfPoints) const
621 {
622   if(!mesh)
623     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::getValueOnMulti : NULL input mesh !");
624   std::vector<int> elts,eltsIndex;
625   mesh->getCellsContainingPoints(loc,nbOfPoints,_precision,elts,eltsIndex);
626   int spaceDim=mesh->getSpaceDimension();
627   int nbOfComponents=arr->getNumberOfComponents();
628   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
629   ret->alloc(nbOfPoints,nbOfComponents);
630   double *ptToFill=ret->getPointer();
631   for(int i=0;i<nbOfPoints;i++,ptToFill+=nbOfComponents)
632     if(eltsIndex[i+1]-eltsIndex[i]>=1)
633       arr->getTuple(elts[eltsIndex[i]],ptToFill);
634     else
635       {
636         std::ostringstream oss; oss << "Point #" << i << " with coordinates : (";
637         std::copy(loc+i*spaceDim,loc+(i+1)*spaceDim,std::ostream_iterator<double>(oss,", "));
638         oss << ") detected outside mesh : unable to apply P0::getValueOnMulti ! ";
639         throw INTERP_KERNEL::Exception(oss.str().c_str());
640       }
641   return ret.retn();
642 }
643
644 /*!
645  * Nothing to do. It's not a bug.
646  */
647 void MEDCouplingFieldDiscretizationP0::renumberValuesOnNodes(double , const int *, int newNbOfNodes, DataArrayDouble *) const
648 {
649 }
650
651 void MEDCouplingFieldDiscretizationP0::renumberValuesOnCells(double epsOnVals, const MEDCouplingMesh *mesh, const int *old2New, int newSz, DataArrayDouble *arr) const
652 {
653   RenumberEntitiesFromO2NArr(epsOnVals,old2New,newSz,arr,"Cell");
654 }
655
656 void MEDCouplingFieldDiscretizationP0::renumberValuesOnCellsR(const MEDCouplingMesh *mesh, const int *new2old, int newSz, DataArrayDouble *arr) const
657 {
658   RenumberEntitiesFromN2OArr(new2old,newSz,arr,"Cell");
659 }
660
661 /*!
662  * This method returns a tuple ids selection from cell ids selection [start;end).
663  * This method is called by MEDCouplingFieldDiscretizationP0::buildSubMeshData to return parameter \b di.
664  * Here for P0 it's very simple !
665  *
666  * \return a newly allocated array containing ids to select into the DataArrayDouble of the field.
667  * 
668  */
669 DataArrayInt *MEDCouplingFieldDiscretizationP0::computeTupleIdsToSelectFromCellIds(const MEDCouplingMesh *mesh, const int *startCellIds, const int *endCellIds) const
670 {
671   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
672   ret->alloc((int)std::distance(startCellIds,endCellIds),1);
673   std::copy(startCellIds,endCellIds,ret->getPointer());
674   return ret.retn();
675 }
676
677 /*!
678  * This method returns a submesh of 'mesh' instance constituting cell ids contained in array defined as an interval [start;end).
679  * @param di is an array returned that specifies entity ids (here cells ids) in mesh 'mesh' of entity in returned submesh.
680  * Example : The first cell id of returned mesh has the (*di)[0] id in 'mesh'
681  *
682  * \sa MEDCouplingFieldDiscretizationP0::buildSubMeshDataRange
683  */
684 MEDCouplingMesh *MEDCouplingFieldDiscretizationP0::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
685 {
686   if(!mesh)
687     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::buildSubMeshData : NULL input mesh !");
688   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPart(start,end);
689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diSafe=DataArrayInt::New();
690   diSafe->alloc((int)std::distance(start,end),1);
691   std::copy(start,end,diSafe->getPointer());
692   di=diSafe.retn();
693   return ret.retn();
694 }
695
696 /*!
697  * This method is strictly equivalent to MEDCouplingFieldDiscretizationP0::buildSubMeshData except that it is optimized for input defined as a range of cell ids.
698  * 
699  * \param [out] beginOut Valid only if \a di is NULL
700  * \param [out] endOut Valid only if \a di is NULL
701  * \param [out] stepOut Valid only if \a di is NULL
702  * \param [out] di is an array returned that specifies entity ids (nodes, cells, Gauss points... ) in array if no output range is foundable.
703  *
704  * \sa MEDCouplingFieldDiscretizationP0::buildSubMeshData
705  */
706 MEDCouplingMesh *MEDCouplingFieldDiscretizationP0::buildSubMeshDataRange(const MEDCouplingMesh *mesh, int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt *&di) const
707 {
708   if(!mesh)
709     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::buildSubMeshDataRange : NULL input mesh !");
710   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPartRange(beginCellIds,endCellIds,stepCellIds);
711   di=0; beginOut=beginCellIds; endOut=endCellIds; stepOut=stepCellIds;
712   return ret.retn();
713 }
714
715 int MEDCouplingFieldDiscretizationOnNodes::getNumberOfTuples(const MEDCouplingMesh *mesh) const throw(INTERP_KERNEL::Exception)
716 {
717   if(!mesh)
718     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::getNumberOfTuples : NULL input mesh !");
719   return mesh->getNumberOfNodes();
720 }
721
722 /*!
723  * mesh is not used here. It is not a bug !
724  */
725 int MEDCouplingFieldDiscretizationOnNodes::getNumberOfTuplesExpectedRegardingCode(const MEDCouplingMesh *mesh, const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
726 {
727   if(code.size()%3!=0)
728     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationOnNodes::getNumberOfTuplesExpectedRegardingCode : invalid input code !");
729   int nbOfSplit=(int)idsPerType.size();
730   int nbOfTypes=(int)code.size()/3;
731   int ret=0;
732   for(int i=0;i<nbOfTypes;i++)
733     {
734       int nbOfEltInChunk=code[3*i+1];
735       if(nbOfEltInChunk<0)
736         throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationOnNodes::getNumberOfTuplesExpectedRegardingCode : invalid input code ! presence of negative value in a type !");
737       int pos=code[3*i+2];
738       if(pos!=-1)
739         {
740           if(pos<0 || pos>=nbOfSplit)
741             {
742               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationOnNodes::getNumberOfTuplesExpectedRegardingCode : input code points to pos " << pos << " in typeid " << i << " ! Should be in [0," << nbOfSplit << ") !";
743               throw INTERP_KERNEL::Exception(oss.str().c_str());
744             }
745           const DataArrayInt *ids(idsPerType[pos]);
746           if(!ids || !ids->isAllocated() || ids->getNumberOfComponents()!=1 || ids->getNumberOfTuples()!=nbOfEltInChunk || ids->getMinValueInArray()<0)
747             {
748               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationOnNodes::getNumberOfTuplesExpectedRegardingCode : input pfl chunck at pos " << pos << " should have " << i << " tuples and one component and with ids all >=0 !";
749               throw INTERP_KERNEL::Exception(oss.str().c_str());
750             }
751         }
752       ret+=nbOfEltInChunk;
753     }
754   return ret;
755 }
756
757 int MEDCouplingFieldDiscretizationOnNodes::getNumberOfMeshPlaces(const MEDCouplingMesh *mesh) const
758 {
759   if(!mesh)
760     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::getNumberOfMeshPlaces : NULL input mesh !");
761   return mesh->getNumberOfNodes();
762 }
763
764 /*!
765  * Nothing to do here.
766  */
767 void MEDCouplingFieldDiscretizationOnNodes::renumberArraysForCell(const MEDCouplingMesh *, const std::vector<DataArray *>& arrays,
768                                                                   const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
769 {
770 }
771
772 DataArrayInt *MEDCouplingFieldDiscretizationOnNodes::getOffsetArr(const MEDCouplingMesh *mesh) const
773 {
774   if(!mesh)
775     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::getOffsetArr : NULL input mesh !");
776   int nbOfTuples=mesh->getNumberOfNodes();
777   DataArrayInt *ret=DataArrayInt::New();
778   ret->alloc(nbOfTuples+1,1);
779   ret->iota(0);
780   return ret;
781 }
782
783 DataArrayDouble *MEDCouplingFieldDiscretizationOnNodes::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const
784 {
785   if(!mesh)
786     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::getLocalizationOfDiscValues : NULL input mesh !");
787   return mesh->getCoordinatesAndOwner();
788 }
789
790 void MEDCouplingFieldDiscretizationOnNodes::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *tupleIdsBg, const int *tupleIdsEnd,
791                                                                                DataArrayInt *&cellRestriction, DataArrayInt *&trueTupleRestriction) const throw(INTERP_KERNEL::Exception)
792 {
793   if(!mesh)
794     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationOnNodes::computeMeshRestrictionFromTupleIds : NULL input mesh !");
795   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=mesh->getCellIdsFullyIncludedInNodeIds(tupleIdsBg,tupleIdsEnd);
796   const MEDCouplingUMesh *meshc=dynamic_cast<const MEDCouplingUMesh *>(mesh);
797   if(!meshc)
798     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationOnNodes::computeMeshRestrictionFromTupleIds : trying to subpart field on nodes by node ids ! Your mesh has to be unstructured !");
799   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshPart=static_cast<MEDCouplingUMesh *>(meshc->buildPartOfMySelf(ret1->begin(),ret1->end(),true));
800   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=meshPart->computeFetchedNodeIds();
801   cellRestriction=ret1.retn();
802   trueTupleRestriction=ret2.retn();
803 }
804
805 void MEDCouplingFieldDiscretizationOnNodes::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception)
806 {
807   if(!mesh || !da)
808     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::checkCoherencyBetween : NULL input mesh or DataArray !");
809   if(mesh->getNumberOfNodes()!=da->getNumberOfTuples())
810     {
811       std::ostringstream message;
812       message << "Field on nodes invalid because there are " << mesh->getNumberOfNodes();
813       message << " nodes in mesh and " << da->getNumberOfTuples() << " tuples in field !";
814       throw INTERP_KERNEL::Exception(message.str().c_str());
815     }
816 }
817
818 /*!
819  * This method returns a submesh of 'mesh' instance constituting cell ids contained in array defined as an interval [start;end).
820 * @param di is an array returned that specifies entity ids (here nodes ids) in mesh 'mesh' of entity in returned submesh.
821  * Example : The first node id of returned mesh has the (*di)[0] id in 'mesh'
822  */
823 MEDCouplingMesh *MEDCouplingFieldDiscretizationOnNodes::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
824 {
825   if(!mesh)
826     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::buildSubMeshData : NULL input mesh !");
827   DataArrayInt *diTmp=0;
828   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPartAndReduceNodes(start,end,diTmp);
829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diTmpSafe(diTmp);
830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> di2=diTmpSafe->invertArrayO2N2N2O(ret->getNumberOfNodes());
831   di=di2.retn();
832   return ret.retn();
833 }
834
835 /*!
836  * This method is strictly equivalent to MEDCouplingFieldDiscretizationNodes::buildSubMeshData except that it is optimized for input defined as a range of cell ids.
837  * 
838  * \param [out] beginOut Valid only if \a di is NULL
839  * \param [out] endOut Valid only if \a di is NULL
840  * \param [out] stepOut Valid only if \a di is NULL
841  * \param [out] di is an array returned that specifies entity ids (nodes, cells, Gauss points... ) in array if no output range is foundable.
842  *
843  * \sa MEDCouplingFieldDiscretizationNodes::buildSubMeshData
844  */
845 MEDCouplingMesh *MEDCouplingFieldDiscretizationOnNodes::buildSubMeshDataRange(const MEDCouplingMesh *mesh, int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt *&di) const
846 {
847   if(!mesh)
848     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationOnNodes::buildSubMeshDataRange : NULL input mesh !");
849   DataArrayInt *diTmp=0;
850   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPartRangeAndReduceNodes(beginCellIds,endCellIds,stepCellIds,beginOut,endOut,stepOut,diTmp);
851   if(diTmp)
852     {
853       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diTmpSafe(diTmp);
854       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> di2=diTmpSafe->invertArrayO2N2N2O(ret->getNumberOfNodes());
855       di=di2.retn();
856     }
857   return ret.retn();
858 }
859
860 /*!
861  * This method returns a tuple ids selection from cell ids selection [start;end).
862  * This method is called by MEDCouplingFieldDiscretizationOnNodes::buildSubMeshData to return parameter \b di.
863  * Here for P1 only nodes fetched by submesh of mesh[startCellIds:endCellIds) is returned !
864  *
865  * \return a newly allocated array containing ids to select into the DataArrayDouble of the field.
866  * 
867  */
868 DataArrayInt *MEDCouplingFieldDiscretizationOnNodes::computeTupleIdsToSelectFromCellIds(const MEDCouplingMesh *mesh, const int *startCellIds, const int *endCellIds) const
869 {
870   if(!mesh)
871     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP1::computeTupleIdsToSelectFromCellIds : NULL input mesh !");
872   const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> umesh=mesh->buildUnstructured();
873   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> umesh2=static_cast<MEDCouplingUMesh *>(umesh->buildPartOfMySelf(startCellIds,endCellIds,true));
874   return umesh2->computeFetchedNodeIds();
875 }
876
877 void MEDCouplingFieldDiscretizationOnNodes::renumberValuesOnNodes(double epsOnVals, const int *old2NewPtr, int newNbOfNodes, DataArrayDouble *arr) const
878 {
879   RenumberEntitiesFromO2NArr(epsOnVals,old2NewPtr,newNbOfNodes,arr,"Node");
880 }
881
882 /*!
883  * Nothing to do it's not a bug.
884  */
885 void MEDCouplingFieldDiscretizationOnNodes::renumberValuesOnCells(double epsOnVals, const MEDCouplingMesh *mesh, const int *old2New, int newSz, DataArrayDouble *arr) const
886 {
887 }
888
889 /*!
890  * Nothing to do it's not a bug.
891  */
892 void MEDCouplingFieldDiscretizationOnNodes::renumberValuesOnCellsR(const MEDCouplingMesh *mesh, const int *new2old, int newSz, DataArrayDouble *arr) const
893 {
894 }
895
896 void MEDCouplingFieldDiscretizationOnNodes::getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const
897 {
898   const MEDCouplingCMesh *meshC=dynamic_cast<const MEDCouplingCMesh *>(mesh);
899   if(!meshC)
900     throw INTERP_KERNEL::Exception("OnNodes::getValueOnPos(i,j,k) is only accessible for structured meshes !");
901   int id=meshC->getNodeIdFromPos(i,j,k);
902   arr->getTuple(id,res);
903 }
904
905 TypeOfField MEDCouplingFieldDiscretizationP1::getEnum() const
906 {
907   return TYPE;
908 }
909
910 /*!
911  * This method is simply called by MEDCouplingFieldDiscretization::deepCpy. It performs the deep copy of \a this.
912  *
913  * \sa MEDCouplingFieldDiscretization::deepCpy.
914  */
915 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationP1::clone() const
916 {
917   return new MEDCouplingFieldDiscretizationP1;
918 }
919
920 std::string MEDCouplingFieldDiscretizationP1::getStringRepr() const
921 {
922   return std::string(REPR);
923 }
924
925 const char *MEDCouplingFieldDiscretizationP1::getRepr() const
926 {
927   return REPR;
928 }
929
930 bool MEDCouplingFieldDiscretizationP1::isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const
931 {
932   if(!other)
933     {
934       reason="other spatial discretization is NULL, and this spatial discretization (P1) is defined.";
935       return false;
936     }
937   const MEDCouplingFieldDiscretizationP1 *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationP1 *>(other);
938   bool ret=otherC!=0;
939   if(!ret)
940     reason="Spatial discrtization of this is ON_NODES, which is not the case of other.";
941   return ret;
942 }
943
944 void MEDCouplingFieldDiscretizationP1::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
945 {
946   if(nat!=ConservativeVolumic)
947     throw INTERP_KERNEL::Exception("Invalid nature for P1 field  : expected ConservativeVolumic !");
948 }
949
950 MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationP1::getMeasureField(const MEDCouplingMesh *mesh, bool isAbs) const
951 {
952   if(!mesh)
953     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP1::getMeasureField : mesh instance specified is NULL !");
954   return mesh->getMeasureFieldOnNode(isAbs);
955 }
956
957 void MEDCouplingFieldDiscretizationP1::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
958 {
959   if(!mesh)
960     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP1::getValueOn : NULL input mesh !");
961   int id=mesh->getCellContainingPoint(loc,_precision);
962   if(id==-1)
963     throw INTERP_KERNEL::Exception("Specified point is detected outside of mesh : unable to apply P1::getValueOn !");
964   INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(id);
965   if(type!=INTERP_KERNEL::NORM_SEG2 && type!=INTERP_KERNEL::NORM_TRI3 && type!=INTERP_KERNEL::NORM_TETRA4)
966     throw INTERP_KERNEL::Exception("P1 getValueOn is not specified for not simplex cells !");
967   getValueInCell(mesh,id,arr,loc,res);
968 }
969
970 /*!
971  * This method localizes a point defined by 'loc' in a cell with id 'cellId' into mesh 'mesh'.
972  * The result is put into res expected to be of size at least arr->getNumberOfComponents()
973  */
974 void MEDCouplingFieldDiscretizationP1::getValueInCell(const MEDCouplingMesh *mesh, int cellId, const DataArrayDouble *arr, const double *loc, double *res) const
975 {
976   if(!mesh)
977     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP1::getValueInCell : NULL input mesh !");
978   std::vector<int> conn;
979   std::vector<double> coo;
980   mesh->getNodeIdsOfCell(cellId,conn);
981   for(std::vector<int>::const_iterator iter=conn.begin();iter!=conn.end();iter++)
982     mesh->getCoordinatesOfNode(*iter,coo);
983   int spaceDim=mesh->getSpaceDimension();
984   std::size_t nbOfNodes=conn.size();
985   std::vector<const double *> vec(nbOfNodes);
986   for(std::size_t i=0;i<nbOfNodes;i++)
987     vec[i]=&coo[i*spaceDim];
988   INTERP_KERNEL::AutoPtr<double> tmp=new double[nbOfNodes];
989   INTERP_KERNEL::barycentric_coords(vec,loc,tmp);
990   int sz=arr->getNumberOfComponents();
991   INTERP_KERNEL::AutoPtr<double> tmp2=new double[sz];
992   std::fill(res,res+sz,0.);
993   for(std::size_t i=0;i<nbOfNodes;i++)
994     {
995       arr->getTuple(conn[i],(double *)tmp2);
996       std::transform((double *)tmp2,((double *)tmp2)+sz,(double *)tmp2,std::bind2nd(std::multiplies<double>(),tmp[i]));
997       std::transform(res,res+sz,(double *)tmp2,res,std::plus<double>());
998     }
999 }
1000
1001 DataArrayDouble *MEDCouplingFieldDiscretizationP1::getValueOnMulti(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, int nbOfPoints) const
1002 {
1003   if(!mesh)
1004     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP1::getValueOnMulti : NULL input mesh !");
1005   std::vector<int> elts,eltsIndex;
1006   mesh->getCellsContainingPoints(loc,nbOfPoints,_precision,elts,eltsIndex);
1007   int spaceDim=mesh->getSpaceDimension();
1008   int nbOfComponents=arr->getNumberOfComponents();
1009   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
1010   ret->alloc(nbOfPoints,nbOfComponents);
1011   double *ptToFill=ret->getPointer();
1012   for(int i=0;i<nbOfPoints;i++)
1013     if(eltsIndex[i+1]-eltsIndex[i]>=1)
1014       getValueInCell(mesh,elts[eltsIndex[i]],arr,loc+i*spaceDim,ptToFill+i*nbOfComponents);
1015     else
1016       {
1017         std::ostringstream oss; oss << "Point #" << i << " with coordinates : (";
1018         std::copy(loc+i*spaceDim,loc+(i+1)*spaceDim,std::ostream_iterator<double>(oss,", "));
1019         oss << ") detected outside mesh : unable to apply P1::getValueOnMulti ! ";
1020         throw INTERP_KERNEL::Exception(oss.str().c_str());
1021       }
1022   return ret.retn();
1023 }
1024
1025 void MEDCouplingFieldDiscretizationP1::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
1026 {
1027   stream << "P1 spatial discretization.";
1028 }
1029
1030 MEDCouplingFieldDiscretizationPerCell::MEDCouplingFieldDiscretizationPerCell():_discr_per_cell(0)
1031 {
1032 }
1033
1034 MEDCouplingFieldDiscretizationPerCell::~MEDCouplingFieldDiscretizationPerCell()
1035 {
1036   if(_discr_per_cell)
1037     _discr_per_cell->decrRef();
1038 }
1039
1040 /*!
1041  * This constructor deep copies ParaMEDMEM::DataArrayInt instance from other (if any).
1042  */
1043 MEDCouplingFieldDiscretizationPerCell::MEDCouplingFieldDiscretizationPerCell(const MEDCouplingFieldDiscretizationPerCell& other, const int *startCellIds, const int *endCellIds):_discr_per_cell(0)
1044 {
1045   DataArrayInt *arr=other._discr_per_cell;
1046   if(arr)
1047     {
1048       if(startCellIds==0 && endCellIds==0)
1049         _discr_per_cell=arr->deepCpy();
1050       else
1051         _discr_per_cell=arr->selectByTupleIdSafe(startCellIds,endCellIds);
1052     }
1053 }
1054
1055 MEDCouplingFieldDiscretizationPerCell::MEDCouplingFieldDiscretizationPerCell(const MEDCouplingFieldDiscretizationPerCell& other, int beginCellIds, int endCellIds, int stepCellIds):_discr_per_cell(0)
1056 {
1057   DataArrayInt *arr=other._discr_per_cell;
1058   if(arr)
1059     {
1060       _discr_per_cell=arr->selectByTupleId2(beginCellIds,endCellIds,stepCellIds);
1061     }
1062 }
1063
1064 void MEDCouplingFieldDiscretizationPerCell::updateTime() const
1065 {
1066   if(_discr_per_cell)
1067     updateTimeWith(*_discr_per_cell);
1068 }
1069
1070 std::size_t MEDCouplingFieldDiscretizationPerCell::getHeapMemorySize() const
1071 {
1072   std::size_t ret=0;
1073   if(_discr_per_cell)
1074     ret+=_discr_per_cell->getHeapMemorySize();
1075   return ret;
1076 }
1077
1078 void MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception)
1079 {
1080   if(!_discr_per_cell)
1081     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell has no discretization per cell !");
1082   if(!mesh)
1083     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween : NULL input mesh or DataArray !");
1084   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1085   if(nbOfTuples!=mesh->getNumberOfCells())
1086     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell has a discretization per cell but it's not matching the underlying mesh !");
1087 }
1088
1089 bool MEDCouplingFieldDiscretizationPerCell::isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const
1090 {
1091   if(!other)
1092     {
1093       reason="other spatial discretization is NULL, and this spatial discretization (PerCell) is defined.";
1094       return false;
1095     }
1096   const MEDCouplingFieldDiscretizationPerCell *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationPerCell *>(other);
1097   if(!otherC)
1098     {
1099       reason="Spatial discretization of this is ON_GAUSS, which is not the case of other.";
1100       return false;
1101     }
1102   if(_discr_per_cell==0)
1103     return otherC->_discr_per_cell==0;
1104   if(otherC->_discr_per_cell==0)
1105     return false;
1106   bool ret=_discr_per_cell->isEqualIfNotWhy(*otherC->_discr_per_cell,reason);
1107   if(!ret)
1108     reason.insert(0,"Field discretization per cell DataArrayInt given the discid per cell :");
1109   return ret;
1110 }
1111
1112 bool MEDCouplingFieldDiscretizationPerCell::isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const
1113 {
1114   const MEDCouplingFieldDiscretizationPerCell *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationPerCell *>(other);
1115   if(!otherC)
1116     return false;
1117   if(_discr_per_cell==0)
1118     return otherC->_discr_per_cell==0;
1119   if(otherC->_discr_per_cell==0)
1120     return false;
1121   return _discr_per_cell->isEqualWithoutConsideringStr(*otherC->_discr_per_cell);
1122 }
1123
1124 /*!
1125  * This method is typically the first step of renumbering. The impact on _discr_per_cell is necessary here.
1126  * virtualy by this method.
1127  */
1128 void MEDCouplingFieldDiscretizationPerCell::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
1129 {
1130   int nbCells=_discr_per_cell->getNumberOfTuples();
1131   const int *array=old2NewBg;
1132   if(check)
1133     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
1134   //
1135   DataArrayInt *dpc=_discr_per_cell->renumber(array);
1136   _discr_per_cell->decrRef();
1137   _discr_per_cell=dpc;
1138   //
1139   if(check)
1140     free(const_cast<int *>(array));
1141 }
1142
1143 void MEDCouplingFieldDiscretizationPerCell::buildDiscrPerCellIfNecessary(const MEDCouplingMesh *mesh)
1144 {
1145   if(!mesh)
1146     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::buildDiscrPerCellIfNecessary : NULL input mesh !");
1147   if(!_discr_per_cell)
1148     {
1149       _discr_per_cell=DataArrayInt::New();
1150       int nbTuples=mesh->getNumberOfCells();
1151       _discr_per_cell->alloc(nbTuples,1);
1152       int *ptr=_discr_per_cell->getPointer();
1153       std::fill(ptr,ptr+nbTuples,DFT_INVALID_LOCID_VALUE);
1154     }
1155 }
1156
1157 void MEDCouplingFieldDiscretizationPerCell::checkNoOrphanCells() const throw(INTERP_KERNEL::Exception)
1158 {
1159   if(!_discr_per_cell)
1160     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::checkNoOrphanCells : no discretization defined !");
1161   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> test=_discr_per_cell->getIdsEqual(DFT_INVALID_LOCID_VALUE);
1162   if(test->getNumberOfTuples()!=0)
1163     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::checkNoOrphanCells : presence of orphan cells !");
1164 }
1165
1166 /*!
1167  * This method is useful when 'this' describes a field discretization with several gauss discretization on a \b same cell type.
1168  * For example same NORM_TRI3 cells having 6 gauss points and others with 12 gauss points.
1169  * This method returns 2 arrays with same size : the return value and 'locIds' output parameter.
1170  * For a given i into [0,locIds.size) ret[i] represents the set of cell ids of i_th set an locIds[i] represents the set of discretisation of the set.
1171  * The return vector contains a set of newly created instance to deal with.
1172  * The returned vector represents a \b partition of cells ids with a gauss discretization set.
1173  * 
1174  * If no descretization is set in 'this' and exception will be thrown.
1175  */
1176 std::vector<DataArrayInt *> MEDCouplingFieldDiscretizationPerCell::splitIntoSingleGaussDicrPerCellType(std::vector<int>& locIds) const throw(INTERP_KERNEL::Exception)
1177 {
1178   if(!_discr_per_cell)
1179     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::splitIntoSingleGaussDicrPerCellType : no descretization set !");
1180   return _discr_per_cell->partitionByDifferentValues(locIds);
1181 }
1182
1183 const DataArrayInt *MEDCouplingFieldDiscretizationPerCell::getArrayOfDiscIds() const
1184 {
1185   return _discr_per_cell;
1186 }
1187
1188 void MEDCouplingFieldDiscretizationPerCell::setArrayOfDiscIds(const DataArrayInt *adids) throw(INTERP_KERNEL::Exception)
1189 {
1190   if(adids!=_discr_per_cell)
1191     {
1192       if(_discr_per_cell)
1193         _discr_per_cell->decrRef();
1194       _discr_per_cell=const_cast<DataArrayInt *>(adids);
1195       if(_discr_per_cell)
1196         _discr_per_cell->incrRef();
1197       declareAsNew();
1198     }
1199 }
1200
1201 MEDCouplingFieldDiscretizationGauss::MEDCouplingFieldDiscretizationGauss()
1202 {
1203 }
1204
1205 MEDCouplingFieldDiscretizationGauss::MEDCouplingFieldDiscretizationGauss(const MEDCouplingFieldDiscretizationGauss& other, const int *startCellIds, const int *endCellIds):MEDCouplingFieldDiscretizationPerCell(other,startCellIds,endCellIds),_loc(other._loc)
1206 {
1207 }
1208
1209 MEDCouplingFieldDiscretizationGauss::MEDCouplingFieldDiscretizationGauss(const MEDCouplingFieldDiscretizationGauss& other, int beginCellIds, int endCellIds, int stepCellIds):MEDCouplingFieldDiscretizationPerCell(other,beginCellIds,endCellIds,stepCellIds),_loc(other._loc)
1210 {
1211 }
1212
1213 TypeOfField MEDCouplingFieldDiscretizationGauss::getEnum() const
1214 {
1215   return TYPE;
1216 }
1217
1218 bool MEDCouplingFieldDiscretizationGauss::isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const
1219 {
1220   if(!other)
1221     {
1222       reason="other spatial discretization is NULL, and this spatial discretization (Gauss) is defined.";
1223       return false;
1224     }
1225   const MEDCouplingFieldDiscretizationGauss *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationGauss *>(other);
1226   if(!otherC)
1227     {
1228       reason="Spatial discrtization of this is ON_GAUSS, which is not the case of other.";
1229       return false;
1230     }
1231   if(!MEDCouplingFieldDiscretizationPerCell::isEqualIfNotWhy(other,eps,reason))
1232     return false;
1233   if(_loc.size()!=otherC->_loc.size())
1234     {
1235       reason="Gauss spatial discretization : localization sizes differ";
1236       return false;
1237     }
1238   std::size_t sz=_loc.size();
1239   for(std::size_t i=0;i<sz;i++)
1240     if(!_loc[i].isEqual(otherC->_loc[i],eps))
1241       {
1242         std::ostringstream oss; oss << "Gauss spatial discretization : Localization #" << i << " differ from this to other.";
1243         reason=oss.str();
1244         return false;
1245       }
1246   return true;
1247 }
1248
1249 bool MEDCouplingFieldDiscretizationGauss::isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const
1250 {
1251   const MEDCouplingFieldDiscretizationGauss *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationGauss *>(other);
1252   if(!otherC)
1253     return false;
1254   if(!MEDCouplingFieldDiscretizationPerCell::isEqualWithoutConsideringStr(other,eps))
1255     return false;
1256   if(_loc.size()!=otherC->_loc.size())
1257     return false;
1258   std::size_t sz=_loc.size();
1259   for(std::size_t i=0;i<sz;i++)
1260     if(!_loc[i].isEqual(otherC->_loc[i],eps))
1261       return false;
1262   return true;
1263 }
1264
1265 /*!
1266  * This method is simply called by MEDCouplingFieldDiscretization::deepCpy. It performs the deep copy of \a this.
1267  *
1268  * \sa MEDCouplingFieldDiscretization::deepCpy.
1269  */
1270 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationGauss::clone() const
1271 {
1272   return new MEDCouplingFieldDiscretizationGauss(*this);
1273 }
1274
1275 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationGauss::clonePart(const int *startCellIds, const int *endCellIds) const
1276 {
1277   return new MEDCouplingFieldDiscretizationGauss(*this,startCellIds,endCellIds);
1278 }
1279
1280 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationGauss::clonePartRange(int beginCellIds, int endCellIds, int stepCellIds) const
1281 {
1282   return new MEDCouplingFieldDiscretizationGauss(*this,beginCellIds,endCellIds,stepCellIds);
1283 }
1284
1285 std::string MEDCouplingFieldDiscretizationGauss::getStringRepr() const
1286 {
1287   std::ostringstream oss; oss << REPR << "." << std::endl;
1288   if(_discr_per_cell)
1289     {
1290       if(_discr_per_cell->isAllocated())
1291         {
1292           oss << "Discretization per cell : ";
1293           std::copy(_discr_per_cell->begin(),_discr_per_cell->end(),std::ostream_iterator<int>(oss,", "));
1294           oss << std::endl;
1295         }
1296     }
1297   oss << "Presence of " << _loc.size() << " localizations." << std::endl;
1298   int i=0;
1299   for(std::vector<MEDCouplingGaussLocalization>::const_iterator it=_loc.begin();it!=_loc.end();it++,i++)
1300     {
1301       oss << "+++++ Localization #" << i << " +++++" << std::endl;
1302       oss << (*it).getStringRepr();
1303       oss << "++++++++++" << std::endl;
1304     }
1305   return oss.str();
1306 }
1307
1308 std::size_t MEDCouplingFieldDiscretizationGauss::getHeapMemorySize() const
1309 {
1310   std::size_t ret=_loc.capacity()*sizeof(MEDCouplingGaussLocalization);
1311   for(std::vector<MEDCouplingGaussLocalization>::const_iterator it=_loc.begin();it!=_loc.end();it++)
1312     ret+=(*it).getHeapMemorySize();
1313   return MEDCouplingFieldDiscretizationPerCell::getHeapMemorySize()+ret;
1314 }
1315
1316 const char *MEDCouplingFieldDiscretizationGauss::getRepr() const
1317 {
1318   return REPR;
1319 }
1320
1321 /*!
1322  * mesh is not used here. It is not a bug !
1323  */
1324 int MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode(const MEDCouplingMesh *mesh, const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
1325 {
1326   if(!_discr_per_cell || !_discr_per_cell->isAllocated() || _discr_per_cell->getNumberOfComponents()!=1)
1327     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode");
1328   if(code.size()%3!=0)
1329     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode : invalid input code !");
1330   int nbOfSplit=(int)idsPerType.size();
1331   int nbOfTypes=(int)code.size()/3;
1332   int ret=0;
1333   for(int i=0;i<nbOfTypes;i++)
1334     {
1335       int nbOfEltInChunk=code[3*i+1];
1336       if(nbOfEltInChunk<0)
1337         throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode : invalid input code ! presence of negative value in a type !");
1338       int pos=code[3*i+2];
1339       if(pos!=-1)
1340         {
1341           if(pos<0 || pos>=nbOfSplit)
1342             {
1343               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode : input code points to pos " << pos << " in typeid " << i << " ! Should be in [0," << nbOfSplit << ") !";
1344               throw INTERP_KERNEL::Exception(oss.str().c_str());
1345             }
1346           const DataArrayInt *ids(idsPerType[pos]);
1347           if(!ids || !ids->isAllocated() || ids->getNumberOfComponents()!=1 || ids->getNumberOfTuples()!=nbOfEltInChunk || ids->getMinValueInArray()<0)
1348             {
1349               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode : input pfl chunck at pos " << pos << " should have " << i << " tuples and one component and with ids all >=0 !";
1350               throw INTERP_KERNEL::Exception(oss.str().c_str());
1351             }
1352         }
1353       ret+=nbOfEltInChunk;
1354     }
1355   if(ret!=_discr_per_cell->getNumberOfTuples())
1356     {
1357       std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode : input code points to " << ret << " cells whereas discretization percell array lgth is " <<  _discr_per_cell->getNumberOfTuples() << " !";
1358     }
1359   return getNumberOfTuples(0);//0 is not an error ! It is to be sure that input mesh is not used
1360 }
1361
1362 int MEDCouplingFieldDiscretizationGauss::getNumberOfTuples(const MEDCouplingMesh *) const throw(INTERP_KERNEL::Exception)
1363 {
1364   int ret=0;
1365   if (_discr_per_cell == 0)
1366     throw INTERP_KERNEL::Exception("Discretization is not initialized!");
1367   const int *dcPtr=_discr_per_cell->getConstPointer();
1368   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1369   int maxSz=(int)_loc.size();
1370   for(const int *w=dcPtr;w!=dcPtr+nbOfTuples;w++)
1371     {
1372       if(*w>=0 && *w<maxSz)
1373         ret+=_loc[*w].getNumberOfGaussPt();
1374       else
1375         {
1376           std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getNumberOfTuples : At cell #" << std::distance(dcPtr,w) << " localization id is " << *w << " should be in [0," << maxSz << ") !";
1377           throw INTERP_KERNEL::Exception(oss.str().c_str());
1378         }
1379     }
1380   return ret;
1381 }
1382
1383 int MEDCouplingFieldDiscretizationGauss::getNumberOfMeshPlaces(const MEDCouplingMesh *mesh) const
1384 {
1385   if(!mesh)
1386     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getNumberOfMeshPlaces : NULL input mesh !");
1387   return mesh->getNumberOfCells();
1388 }
1389
1390 /*!
1391  * This method is redevelopped for performance reasons, but it is equivalent to a call to MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField
1392  * and a call to DataArrayDouble::computeOffsets2 on the returned array.
1393  */
1394 DataArrayInt *MEDCouplingFieldDiscretizationGauss::getOffsetArr(const MEDCouplingMesh *mesh) const
1395 {
1396   if(!mesh)
1397     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getOffsetArr : NULL input mesh !");
1398   int nbOfTuples=mesh->getNumberOfCells();
1399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1400   ret->alloc(nbOfTuples+1,1);
1401   int *retPtr=ret->getPointer();
1402   const int *start=_discr_per_cell->getConstPointer();
1403   if(_discr_per_cell->getNumberOfTuples()!=nbOfTuples)
1404     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getOffsetArr : mismatch between the mesh and the discretization ids array length !");
1405   int maxPossible=(int)_loc.size();
1406   retPtr[0]=0;
1407   for(int i=0;i<nbOfTuples;i++,start++)
1408     {
1409       if(*start>=0 && *start<maxPossible)
1410         retPtr[i+1]=retPtr[i]+_loc[*start].getNumberOfGaussPt();
1411       else
1412         {
1413           std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getOffsetArr : At position #" << i << " the locid = " << *start << " whereas it should be in [0," << maxPossible << ") !";
1414           throw INTERP_KERNEL::Exception(oss.str().c_str());
1415         }
1416     }
1417   return ret.retn();
1418 }
1419
1420 void MEDCouplingFieldDiscretizationGauss::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArray *>& arrays,
1421                                                                 const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
1422 {
1423   if(!mesh)
1424     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::renumberArraysForCell : NULL input mesh !");
1425   const int *array=old2NewBg;
1426   if(check)
1427     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+mesh->getNumberOfCells());
1428   int nbOfCells=_discr_per_cell->getNumberOfTuples();
1429   int nbOfTuples=getNumberOfTuples(0);
1430   const int *dcPtr=_discr_per_cell->getConstPointer();
1431   int *array2=new int[nbOfTuples];//stores the final conversion array old2New to give to arrays in renumberInPlace.
1432   int *array3=new int[nbOfCells];//store for each cell in present dcp array (already renumbered) the offset needed by each cell in new numbering.
1433   array3[0]=0;
1434   for(int i=1;i<nbOfCells;i++)
1435     array3[i]=array3[i-1]+_loc[dcPtr[i-1]].getNumberOfGaussPt();
1436   int j=0;
1437   for(int i=0;i<nbOfCells;i++)
1438     {
1439       int nbOfGaussPt=_loc[dcPtr[array[i]]].getNumberOfGaussPt();
1440       for(int k=0;k<nbOfGaussPt;k++,j++)
1441         array2[j]=array3[array[i]]+k;
1442     }
1443   delete [] array3;
1444   for(std::vector<DataArray *>::const_iterator it=arrays.begin();it!=arrays.end();it++)
1445     if(*it)
1446       (*it)->renumberInPlace(array2);
1447   delete [] array2;
1448   if(check)
1449     free(const_cast<int*>(array));
1450 }
1451
1452 DataArrayDouble *MEDCouplingFieldDiscretizationGauss::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const
1453 {
1454   if(!mesh)
1455     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getLocalizationOfDiscValues : NULL input mesh !");
1456   checkNoOrphanCells();
1457   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> umesh=mesh->buildUnstructured();//in general do nothing
1458   int nbOfTuples=getNumberOfTuples(mesh);
1459   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
1460   int spaceDim=mesh->getSpaceDimension();
1461   ret->alloc(nbOfTuples,spaceDim);
1462   std::vector< int > locIds;
1463   std::vector<DataArrayInt *> parts=splitIntoSingleGaussDicrPerCellType(locIds);
1464   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > parts2(parts.size());
1465   std::copy(parts.begin(),parts.end(),parts2.begin());
1466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=buildNbOfGaussPointPerCellField();
1467   offsets->computeOffsets();
1468   const int *ptrOffsets=offsets->getConstPointer();
1469   const double *coords=umesh->getCoords()->getConstPointer();
1470   const int *connI=umesh->getNodalConnectivityIndex()->getConstPointer();
1471   const int *conn=umesh->getNodalConnectivity()->getConstPointer();
1472   double *valsToFill=ret->getPointer();
1473   for(std::size_t i=0;i<parts2.size();i++)
1474     {
1475       INTERP_KERNEL::GaussCoords calculator;
1476       //
1477       const MEDCouplingGaussLocalization& cli=_loc[locIds[i]];//curLocInfo
1478       INTERP_KERNEL::NormalizedCellType typ=cli.getType();
1479       const std::vector<double>& wg=cli.getWeights();
1480       calculator.addGaussInfo(typ,INTERP_KERNEL::CellModel::GetCellModel(typ).getDimension(),
1481                                   &cli.getGaussCoords()[0],(int)wg.size(),&cli.getRefCoords()[0],
1482                                   INTERP_KERNEL::CellModel::GetCellModel(typ).getNumberOfNodes());
1483       //
1484       int nbt=parts2[i]->getNumberOfTuples();
1485       for(const int *w=parts2[i]->getConstPointer();w!=parts2[i]->getConstPointer()+nbt;w++)
1486         calculator.calculateCoords(cli.getType(),coords,spaceDim,conn+connI[*w]+1,valsToFill+spaceDim*(ptrOffsets[*w]));
1487     }
1488   ret->copyStringInfoFrom(*umesh->getCoords());
1489   return ret.retn();
1490 }
1491
1492 void MEDCouplingFieldDiscretizationGauss::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *tupleIdsBg, const int *tupleIdsEnd,
1493                                                                              DataArrayInt *&cellRestriction, DataArrayInt *&trueTupleRestriction) const throw(INTERP_KERNEL::Exception)
1494 {
1495   if(!mesh)
1496     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::computeMeshRestrictionFromTupleIds : NULL input mesh !");
1497   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=DataArrayInt::New(); tmp->alloc((int)std::distance(tupleIdsBg,tupleIdsEnd),1);
1498   std::copy(tupleIdsBg,tupleIdsEnd,tmp->getPointer());
1499   tmp->sort(true);
1500   tmp=tmp->buildUnique();
1501   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=buildNbOfGaussPointPerCellField();
1502   nbOfNodesPerCell->computeOffsets2();
1503   nbOfNodesPerCell->searchRangesInListOfIds(tmp,cellRestriction,trueTupleRestriction);
1504 }
1505
1506 /*!
1507  * Empty : not a bug
1508  */
1509 void MEDCouplingFieldDiscretizationGauss::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
1510 {
1511 }
1512
1513 void MEDCouplingFieldDiscretizationGauss::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
1514 {
1515   int val=-1;
1516   if(_discr_per_cell)
1517     val=_discr_per_cell->getNumberOfTuples();
1518   tinyInfo.push_back(val);
1519   tinyInfo.push_back((int)_loc.size());
1520   if(_loc.empty())
1521     tinyInfo.push_back(-1);
1522   else
1523     tinyInfo.push_back(_loc[0].getDimension());
1524   for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++)
1525     (*iter).pushTinySerializationIntInfo(tinyInfo);
1526 }
1527
1528 void MEDCouplingFieldDiscretizationGauss::getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const
1529 {
1530   for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++)
1531     (*iter).pushTinySerializationDblInfo(tinyInfo);
1532 }
1533
1534 void MEDCouplingFieldDiscretizationGauss::getSerializationIntArray(DataArrayInt *& arr) const
1535 {
1536   arr=0;
1537   if(_discr_per_cell)
1538     arr=_discr_per_cell;
1539 }
1540
1541 void MEDCouplingFieldDiscretizationGauss::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *& arr)
1542 {
1543   int val=tinyInfo[0];
1544   if(val>=0)
1545     {
1546       _discr_per_cell=DataArrayInt::New();
1547       _discr_per_cell->alloc(val,1);
1548     }
1549   else
1550     _discr_per_cell=0;
1551   arr=_discr_per_cell;
1552   int nbOfLoc=tinyInfo[1];
1553   _loc.clear();
1554   int dim=tinyInfo[2];
1555   int delta=-1;
1556   if(nbOfLoc>0)
1557     delta=((int)tinyInfo.size()-3)/nbOfLoc;
1558   for(int i=0;i<nbOfLoc;i++)
1559     {
1560       std::vector<int> tmp(tinyInfo.begin()+3+i*delta,tinyInfo.begin()+3+(i+1)*delta);
1561       MEDCouplingGaussLocalization elt=MEDCouplingGaussLocalization::BuildNewInstanceFromTinyInfo(dim,tmp);
1562       _loc.push_back(elt);
1563     }
1564 }
1565
1566 void MEDCouplingFieldDiscretizationGauss::finishUnserialization(const std::vector<double>& tinyInfo)
1567 {
1568   double *tmp=new double[tinyInfo.size()];
1569   std::copy(tinyInfo.begin(),tinyInfo.end(),tmp);
1570   const double *work=tmp;
1571   for(std::vector<MEDCouplingGaussLocalization>::iterator iter=_loc.begin();iter!=_loc.end();iter++)
1572     work=(*iter).fillWithValues(work);
1573   delete [] tmp;
1574 }
1575
1576 double MEDCouplingFieldDiscretizationGauss::getIJK(const MEDCouplingMesh *mesh, const DataArrayDouble *da,
1577                                                    int cellId, int nodeIdInCell, int compoId) const throw(INTERP_KERNEL::Exception)
1578 {
1579   int offset=getOffsetOfCell(cellId);
1580   return da->getIJ(offset+nodeIdInCell,compoId);
1581 }
1582
1583 void MEDCouplingFieldDiscretizationGauss::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception)
1584 {
1585   if(!mesh || !da)
1586     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::checkCoherencyBetween : NULL input mesh or DataArray !");
1587   MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween(mesh,da);
1588   for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++)
1589     (*iter).checkCoherency();
1590   int nbOfDesc=(int)_loc.size();
1591   int nbOfCells=mesh->getNumberOfCells();
1592   const int *dc=_discr_per_cell->getConstPointer();
1593   for(int i=0;i<nbOfCells;i++)
1594     {
1595       if(dc[i]>=nbOfDesc)
1596         {
1597           std::ostringstream oss; oss << "Cell # " << i << " of mesh \"" << mesh->getName() << "\" has an undefined gauss location ! Should never happend !";
1598           throw INTERP_KERNEL::Exception(oss.str().c_str());
1599         }
1600       if(dc[i]<0)
1601         {
1602           std::ostringstream oss; oss << "Cell # " << i << " of mesh \"" << mesh->getName() << "\" has no gauss location !";
1603           throw INTERP_KERNEL::Exception(oss.str().c_str());
1604         }
1605       if(mesh->getTypeOfCell(i)!=_loc[dc[i]].getType())
1606         {
1607           std::ostringstream oss; oss << "Types of mesh and gauss location mismatch for cell # " << i;
1608           throw INTERP_KERNEL::Exception(oss.str().c_str());
1609         }
1610     }
1611   int nbOfTuples=getNumberOfTuples(mesh);
1612   if(nbOfTuples!=da->getNumberOfTuples())
1613     {
1614       std::ostringstream oss; oss << "Invalid number of tuples in the array : expecting " << nbOfTuples << " !";
1615       throw INTERP_KERNEL::Exception(oss.str().c_str());
1616     }
1617 }
1618
1619 MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationGauss::getMeasureField(const MEDCouplingMesh *mesh, bool isAbs) const
1620 {
1621   if(!mesh)
1622     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getMeasureField : mesh instance specified is NULL !");
1623   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> vol=mesh->getMeasureField(isAbs);
1624   const double *volPtr=vol->getArray()->begin();
1625   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_GAUSS_PT);
1626   ret->setMesh(mesh);
1627   ret->setDiscretization(const_cast<MEDCouplingFieldDiscretizationGauss *>(this));
1628   if(!_discr_per_cell)
1629     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getMeasureField : no discr per cell array not defined ! spatial localization is incorrect !");
1630   _discr_per_cell->checkAllocated();
1631   if(_discr_per_cell->getNumberOfComponents()!=1)
1632     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getMeasureField : no discr per cell array defined but with nb of components different from 1 !");
1633   if(_discr_per_cell->getNumberOfTuples()!=vol->getNumberOfTuples())
1634     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getMeasureField : no discr per cell array defined but mismatch between nb of cells of mesh and size of spatial disr array !");
1635   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offset=getOffsetArr(mesh);
1636   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New(); arr->alloc(getNumberOfTuples(mesh),1);
1637   ret->setArray(arr);
1638   double *arrPtr=arr->getPointer();
1639   const int *offsetPtr=offset->getConstPointer();
1640   int maxGaussLoc=(int)_loc.size();
1641   std::vector<int> locIds;
1642   std::vector<DataArrayInt *> ids=splitIntoSingleGaussDicrPerCellType(locIds);
1643   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ids2(ids.size()); std::copy(ids.begin(),ids.end(),ids2.begin());
1644   for(std::size_t i=0;i<locIds.size();i++)
1645     {
1646       const DataArrayInt *curIds=ids[i];
1647       int locId=locIds[i];
1648       if(locId>=0 && locId<maxGaussLoc)
1649         {
1650           const MEDCouplingGaussLocalization& loc=_loc[locId];
1651           int nbOfGaussPt=loc.getNumberOfGaussPt();
1652           INTERP_KERNEL::AutoPtr<double> weights=new double[nbOfGaussPt];
1653           double sum=std::accumulate(loc.getWeights().begin(),loc.getWeights().end(),0.);
1654           std::transform(loc.getWeights().begin(),loc.getWeights().end(),(double *)weights,std::bind2nd(std::multiplies<double>(),1./sum));
1655           for(const int *cellId=curIds->begin();cellId!=curIds->end();cellId++)
1656             for(int j=0;j<nbOfGaussPt;j++)
1657               arrPtr[offsetPtr[*cellId]+j]=weights[j]*volPtr[*cellId];
1658         }
1659       else
1660         {
1661           std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getMeasureField : Presence of localization id " << locId << " in cell #" << curIds->getIJ(0,0) << " ! Must be in [0," << maxGaussLoc << ") !";
1662           throw INTERP_KERNEL::Exception(oss.str().c_str());
1663         }
1664     }
1665   ret->synchronizeTimeWithSupport();
1666   return ret.retn();
1667 }
1668
1669 void MEDCouplingFieldDiscretizationGauss::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
1670 {
1671   throw INTERP_KERNEL::Exception("Not implemented yet !");
1672 }
1673
1674 void MEDCouplingFieldDiscretizationGauss::getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const
1675 {
1676   throw INTERP_KERNEL::Exception("getValueOnPos(i,j,k) : Not applyable for Gauss points !");
1677 }
1678
1679 DataArrayDouble *MEDCouplingFieldDiscretizationGauss::getValueOnMulti(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, int nbOfPoints) const
1680 {
1681   throw INTERP_KERNEL::Exception("getValueOnMulti : Not implemented yet for gauss points !");
1682 }
1683
1684 MEDCouplingMesh *MEDCouplingFieldDiscretizationGauss::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
1685 {
1686   if(!mesh)
1687     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildSubMeshData : NULL input mesh !");
1688   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diSafe=computeTupleIdsToSelectFromCellIds(mesh,start,end);
1689   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPart(start,end);
1690   di=diSafe.retn();
1691   return ret.retn();
1692 }
1693
1694 /*!
1695  * This method is strictly equivalent to MEDCouplingFieldDiscretizationGauss::buildSubMeshData except that it is optimized for input defined as a range of cell ids.
1696  * 
1697  * \param [out] beginOut Valid only if \a di is NULL
1698  * \param [out] endOut Valid only if \a di is NULL
1699  * \param [out] stepOut Valid only if \a di is NULL
1700  * \param [out] di is an array returned that specifies entity ids (nodes, cells, Gauss points... ) in array if no output range is foundable.
1701  *
1702  * \sa MEDCouplingFieldDiscretizationGauss::buildSubMeshData
1703  */
1704 MEDCouplingMesh *MEDCouplingFieldDiscretizationGauss::buildSubMeshDataRange(const MEDCouplingMesh *mesh, int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt *&di) const
1705 {
1706   if(stepCellIds!=1)//even for stepCellIds==-1 the output will not be a range
1707     return MEDCouplingFieldDiscretization::buildSubMeshDataRange(mesh,beginCellIds,endCellIds,stepCellIds,beginOut,endOut,stepOut,di);
1708   if(!mesh)
1709     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildSubMeshDataRange : NULL input mesh !");
1710   if(!_discr_per_cell)
1711     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildSubMeshDataRange : no discretization array set !");
1712   di=0; beginOut=0; endOut=0; stepOut=stepCellIds;
1713   const char msg[]="MEDCouplingFieldDiscretizationGauss::buildSubMeshDataRange : cell #";
1714   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1715   const int *w=_discr_per_cell->begin();
1716   int nbMaxOfLocId=(int)_loc.size();
1717   for(int i=0;i<nbOfTuples;i++,w++)
1718     {
1719       if(*w!=DFT_INVALID_LOCID_VALUE)
1720         {
1721           if(*w>=0 && *w<nbMaxOfLocId)
1722             {
1723               int delta=_loc[*w].getNumberOfGaussPt();
1724               if(i<beginCellIds)
1725                 beginOut+=delta;
1726               endOut+=delta;
1727               if(i>=endCellIds)
1728                 break;
1729             }
1730           else
1731             { std::ostringstream oss; oss << msg << i << " has invalid id (" << *w << ") ! Should be in [0," << nbMaxOfLocId << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
1732         }
1733       else
1734         { std::ostringstream oss; oss << msg << i << " is detected as orphan !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
1735     }
1736   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPartRange(beginCellIds,endCellIds,stepCellIds);
1737   return ret.retn();
1738 }
1739
1740 /*!
1741  * This method returns a tuple ids selection from cell ids selection [start;end).
1742  * This method is called by MEDCouplingFieldDiscretizationGauss::buildSubMeshData to return parameter \b di.
1743  *
1744  * \return a newly allocated array containing ids to select into the DataArrayDouble of the field.
1745  * 
1746  */
1747 DataArrayInt *MEDCouplingFieldDiscretizationGauss::computeTupleIdsToSelectFromCellIds(const MEDCouplingMesh *mesh, const int *startCellIds, const int *endCellIds) const
1748 {
1749   if(!mesh)
1750     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::computeTupleIdsToSelectFromCellIds : null mesh !");
1751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=buildNbOfGaussPointPerCellField();//check of _discr_per_cell not NULL pointer
1752   int nbOfCells=mesh->getNumberOfCells();
1753   if(_discr_per_cell->getNumberOfTuples()!=nbOfCells)
1754     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::computeTupleIdsToSelectFromCellIds : mismatch of nb of tuples of cell ids array and number of cells !");
1755   nbOfNodesPerCell->computeOffsets2();
1756   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> sel=DataArrayInt::New(); sel->useArray(startCellIds,false,CPP_DEALLOC,(int)std::distance(startCellIds,endCellIds),1);
1757   return sel->buildExplicitArrByRanges(nbOfNodesPerCell);
1758 }
1759
1760 /*!
1761  * No implementation needed !
1762  */
1763 void MEDCouplingFieldDiscretizationGauss::renumberValuesOnNodes(double , const int *, int newNbOfNodes, DataArrayDouble *) const
1764 {
1765 }
1766
1767 void MEDCouplingFieldDiscretizationGauss::renumberValuesOnCells(double epsOnVals, const MEDCouplingMesh *mesh, const int *old2New, int newSz, DataArrayDouble *arr) const
1768 {
1769   throw INTERP_KERNEL::Exception("Not implemented yet !");
1770 }
1771
1772 void MEDCouplingFieldDiscretizationGauss::renumberValuesOnCellsR(const MEDCouplingMesh *mesh, const int *new2old, int newSz, DataArrayDouble *arr) const
1773 {
1774   throw INTERP_KERNEL::Exception("Number of cells has changed and becomes higher with some cells that have been split ! Unable to conserve the Gauss field !");
1775 }
1776
1777 void MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnType(const MEDCouplingMesh *mesh, INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
1778                                                                      const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
1779 {
1780   if(!mesh)
1781     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnType : NULL input mesh !");
1782   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1783   if((int)cm.getDimension()!=mesh->getMeshDimension())
1784     {
1785       std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnType : mismatch of dimensions ! MeshDim==" << mesh->getMeshDimension();
1786       oss << " whereas Type '" << cm.getRepr() << "' has dimension " << cm.getDimension() << " !";
1787       throw INTERP_KERNEL::Exception(oss.str().c_str());
1788     }
1789   buildDiscrPerCellIfNecessary(mesh);
1790   int id=(int)_loc.size();
1791   MEDCouplingGaussLocalization elt(type,refCoo,gsCoo,wg);
1792   _loc.push_back(elt);
1793   int *ptr=_discr_per_cell->getPointer();
1794   int nbCells=mesh->getNumberOfCells();
1795   for(int i=0;i<nbCells;i++)
1796     if(mesh->getTypeOfCell(i)==type)
1797       ptr[i]=id;
1798   zipGaussLocalizations();
1799 }
1800
1801 void MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnCells(const MEDCouplingMesh *mesh, const int *begin, const int *end, const std::vector<double>& refCoo,
1802                                                                       const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
1803 {
1804   if(!mesh)
1805     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnCells : NULL input mesh !");
1806   buildDiscrPerCellIfNecessary(mesh);
1807   if(std::distance(begin,end)<1)
1808     throw INTERP_KERNEL::Exception("Size of [begin,end) must be equal or greater than 1 !");
1809   INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(*begin);
1810   MEDCouplingGaussLocalization elt(type,refCoo,gsCoo,wg);
1811   int id=(int)_loc.size();
1812   int *ptr=_discr_per_cell->getPointer();
1813   for(const int *w=begin+1;w!=end;w++)
1814     {
1815       if(mesh->getTypeOfCell(*w)!=type)
1816         {
1817           std::ostringstream oss; oss << "The cell with id " << *w << " has been detected to be incompatible in the [begin,end) array specified !";
1818           throw INTERP_KERNEL::Exception(oss.str().c_str());
1819         }
1820     }
1821   //
1822   for(const int *w2=begin;w2!=end;w2++)
1823     ptr[*w2]=id;
1824   //
1825   _loc.push_back(elt);
1826   zipGaussLocalizations();
1827 }
1828
1829 void MEDCouplingFieldDiscretizationGauss::clearGaussLocalizations() throw(INTERP_KERNEL::Exception)
1830 {
1831   if(_discr_per_cell)
1832     {
1833       _discr_per_cell->decrRef();
1834       _discr_per_cell=0;
1835     }
1836   _loc.clear();
1837 }
1838
1839 void MEDCouplingFieldDiscretizationGauss::setGaussLocalization(int locId, const MEDCouplingGaussLocalization& loc) throw(INTERP_KERNEL::Exception)
1840 {
1841   if(locId<0)
1842     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::setGaussLocalization : localization id has to be >=0 !");
1843   int sz=(int)_loc.size();
1844   MEDCouplingGaussLocalization gLoc(INTERP_KERNEL::NORM_ERROR);
1845   if(locId>=sz)
1846     _loc.resize(locId+1,gLoc);
1847   _loc[locId]=loc;
1848 }
1849
1850 void MEDCouplingFieldDiscretizationGauss::resizeLocalizationVector(int newSz) throw(INTERP_KERNEL::Exception)
1851 {
1852   if(newSz<0)
1853     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::resizeLocalizationVector : new size has to be >=0 !");
1854   MEDCouplingGaussLocalization gLoc(INTERP_KERNEL::NORM_ERROR);
1855   _loc.resize(newSz,gLoc);
1856 }
1857
1858 MEDCouplingGaussLocalization& MEDCouplingFieldDiscretizationGauss::getGaussLocalization(int locId) throw(INTERP_KERNEL::Exception)
1859 {
1860   checkLocalizationId(locId);
1861   return _loc[locId];
1862 }
1863
1864 int MEDCouplingFieldDiscretizationGauss::getNbOfGaussLocalization() const throw(INTERP_KERNEL::Exception)
1865 {
1866   return (int)_loc.size();
1867 }
1868
1869 int MEDCouplingFieldDiscretizationGauss::getGaussLocalizationIdOfOneCell(int cellId) const throw(INTERP_KERNEL::Exception)
1870 {
1871   if(!_discr_per_cell)
1872     throw INTERP_KERNEL::Exception("No Gauss localization still set !");
1873   int locId=_discr_per_cell->begin()[cellId];
1874   if(locId<0)
1875     throw INTERP_KERNEL::Exception("No Gauss localization set for the specified cell !");
1876   return locId;
1877 }
1878
1879 int MEDCouplingFieldDiscretizationGauss::getGaussLocalizationIdOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
1880 {
1881   std::set<int> ret=getGaussLocalizationIdsOfOneType(type);
1882   if(ret.empty())
1883     throw INTERP_KERNEL::Exception("No gauss discretization found for the specified type !");
1884   if(ret.size()>1)
1885     throw INTERP_KERNEL::Exception("Several gauss discretizations have been found for the specified type !");
1886   return *ret.begin();
1887 }
1888
1889 std::set<int> MEDCouplingFieldDiscretizationGauss::getGaussLocalizationIdsOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
1890 {
1891   if(!_discr_per_cell)
1892     throw INTERP_KERNEL::Exception("No Gauss localization still set !");
1893   std::set<int> ret;
1894   int id=0;
1895   for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++,id++)
1896     if((*iter).getType()==type)
1897       ret.insert(id);
1898   return ret;
1899 }
1900
1901 void MEDCouplingFieldDiscretizationGauss::getCellIdsHavingGaussLocalization(int locId, std::vector<int>& cellIds) const throw(INTERP_KERNEL::Exception)
1902 {
1903   if(locId<0 || locId>=(int)_loc.size())
1904     throw INTERP_KERNEL::Exception("Invalid locId given : must be in range [0:getNbOfGaussLocalization()) !");
1905   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1906   const int *ptr=_discr_per_cell->getConstPointer();
1907   for(int i=0;i<nbOfTuples;i++)
1908     if(ptr[i]==locId)
1909       cellIds.push_back(i);
1910 }
1911
1912 const MEDCouplingGaussLocalization& MEDCouplingFieldDiscretizationGauss::getGaussLocalization(int locId) const throw(INTERP_KERNEL::Exception)
1913 {
1914   checkLocalizationId(locId);
1915   return _loc[locId];
1916 }
1917
1918 void MEDCouplingFieldDiscretizationGauss::checkLocalizationId(int locId) const throw(INTERP_KERNEL::Exception)
1919 {
1920   if(locId<0 || locId>=(int)_loc.size())
1921     throw INTERP_KERNEL::Exception("Invalid locId given : must be in range [0:getNbOfGaussLocalization()) !");
1922 }
1923
1924 int MEDCouplingFieldDiscretizationGauss::getOffsetOfCell(int cellId) const throw(INTERP_KERNEL::Exception)
1925 {
1926   int ret=0;
1927   const int *start=_discr_per_cell->getConstPointer();
1928   for(const int *w=start;w!=start+cellId;w++)
1929     ret+=_loc[*w].getNumberOfGaussPt();
1930   return ret;
1931 }
1932
1933 /*!
1934  * This method do the assumption that there is no orphan cell. If there is an exception is thrown.
1935  * This method makes the assumption too that '_discr_per_cell' is defined. If not an exception is thrown.
1936  * This method returns a newly created array with number of tuples equals to '_discr_per_cell->getNumberOfTuples' and number of components equal to 1.
1937  * The i_th tuple in returned array is the number of gauss point if the corresponding cell.
1938  */
1939 DataArrayInt *MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField() const throw(INTERP_KERNEL::Exception)
1940 {
1941   if(!_discr_per_cell)
1942     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField : no discretization array set !");
1943   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1944   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1945   const int *w=_discr_per_cell->begin();
1946   ret->alloc(nbOfTuples,1);
1947   int *valsToFill=ret->getPointer();
1948   int nbMaxOfLocId=(int)_loc.size();
1949   for(int i=0;i<nbOfTuples;i++,w++)
1950     if(*w!=DFT_INVALID_LOCID_VALUE)
1951       {
1952         if(*w>=0 && *w<nbMaxOfLocId)
1953           valsToFill[i]=_loc[*w].getNumberOfGaussPt();
1954         else
1955           {
1956             std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField : cell #" << i << " has invalid id (" << *w << ") ! Should be in [0," << nbMaxOfLocId << ") !";
1957             throw INTERP_KERNEL::Exception(oss.str().c_str());
1958           }
1959       }
1960     else
1961       {
1962         std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField : cell #" << i << " is detected as orphan !";
1963         throw INTERP_KERNEL::Exception(oss.str().c_str());
1964       }
1965   return ret.retn();
1966 }
1967
1968 void MEDCouplingFieldDiscretizationGauss::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
1969 {
1970   stream << "Gauss points spatial discretization.";
1971 }
1972
1973 /*!
1974  * This method makes the assumption that _discr_per_cell is set.
1975  * This method reduces as much as possible number size of _loc.
1976  * This method is useful when several set on same cells has been done and that some Gauss Localization are no more used.
1977  */
1978 void MEDCouplingFieldDiscretizationGauss::zipGaussLocalizations()
1979 {
1980   const int *start=_discr_per_cell->begin();
1981   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1982   INTERP_KERNEL::AutoPtr<int> tmp=new int[_loc.size()];
1983   std::fill((int *)tmp,(int *)tmp+_loc.size(),-2);
1984   for(const int *w=start;w!=start+nbOfTuples;w++)
1985     if(*w>=0)
1986       tmp[*w]=1;
1987   int fid=0;
1988   for(int i=0;i<(int)_loc.size();i++)
1989     if(tmp[i]!=-2)
1990       tmp[i]=fid++;
1991   if(fid==(int)_loc.size())
1992     return;
1993   // zip needed
1994   int *start2=_discr_per_cell->getPointer();
1995   for(int *w2=start2;w2!=start2+nbOfTuples;w2++)
1996     if(*w2>=0)
1997       *w2=tmp[*w2];
1998   std::vector<MEDCouplingGaussLocalization> tmpLoc;
1999   for(int i=0;i<(int)_loc.size();i++)
2000     if(tmp[i]!=-2)
2001       tmpLoc.push_back(_loc[tmp[i]]);
2002   _loc=tmpLoc;
2003 }
2004
2005 MEDCouplingFieldDiscretizationGaussNE::MEDCouplingFieldDiscretizationGaussNE()
2006 {
2007 }
2008
2009 TypeOfField MEDCouplingFieldDiscretizationGaussNE::getEnum() const
2010 {
2011   return TYPE;
2012 }
2013
2014 /*!
2015  * This method is simply called by MEDCouplingFieldDiscretization::deepCpy. It performs the deep copy of \a this.
2016  *
2017  * \sa MEDCouplingFieldDiscretization::deepCpy.
2018  */
2019 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationGaussNE::clone() const
2020 {
2021   return new MEDCouplingFieldDiscretizationGaussNE(*this);
2022 }
2023
2024 std::string MEDCouplingFieldDiscretizationGaussNE::getStringRepr() const
2025 {
2026   return std::string(REPR);
2027 }
2028
2029 const char *MEDCouplingFieldDiscretizationGaussNE::getRepr() const
2030 {
2031   return REPR;
2032 }
2033
2034 bool MEDCouplingFieldDiscretizationGaussNE::isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const
2035 {
2036   if(!other)
2037     {
2038       reason="other spatial discretization is NULL, and this spatial discretization (GaussNE) is defined.";
2039       return false;
2040     }
2041   const MEDCouplingFieldDiscretizationGaussNE *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationGaussNE *>(other);
2042   bool ret=otherC!=0;
2043   if(!ret)
2044     reason="Spatial discrtization of this is ON_GAUSS_NE, which is not the case of other.";
2045   return ret;
2046 }
2047
2048 int MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode(const MEDCouplingMesh *mesh, const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
2049 {
2050   if(code.size()%3!=0)
2051     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : invalid input code !");
2052   int nbOfSplit=(int)idsPerType.size();
2053   int nbOfTypes=(int)code.size()/3;
2054   int ret=0;
2055   for(int i=0;i<nbOfTypes;i++)
2056     {
2057       int nbOfEltInChunk=code[3*i+1];
2058       if(nbOfEltInChunk<0)
2059         throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : invalid input code ! presence of negative value in a type !");
2060       int pos=code[3*i+2];
2061       if(pos!=-1)
2062         {
2063           if(pos<0 || pos>=nbOfSplit)
2064             {
2065               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : input code points to pos " << pos << " in typeid " << i << " ! Should be in [0," << nbOfSplit << ") !";
2066               throw INTERP_KERNEL::Exception(oss.str().c_str());
2067             }
2068           const DataArrayInt *ids(idsPerType[pos]);
2069           if(!ids || !ids->isAllocated() || ids->getNumberOfComponents()!=1 || ids->getNumberOfTuples()!=nbOfEltInChunk || ids->getMinValueInArray()<0)
2070             {
2071               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : input pfl chunck at pos " << pos << " should have " << i << " tuples and one component and with ids all >=0 !";
2072               throw INTERP_KERNEL::Exception(oss.str().c_str());
2073             }
2074         }
2075       ret+=nbOfEltInChunk;
2076     }
2077   if(!mesh)
2078     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : NULL input mesh !");
2079   if(ret!=mesh->getNumberOfCells())
2080     {
2081       std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : input code points to " << ret << " number of cells should be " <<  mesh->getNumberOfCells() << " !";
2082     }
2083   return getNumberOfTuples(mesh);
2084 }
2085
2086 int MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuples(const MEDCouplingMesh *mesh) const throw(INTERP_KERNEL::Exception)
2087 {
2088   if(!mesh)
2089     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuples : NULL input mesh !");
2090   int ret=0;
2091   int nbOfCells=mesh->getNumberOfCells();
2092   for(int i=0;i<nbOfCells;i++)
2093     {
2094       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2095       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2096       if(cm.isDynamic())
2097         throw INTERP_KERNEL::Exception("Not implemented yet Gauss node on elements for polygons and polyedrons !");
2098       ret+=cm.getNumberOfNodes();
2099     }
2100   return ret;
2101 }
2102
2103 int MEDCouplingFieldDiscretizationGaussNE::getNumberOfMeshPlaces(const MEDCouplingMesh *mesh) const
2104 {
2105   if(!mesh)
2106     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfMeshPlaces : NULL input mesh !");
2107   return mesh->getNumberOfCells();
2108 }
2109
2110 DataArrayInt *MEDCouplingFieldDiscretizationGaussNE::getOffsetArr(const MEDCouplingMesh *mesh) const
2111 {
2112   if(!mesh)
2113     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getOffsetArr : NULL input mesh !");
2114   int nbOfTuples=mesh->getNumberOfCells();
2115   DataArrayInt *ret=DataArrayInt::New();
2116   ret->alloc(nbOfTuples+1,1);
2117   int *retPtr=ret->getPointer();
2118   retPtr[0]=0;
2119   for(int i=0;i<nbOfTuples;i++)
2120     {
2121       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2122       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2123       if(cm.isDynamic())
2124         throw INTERP_KERNEL::Exception("Not implemented yet Gauss node on elements for polygons and polyedrons !");
2125       retPtr[i+1]=retPtr[i]+cm.getNumberOfNodes();
2126     }
2127   return ret;
2128 }
2129
2130 void MEDCouplingFieldDiscretizationGaussNE::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArray *>& arrays,
2131                                                                   const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2132 {
2133   if(!mesh)
2134     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::renumberArraysForCell : NULL input mesh !");
2135   const int *array=old2NewBg;
2136   if(check)
2137     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+mesh->getNumberOfCells());
2138   int nbOfCells=mesh->getNumberOfCells();
2139   int nbOfTuples=getNumberOfTuples(mesh);
2140   int *array2=new int[nbOfTuples];//stores the final conversion array old2New to give to arrays in renumberInPlace.
2141   int *array3=new int[nbOfCells];//store for each cell in after renumbering the offset needed by each cell in new numbering.
2142   array3[0]=0;
2143   for(int i=1;i<nbOfCells;i++)
2144     {
2145       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell((int)std::distance(array,std::find(array,array+nbOfCells,i-1)));
2146       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2147       array3[i]=array3[i-1]+cm.getNumberOfNodes();
2148     }
2149   int j=0;
2150   for(int i=0;i<nbOfCells;i++)
2151     {
2152       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2153       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2154       for(int k=0;k<(int)cm.getNumberOfNodes();k++,j++)
2155         array2[j]=array3[array[i]]+k;
2156     }
2157   delete [] array3;
2158   for(std::vector<DataArray *>::const_iterator it=arrays.begin();it!=arrays.end();it++)
2159     if(*it)
2160       (*it)->renumberInPlace(array2);
2161   delete [] array2;
2162   if(check)
2163     free(const_cast<int *>(array));
2164 }
2165
2166 DataArrayDouble *MEDCouplingFieldDiscretizationGaussNE::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const
2167 {
2168   if(!mesh)
2169     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getLocalizationOfDiscValues : NULL input mesh !");
2170   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
2171   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> umesh=mesh->buildUnstructured();//in general do nothing
2172   int nbOfTuples=getNumberOfTuples(umesh);
2173   int spaceDim=mesh->getSpaceDimension();
2174   ret->alloc(nbOfTuples,spaceDim);
2175   const double *coords=umesh->getCoords()->begin();
2176   const int *connI=umesh->getNodalConnectivityIndex()->getConstPointer();
2177   const int *conn=umesh->getNodalConnectivity()->getConstPointer();
2178   int nbCells=umesh->getNumberOfCells();
2179   double *retPtr=ret->getPointer();
2180   for(int i=0;i<nbCells;i++,connI++)
2181     for(const int *w=conn+connI[0]+1;w!=conn+connI[1];w++)
2182       if(*w>=0)
2183         retPtr=std::copy(coords+(*w)*spaceDim,coords+((*w)+1)*spaceDim,retPtr);
2184   return ret.retn();
2185 }
2186
2187 /*!
2188  * Reimplemented from MEDCouplingFieldDiscretization::integral for performance reason. The default implementation is valid too for GAUSS_NE spatial discretization.
2189  */
2190 void MEDCouplingFieldDiscretizationGaussNE::integral(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, bool isWAbs, double *res) const throw(INTERP_KERNEL::Exception)
2191 {
2192   if(!mesh || !arr)
2193     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::integral : input mesh or array is null !");
2194   int nbOfCompo=arr->getNumberOfComponents();
2195   std::fill(res,res+nbOfCompo,0.);
2196   //
2197   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> vol=mesh->getMeasureField(isWAbs);
2198   std::set<INTERP_KERNEL::NormalizedCellType> types=mesh->getAllGeoTypes();
2199   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=mesh->computeNbOfNodesPerCell();
2200   nbOfNodesPerCell->computeOffsets2();
2201   const double *arrPtr=arr->begin(),*volPtr=vol->getArray()->begin();
2202   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
2203     {
2204       std::size_t wArrSz=-1;
2205       const double *wArr=GetWeightArrayFromGeometricType(*it,wArrSz);
2206       INTERP_KERNEL::AutoPtr<double> wArr2=new double[wArrSz];
2207       double sum=std::accumulate(wArr,wArr+wArrSz,0.);
2208       std::transform(wArr,wArr+wArrSz,(double *)wArr2,std::bind2nd(std::multiplies<double>(),1./sum));      
2209       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=mesh->giveCellsWithType(*it);
2210       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->buildExplicitArrByRanges(nbOfNodesPerCell);
2211       const int *ptIds2=ids2->begin(),*ptIds=ids->begin();
2212       int nbOfCellsWithCurGeoType=ids->getNumberOfTuples();
2213       for(int i=0;i<nbOfCellsWithCurGeoType;i++,ptIds++,ptIds2+=wArrSz)
2214         {
2215           for(int k=0;k<nbOfCompo;k++)
2216             {
2217               double tmp=0.;
2218               for(std::size_t j=0;j<wArrSz;j++)
2219                 tmp+=arrPtr[nbOfCompo*ptIds2[j]+k]*wArr2[j];
2220               res[k]+=tmp*volPtr[*ptIds];
2221             }
2222         }
2223     }
2224 }
2225
2226 const double *MEDCouplingFieldDiscretizationGaussNE::GetWeightArrayFromGeometricType(INTERP_KERNEL::NormalizedCellType geoType, std::size_t& lgth) throw(INTERP_KERNEL::Exception)
2227 {
2228   switch(geoType)
2229     {
2230     case INTERP_KERNEL::NORM_SEG2:
2231       lgth=(int)sizeof(FGP_SEG2)/sizeof(double);
2232       return FGP_SEG2;
2233     case INTERP_KERNEL::NORM_SEG3:
2234       lgth=(int)sizeof(FGP_SEG3)/sizeof(double);
2235       return FGP_SEG3;
2236     case INTERP_KERNEL::NORM_SEG4:
2237       lgth=(int)sizeof(FGP_SEG4)/sizeof(double);
2238       return FGP_SEG4;
2239     case INTERP_KERNEL::NORM_TRI3:
2240       lgth=(int)sizeof(FGP_TRI3)/sizeof(double);
2241       return FGP_TRI3;
2242     case INTERP_KERNEL::NORM_TRI6:
2243       lgth=(int)sizeof(FGP_TRI6)/sizeof(double);
2244       return FGP_TRI6;
2245     case INTERP_KERNEL::NORM_TRI7:
2246       lgth=(int)sizeof(FGP_TRI7)/sizeof(double);
2247       return FGP_TRI7;
2248     case INTERP_KERNEL::NORM_QUAD4:
2249       lgth=(int)sizeof(FGP_QUAD4)/sizeof(double);
2250       return FGP_QUAD4;
2251     case INTERP_KERNEL::NORM_QUAD9:
2252       lgth=(int)sizeof(FGP_QUAD9)/sizeof(double);
2253       return FGP_QUAD9;
2254     case INTERP_KERNEL::NORM_TETRA4:
2255       lgth=(int)sizeof(FGP_TETRA4)/sizeof(double);
2256       return FGP_TETRA4;
2257     case INTERP_KERNEL::NORM_PENTA6:
2258       lgth=(int)sizeof(FGP_PENTA6)/sizeof(double);
2259       return FGP_PENTA6;
2260     case INTERP_KERNEL::NORM_HEXA8:
2261       lgth=(int)sizeof(FGP_HEXA8)/sizeof(double);
2262       return FGP_HEXA8;
2263     case INTERP_KERNEL::NORM_HEXA27:
2264       lgth=(int)sizeof(FGP_HEXA27)/sizeof(double);
2265       return FGP_HEXA27;
2266     case INTERP_KERNEL::NORM_PYRA5:
2267       lgth=(int)sizeof(FGP_PYRA5)/sizeof(double);
2268       return FGP_PYRA5;
2269     default:
2270       throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::GetWeightArrayFromGeometricType : only SEG[2,3,4], TRI[3,6,7], QUAD[4,9], TETRA4, PENTA6, HEXA[8,27], PYRA5 supported !");
2271     }
2272 }
2273
2274 const double *MEDCouplingFieldDiscretizationGaussNE::GetRefCoordsFromGeometricType(INTERP_KERNEL::NormalizedCellType geoType, std::size_t& lgth) throw(INTERP_KERNEL::Exception)
2275 {
2276   switch(geoType)
2277     {
2278     case INTERP_KERNEL::NORM_SEG2:
2279       lgth=(int)sizeof(REF_SEG2)/sizeof(double);
2280       return REF_SEG2;
2281     case INTERP_KERNEL::NORM_SEG3:
2282       lgth=(int)sizeof(REF_SEG3)/sizeof(double);
2283       return REF_SEG3;
2284     case INTERP_KERNEL::NORM_SEG4:
2285       lgth=(int)sizeof(REF_SEG4)/sizeof(double);
2286       return REF_SEG4;
2287     case INTERP_KERNEL::NORM_TRI3:
2288       lgth=(int)sizeof(REF_TRI3)/sizeof(double);
2289       return REF_TRI3;
2290     case INTERP_KERNEL::NORM_TRI6:
2291       lgth=(int)sizeof(REF_TRI6)/sizeof(double);
2292       return REF_TRI6;
2293     case INTERP_KERNEL::NORM_TRI7:
2294       lgth=(int)sizeof(REF_TRI7)/sizeof(double);
2295       return REF_TRI7;
2296     case INTERP_KERNEL::NORM_QUAD4:
2297       lgth=(int)sizeof(REF_QUAD4)/sizeof(double);
2298       return REF_QUAD4;
2299     case INTERP_KERNEL::NORM_QUAD8:
2300       lgth=(int)sizeof(REF_QUAD8)/sizeof(double);
2301       return REF_QUAD8;
2302     case INTERP_KERNEL::NORM_QUAD9:
2303       lgth=(int)sizeof(REF_QUAD9)/sizeof(double);
2304       return REF_QUAD9;
2305     case INTERP_KERNEL::NORM_TETRA4:
2306       lgth=(int)sizeof(REF_TETRA4)/sizeof(double);
2307       return REF_TETRA4;
2308     case INTERP_KERNEL::NORM_TETRA10:
2309       lgth=(int)sizeof(REF_TETRA10)/sizeof(double);
2310       return REF_TETRA10;
2311     case INTERP_KERNEL::NORM_PENTA6:
2312       lgth=(int)sizeof(REF_PENTA6)/sizeof(double);
2313       return REF_PENTA6;
2314     case INTERP_KERNEL::NORM_PENTA15:
2315       lgth=(int)sizeof(REF_PENTA15)/sizeof(double);
2316       return REF_PENTA15;
2317     case INTERP_KERNEL::NORM_HEXA8:
2318       lgth=(int)sizeof(REF_HEXA8)/sizeof(double);
2319       return REF_HEXA8;
2320     case INTERP_KERNEL::NORM_HEXA20:
2321       lgth=(int)sizeof(REF_HEXA20)/sizeof(double);
2322       return REF_HEXA20;
2323     case INTERP_KERNEL::NORM_HEXA27:
2324       lgth=(int)sizeof(REF_HEXA27)/sizeof(double);
2325       return REF_HEXA27;
2326     case INTERP_KERNEL::NORM_PYRA5:
2327       lgth=(int)sizeof(REF_PYRA5)/sizeof(double);
2328       return REF_PYRA5;
2329     case INTERP_KERNEL::NORM_PYRA13:
2330       lgth=(int)sizeof(REF_PYRA13)/sizeof(double);
2331       return REF_PYRA13;
2332     default:
2333       throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::GetRefCoordsFromGeometricType : only SEG[2,3,4], TRI[3,6,7], QUAD[4,8,9], TETRA[4,10], PENTA[6,15], HEXA[8,20,27], PYRA[5,13] supported !");
2334     }
2335 }
2336
2337 void MEDCouplingFieldDiscretizationGaussNE::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *tupleIdsBg, const int *tupleIdsEnd,
2338                                                                                DataArrayInt *&cellRestriction, DataArrayInt *&trueTupleRestriction) const throw(INTERP_KERNEL::Exception)
2339 {
2340   if(!mesh)
2341     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::computeMeshRestrictionFromTupleIds : NULL input mesh !");
2342   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=DataArrayInt::New(); tmp->alloc((int)std::distance(tupleIdsBg,tupleIdsEnd),1);
2343   std::copy(tupleIdsBg,tupleIdsEnd,tmp->getPointer());
2344   tmp->sort(true);
2345   tmp=tmp->buildUnique();
2346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=mesh->computeNbOfNodesPerCell();
2347   nbOfNodesPerCell->computeOffsets2();
2348   nbOfNodesPerCell->searchRangesInListOfIds(tmp,cellRestriction,trueTupleRestriction);
2349 }
2350
2351 void MEDCouplingFieldDiscretizationGaussNE::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
2352 {
2353 }
2354
2355 double MEDCouplingFieldDiscretizationGaussNE::getIJK(const MEDCouplingMesh *mesh, const DataArrayDouble *da,
2356                                                      int cellId, int nodeIdInCell, int compoId) const throw(INTERP_KERNEL::Exception)
2357 {
2358   if(!mesh)
2359     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getIJK : NULL input mesh !");
2360   int offset=0;
2361   for(int i=0;i<cellId;i++)
2362     {
2363       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2364       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2365       offset+=cm.getNumberOfNodes();
2366     }
2367   return da->getIJ(offset+nodeIdInCell,compoId);
2368 }
2369
2370 void MEDCouplingFieldDiscretizationGaussNE::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception)
2371 {
2372   int nbOfTuples=getNumberOfTuples(mesh);
2373   if(nbOfTuples!=da->getNumberOfTuples())
2374     {
2375       std::ostringstream oss; oss << "Invalid number of tuples in the array : expecting " << nbOfTuples << " !";
2376       throw INTERP_KERNEL::Exception(oss.str().c_str());
2377     }
2378 }
2379
2380 MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationGaussNE::getMeasureField(const MEDCouplingMesh *mesh, bool isAbs) const
2381 {
2382   if(!mesh)
2383     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getMeasureField : mesh instance specified is NULL !");
2384   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> vol=mesh->getMeasureField(isAbs);
2385   const double *volPtr=vol->getArray()->begin();
2386   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_GAUSS_NE);
2387   ret->setMesh(mesh);
2388   //
2389   std::set<INTERP_KERNEL::NormalizedCellType> types=mesh->getAllGeoTypes();
2390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=mesh->computeNbOfNodesPerCell();
2391   int nbTuples=nbOfNodesPerCell->accumulate(0);
2392   nbOfNodesPerCell->computeOffsets2();
2393   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New(); arr->alloc(nbTuples,1);
2394   ret->setArray(arr);
2395   double *arrPtr=arr->getPointer();
2396   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
2397     {
2398       std::size_t wArrSz=-1;
2399       const double *wArr=GetWeightArrayFromGeometricType(*it,wArrSz);
2400       INTERP_KERNEL::AutoPtr<double> wArr2=new double[wArrSz];
2401       double sum=std::accumulate(wArr,wArr+wArrSz,0.);
2402       std::transform(wArr,wArr+wArrSz,(double *)wArr2,std::bind2nd(std::multiplies<double>(),1./sum));      
2403       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=mesh->giveCellsWithType(*it);
2404       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->buildExplicitArrByRanges(nbOfNodesPerCell);
2405       const int *ptIds2=ids2->begin(),*ptIds=ids->begin();
2406       int nbOfCellsWithCurGeoType=ids->getNumberOfTuples();
2407       for(int i=0;i<nbOfCellsWithCurGeoType;i++,ptIds++)
2408         for(std::size_t j=0;j<wArrSz;j++,ptIds2++)
2409           arrPtr[*ptIds2]=wArr2[j]*volPtr[*ptIds];
2410     }
2411   ret->synchronizeTimeWithSupport();
2412   return ret.retn();
2413 }
2414
2415 void MEDCouplingFieldDiscretizationGaussNE::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
2416 {
2417   throw INTERP_KERNEL::Exception("Not implemented yet !");
2418 }
2419
2420 void MEDCouplingFieldDiscretizationGaussNE::getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const
2421 {
2422   throw INTERP_KERNEL::Exception("getValueOnPos(i,j,k) : Not applyable for Gauss points !");
2423 }
2424
2425 DataArrayDouble *MEDCouplingFieldDiscretizationGaussNE::getValueOnMulti(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, int nbOfPoints) const
2426 {
2427   throw INTERP_KERNEL::Exception("getValueOnMulti : Not implemented for Gauss NE !");
2428 }
2429
2430 MEDCouplingMesh *MEDCouplingFieldDiscretizationGaussNE::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
2431 {
2432   if(!mesh)
2433     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::buildSubMeshData : NULL input mesh !");
2434   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diSafe=computeTupleIdsToSelectFromCellIds(mesh,start,end);
2435   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPart(start,end);
2436   di=diSafe.retn();
2437   return ret.retn();
2438 }
2439
2440 /*!
2441  * This method is strictly equivalent to MEDCouplingFieldDiscretizationGauss::buildSubMeshData except that it is optimized for input defined as a range of cell ids.
2442  * 
2443  * \param [out] beginOut Valid only if \a di is NULL
2444  * \param [out] endOut Valid only if \a di is NULL
2445  * \param [out] stepOut Valid only if \a di is NULL
2446  * \param [out] di is an array returned that specifies entity ids (nodes, cells, Gauss points... ) in array if no output range is foundable.
2447  *
2448  * \sa MEDCouplingFieldDiscretizationGauss::buildSubMeshData
2449  */
2450 MEDCouplingMesh *MEDCouplingFieldDiscretizationGaussNE::buildSubMeshDataRange(const MEDCouplingMesh *mesh, int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt *&di) const
2451 {
2452   if(stepCellIds!=1)//even for stepCellIds==-1 the output will not be a range
2453     return MEDCouplingFieldDiscretization::buildSubMeshDataRange(mesh,beginCellIds,endCellIds,stepCellIds,beginOut,endOut,stepOut,di);
2454   if(!mesh)
2455     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::buildSubMeshDataRange : NULL input mesh !");
2456   int nbOfCells=mesh->getNumberOfCells();
2457   di=0; beginOut=0; endOut=0; stepOut=stepCellIds;
2458   const char msg[]="MEDCouplingFieldDiscretizationGaussNE::buildSubMeshDataRange : cell #";
2459   for(int i=0;i<nbOfCells;i++)
2460     {
2461       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2462       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2463       if(cm.isDynamic())
2464         { std::ostringstream oss; oss << msg << i << " presence of dynamic cell (polygons and polyedrons) ! Not implemented !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
2465       int delta=cm.getNumberOfNodes();
2466       if(i<beginCellIds)
2467         beginOut+=delta;
2468       endOut+=delta;
2469       if(i>=endCellIds)
2470         break;
2471     }
2472   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPartRange(beginCellIds,endCellIds,stepCellIds);
2473   return ret.retn();
2474 }
2475
2476
2477 /*!
2478  * This method returns a tuple ids selection from cell ids selection [start;end).
2479  * This method is called by MEDCouplingFieldDiscretizationGaussNE::buildSubMeshData to return parameter \b di.
2480  *
2481  * \return a newly allocated array containing ids to select into the DataArrayDouble of the field.
2482  * 
2483  */
2484 DataArrayInt *MEDCouplingFieldDiscretizationGaussNE::computeTupleIdsToSelectFromCellIds(const MEDCouplingMesh *mesh, const int *startCellIds, const int *endCellIds) const
2485 {
2486   if(!mesh)
2487     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::computeTupleIdsToSelectFromCellIds : null mesh !");
2488   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=mesh->computeNbOfNodesPerCell();
2489   nbOfNodesPerCell->computeOffsets2();
2490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> sel=DataArrayInt::New(); sel->useArray(startCellIds,false,CPP_DEALLOC,(int)std::distance(startCellIds,endCellIds),1);
2491   return sel->buildExplicitArrByRanges(nbOfNodesPerCell);
2492 }
2493
2494 /*!
2495  * No implementation needed !
2496  */
2497 void MEDCouplingFieldDiscretizationGaussNE::renumberValuesOnNodes(double , const int *, int newNbOfNodes, DataArrayDouble *) const
2498 {
2499 }
2500
2501 void MEDCouplingFieldDiscretizationGaussNE::renumberValuesOnCells(double epsOnVals, const MEDCouplingMesh *mesh, const int *old2New, int newSz, DataArrayDouble *arr) const
2502 {
2503   throw INTERP_KERNEL::Exception("Not implemented yet !");
2504 }
2505
2506 void MEDCouplingFieldDiscretizationGaussNE::renumberValuesOnCellsR(const MEDCouplingMesh *mesh, const int *new2old, int newSz, DataArrayDouble *arr) const
2507 {
2508   throw INTERP_KERNEL::Exception("Not implemented yet !");
2509 }
2510
2511 void MEDCouplingFieldDiscretizationGaussNE::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2512 {
2513   stream << "Gauss points on nodes per element spatial discretization.";
2514 }
2515
2516 MEDCouplingFieldDiscretizationGaussNE::MEDCouplingFieldDiscretizationGaussNE(const MEDCouplingFieldDiscretizationGaussNE& other):MEDCouplingFieldDiscretization(other)
2517 {
2518 }
2519
2520 TypeOfField MEDCouplingFieldDiscretizationKriging::getEnum() const
2521 {
2522   return TYPE;
2523 }
2524
2525 const char *MEDCouplingFieldDiscretizationKriging::getRepr() const
2526 {
2527   return REPR;
2528 }
2529
2530 /*!
2531  * This method is simply called by MEDCouplingFieldDiscretization::deepCpy. It performs the deep copy of \a this.
2532  *
2533  * \sa MEDCouplingFieldDiscretization::deepCpy.
2534  */
2535 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationKriging::clone() const
2536 {
2537   return new MEDCouplingFieldDiscretizationKriging;
2538 }
2539
2540 std::string MEDCouplingFieldDiscretizationKriging::getStringRepr() const
2541 {
2542   return std::string(REPR);
2543 }
2544
2545 void MEDCouplingFieldDiscretizationKriging::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
2546 {
2547   if(nat!=ConservativeVolumic)
2548     throw INTERP_KERNEL::Exception("Invalid nature for Kriging field : expected ConservativeVolumic !");
2549 }
2550
2551 bool MEDCouplingFieldDiscretizationKriging::isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const
2552 {
2553   if(!other)
2554     {
2555       reason="other spatial discretization is NULL, and this spatial discretization (Kriginig) is defined.";
2556       return false;
2557     }
2558   const MEDCouplingFieldDiscretizationKriging *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationKriging *>(other);
2559   bool ret=otherC!=0;
2560   if(!ret)
2561     reason="Spatial discrtization of this is ON_NODES_KR, which is not the case of other.";
2562   return ret;
2563 }
2564
2565 MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationKriging::getMeasureField(const MEDCouplingMesh *mesh, bool isAbs) const
2566 {
2567   if(!mesh)
2568     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::getMeasureField : mesh instance specified is NULL !");
2569   throw INTERP_KERNEL::Exception("getMeasureField on FieldDiscretizationKriging : not implemented yet !");
2570 }
2571
2572 void MEDCouplingFieldDiscretizationKriging::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
2573 {
2574   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res2=MEDCouplingFieldDiscretizationKriging::getValueOnMulti(arr,mesh,loc,1);
2575   std::copy(res2->begin(),res2->end(),res);
2576 }
2577
2578 DataArrayDouble *MEDCouplingFieldDiscretizationKriging::getValueOnMulti(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, int nbOfTargetPoints) const
2579 {
2580   if(!mesh)
2581     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::getValueOnMulti : NULL input mesh !");
2582   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getLocalizationOfDiscValues(mesh);
2583   int nbOfPts=coords->getNumberOfTuples();
2584   int dimension=coords->getNumberOfComponents();
2585   //
2586   int delta=0;
2587   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> KnewiK=computeVectorOfCoefficients(mesh,arr,delta);
2588   //
2589   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> locArr=DataArrayDouble::New();
2590   locArr->useArray(loc,false,CPP_DEALLOC,nbOfTargetPoints,dimension);
2591   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrix2=coords->buildEuclidianDistanceDenseMatrixWith(locArr);
2592   operateOnDenseMatrix(mesh->getSpaceDimension(),nbOfPts*nbOfTargetPoints,matrix2->getPointer());
2593   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrix3=DataArrayDouble::New();
2594   matrix3->alloc((nbOfPts+delta)*nbOfTargetPoints,1);
2595   double *work=matrix3->getPointer();
2596   const double *workCst=matrix2->getConstPointer();
2597   const double *workCst2=loc;
2598   for(int i=0;i<nbOfTargetPoints;i++,workCst+=nbOfPts,workCst2+=delta-1)
2599     {
2600       for(int j=0;j<nbOfPts;j++)
2601         work[j*nbOfTargetPoints+i]=workCst[j];
2602       work[nbOfPts*nbOfTargetPoints+i]=1.0;
2603       for(int j=0;j<delta-1;j++)
2604         work[(nbOfPts+1+j)*nbOfTargetPoints+i]=workCst2[j];
2605     }
2606   //
2607   int nbOfCompo=arr->getNumberOfComponents();
2608   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
2609   ret->alloc(nbOfTargetPoints,nbOfCompo);
2610   INTERP_KERNEL::matrixProduct(KnewiK->getConstPointer(),1,nbOfPts+delta,matrix3->getConstPointer(),nbOfPts+delta,nbOfTargetPoints*nbOfCompo,ret->getPointer());
2611   return ret.retn();
2612 }
2613
2614 void MEDCouplingFieldDiscretizationKriging::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2615 {
2616   stream << "Kriging spatial discretization.";
2617 }
2618
2619 /*!
2620  * This method computes coefficients to apply to each representing points of \a mesh, that is to say the nodes of \a mesh given a field array \a arr whose
2621  * number of tuples should be equal to the number of representing points in \a mesh.
2622  * 
2623  * \param [in] mesh is the sources of nodes on which kriging will be done regarding the parameters and the value of \c this->getSpaceDimension()
2624  * \param [in] arr input field DataArrayDouble whose number of tuples must be equal to the number of nodes in \a mesh
2625  * \param [out] isDrift return if drift coefficients are present in the returned vector of coefficients, and if. If different from 0 there is presence of drift coefficients.
2626  *              Whatever the value of \a isDrift the number of tuples of returned DataArrayDouble  will be equal to \c arr->getNumberOfTuples() + \a isDrift.
2627  * \return a newly allocated array containing coefficients including or not drift coefficient at the end depending the value of \a isDrift parameter.
2628  */
2629 DataArrayDouble *MEDCouplingFieldDiscretizationKriging::computeVectorOfCoefficients(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, int& isDrift) const
2630 {
2631   if(!mesh)
2632     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::computeVectorOfCoefficients : NULL input mesh !");
2633   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getLocalizationOfDiscValues(mesh);
2634   int nbOfPts=coords->getNumberOfTuples();
2635   //int dimension=coords->getNumberOfComponents();
2636   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrix=coords->buildEuclidianDistanceDenseMatrix();
2637   operateOnDenseMatrix(mesh->getSpaceDimension(),nbOfPts*nbOfPts,matrix->getPointer());
2638   // Drift
2639   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixWithDrift=performDrift(matrix,coords,isDrift);
2640   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixInv=DataArrayDouble::New();
2641   matrixInv->alloc((nbOfPts+isDrift)*(nbOfPts+isDrift),1);
2642   INTERP_KERNEL::inverseMatrix(matrixWithDrift->getConstPointer(),nbOfPts+isDrift,matrixInv->getPointer());
2643   //
2644   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> KnewiK=DataArrayDouble::New();
2645   KnewiK->alloc((nbOfPts+isDrift)*1,1);
2646   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2=DataArrayDouble::New();
2647   arr2->alloc((nbOfPts+isDrift)*1,1);
2648   double *work=std::copy(arr->begin(),arr->end(),arr2->getPointer());
2649   std::fill(work,work+isDrift,0.);
2650   INTERP_KERNEL::matrixProduct(matrixInv->getConstPointer(),nbOfPts+isDrift,nbOfPts+isDrift,arr2->getConstPointer(),nbOfPts+isDrift,1,KnewiK->getPointer());
2651   return KnewiK.retn();
2652 }
2653
2654 /*!
2655  * Apply \f f(x) on each element x in \a matrixPtr. \a matrixPtr is expected to be a dense matrix represented by a chunck of memory of size at least equal to \a nbOfElems.
2656  *
2657  * \param [in] spaceDimension space dimension of the input mesh on which the Kriging has to be performed
2658  * \param [in] nbOfElems is the result of the product of nb of rows and the nb of columns of matrix \a matrixPtr
2659  * \param [in,out] matrixPtr is the dense matrix whose on each values the operation will be applied
2660  */
2661 void MEDCouplingFieldDiscretizationKriging::operateOnDenseMatrix(int spaceDimension, int nbOfElems, double *matrixPtr) const
2662 {
2663   switch(spaceDimension)
2664     {
2665     case 1:
2666       {
2667         for(int i=0;i<nbOfElems;i++)
2668           {
2669             double val=matrixPtr[i];
2670             matrixPtr[i]=val*val*val;
2671           }
2672         break;
2673       }
2674     default:
2675       throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::operateOnDenseMatrix : only dimension 1 implemented !");
2676     }
2677 }
2678
2679 /*!
2680  * Starting from a square matrix \a matr, this method returns a newly allocated dense square matrix whose \a matr is included in returned matrix
2681  * in the top left corner, and in the remaining returned matrix the parameters to take into account about the kriging drift.
2682  * For the moment only linear srift is implemented.
2683  *
2684  * \param [in] arr the position of points were input mesh geometry is considered for Kriging
2685  * \param [in] matr input matrix whose drift part will be added
2686  * \param [out] delta the difference between the size of the output matrix and the input matrix \a matr.
2687  * \return a newly allocated matrix bigger than input matrix \a matr.
2688  */
2689 DataArrayDouble *MEDCouplingFieldDiscretizationKriging::performDrift(const DataArrayDouble *matr, const DataArrayDouble *arr, int& delta) const
2690 {
2691   int spaceDimension=arr->getNumberOfComponents();
2692   delta=spaceDimension+1;
2693   int szOfMatrix=arr->getNumberOfTuples();
2694   if(szOfMatrix*szOfMatrix!=matr->getNumberOfTuples())
2695     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::performDrift : invalid size");
2696   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
2697   ret->alloc((szOfMatrix+delta)*(szOfMatrix+delta),1);
2698   const double *srcWork=matr->getConstPointer();
2699   const double *srcWork2=arr->getConstPointer();
2700   double *destWork=ret->getPointer();
2701   for(int i=0;i<szOfMatrix;i++)
2702     {
2703       destWork=std::copy(srcWork,srcWork+szOfMatrix,destWork);
2704       srcWork+=szOfMatrix;
2705       *destWork++=1.;
2706       destWork=std::copy(srcWork2,srcWork2+spaceDimension,destWork);
2707       srcWork2+=spaceDimension;
2708     }
2709   std::fill(destWork,destWork+szOfMatrix,1.); destWork+=szOfMatrix;
2710   std::fill(destWork,destWork+spaceDimension+1,0.); destWork+=spaceDimension+1;
2711   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arrNoI=arr->toNoInterlace();
2712   srcWork2=arrNoI->getConstPointer();
2713   for(int i=0;i<spaceDimension;i++)
2714     {
2715       destWork=std::copy(srcWork2,srcWork2+szOfMatrix,destWork);
2716       srcWork2+=szOfMatrix;
2717       std::fill(destWork,destWork+spaceDimension+1,0.);
2718       destWork+=spaceDimension;
2719     }
2720   //
2721   return ret.retn();
2722 }