Salome HOME
With omniorbpy it will be better....
[modules/med.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   for(const int *w=dcPtr;w!=dcPtr+nbOfTuples;w++)
1370     ret+=_loc[*w].getNumberOfGaussPt();
1371   return ret;
1372 }
1373
1374 int MEDCouplingFieldDiscretizationGauss::getNumberOfMeshPlaces(const MEDCouplingMesh *mesh) const
1375 {
1376   if(!mesh)
1377     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getNumberOfMeshPlaces : NULL input mesh !");
1378   return mesh->getNumberOfCells();
1379 }
1380
1381 /*!
1382  * This method is redevelopped for performance reasons, but it is equivalent to a call to MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField
1383  * and a call to DataArrayDouble::computeOffsets2 on the returned array.
1384  */
1385 DataArrayInt *MEDCouplingFieldDiscretizationGauss::getOffsetArr(const MEDCouplingMesh *mesh) const
1386 {
1387   if(!mesh)
1388     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getOffsetArr : NULL input mesh !");
1389   int nbOfTuples=mesh->getNumberOfCells();
1390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1391   ret->alloc(nbOfTuples+1,1);
1392   int *retPtr=ret->getPointer();
1393   const int *start=_discr_per_cell->getConstPointer();
1394   if(_discr_per_cell->getNumberOfTuples()!=nbOfTuples)
1395     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getOffsetArr : mismatch between the mesh and the discretization ids array length !");
1396   int maxPossible=(int)_loc.size();
1397   retPtr[0]=0;
1398   for(int i=0;i<nbOfTuples;i++,start++)
1399     {
1400       if(*start>=0 && *start<maxPossible)
1401         retPtr[i+1]=retPtr[i]+_loc[*start].getNumberOfGaussPt();
1402       else
1403         {
1404           std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getOffsetArr : At position #" << i << " the locid = " << *start << " whereas it should be in [0," << maxPossible << ") !";
1405           throw INTERP_KERNEL::Exception(oss.str().c_str());
1406         }
1407     }
1408   return ret.retn();
1409 }
1410
1411 void MEDCouplingFieldDiscretizationGauss::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArray *>& arrays,
1412                                                                 const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
1413 {
1414   if(!mesh)
1415     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::renumberArraysForCell : NULL input mesh !");
1416   const int *array=old2NewBg;
1417   if(check)
1418     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+mesh->getNumberOfCells());
1419   int nbOfCells=_discr_per_cell->getNumberOfTuples();
1420   int nbOfTuples=getNumberOfTuples(0);
1421   const int *dcPtr=_discr_per_cell->getConstPointer();
1422   int *array2=new int[nbOfTuples];//stores the final conversion array old2New to give to arrays in renumberInPlace.
1423   int *array3=new int[nbOfCells];//store for each cell in present dcp array (already renumbered) the offset needed by each cell in new numbering.
1424   array3[0]=0;
1425   for(int i=1;i<nbOfCells;i++)
1426     array3[i]=array3[i-1]+_loc[dcPtr[i-1]].getNumberOfGaussPt();
1427   int j=0;
1428   for(int i=0;i<nbOfCells;i++)
1429     {
1430       int nbOfGaussPt=_loc[dcPtr[array[i]]].getNumberOfGaussPt();
1431       for(int k=0;k<nbOfGaussPt;k++,j++)
1432         array2[j]=array3[array[i]]+k;
1433     }
1434   delete [] array3;
1435   for(std::vector<DataArray *>::const_iterator it=arrays.begin();it!=arrays.end();it++)
1436     if(*it)
1437       (*it)->renumberInPlace(array2);
1438   delete [] array2;
1439   if(check)
1440     free(const_cast<int*>(array));
1441 }
1442
1443 DataArrayDouble *MEDCouplingFieldDiscretizationGauss::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const
1444 {
1445   if(!mesh)
1446     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getLocalizationOfDiscValues : NULL input mesh !");
1447   checkNoOrphanCells();
1448   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> umesh=mesh->buildUnstructured();//in general do nothing
1449   int nbOfTuples=getNumberOfTuples(mesh);
1450   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
1451   int spaceDim=mesh->getSpaceDimension();
1452   ret->alloc(nbOfTuples,spaceDim);
1453   std::vector< int > locIds;
1454   std::vector<DataArrayInt *> parts=splitIntoSingleGaussDicrPerCellType(locIds);
1455   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > parts2(parts.size());
1456   std::copy(parts.begin(),parts.end(),parts2.begin());
1457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=buildNbOfGaussPointPerCellField();
1458   offsets->computeOffsets();
1459   const int *ptrOffsets=offsets->getConstPointer();
1460   const double *coords=umesh->getCoords()->getConstPointer();
1461   const int *connI=umesh->getNodalConnectivityIndex()->getConstPointer();
1462   const int *conn=umesh->getNodalConnectivity()->getConstPointer();
1463   double *valsToFill=ret->getPointer();
1464   for(std::size_t i=0;i<parts2.size();i++)
1465     {
1466       INTERP_KERNEL::GaussCoords calculator;
1467       //
1468       const MEDCouplingGaussLocalization& cli=_loc[locIds[i]];//curLocInfo
1469       INTERP_KERNEL::NormalizedCellType typ=cli.getType();
1470       const std::vector<double>& wg=cli.getWeights();
1471       calculator.addGaussInfo(typ,INTERP_KERNEL::CellModel::GetCellModel(typ).getDimension(),
1472                                   &cli.getGaussCoords()[0],(int)wg.size(),&cli.getRefCoords()[0],
1473                                   INTERP_KERNEL::CellModel::GetCellModel(typ).getNumberOfNodes());
1474       //
1475       int nbt=parts2[i]->getNumberOfTuples();
1476       for(const int *w=parts2[i]->getConstPointer();w!=parts2[i]->getConstPointer()+nbt;w++)
1477         calculator.calculateCoords(cli.getType(),coords,spaceDim,conn+connI[*w]+1,valsToFill+spaceDim*(ptrOffsets[*w]));
1478     }
1479   ret->copyStringInfoFrom(*umesh->getCoords());
1480   return ret.retn();
1481 }
1482
1483 void MEDCouplingFieldDiscretizationGauss::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *tupleIdsBg, const int *tupleIdsEnd,
1484                                                                              DataArrayInt *&cellRestriction, DataArrayInt *&trueTupleRestriction) const throw(INTERP_KERNEL::Exception)
1485 {
1486   if(!mesh)
1487     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::computeMeshRestrictionFromTupleIds : NULL input mesh !");
1488   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=DataArrayInt::New(); tmp->alloc((int)std::distance(tupleIdsBg,tupleIdsEnd),1);
1489   std::copy(tupleIdsBg,tupleIdsEnd,tmp->getPointer());
1490   tmp->sort(true);
1491   tmp=tmp->buildUnique();
1492   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=buildNbOfGaussPointPerCellField();
1493   nbOfNodesPerCell->computeOffsets2();
1494   nbOfNodesPerCell->searchRangesInListOfIds(tmp,cellRestriction,trueTupleRestriction);
1495 }
1496
1497 /*!
1498  * Empty : not a bug
1499  */
1500 void MEDCouplingFieldDiscretizationGauss::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
1501 {
1502 }
1503
1504 void MEDCouplingFieldDiscretizationGauss::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
1505 {
1506   int val=-1;
1507   if(_discr_per_cell)
1508     val=_discr_per_cell->getNumberOfTuples();
1509   tinyInfo.push_back(val);
1510   tinyInfo.push_back((int)_loc.size());
1511   if(_loc.empty())
1512     tinyInfo.push_back(-1);
1513   else
1514     tinyInfo.push_back(_loc[0].getDimension());
1515   for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++)
1516     (*iter).pushTinySerializationIntInfo(tinyInfo);
1517 }
1518
1519 void MEDCouplingFieldDiscretizationGauss::getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const
1520 {
1521   for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++)
1522     (*iter).pushTinySerializationDblInfo(tinyInfo);
1523 }
1524
1525 void MEDCouplingFieldDiscretizationGauss::getSerializationIntArray(DataArrayInt *& arr) const
1526 {
1527   arr=0;
1528   if(_discr_per_cell)
1529     arr=_discr_per_cell;
1530 }
1531
1532 void MEDCouplingFieldDiscretizationGauss::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *& arr)
1533 {
1534   int val=tinyInfo[0];
1535   if(val>=0)
1536     {
1537       _discr_per_cell=DataArrayInt::New();
1538       _discr_per_cell->alloc(val,1);
1539     }
1540   else
1541     _discr_per_cell=0;
1542   arr=_discr_per_cell;
1543   int nbOfLoc=tinyInfo[1];
1544   _loc.clear();
1545   int dim=tinyInfo[2];
1546   int delta=-1;
1547   if(nbOfLoc>0)
1548     delta=((int)tinyInfo.size()-3)/nbOfLoc;
1549   for(int i=0;i<nbOfLoc;i++)
1550     {
1551       std::vector<int> tmp(tinyInfo.begin()+3+i*delta,tinyInfo.begin()+3+(i+1)*delta);
1552       MEDCouplingGaussLocalization elt=MEDCouplingGaussLocalization::BuildNewInstanceFromTinyInfo(dim,tmp);
1553       _loc.push_back(elt);
1554     }
1555 }
1556
1557 void MEDCouplingFieldDiscretizationGauss::finishUnserialization(const std::vector<double>& tinyInfo)
1558 {
1559   double *tmp=new double[tinyInfo.size()];
1560   std::copy(tinyInfo.begin(),tinyInfo.end(),tmp);
1561   const double *work=tmp;
1562   for(std::vector<MEDCouplingGaussLocalization>::iterator iter=_loc.begin();iter!=_loc.end();iter++)
1563     work=(*iter).fillWithValues(work);
1564   delete [] tmp;
1565 }
1566
1567 double MEDCouplingFieldDiscretizationGauss::getIJK(const MEDCouplingMesh *mesh, const DataArrayDouble *da,
1568                                                    int cellId, int nodeIdInCell, int compoId) const throw(INTERP_KERNEL::Exception)
1569 {
1570   int offset=getOffsetOfCell(cellId);
1571   return da->getIJ(offset+nodeIdInCell,compoId);
1572 }
1573
1574 void MEDCouplingFieldDiscretizationGauss::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception)
1575 {
1576   if(!mesh || !da)
1577     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::checkCoherencyBetween : NULL input mesh or DataArray !");
1578   MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween(mesh,da);
1579   for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++)
1580     (*iter).checkCoherency();
1581   int nbOfDesc=(int)_loc.size();
1582   int nbOfCells=mesh->getNumberOfCells();
1583   const int *dc=_discr_per_cell->getConstPointer();
1584   for(int i=0;i<nbOfCells;i++)
1585     {
1586       if(dc[i]>=nbOfDesc)
1587         {
1588           std::ostringstream oss; oss << "Cell # " << i << " of mesh \"" << mesh->getName() << "\" has an undefined gauss location ! Should never happend !";
1589           throw INTERP_KERNEL::Exception(oss.str().c_str());
1590         }
1591       if(dc[i]<0)
1592         {
1593           std::ostringstream oss; oss << "Cell # " << i << " of mesh \"" << mesh->getName() << "\" has no gauss location !";
1594           throw INTERP_KERNEL::Exception(oss.str().c_str());
1595         }
1596       if(mesh->getTypeOfCell(i)!=_loc[dc[i]].getType())
1597         {
1598           std::ostringstream oss; oss << "Types of mesh and gauss location mismatch for cell # " << i;
1599           throw INTERP_KERNEL::Exception(oss.str().c_str());
1600         }
1601     }
1602   int nbOfTuples=getNumberOfTuples(mesh);
1603   if(nbOfTuples!=da->getNumberOfTuples())
1604     {
1605       std::ostringstream oss; oss << "Invalid number of tuples in the array : expecting " << nbOfTuples << " !";
1606       throw INTERP_KERNEL::Exception(oss.str().c_str());
1607     }
1608 }
1609
1610 MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationGauss::getMeasureField(const MEDCouplingMesh *mesh, bool isAbs) const
1611 {
1612   if(!mesh)
1613     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getMeasureField : mesh instance specified is NULL !");
1614   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> vol=mesh->getMeasureField(isAbs);
1615   const double *volPtr=vol->getArray()->begin();
1616   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_GAUSS_PT);
1617   ret->setMesh(mesh);
1618   ret->setDiscretization(const_cast<MEDCouplingFieldDiscretizationGauss *>(this));
1619   if(!_discr_per_cell)
1620     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getMeasureField : no discr per cell array not defined ! spatial localization is incorrect !");
1621   _discr_per_cell->checkAllocated();
1622   if(_discr_per_cell->getNumberOfComponents()!=1)
1623     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getMeasureField : no discr per cell array defined but with nb of components different from 1 !");
1624   if(_discr_per_cell->getNumberOfTuples()!=vol->getNumberOfTuples())
1625     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 !");
1626   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offset=getOffsetArr(mesh);
1627   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New(); arr->alloc(getNumberOfTuples(mesh),1);
1628   ret->setArray(arr);
1629   double *arrPtr=arr->getPointer();
1630   const int *offsetPtr=offset->getConstPointer();
1631   int maxGaussLoc=(int)_loc.size();
1632   std::vector<int> locIds;
1633   std::vector<DataArrayInt *> ids=splitIntoSingleGaussDicrPerCellType(locIds);
1634   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ids2(ids.size()); std::copy(ids.begin(),ids.end(),ids2.begin());
1635   for(std::size_t i=0;i<locIds.size();i++)
1636     {
1637       const DataArrayInt *curIds=ids[i];
1638       int locId=locIds[i];
1639       if(locId>=0 && locId<maxGaussLoc)
1640         {
1641           const MEDCouplingGaussLocalization& loc=_loc[locId];
1642           int nbOfGaussPt=loc.getNumberOfGaussPt();
1643           INTERP_KERNEL::AutoPtr<double> weights=new double[nbOfGaussPt];
1644           double sum=std::accumulate(loc.getWeights().begin(),loc.getWeights().end(),0.);
1645           std::transform(loc.getWeights().begin(),loc.getWeights().end(),(double *)weights,std::bind2nd(std::multiplies<double>(),1./sum));
1646           for(const int *cellId=curIds->begin();cellId!=curIds->end();cellId++)
1647             for(int j=0;j<nbOfGaussPt;j++)
1648               arrPtr[offsetPtr[*cellId]+j]=weights[j]*volPtr[*cellId];
1649         }
1650       else
1651         {
1652           std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getMeasureField : Presence of localization id " << locId << " in cell #" << curIds->getIJ(0,0) << " ! Must be in [0," << maxGaussLoc << ") !";
1653           throw INTERP_KERNEL::Exception(oss.str().c_str());
1654         }
1655     }
1656   ret->synchronizeTimeWithSupport();
1657   return ret.retn();
1658 }
1659
1660 void MEDCouplingFieldDiscretizationGauss::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
1661 {
1662   throw INTERP_KERNEL::Exception("Not implemented yet !");
1663 }
1664
1665 void MEDCouplingFieldDiscretizationGauss::getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const
1666 {
1667   throw INTERP_KERNEL::Exception("getValueOnPos(i,j,k) : Not applyable for Gauss points !");
1668 }
1669
1670 DataArrayDouble *MEDCouplingFieldDiscretizationGauss::getValueOnMulti(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, int nbOfPoints) const
1671 {
1672   throw INTERP_KERNEL::Exception("getValueOnMulti : Not implemented yet for gauss points !");
1673 }
1674
1675 MEDCouplingMesh *MEDCouplingFieldDiscretizationGauss::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
1676 {
1677   if(!mesh)
1678     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildSubMeshData : NULL input mesh !");
1679   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diSafe=computeTupleIdsToSelectFromCellIds(mesh,start,end);
1680   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPart(start,end);
1681   di=diSafe.retn();
1682   return ret.retn();
1683 }
1684
1685 /*!
1686  * This method is strictly equivalent to MEDCouplingFieldDiscretizationGauss::buildSubMeshData except that it is optimized for input defined as a range of cell ids.
1687  * 
1688  * \param [out] beginOut Valid only if \a di is NULL
1689  * \param [out] endOut Valid only if \a di is NULL
1690  * \param [out] stepOut Valid only if \a di is NULL
1691  * \param [out] di is an array returned that specifies entity ids (nodes, cells, Gauss points... ) in array if no output range is foundable.
1692  *
1693  * \sa MEDCouplingFieldDiscretizationGauss::buildSubMeshData
1694  */
1695 MEDCouplingMesh *MEDCouplingFieldDiscretizationGauss::buildSubMeshDataRange(const MEDCouplingMesh *mesh, int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt *&di) const
1696 {
1697   if(stepCellIds!=1)//even for stepCellIds==-1 the output will not be a range
1698     return MEDCouplingFieldDiscretization::buildSubMeshDataRange(mesh,beginCellIds,endCellIds,stepCellIds,beginOut,endOut,stepOut,di);
1699   if(!mesh)
1700     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildSubMeshDataRange : NULL input mesh !");
1701   if(!_discr_per_cell)
1702     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildSubMeshDataRange : no discretization array set !");
1703   di=0; beginOut=0; endOut=0; stepOut=stepCellIds;
1704   const char msg[]="MEDCouplingFieldDiscretizationGauss::buildSubMeshDataRange : cell #";
1705   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1706   const int *w=_discr_per_cell->begin();
1707   int nbMaxOfLocId=(int)_loc.size();
1708   for(int i=0;i<nbOfTuples;i++,w++)
1709     {
1710       if(*w!=DFT_INVALID_LOCID_VALUE)
1711         {
1712           if(*w>=0 && *w<nbMaxOfLocId)
1713             {
1714               int delta=_loc[*w].getNumberOfGaussPt();
1715               if(i<beginCellIds)
1716                 beginOut+=delta;
1717               endOut+=delta;
1718               if(i>=endCellIds)
1719                 break;
1720             }
1721           else
1722             { std::ostringstream oss; oss << msg << i << " has invalid id (" << *w << ") ! Should be in [0," << nbMaxOfLocId << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
1723         }
1724       else
1725         { std::ostringstream oss; oss << msg << i << " is detected as orphan !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
1726     }
1727   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPartRange(beginCellIds,endCellIds,stepCellIds);
1728   return ret.retn();
1729 }
1730
1731 /*!
1732  * This method returns a tuple ids selection from cell ids selection [start;end).
1733  * This method is called by MEDCouplingFieldDiscretizationGauss::buildSubMeshData to return parameter \b di.
1734  *
1735  * \return a newly allocated array containing ids to select into the DataArrayDouble of the field.
1736  * 
1737  */
1738 DataArrayInt *MEDCouplingFieldDiscretizationGauss::computeTupleIdsToSelectFromCellIds(const MEDCouplingMesh *mesh, const int *startCellIds, const int *endCellIds) const
1739 {
1740   if(!mesh)
1741     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::computeTupleIdsToSelectFromCellIds : null mesh !");
1742   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=buildNbOfGaussPointPerCellField();//check of _discr_per_cell not NULL pointer
1743   int nbOfCells=mesh->getNumberOfCells();
1744   if(_discr_per_cell->getNumberOfTuples()!=nbOfCells)
1745     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::computeTupleIdsToSelectFromCellIds : mismatch of nb of tuples of cell ids array and number of cells !");
1746   nbOfNodesPerCell->computeOffsets2();
1747   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> sel=DataArrayInt::New(); sel->useArray(startCellIds,false,CPP_DEALLOC,(int)std::distance(startCellIds,endCellIds),1);
1748   return sel->buildExplicitArrByRanges(nbOfNodesPerCell);
1749 }
1750
1751 /*!
1752  * No implementation needed !
1753  */
1754 void MEDCouplingFieldDiscretizationGauss::renumberValuesOnNodes(double , const int *, int newNbOfNodes, DataArrayDouble *) const
1755 {
1756 }
1757
1758 void MEDCouplingFieldDiscretizationGauss::renumberValuesOnCells(double epsOnVals, const MEDCouplingMesh *mesh, const int *old2New, int newSz, DataArrayDouble *arr) const
1759 {
1760   throw INTERP_KERNEL::Exception("Not implemented yet !");
1761 }
1762
1763 void MEDCouplingFieldDiscretizationGauss::renumberValuesOnCellsR(const MEDCouplingMesh *mesh, const int *new2old, int newSz, DataArrayDouble *arr) const
1764 {
1765   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 !");
1766 }
1767
1768 void MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnType(const MEDCouplingMesh *mesh, INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
1769                                                                      const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
1770 {
1771   if(!mesh)
1772     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnType : NULL input mesh !");
1773   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1774   if((int)cm.getDimension()!=mesh->getMeshDimension())
1775     {
1776       std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnType : mismatch of dimensions ! MeshDim==" << mesh->getMeshDimension();
1777       oss << " whereas Type '" << cm.getRepr() << "' has dimension " << cm.getDimension() << " !";
1778       throw INTERP_KERNEL::Exception(oss.str().c_str());
1779     }
1780   buildDiscrPerCellIfNecessary(mesh);
1781   int id=(int)_loc.size();
1782   MEDCouplingGaussLocalization elt(type,refCoo,gsCoo,wg);
1783   _loc.push_back(elt);
1784   int *ptr=_discr_per_cell->getPointer();
1785   int nbCells=mesh->getNumberOfCells();
1786   for(int i=0;i<nbCells;i++)
1787     if(mesh->getTypeOfCell(i)==type)
1788       ptr[i]=id;
1789   zipGaussLocalizations();
1790 }
1791
1792 void MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnCells(const MEDCouplingMesh *mesh, const int *begin, const int *end, const std::vector<double>& refCoo,
1793                                                                       const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
1794 {
1795   if(!mesh)
1796     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnCells : NULL input mesh !");
1797   buildDiscrPerCellIfNecessary(mesh);
1798   if(std::distance(begin,end)<1)
1799     throw INTERP_KERNEL::Exception("Size of [begin,end) must be equal or greater than 1 !");
1800   INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(*begin);
1801   MEDCouplingGaussLocalization elt(type,refCoo,gsCoo,wg);
1802   int id=(int)_loc.size();
1803   int *ptr=_discr_per_cell->getPointer();
1804   for(const int *w=begin+1;w!=end;w++)
1805     {
1806       if(mesh->getTypeOfCell(*w)!=type)
1807         {
1808           std::ostringstream oss; oss << "The cell with id " << *w << " has been detected to be incompatible in the [begin,end) array specified !";
1809           throw INTERP_KERNEL::Exception(oss.str().c_str());
1810         }
1811     }
1812   //
1813   for(const int *w2=begin;w2!=end;w2++)
1814     ptr[*w2]=id;
1815   //
1816   _loc.push_back(elt);
1817   zipGaussLocalizations();
1818 }
1819
1820 void MEDCouplingFieldDiscretizationGauss::clearGaussLocalizations() throw(INTERP_KERNEL::Exception)
1821 {
1822   if(_discr_per_cell)
1823     {
1824       _discr_per_cell->decrRef();
1825       _discr_per_cell=0;
1826     }
1827   _loc.clear();
1828 }
1829
1830 void MEDCouplingFieldDiscretizationGauss::setGaussLocalization(int locId, const MEDCouplingGaussLocalization& loc) throw(INTERP_KERNEL::Exception)
1831 {
1832   if(locId<0)
1833     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::setGaussLocalization : localization id has to be >=0 !");
1834   int sz=(int)_loc.size();
1835   MEDCouplingGaussLocalization gLoc(INTERP_KERNEL::NORM_ERROR);
1836   if(locId>=sz)
1837     _loc.resize(locId+1,gLoc);
1838   _loc[locId]=loc;
1839 }
1840
1841 void MEDCouplingFieldDiscretizationGauss::resizeLocalizationVector(int newSz) throw(INTERP_KERNEL::Exception)
1842 {
1843   if(newSz<0)
1844     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::resizeLocalizationVector : new size has to be >=0 !");
1845   MEDCouplingGaussLocalization gLoc(INTERP_KERNEL::NORM_ERROR);
1846   _loc.resize(newSz,gLoc);
1847 }
1848
1849 MEDCouplingGaussLocalization& MEDCouplingFieldDiscretizationGauss::getGaussLocalization(int locId) throw(INTERP_KERNEL::Exception)
1850 {
1851   checkLocalizationId(locId);
1852   return _loc[locId];
1853 }
1854
1855 int MEDCouplingFieldDiscretizationGauss::getNbOfGaussLocalization() const throw(INTERP_KERNEL::Exception)
1856 {
1857   return (int)_loc.size();
1858 }
1859
1860 int MEDCouplingFieldDiscretizationGauss::getGaussLocalizationIdOfOneCell(int cellId) const throw(INTERP_KERNEL::Exception)
1861 {
1862   if(!_discr_per_cell)
1863     throw INTERP_KERNEL::Exception("No Gauss localization still set !");
1864   int locId=_discr_per_cell->begin()[cellId];
1865   if(locId<0)
1866     throw INTERP_KERNEL::Exception("No Gauss localization set for the specified cell !");
1867   return locId;
1868 }
1869
1870 int MEDCouplingFieldDiscretizationGauss::getGaussLocalizationIdOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
1871 {
1872   std::set<int> ret=getGaussLocalizationIdsOfOneType(type);
1873   if(ret.empty())
1874     throw INTERP_KERNEL::Exception("No gauss discretization found for the specified type !");
1875   if(ret.size()>1)
1876     throw INTERP_KERNEL::Exception("Several gauss discretizations have been found for the specified type !");
1877   return *ret.begin();
1878 }
1879
1880 std::set<int> MEDCouplingFieldDiscretizationGauss::getGaussLocalizationIdsOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
1881 {
1882   if(!_discr_per_cell)
1883     throw INTERP_KERNEL::Exception("No Gauss localization still set !");
1884   std::set<int> ret;
1885   int id=0;
1886   for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++,id++)
1887     if((*iter).getType()==type)
1888       ret.insert(id);
1889   return ret;
1890 }
1891
1892 void MEDCouplingFieldDiscretizationGauss::getCellIdsHavingGaussLocalization(int locId, std::vector<int>& cellIds) const throw(INTERP_KERNEL::Exception)
1893 {
1894   if(locId<0 || locId>=(int)_loc.size())
1895     throw INTERP_KERNEL::Exception("Invalid locId given : must be in range [0:getNbOfGaussLocalization()) !");
1896   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1897   const int *ptr=_discr_per_cell->getConstPointer();
1898   for(int i=0;i<nbOfTuples;i++)
1899     if(ptr[i]==locId)
1900       cellIds.push_back(i);
1901 }
1902
1903 const MEDCouplingGaussLocalization& MEDCouplingFieldDiscretizationGauss::getGaussLocalization(int locId) const throw(INTERP_KERNEL::Exception)
1904 {
1905   checkLocalizationId(locId);
1906   return _loc[locId];
1907 }
1908
1909 void MEDCouplingFieldDiscretizationGauss::checkLocalizationId(int locId) const throw(INTERP_KERNEL::Exception)
1910 {
1911   if(locId<0 || locId>=(int)_loc.size())
1912     throw INTERP_KERNEL::Exception("Invalid locId given : must be in range [0:getNbOfGaussLocalization()) !");
1913 }
1914
1915 int MEDCouplingFieldDiscretizationGauss::getOffsetOfCell(int cellId) const throw(INTERP_KERNEL::Exception)
1916 {
1917   int ret=0;
1918   const int *start=_discr_per_cell->getConstPointer();
1919   for(const int *w=start;w!=start+cellId;w++)
1920     ret+=_loc[*w].getNumberOfGaussPt();
1921   return ret;
1922 }
1923
1924 /*!
1925  * This method do the assumption that there is no orphan cell. If there is an exception is thrown.
1926  * This method makes the assumption too that '_discr_per_cell' is defined. If not an exception is thrown.
1927  * This method returns a newly created array with number of tuples equals to '_discr_per_cell->getNumberOfTuples' and number of components equal to 1.
1928  * The i_th tuple in returned array is the number of gauss point if the corresponding cell.
1929  */
1930 DataArrayInt *MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField() const throw(INTERP_KERNEL::Exception)
1931 {
1932   if(!_discr_per_cell)
1933     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField : no discretization array set !");
1934   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1935   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1936   const int *w=_discr_per_cell->begin();
1937   ret->alloc(nbOfTuples,1);
1938   int *valsToFill=ret->getPointer();
1939   int nbMaxOfLocId=(int)_loc.size();
1940   for(int i=0;i<nbOfTuples;i++,w++)
1941     if(*w!=DFT_INVALID_LOCID_VALUE)
1942       {
1943         if(*w>=0 && *w<nbMaxOfLocId)
1944           valsToFill[i]=_loc[*w].getNumberOfGaussPt();
1945         else
1946           {
1947             std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField : cell #" << i << " has invalid id (" << *w << ") ! Should be in [0," << nbMaxOfLocId << ") !";
1948             throw INTERP_KERNEL::Exception(oss.str().c_str());
1949           }
1950       }
1951     else
1952       {
1953         std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField : cell #" << i << " is detected as orphan !";
1954         throw INTERP_KERNEL::Exception(oss.str().c_str());
1955       }
1956   return ret.retn();
1957 }
1958
1959 void MEDCouplingFieldDiscretizationGauss::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
1960 {
1961   stream << "Gauss points spatial discretization.";
1962 }
1963
1964 /*!
1965  * This method makes the assumption that _discr_per_cell is set.
1966  * This method reduces as much as possible number size of _loc.
1967  * This method is useful when several set on same cells has been done and that some Gauss Localization are no more used.
1968  */
1969 void MEDCouplingFieldDiscretizationGauss::zipGaussLocalizations()
1970 {
1971   const int *start=_discr_per_cell->begin();
1972   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1973   INTERP_KERNEL::AutoPtr<int> tmp=new int[_loc.size()];
1974   std::fill((int *)tmp,(int *)tmp+_loc.size(),-2);
1975   for(const int *w=start;w!=start+nbOfTuples;w++)
1976     if(*w>=0)
1977       tmp[*w]=1;
1978   int fid=0;
1979   for(int i=0;i<(int)_loc.size();i++)
1980     if(tmp[i]!=-2)
1981       tmp[i]=fid++;
1982   if(fid==(int)_loc.size())
1983     return;
1984   // zip needed
1985   int *start2=_discr_per_cell->getPointer();
1986   for(int *w2=start2;w2!=start2+nbOfTuples;w2++)
1987     if(*w2>=0)
1988       *w2=tmp[*w2];
1989   std::vector<MEDCouplingGaussLocalization> tmpLoc;
1990   for(int i=0;i<(int)_loc.size();i++)
1991     if(tmp[i]!=-2)
1992       tmpLoc.push_back(_loc[tmp[i]]);
1993   _loc=tmpLoc;
1994 }
1995
1996 MEDCouplingFieldDiscretizationGaussNE::MEDCouplingFieldDiscretizationGaussNE()
1997 {
1998 }
1999
2000 TypeOfField MEDCouplingFieldDiscretizationGaussNE::getEnum() const
2001 {
2002   return TYPE;
2003 }
2004
2005 /*!
2006  * This method is simply called by MEDCouplingFieldDiscretization::deepCpy. It performs the deep copy of \a this.
2007  *
2008  * \sa MEDCouplingFieldDiscretization::deepCpy.
2009  */
2010 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationGaussNE::clone() const
2011 {
2012   return new MEDCouplingFieldDiscretizationGaussNE(*this);
2013 }
2014
2015 std::string MEDCouplingFieldDiscretizationGaussNE::getStringRepr() const
2016 {
2017   return std::string(REPR);
2018 }
2019
2020 const char *MEDCouplingFieldDiscretizationGaussNE::getRepr() const
2021 {
2022   return REPR;
2023 }
2024
2025 bool MEDCouplingFieldDiscretizationGaussNE::isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const
2026 {
2027   if(!other)
2028     {
2029       reason="other spatial discretization is NULL, and this spatial discretization (GaussNE) is defined.";
2030       return false;
2031     }
2032   const MEDCouplingFieldDiscretizationGaussNE *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationGaussNE *>(other);
2033   bool ret=otherC!=0;
2034   if(!ret)
2035     reason="Spatial discrtization of this is ON_GAUSS_NE, which is not the case of other.";
2036   return ret;
2037 }
2038
2039 int MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode(const MEDCouplingMesh *mesh, const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
2040 {
2041   if(code.size()%3!=0)
2042     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : invalid input code !");
2043   int nbOfSplit=(int)idsPerType.size();
2044   int nbOfTypes=(int)code.size()/3;
2045   int ret=0;
2046   for(int i=0;i<nbOfTypes;i++)
2047     {
2048       int nbOfEltInChunk=code[3*i+1];
2049       if(nbOfEltInChunk<0)
2050         throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : invalid input code ! presence of negative value in a type !");
2051       int pos=code[3*i+2];
2052       if(pos!=-1)
2053         {
2054           if(pos<0 || pos>=nbOfSplit)
2055             {
2056               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : input code points to pos " << pos << " in typeid " << i << " ! Should be in [0," << nbOfSplit << ") !";
2057               throw INTERP_KERNEL::Exception(oss.str().c_str());
2058             }
2059           const DataArrayInt *ids(idsPerType[pos]);
2060           if(!ids || !ids->isAllocated() || ids->getNumberOfComponents()!=1 || ids->getNumberOfTuples()!=nbOfEltInChunk || ids->getMinValueInArray()<0)
2061             {
2062               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : input pfl chunck at pos " << pos << " should have " << i << " tuples and one component and with ids all >=0 !";
2063               throw INTERP_KERNEL::Exception(oss.str().c_str());
2064             }
2065         }
2066       ret+=nbOfEltInChunk;
2067     }
2068   if(!mesh)
2069     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : NULL input mesh !");
2070   if(ret!=mesh->getNumberOfCells())
2071     {
2072       std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : input code points to " << ret << " number of cells should be " <<  mesh->getNumberOfCells() << " !";
2073     }
2074   return getNumberOfTuples(mesh);
2075 }
2076
2077 int MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuples(const MEDCouplingMesh *mesh) const throw(INTERP_KERNEL::Exception)
2078 {
2079   if(!mesh)
2080     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuples : NULL input mesh !");
2081   int ret=0;
2082   int nbOfCells=mesh->getNumberOfCells();
2083   for(int i=0;i<nbOfCells;i++)
2084     {
2085       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2086       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2087       if(cm.isDynamic())
2088         throw INTERP_KERNEL::Exception("Not implemented yet Gauss node on elements for polygons and polyedrons !");
2089       ret+=cm.getNumberOfNodes();
2090     }
2091   return ret;
2092 }
2093
2094 int MEDCouplingFieldDiscretizationGaussNE::getNumberOfMeshPlaces(const MEDCouplingMesh *mesh) const
2095 {
2096   if(!mesh)
2097     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfMeshPlaces : NULL input mesh !");
2098   return mesh->getNumberOfCells();
2099 }
2100
2101 DataArrayInt *MEDCouplingFieldDiscretizationGaussNE::getOffsetArr(const MEDCouplingMesh *mesh) const
2102 {
2103   if(!mesh)
2104     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getOffsetArr : NULL input mesh !");
2105   int nbOfTuples=mesh->getNumberOfCells();
2106   DataArrayInt *ret=DataArrayInt::New();
2107   ret->alloc(nbOfTuples+1,1);
2108   int *retPtr=ret->getPointer();
2109   retPtr[0]=0;
2110   for(int i=0;i<nbOfTuples;i++)
2111     {
2112       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2113       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2114       if(cm.isDynamic())
2115         throw INTERP_KERNEL::Exception("Not implemented yet Gauss node on elements for polygons and polyedrons !");
2116       retPtr[i+1]=retPtr[i]+cm.getNumberOfNodes();
2117     }
2118   return ret;
2119 }
2120
2121 void MEDCouplingFieldDiscretizationGaussNE::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArray *>& arrays,
2122                                                                   const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2123 {
2124   if(!mesh)
2125     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::renumberArraysForCell : NULL input mesh !");
2126   const int *array=old2NewBg;
2127   if(check)
2128     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+mesh->getNumberOfCells());
2129   int nbOfCells=mesh->getNumberOfCells();
2130   int nbOfTuples=getNumberOfTuples(mesh);
2131   int *array2=new int[nbOfTuples];//stores the final conversion array old2New to give to arrays in renumberInPlace.
2132   int *array3=new int[nbOfCells];//store for each cell in after renumbering the offset needed by each cell in new numbering.
2133   array3[0]=0;
2134   for(int i=1;i<nbOfCells;i++)
2135     {
2136       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell((int)std::distance(array,std::find(array,array+nbOfCells,i-1)));
2137       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2138       array3[i]=array3[i-1]+cm.getNumberOfNodes();
2139     }
2140   int j=0;
2141   for(int i=0;i<nbOfCells;i++)
2142     {
2143       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2144       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2145       for(int k=0;k<(int)cm.getNumberOfNodes();k++,j++)
2146         array2[j]=array3[array[i]]+k;
2147     }
2148   delete [] array3;
2149   for(std::vector<DataArray *>::const_iterator it=arrays.begin();it!=arrays.end();it++)
2150     if(*it)
2151       (*it)->renumberInPlace(array2);
2152   delete [] array2;
2153   if(check)
2154     free(const_cast<int *>(array));
2155 }
2156
2157 DataArrayDouble *MEDCouplingFieldDiscretizationGaussNE::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const
2158 {
2159   if(!mesh)
2160     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getLocalizationOfDiscValues : NULL input mesh !");
2161   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
2162   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> umesh=mesh->buildUnstructured();//in general do nothing
2163   int nbOfTuples=getNumberOfTuples(umesh);
2164   int spaceDim=mesh->getSpaceDimension();
2165   ret->alloc(nbOfTuples,spaceDim);
2166   const double *coords=umesh->getCoords()->begin();
2167   const int *connI=umesh->getNodalConnectivityIndex()->getConstPointer();
2168   const int *conn=umesh->getNodalConnectivity()->getConstPointer();
2169   int nbCells=umesh->getNumberOfCells();
2170   double *retPtr=ret->getPointer();
2171   for(int i=0;i<nbCells;i++,connI++)
2172     for(const int *w=conn+connI[0]+1;w!=conn+connI[1];w++)
2173       if(*w>=0)
2174         retPtr=std::copy(coords+(*w)*spaceDim,coords+((*w)+1)*spaceDim,retPtr);
2175   return ret.retn();
2176 }
2177
2178 /*!
2179  * Reimplemented from MEDCouplingFieldDiscretization::integral for performance reason. The default implementation is valid too for GAUSS_NE spatial discretization.
2180  */
2181 void MEDCouplingFieldDiscretizationGaussNE::integral(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, bool isWAbs, double *res) const throw(INTERP_KERNEL::Exception)
2182 {
2183   if(!mesh || !arr)
2184     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::integral : input mesh or array is null !");
2185   int nbOfCompo=arr->getNumberOfComponents();
2186   std::fill(res,res+nbOfCompo,0.);
2187   //
2188   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> vol=mesh->getMeasureField(isWAbs);
2189   std::set<INTERP_KERNEL::NormalizedCellType> types=mesh->getAllGeoTypes();
2190   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=mesh->computeNbOfNodesPerCell();
2191   nbOfNodesPerCell->computeOffsets2();
2192   const double *arrPtr=arr->begin(),*volPtr=vol->getArray()->begin();
2193   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
2194     {
2195       std::size_t wArrSz=-1;
2196       const double *wArr=GetWeightArrayFromGeometricType(*it,wArrSz);
2197       INTERP_KERNEL::AutoPtr<double> wArr2=new double[wArrSz];
2198       double sum=std::accumulate(wArr,wArr+wArrSz,0.);
2199       std::transform(wArr,wArr+wArrSz,(double *)wArr2,std::bind2nd(std::multiplies<double>(),1./sum));      
2200       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=mesh->giveCellsWithType(*it);
2201       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->buildExplicitArrByRanges(nbOfNodesPerCell);
2202       const int *ptIds2=ids2->begin(),*ptIds=ids->begin();
2203       int nbOfCellsWithCurGeoType=ids->getNumberOfTuples();
2204       for(int i=0;i<nbOfCellsWithCurGeoType;i++,ptIds++,ptIds2+=wArrSz)
2205         {
2206           for(int k=0;k<nbOfCompo;k++)
2207             {
2208               double tmp=0.;
2209               for(std::size_t j=0;j<wArrSz;j++)
2210                 tmp+=arrPtr[nbOfCompo*ptIds2[j]+k]*wArr2[j];
2211               res[k]+=tmp*volPtr[*ptIds];
2212             }
2213         }
2214     }
2215 }
2216
2217 const double *MEDCouplingFieldDiscretizationGaussNE::GetWeightArrayFromGeometricType(INTERP_KERNEL::NormalizedCellType geoType, std::size_t& lgth) throw(INTERP_KERNEL::Exception)
2218 {
2219   switch(geoType)
2220     {
2221     case INTERP_KERNEL::NORM_SEG2:
2222       lgth=(int)sizeof(FGP_SEG2)/sizeof(double);
2223       return FGP_SEG2;
2224     case INTERP_KERNEL::NORM_SEG3:
2225       lgth=(int)sizeof(FGP_SEG3)/sizeof(double);
2226       return FGP_SEG3;
2227     case INTERP_KERNEL::NORM_SEG4:
2228       lgth=(int)sizeof(FGP_SEG4)/sizeof(double);
2229       return FGP_SEG4;
2230     case INTERP_KERNEL::NORM_TRI3:
2231       lgth=(int)sizeof(FGP_TRI3)/sizeof(double);
2232       return FGP_TRI3;
2233     case INTERP_KERNEL::NORM_TRI6:
2234       lgth=(int)sizeof(FGP_TRI6)/sizeof(double);
2235       return FGP_TRI6;
2236     case INTERP_KERNEL::NORM_TRI7:
2237       lgth=(int)sizeof(FGP_TRI7)/sizeof(double);
2238       return FGP_TRI7;
2239     case INTERP_KERNEL::NORM_QUAD4:
2240       lgth=(int)sizeof(FGP_QUAD4)/sizeof(double);
2241       return FGP_QUAD4;
2242     case INTERP_KERNEL::NORM_QUAD9:
2243       lgth=(int)sizeof(FGP_QUAD9)/sizeof(double);
2244       return FGP_QUAD9;
2245     case INTERP_KERNEL::NORM_TETRA4:
2246       lgth=(int)sizeof(FGP_TETRA4)/sizeof(double);
2247       return FGP_TETRA4;
2248     case INTERP_KERNEL::NORM_PENTA6:
2249       lgth=(int)sizeof(FGP_PENTA6)/sizeof(double);
2250       return FGP_PENTA6;
2251     case INTERP_KERNEL::NORM_HEXA8:
2252       lgth=(int)sizeof(FGP_HEXA8)/sizeof(double);
2253       return FGP_HEXA8;
2254     case INTERP_KERNEL::NORM_HEXA27:
2255       lgth=(int)sizeof(FGP_HEXA27)/sizeof(double);
2256       return FGP_HEXA27;
2257     case INTERP_KERNEL::NORM_PYRA5:
2258       lgth=(int)sizeof(FGP_PYRA5)/sizeof(double);
2259       return FGP_PYRA5;
2260     default:
2261       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 !");
2262     }
2263 }
2264
2265 const double *MEDCouplingFieldDiscretizationGaussNE::GetRefCoordsFromGeometricType(INTERP_KERNEL::NormalizedCellType geoType, std::size_t& lgth) throw(INTERP_KERNEL::Exception)
2266 {
2267   switch(geoType)
2268     {
2269     case INTERP_KERNEL::NORM_SEG2:
2270       lgth=(int)sizeof(REF_SEG2)/sizeof(double);
2271       return REF_SEG2;
2272     case INTERP_KERNEL::NORM_SEG3:
2273       lgth=(int)sizeof(REF_SEG3)/sizeof(double);
2274       return REF_SEG3;
2275     case INTERP_KERNEL::NORM_SEG4:
2276       lgth=(int)sizeof(REF_SEG4)/sizeof(double);
2277       return REF_SEG4;
2278     case INTERP_KERNEL::NORM_TRI3:
2279       lgth=(int)sizeof(REF_TRI3)/sizeof(double);
2280       return REF_TRI3;
2281     case INTERP_KERNEL::NORM_TRI6:
2282       lgth=(int)sizeof(REF_TRI6)/sizeof(double);
2283       return REF_TRI6;
2284     case INTERP_KERNEL::NORM_TRI7:
2285       lgth=(int)sizeof(REF_TRI7)/sizeof(double);
2286       return REF_TRI7;
2287     case INTERP_KERNEL::NORM_QUAD4:
2288       lgth=(int)sizeof(REF_QUAD4)/sizeof(double);
2289       return REF_QUAD4;
2290     case INTERP_KERNEL::NORM_QUAD8:
2291       lgth=(int)sizeof(REF_QUAD8)/sizeof(double);
2292       return REF_QUAD8;
2293     case INTERP_KERNEL::NORM_QUAD9:
2294       lgth=(int)sizeof(REF_QUAD9)/sizeof(double);
2295       return REF_QUAD9;
2296     case INTERP_KERNEL::NORM_TETRA4:
2297       lgth=(int)sizeof(REF_TETRA4)/sizeof(double);
2298       return REF_TETRA4;
2299     case INTERP_KERNEL::NORM_TETRA10:
2300       lgth=(int)sizeof(REF_TETRA10)/sizeof(double);
2301       return REF_TETRA10;
2302     case INTERP_KERNEL::NORM_PENTA6:
2303       lgth=(int)sizeof(REF_PENTA6)/sizeof(double);
2304       return REF_PENTA6;
2305     case INTERP_KERNEL::NORM_PENTA15:
2306       lgth=(int)sizeof(REF_PENTA15)/sizeof(double);
2307       return REF_PENTA15;
2308     case INTERP_KERNEL::NORM_HEXA8:
2309       lgth=(int)sizeof(REF_HEXA8)/sizeof(double);
2310       return REF_HEXA8;
2311     case INTERP_KERNEL::NORM_HEXA20:
2312       lgth=(int)sizeof(REF_HEXA20)/sizeof(double);
2313       return REF_HEXA20;
2314     case INTERP_KERNEL::NORM_HEXA27:
2315       lgth=(int)sizeof(REF_HEXA27)/sizeof(double);
2316       return REF_HEXA27;
2317     case INTERP_KERNEL::NORM_PYRA5:
2318       lgth=(int)sizeof(REF_PYRA5)/sizeof(double);
2319       return REF_PYRA5;
2320     case INTERP_KERNEL::NORM_PYRA13:
2321       lgth=(int)sizeof(REF_PYRA13)/sizeof(double);
2322       return REF_PYRA13;
2323     default:
2324       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 !");
2325     }
2326 }
2327
2328 void MEDCouplingFieldDiscretizationGaussNE::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *tupleIdsBg, const int *tupleIdsEnd,
2329                                                                                DataArrayInt *&cellRestriction, DataArrayInt *&trueTupleRestriction) const throw(INTERP_KERNEL::Exception)
2330 {
2331   if(!mesh)
2332     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::computeMeshRestrictionFromTupleIds : NULL input mesh !");
2333   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=DataArrayInt::New(); tmp->alloc((int)std::distance(tupleIdsBg,tupleIdsEnd),1);
2334   std::copy(tupleIdsBg,tupleIdsEnd,tmp->getPointer());
2335   tmp->sort(true);
2336   tmp=tmp->buildUnique();
2337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=mesh->computeNbOfNodesPerCell();
2338   nbOfNodesPerCell->computeOffsets2();
2339   nbOfNodesPerCell->searchRangesInListOfIds(tmp,cellRestriction,trueTupleRestriction);
2340 }
2341
2342 void MEDCouplingFieldDiscretizationGaussNE::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
2343 {
2344 }
2345
2346 double MEDCouplingFieldDiscretizationGaussNE::getIJK(const MEDCouplingMesh *mesh, const DataArrayDouble *da,
2347                                                      int cellId, int nodeIdInCell, int compoId) const throw(INTERP_KERNEL::Exception)
2348 {
2349   if(!mesh)
2350     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getIJK : NULL input mesh !");
2351   int offset=0;
2352   for(int i=0;i<cellId;i++)
2353     {
2354       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2355       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2356       offset+=cm.getNumberOfNodes();
2357     }
2358   return da->getIJ(offset+nodeIdInCell,compoId);
2359 }
2360
2361 void MEDCouplingFieldDiscretizationGaussNE::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception)
2362 {
2363   int nbOfTuples=getNumberOfTuples(mesh);
2364   if(nbOfTuples!=da->getNumberOfTuples())
2365     {
2366       std::ostringstream oss; oss << "Invalid number of tuples in the array : expecting " << nbOfTuples << " !";
2367       throw INTERP_KERNEL::Exception(oss.str().c_str());
2368     }
2369 }
2370
2371 MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationGaussNE::getMeasureField(const MEDCouplingMesh *mesh, bool isAbs) const
2372 {
2373   if(!mesh)
2374     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getMeasureField : mesh instance specified is NULL !");
2375   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> vol=mesh->getMeasureField(isAbs);
2376   const double *volPtr=vol->getArray()->begin();
2377   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_GAUSS_NE);
2378   ret->setMesh(mesh);
2379   //
2380   std::set<INTERP_KERNEL::NormalizedCellType> types=mesh->getAllGeoTypes();
2381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=mesh->computeNbOfNodesPerCell();
2382   int nbTuples=nbOfNodesPerCell->accumulate(0);
2383   nbOfNodesPerCell->computeOffsets2();
2384   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New(); arr->alloc(nbTuples,1);
2385   ret->setArray(arr);
2386   double *arrPtr=arr->getPointer();
2387   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
2388     {
2389       std::size_t wArrSz=-1;
2390       const double *wArr=GetWeightArrayFromGeometricType(*it,wArrSz);
2391       INTERP_KERNEL::AutoPtr<double> wArr2=new double[wArrSz];
2392       double sum=std::accumulate(wArr,wArr+wArrSz,0.);
2393       std::transform(wArr,wArr+wArrSz,(double *)wArr2,std::bind2nd(std::multiplies<double>(),1./sum));      
2394       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=mesh->giveCellsWithType(*it);
2395       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->buildExplicitArrByRanges(nbOfNodesPerCell);
2396       const int *ptIds2=ids2->begin(),*ptIds=ids->begin();
2397       int nbOfCellsWithCurGeoType=ids->getNumberOfTuples();
2398       for(int i=0;i<nbOfCellsWithCurGeoType;i++,ptIds++)
2399         for(std::size_t j=0;j<wArrSz;j++,ptIds2++)
2400           arrPtr[*ptIds2]=wArr2[j]*volPtr[*ptIds];
2401     }
2402   ret->synchronizeTimeWithSupport();
2403   return ret.retn();
2404 }
2405
2406 void MEDCouplingFieldDiscretizationGaussNE::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
2407 {
2408   throw INTERP_KERNEL::Exception("Not implemented yet !");
2409 }
2410
2411 void MEDCouplingFieldDiscretizationGaussNE::getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const
2412 {
2413   throw INTERP_KERNEL::Exception("getValueOnPos(i,j,k) : Not applyable for Gauss points !");
2414 }
2415
2416 DataArrayDouble *MEDCouplingFieldDiscretizationGaussNE::getValueOnMulti(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, int nbOfPoints) const
2417 {
2418   throw INTERP_KERNEL::Exception("getValueOnMulti : Not implemented for Gauss NE !");
2419 }
2420
2421 MEDCouplingMesh *MEDCouplingFieldDiscretizationGaussNE::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
2422 {
2423   if(!mesh)
2424     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::buildSubMeshData : NULL input mesh !");
2425   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diSafe=computeTupleIdsToSelectFromCellIds(mesh,start,end);
2426   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPart(start,end);
2427   di=diSafe.retn();
2428   return ret.retn();
2429 }
2430
2431 /*!
2432  * This method is strictly equivalent to MEDCouplingFieldDiscretizationGauss::buildSubMeshData except that it is optimized for input defined as a range of cell ids.
2433  * 
2434  * \param [out] beginOut Valid only if \a di is NULL
2435  * \param [out] endOut Valid only if \a di is NULL
2436  * \param [out] stepOut Valid only if \a di is NULL
2437  * \param [out] di is an array returned that specifies entity ids (nodes, cells, Gauss points... ) in array if no output range is foundable.
2438  *
2439  * \sa MEDCouplingFieldDiscretizationGauss::buildSubMeshData
2440  */
2441 MEDCouplingMesh *MEDCouplingFieldDiscretizationGaussNE::buildSubMeshDataRange(const MEDCouplingMesh *mesh, int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt *&di) const
2442 {
2443   if(stepCellIds!=1)//even for stepCellIds==-1 the output will not be a range
2444     return MEDCouplingFieldDiscretization::buildSubMeshDataRange(mesh,beginCellIds,endCellIds,stepCellIds,beginOut,endOut,stepOut,di);
2445   if(!mesh)
2446     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::buildSubMeshDataRange : NULL input mesh !");
2447   int nbOfCells=mesh->getNumberOfCells();
2448   di=0; beginOut=0; endOut=0; stepOut=stepCellIds;
2449   const char msg[]="MEDCouplingFieldDiscretizationGaussNE::buildSubMeshDataRange : cell #";
2450   for(int i=0;i<nbOfCells;i++)
2451     {
2452       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2453       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2454       if(cm.isDynamic())
2455         { std::ostringstream oss; oss << msg << i << " presence of dynamic cell (polygons and polyedrons) ! Not implemented !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
2456       int delta=cm.getNumberOfNodes();
2457       if(i<beginCellIds)
2458         beginOut+=delta;
2459       endOut+=delta;
2460       if(i>=endCellIds)
2461         break;
2462     }
2463   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPartRange(beginCellIds,endCellIds,stepCellIds);
2464   return ret.retn();
2465 }
2466
2467
2468 /*!
2469  * This method returns a tuple ids selection from cell ids selection [start;end).
2470  * This method is called by MEDCouplingFieldDiscretizationGaussNE::buildSubMeshData to return parameter \b di.
2471  *
2472  * \return a newly allocated array containing ids to select into the DataArrayDouble of the field.
2473  * 
2474  */
2475 DataArrayInt *MEDCouplingFieldDiscretizationGaussNE::computeTupleIdsToSelectFromCellIds(const MEDCouplingMesh *mesh, const int *startCellIds, const int *endCellIds) const
2476 {
2477   if(!mesh)
2478     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::computeTupleIdsToSelectFromCellIds : null mesh !");
2479   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=mesh->computeNbOfNodesPerCell();
2480   nbOfNodesPerCell->computeOffsets2();
2481   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> sel=DataArrayInt::New(); sel->useArray(startCellIds,false,CPP_DEALLOC,(int)std::distance(startCellIds,endCellIds),1);
2482   return sel->buildExplicitArrByRanges(nbOfNodesPerCell);
2483 }
2484
2485 /*!
2486  * No implementation needed !
2487  */
2488 void MEDCouplingFieldDiscretizationGaussNE::renumberValuesOnNodes(double , const int *, int newNbOfNodes, DataArrayDouble *) const
2489 {
2490 }
2491
2492 void MEDCouplingFieldDiscretizationGaussNE::renumberValuesOnCells(double epsOnVals, const MEDCouplingMesh *mesh, const int *old2New, int newSz, DataArrayDouble *arr) const
2493 {
2494   throw INTERP_KERNEL::Exception("Not implemented yet !");
2495 }
2496
2497 void MEDCouplingFieldDiscretizationGaussNE::renumberValuesOnCellsR(const MEDCouplingMesh *mesh, const int *new2old, int newSz, DataArrayDouble *arr) const
2498 {
2499   throw INTERP_KERNEL::Exception("Not implemented yet !");
2500 }
2501
2502 void MEDCouplingFieldDiscretizationGaussNE::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2503 {
2504   stream << "Gauss points on nodes per element spatial discretization.";
2505 }
2506
2507 MEDCouplingFieldDiscretizationGaussNE::MEDCouplingFieldDiscretizationGaussNE(const MEDCouplingFieldDiscretizationGaussNE& other):MEDCouplingFieldDiscretization(other)
2508 {
2509 }
2510
2511 TypeOfField MEDCouplingFieldDiscretizationKriging::getEnum() const
2512 {
2513   return TYPE;
2514 }
2515
2516 const char *MEDCouplingFieldDiscretizationKriging::getRepr() const
2517 {
2518   return REPR;
2519 }
2520
2521 /*!
2522  * This method is simply called by MEDCouplingFieldDiscretization::deepCpy. It performs the deep copy of \a this.
2523  *
2524  * \sa MEDCouplingFieldDiscretization::deepCpy.
2525  */
2526 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationKriging::clone() const
2527 {
2528   return new MEDCouplingFieldDiscretizationKriging;
2529 }
2530
2531 std::string MEDCouplingFieldDiscretizationKriging::getStringRepr() const
2532 {
2533   return std::string(REPR);
2534 }
2535
2536 void MEDCouplingFieldDiscretizationKriging::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
2537 {
2538   if(nat!=ConservativeVolumic)
2539     throw INTERP_KERNEL::Exception("Invalid nature for Kriging field : expected ConservativeVolumic !");
2540 }
2541
2542 bool MEDCouplingFieldDiscretizationKriging::isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const
2543 {
2544   if(!other)
2545     {
2546       reason="other spatial discretization is NULL, and this spatial discretization (Kriginig) is defined.";
2547       return false;
2548     }
2549   const MEDCouplingFieldDiscretizationKriging *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationKriging *>(other);
2550   bool ret=otherC!=0;
2551   if(!ret)
2552     reason="Spatial discrtization of this is ON_NODES_KR, which is not the case of other.";
2553   return ret;
2554 }
2555
2556 MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationKriging::getMeasureField(const MEDCouplingMesh *mesh, bool isAbs) const
2557 {
2558   if(!mesh)
2559     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::getMeasureField : mesh instance specified is NULL !");
2560   throw INTERP_KERNEL::Exception("getMeasureField on FieldDiscretizationKriging : not implemented yet !");
2561 }
2562
2563 void MEDCouplingFieldDiscretizationKriging::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
2564 {
2565   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res2=MEDCouplingFieldDiscretizationKriging::getValueOnMulti(arr,mesh,loc,1);
2566   std::copy(res2->begin(),res2->end(),res);
2567 }
2568
2569 DataArrayDouble *MEDCouplingFieldDiscretizationKriging::getValueOnMulti(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, int nbOfTargetPoints) const
2570 {
2571   if(!mesh)
2572     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::getValueOnMulti : NULL input mesh !");
2573   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getLocalizationOfDiscValues(mesh);
2574   int nbOfPts=coords->getNumberOfTuples();
2575   int dimension=coords->getNumberOfComponents();
2576   //
2577   int delta=0;
2578   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> KnewiK=computeVectorOfCoefficients(mesh,arr,delta);
2579   //
2580   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> locArr=DataArrayDouble::New();
2581   locArr->useArray(loc,false,CPP_DEALLOC,nbOfTargetPoints,dimension);
2582   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrix2=coords->buildEuclidianDistanceDenseMatrixWith(locArr);
2583   operateOnDenseMatrix(mesh->getSpaceDimension(),nbOfPts*nbOfTargetPoints,matrix2->getPointer());
2584   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrix3=DataArrayDouble::New();
2585   matrix3->alloc((nbOfPts+delta)*nbOfTargetPoints,1);
2586   double *work=matrix3->getPointer();
2587   const double *workCst=matrix2->getConstPointer();
2588   const double *workCst2=loc;
2589   for(int i=0;i<nbOfTargetPoints;i++,workCst+=nbOfPts,workCst2+=delta-1)
2590     {
2591       for(int j=0;j<nbOfPts;j++)
2592         work[j*nbOfTargetPoints+i]=workCst[j];
2593       work[nbOfPts*nbOfTargetPoints+i]=1.0;
2594       for(int j=0;j<delta-1;j++)
2595         work[(nbOfPts+1+j)*nbOfTargetPoints+i]=workCst2[j];
2596     }
2597   //
2598   int nbOfCompo=arr->getNumberOfComponents();
2599   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
2600   ret->alloc(nbOfTargetPoints,nbOfCompo);
2601   INTERP_KERNEL::matrixProduct(KnewiK->getConstPointer(),1,nbOfPts+delta,matrix3->getConstPointer(),nbOfPts+delta,nbOfTargetPoints*nbOfCompo,ret->getPointer());
2602   return ret.retn();
2603 }
2604
2605 void MEDCouplingFieldDiscretizationKriging::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2606 {
2607   stream << "Kriging spatial discretization.";
2608 }
2609
2610 /*!
2611  * 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
2612  * number of tuples should be equal to the number of representing points in \a mesh.
2613  * 
2614  * \param [in] mesh is the sources of nodes on which kriging will be done regarding the parameters and the value of \c this->getSpaceDimension()
2615  * \param [in] arr input field DataArrayDouble whose number of tuples must be equal to the number of nodes in \a mesh
2616  * \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.
2617  *              Whatever the value of \a isDrift the number of tuples of returned DataArrayDouble  will be equal to \c arr->getNumberOfTuples() + \a isDrift.
2618  * \return a newly allocated array containing coefficients including or not drift coefficient at the end depending the value of \a isDrift parameter.
2619  */
2620 DataArrayDouble *MEDCouplingFieldDiscretizationKriging::computeVectorOfCoefficients(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, int& isDrift) const
2621 {
2622   if(!mesh)
2623     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::computeVectorOfCoefficients : NULL input mesh !");
2624   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getLocalizationOfDiscValues(mesh);
2625   int nbOfPts=coords->getNumberOfTuples();
2626   //int dimension=coords->getNumberOfComponents();
2627   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrix=coords->buildEuclidianDistanceDenseMatrix();
2628   operateOnDenseMatrix(mesh->getSpaceDimension(),nbOfPts*nbOfPts,matrix->getPointer());
2629   // Drift
2630   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixWithDrift=performDrift(matrix,coords,isDrift);
2631   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixInv=DataArrayDouble::New();
2632   matrixInv->alloc((nbOfPts+isDrift)*(nbOfPts+isDrift),1);
2633   INTERP_KERNEL::inverseMatrix(matrixWithDrift->getConstPointer(),nbOfPts+isDrift,matrixInv->getPointer());
2634   //
2635   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> KnewiK=DataArrayDouble::New();
2636   KnewiK->alloc((nbOfPts+isDrift)*1,1);
2637   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2=DataArrayDouble::New();
2638   arr2->alloc((nbOfPts+isDrift)*1,1);
2639   double *work=std::copy(arr->begin(),arr->end(),arr2->getPointer());
2640   std::fill(work,work+isDrift,0.);
2641   INTERP_KERNEL::matrixProduct(matrixInv->getConstPointer(),nbOfPts+isDrift,nbOfPts+isDrift,arr2->getConstPointer(),nbOfPts+isDrift,1,KnewiK->getPointer());
2642   return KnewiK.retn();
2643 }
2644
2645 /*!
2646  * 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.
2647  *
2648  * \param [in] spaceDimension space dimension of the input mesh on which the Kriging has to be performed
2649  * \param [in] nbOfElems is the result of the product of nb of rows and the nb of columns of matrix \a matrixPtr
2650  * \param [in,out] matrixPtr is the dense matrix whose on each values the operation will be applied
2651  */
2652 void MEDCouplingFieldDiscretizationKriging::operateOnDenseMatrix(int spaceDimension, int nbOfElems, double *matrixPtr) const
2653 {
2654   switch(spaceDimension)
2655     {
2656     case 1:
2657       {
2658         for(int i=0;i<nbOfElems;i++)
2659           {
2660             double val=matrixPtr[i];
2661             matrixPtr[i]=val*val*val;
2662           }
2663         break;
2664       }
2665     default:
2666       throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::operateOnDenseMatrix : only dimension 1 implemented !");
2667     }
2668 }
2669
2670 /*!
2671  * Starting from a square matrix \a matr, this method returns a newly allocated dense square matrix whose \a matr is included in returned matrix
2672  * in the top left corner, and in the remaining returned matrix the parameters to take into account about the kriging drift.
2673  * For the moment only linear srift is implemented.
2674  *
2675  * \param [in] arr the position of points were input mesh geometry is considered for Kriging
2676  * \param [in] matr input matrix whose drift part will be added
2677  * \param [out] delta the difference between the size of the output matrix and the input matrix \a matr.
2678  * \return a newly allocated matrix bigger than input matrix \a matr.
2679  */
2680 DataArrayDouble *MEDCouplingFieldDiscretizationKriging::performDrift(const DataArrayDouble *matr, const DataArrayDouble *arr, int& delta) const
2681 {
2682   int spaceDimension=arr->getNumberOfComponents();
2683   delta=spaceDimension+1;
2684   int szOfMatrix=arr->getNumberOfTuples();
2685   if(szOfMatrix*szOfMatrix!=matr->getNumberOfTuples())
2686     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::performDrift : invalid size");
2687   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
2688   ret->alloc((szOfMatrix+delta)*(szOfMatrix+delta),1);
2689   const double *srcWork=matr->getConstPointer();
2690   const double *srcWork2=arr->getConstPointer();
2691   double *destWork=ret->getPointer();
2692   for(int i=0;i<szOfMatrix;i++)
2693     {
2694       destWork=std::copy(srcWork,srcWork+szOfMatrix,destWork);
2695       srcWork+=szOfMatrix;
2696       *destWork++=1.;
2697       destWork=std::copy(srcWork2,srcWork2+spaceDimension,destWork);
2698       srcWork2+=spaceDimension;
2699     }
2700   std::fill(destWork,destWork+szOfMatrix,1.); destWork+=szOfMatrix;
2701   std::fill(destWork,destWork+spaceDimension+1,0.); destWork+=spaceDimension+1;
2702   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arrNoI=arr->toNoInterlace();
2703   srcWork2=arrNoI->getConstPointer();
2704   for(int i=0;i<spaceDimension;i++)
2705     {
2706       destWork=std::copy(srcWork2,srcWork2+szOfMatrix,destWork);
2707       srcWork2+=szOfMatrix;
2708       std::fill(destWork,destWork+spaceDimension+1,0.);
2709       destWork+=spaceDimension;
2710     }
2711   //
2712   return ret.retn();
2713 }