Salome HOME
4742a3ed08ce7f2d82f8bb8562d816bbdfd7a51b
[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   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsArr,eltsIndexArr;
625   mesh->getCellsContainingPoints(loc,nbOfPoints,_precision,eltsArr,eltsIndexArr);
626   const int *elts(eltsArr->begin()),*eltsIndex(eltsIndexArr->begin());
627   int spaceDim=mesh->getSpaceDimension();
628   int nbOfComponents=arr->getNumberOfComponents();
629   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
630   ret->alloc(nbOfPoints,nbOfComponents);
631   double *ptToFill=ret->getPointer();
632   for(int i=0;i<nbOfPoints;i++,ptToFill+=nbOfComponents)
633     if(eltsIndex[i+1]-eltsIndex[i]>=1)
634       arr->getTuple(elts[eltsIndex[i]],ptToFill);
635     else
636       {
637         std::ostringstream oss; oss << "Point #" << i << " with coordinates : (";
638         std::copy(loc+i*spaceDim,loc+(i+1)*spaceDim,std::ostream_iterator<double>(oss,", "));
639         oss << ") detected outside mesh : unable to apply P0::getValueOnMulti ! ";
640         throw INTERP_KERNEL::Exception(oss.str().c_str());
641       }
642   return ret.retn();
643 }
644
645 /*!
646  * Nothing to do. It's not a bug.
647  */
648 void MEDCouplingFieldDiscretizationP0::renumberValuesOnNodes(double , const int *, int newNbOfNodes, DataArrayDouble *) const
649 {
650 }
651
652 void MEDCouplingFieldDiscretizationP0::renumberValuesOnCells(double epsOnVals, const MEDCouplingMesh *mesh, const int *old2New, int newSz, DataArrayDouble *arr) const
653 {
654   RenumberEntitiesFromO2NArr(epsOnVals,old2New,newSz,arr,"Cell");
655 }
656
657 void MEDCouplingFieldDiscretizationP0::renumberValuesOnCellsR(const MEDCouplingMesh *mesh, const int *new2old, int newSz, DataArrayDouble *arr) const
658 {
659   RenumberEntitiesFromN2OArr(new2old,newSz,arr,"Cell");
660 }
661
662 /*!
663  * This method returns a tuple ids selection from cell ids selection [start;end).
664  * This method is called by MEDCouplingFieldDiscretizationP0::buildSubMeshData to return parameter \b di.
665  * Here for P0 it's very simple !
666  *
667  * \return a newly allocated array containing ids to select into the DataArrayDouble of the field.
668  * 
669  */
670 DataArrayInt *MEDCouplingFieldDiscretizationP0::computeTupleIdsToSelectFromCellIds(const MEDCouplingMesh *mesh, const int *startCellIds, const int *endCellIds) const
671 {
672   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
673   ret->alloc((int)std::distance(startCellIds,endCellIds),1);
674   std::copy(startCellIds,endCellIds,ret->getPointer());
675   return ret.retn();
676 }
677
678 /*!
679  * This method returns a submesh of 'mesh' instance constituting cell ids contained in array defined as an interval [start;end).
680  * @param di is an array returned that specifies entity ids (here cells ids) in mesh 'mesh' of entity in returned submesh.
681  * Example : The first cell id of returned mesh has the (*di)[0] id in 'mesh'
682  *
683  * \sa MEDCouplingFieldDiscretizationP0::buildSubMeshDataRange
684  */
685 MEDCouplingMesh *MEDCouplingFieldDiscretizationP0::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
686 {
687   if(!mesh)
688     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::buildSubMeshData : NULL input mesh !");
689   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPart(start,end);
690   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diSafe=DataArrayInt::New();
691   diSafe->alloc((int)std::distance(start,end),1);
692   std::copy(start,end,diSafe->getPointer());
693   di=diSafe.retn();
694   return ret.retn();
695 }
696
697 /*!
698  * This method is strictly equivalent to MEDCouplingFieldDiscretizationP0::buildSubMeshData except that it is optimized for input defined as a range of cell ids.
699  * 
700  * \param [out] beginOut Valid only if \a di is NULL
701  * \param [out] endOut Valid only if \a di is NULL
702  * \param [out] stepOut Valid only if \a di is NULL
703  * \param [out] di is an array returned that specifies entity ids (nodes, cells, Gauss points... ) in array if no output range is foundable.
704  *
705  * \sa MEDCouplingFieldDiscretizationP0::buildSubMeshData
706  */
707 MEDCouplingMesh *MEDCouplingFieldDiscretizationP0::buildSubMeshDataRange(const MEDCouplingMesh *mesh, int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt *&di) const
708 {
709   if(!mesh)
710     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP0::buildSubMeshDataRange : NULL input mesh !");
711   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPartRange(beginCellIds,endCellIds,stepCellIds);
712   di=0; beginOut=beginCellIds; endOut=endCellIds; stepOut=stepCellIds;
713   return ret.retn();
714 }
715
716 int MEDCouplingFieldDiscretizationOnNodes::getNumberOfTuples(const MEDCouplingMesh *mesh) const throw(INTERP_KERNEL::Exception)
717 {
718   if(!mesh)
719     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::getNumberOfTuples : NULL input mesh !");
720   return mesh->getNumberOfNodes();
721 }
722
723 /*!
724  * mesh is not used here. It is not a bug !
725  */
726 int MEDCouplingFieldDiscretizationOnNodes::getNumberOfTuplesExpectedRegardingCode(const MEDCouplingMesh *mesh, const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
727 {
728   if(code.size()%3!=0)
729     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationOnNodes::getNumberOfTuplesExpectedRegardingCode : invalid input code !");
730   int nbOfSplit=(int)idsPerType.size();
731   int nbOfTypes=(int)code.size()/3;
732   int ret=0;
733   for(int i=0;i<nbOfTypes;i++)
734     {
735       int nbOfEltInChunk=code[3*i+1];
736       if(nbOfEltInChunk<0)
737         throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationOnNodes::getNumberOfTuplesExpectedRegardingCode : invalid input code ! presence of negative value in a type !");
738       int pos=code[3*i+2];
739       if(pos!=-1)
740         {
741           if(pos<0 || pos>=nbOfSplit)
742             {
743               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationOnNodes::getNumberOfTuplesExpectedRegardingCode : input code points to pos " << pos << " in typeid " << i << " ! Should be in [0," << nbOfSplit << ") !";
744               throw INTERP_KERNEL::Exception(oss.str().c_str());
745             }
746           const DataArrayInt *ids(idsPerType[pos]);
747           if(!ids || !ids->isAllocated() || ids->getNumberOfComponents()!=1 || ids->getNumberOfTuples()!=nbOfEltInChunk || ids->getMinValueInArray()<0)
748             {
749               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationOnNodes::getNumberOfTuplesExpectedRegardingCode : input pfl chunck at pos " << pos << " should have " << i << " tuples and one component and with ids all >=0 !";
750               throw INTERP_KERNEL::Exception(oss.str().c_str());
751             }
752         }
753       ret+=nbOfEltInChunk;
754     }
755   return ret;
756 }
757
758 int MEDCouplingFieldDiscretizationOnNodes::getNumberOfMeshPlaces(const MEDCouplingMesh *mesh) const
759 {
760   if(!mesh)
761     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::getNumberOfMeshPlaces : NULL input mesh !");
762   return mesh->getNumberOfNodes();
763 }
764
765 /*!
766  * Nothing to do here.
767  */
768 void MEDCouplingFieldDiscretizationOnNodes::renumberArraysForCell(const MEDCouplingMesh *, const std::vector<DataArray *>& arrays,
769                                                                   const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
770 {
771 }
772
773 DataArrayInt *MEDCouplingFieldDiscretizationOnNodes::getOffsetArr(const MEDCouplingMesh *mesh) const
774 {
775   if(!mesh)
776     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::getOffsetArr : NULL input mesh !");
777   int nbOfTuples=mesh->getNumberOfNodes();
778   DataArrayInt *ret=DataArrayInt::New();
779   ret->alloc(nbOfTuples+1,1);
780   ret->iota(0);
781   return ret;
782 }
783
784 DataArrayDouble *MEDCouplingFieldDiscretizationOnNodes::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const
785 {
786   if(!mesh)
787     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::getLocalizationOfDiscValues : NULL input mesh !");
788   return mesh->getCoordinatesAndOwner();
789 }
790
791 void MEDCouplingFieldDiscretizationOnNodes::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *tupleIdsBg, const int *tupleIdsEnd,
792                                                                                DataArrayInt *&cellRestriction, DataArrayInt *&trueTupleRestriction) const throw(INTERP_KERNEL::Exception)
793 {
794   if(!mesh)
795     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationOnNodes::computeMeshRestrictionFromTupleIds : NULL input mesh !");
796   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=mesh->getCellIdsFullyIncludedInNodeIds(tupleIdsBg,tupleIdsEnd);
797   const MEDCouplingUMesh *meshc=dynamic_cast<const MEDCouplingUMesh *>(mesh);
798   if(!meshc)
799     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationOnNodes::computeMeshRestrictionFromTupleIds : trying to subpart field on nodes by node ids ! Your mesh has to be unstructured !");
800   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshPart=static_cast<MEDCouplingUMesh *>(meshc->buildPartOfMySelf(ret1->begin(),ret1->end(),true));
801   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=meshPart->computeFetchedNodeIds();
802   cellRestriction=ret1.retn();
803   trueTupleRestriction=ret2.retn();
804 }
805
806 void MEDCouplingFieldDiscretizationOnNodes::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception)
807 {
808   if(!mesh || !da)
809     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::checkCoherencyBetween : NULL input mesh or DataArray !");
810   if(mesh->getNumberOfNodes()!=da->getNumberOfTuples())
811     {
812       std::ostringstream message;
813       message << "Field on nodes invalid because there are " << mesh->getNumberOfNodes();
814       message << " nodes in mesh and " << da->getNumberOfTuples() << " tuples in field !";
815       throw INTERP_KERNEL::Exception(message.str().c_str());
816     }
817 }
818
819 /*!
820  * This method returns a submesh of 'mesh' instance constituting cell ids contained in array defined as an interval [start;end).
821 * @param di is an array returned that specifies entity ids (here nodes ids) in mesh 'mesh' of entity in returned submesh.
822  * Example : The first node id of returned mesh has the (*di)[0] id in 'mesh'
823  */
824 MEDCouplingMesh *MEDCouplingFieldDiscretizationOnNodes::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
825 {
826   if(!mesh)
827     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationNodes::buildSubMeshData : NULL input mesh !");
828   DataArrayInt *diTmp=0;
829   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPartAndReduceNodes(start,end,diTmp);
830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diTmpSafe(diTmp);
831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> di2=diTmpSafe->invertArrayO2N2N2O(ret->getNumberOfNodes());
832   di=di2.retn();
833   return ret.retn();
834 }
835
836 /*!
837  * This method is strictly equivalent to MEDCouplingFieldDiscretizationNodes::buildSubMeshData except that it is optimized for input defined as a range of cell ids.
838  * 
839  * \param [out] beginOut Valid only if \a di is NULL
840  * \param [out] endOut Valid only if \a di is NULL
841  * \param [out] stepOut Valid only if \a di is NULL
842  * \param [out] di is an array returned that specifies entity ids (nodes, cells, Gauss points... ) in array if no output range is foundable.
843  *
844  * \sa MEDCouplingFieldDiscretizationNodes::buildSubMeshData
845  */
846 MEDCouplingMesh *MEDCouplingFieldDiscretizationOnNodes::buildSubMeshDataRange(const MEDCouplingMesh *mesh, int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt *&di) const
847 {
848   if(!mesh)
849     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationOnNodes::buildSubMeshDataRange : NULL input mesh !");
850   DataArrayInt *diTmp=0;
851   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPartRangeAndReduceNodes(beginCellIds,endCellIds,stepCellIds,beginOut,endOut,stepOut,diTmp);
852   if(diTmp)
853     {
854       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diTmpSafe(diTmp);
855       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> di2=diTmpSafe->invertArrayO2N2N2O(ret->getNumberOfNodes());
856       di=di2.retn();
857     }
858   return ret.retn();
859 }
860
861 /*!
862  * This method returns a tuple ids selection from cell ids selection [start;end).
863  * This method is called by MEDCouplingFieldDiscretizationOnNodes::buildSubMeshData to return parameter \b di.
864  * Here for P1 only nodes fetched by submesh of mesh[startCellIds:endCellIds) is returned !
865  *
866  * \return a newly allocated array containing ids to select into the DataArrayDouble of the field.
867  * 
868  */
869 DataArrayInt *MEDCouplingFieldDiscretizationOnNodes::computeTupleIdsToSelectFromCellIds(const MEDCouplingMesh *mesh, const int *startCellIds, const int *endCellIds) const
870 {
871   if(!mesh)
872     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP1::computeTupleIdsToSelectFromCellIds : NULL input mesh !");
873   const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> umesh=mesh->buildUnstructured();
874   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> umesh2=static_cast<MEDCouplingUMesh *>(umesh->buildPartOfMySelf(startCellIds,endCellIds,true));
875   return umesh2->computeFetchedNodeIds();
876 }
877
878 void MEDCouplingFieldDiscretizationOnNodes::renumberValuesOnNodes(double epsOnVals, const int *old2NewPtr, int newNbOfNodes, DataArrayDouble *arr) const
879 {
880   RenumberEntitiesFromO2NArr(epsOnVals,old2NewPtr,newNbOfNodes,arr,"Node");
881 }
882
883 /*!
884  * Nothing to do it's not a bug.
885  */
886 void MEDCouplingFieldDiscretizationOnNodes::renumberValuesOnCells(double epsOnVals, const MEDCouplingMesh *mesh, const int *old2New, int newSz, DataArrayDouble *arr) const
887 {
888 }
889
890 /*!
891  * Nothing to do it's not a bug.
892  */
893 void MEDCouplingFieldDiscretizationOnNodes::renumberValuesOnCellsR(const MEDCouplingMesh *mesh, const int *new2old, int newSz, DataArrayDouble *arr) const
894 {
895 }
896
897 void MEDCouplingFieldDiscretizationOnNodes::getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const
898 {
899   const MEDCouplingCMesh *meshC=dynamic_cast<const MEDCouplingCMesh *>(mesh);
900   if(!meshC)
901     throw INTERP_KERNEL::Exception("OnNodes::getValueOnPos(i,j,k) is only accessible for structured meshes !");
902   int id=meshC->getNodeIdFromPos(i,j,k);
903   arr->getTuple(id,res);
904 }
905
906 TypeOfField MEDCouplingFieldDiscretizationP1::getEnum() const
907 {
908   return TYPE;
909 }
910
911 /*!
912  * This method is simply called by MEDCouplingFieldDiscretization::deepCpy. It performs the deep copy of \a this.
913  *
914  * \sa MEDCouplingFieldDiscretization::deepCpy.
915  */
916 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationP1::clone() const
917 {
918   return new MEDCouplingFieldDiscretizationP1;
919 }
920
921 std::string MEDCouplingFieldDiscretizationP1::getStringRepr() const
922 {
923   return std::string(REPR);
924 }
925
926 const char *MEDCouplingFieldDiscretizationP1::getRepr() const
927 {
928   return REPR;
929 }
930
931 bool MEDCouplingFieldDiscretizationP1::isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const
932 {
933   if(!other)
934     {
935       reason="other spatial discretization is NULL, and this spatial discretization (P1) is defined.";
936       return false;
937     }
938   const MEDCouplingFieldDiscretizationP1 *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationP1 *>(other);
939   bool ret=otherC!=0;
940   if(!ret)
941     reason="Spatial discrtization of this is ON_NODES, which is not the case of other.";
942   return ret;
943 }
944
945 void MEDCouplingFieldDiscretizationP1::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
946 {
947   if(nat!=ConservativeVolumic)
948     throw INTERP_KERNEL::Exception("Invalid nature for P1 field  : expected ConservativeVolumic !");
949 }
950
951 MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationP1::getMeasureField(const MEDCouplingMesh *mesh, bool isAbs) const
952 {
953   if(!mesh)
954     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP1::getMeasureField : mesh instance specified is NULL !");
955   return mesh->getMeasureFieldOnNode(isAbs);
956 }
957
958 void MEDCouplingFieldDiscretizationP1::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
959 {
960   if(!mesh)
961     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP1::getValueOn : NULL input mesh !");
962   int id=mesh->getCellContainingPoint(loc,_precision);
963   if(id==-1)
964     throw INTERP_KERNEL::Exception("Specified point is detected outside of mesh : unable to apply P1::getValueOn !");
965   INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(id);
966   if(type!=INTERP_KERNEL::NORM_SEG2 && type!=INTERP_KERNEL::NORM_TRI3 && type!=INTERP_KERNEL::NORM_TETRA4)
967     throw INTERP_KERNEL::Exception("P1 getValueOn is not specified for not simplex cells !");
968   getValueInCell(mesh,id,arr,loc,res);
969 }
970
971 /*!
972  * This method localizes a point defined by 'loc' in a cell with id 'cellId' into mesh 'mesh'.
973  * The result is put into res expected to be of size at least arr->getNumberOfComponents()
974  */
975 void MEDCouplingFieldDiscretizationP1::getValueInCell(const MEDCouplingMesh *mesh, int cellId, const DataArrayDouble *arr, const double *loc, double *res) const
976 {
977   if(!mesh)
978     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP1::getValueInCell : NULL input mesh !");
979   std::vector<int> conn;
980   std::vector<double> coo;
981   mesh->getNodeIdsOfCell(cellId,conn);
982   for(std::vector<int>::const_iterator iter=conn.begin();iter!=conn.end();iter++)
983     mesh->getCoordinatesOfNode(*iter,coo);
984   int spaceDim=mesh->getSpaceDimension();
985   std::size_t nbOfNodes=conn.size();
986   std::vector<const double *> vec(nbOfNodes);
987   for(std::size_t i=0;i<nbOfNodes;i++)
988     vec[i]=&coo[i*spaceDim];
989   INTERP_KERNEL::AutoPtr<double> tmp=new double[nbOfNodes];
990   INTERP_KERNEL::barycentric_coords(vec,loc,tmp);
991   int sz=arr->getNumberOfComponents();
992   INTERP_KERNEL::AutoPtr<double> tmp2=new double[sz];
993   std::fill(res,res+sz,0.);
994   for(std::size_t i=0;i<nbOfNodes;i++)
995     {
996       arr->getTuple(conn[i],(double *)tmp2);
997       std::transform((double *)tmp2,((double *)tmp2)+sz,(double *)tmp2,std::bind2nd(std::multiplies<double>(),tmp[i]));
998       std::transform(res,res+sz,(double *)tmp2,res,std::plus<double>());
999     }
1000 }
1001
1002 DataArrayDouble *MEDCouplingFieldDiscretizationP1::getValueOnMulti(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, int nbOfPoints) const
1003 {
1004   if(!mesh)
1005     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationP1::getValueOnMulti : NULL input mesh !");
1006   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsArr,eltsIndexArr;
1007   mesh->getCellsContainingPoints(loc,nbOfPoints,_precision,eltsArr,eltsIndexArr);
1008   const int *elts(eltsArr->begin()),*eltsIndex(eltsIndexArr->begin());
1009   int spaceDim=mesh->getSpaceDimension();
1010   int nbOfComponents=arr->getNumberOfComponents();
1011   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
1012   ret->alloc(nbOfPoints,nbOfComponents);
1013   double *ptToFill=ret->getPointer();
1014   for(int i=0;i<nbOfPoints;i++)
1015     if(eltsIndex[i+1]-eltsIndex[i]>=1)
1016       getValueInCell(mesh,elts[eltsIndex[i]],arr,loc+i*spaceDim,ptToFill+i*nbOfComponents);
1017     else
1018       {
1019         std::ostringstream oss; oss << "Point #" << i << " with coordinates : (";
1020         std::copy(loc+i*spaceDim,loc+(i+1)*spaceDim,std::ostream_iterator<double>(oss,", "));
1021         oss << ") detected outside mesh : unable to apply P1::getValueOnMulti ! ";
1022         throw INTERP_KERNEL::Exception(oss.str().c_str());
1023       }
1024   return ret.retn();
1025 }
1026
1027 void MEDCouplingFieldDiscretizationP1::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
1028 {
1029   stream << "P1 spatial discretization.";
1030 }
1031
1032 MEDCouplingFieldDiscretizationPerCell::MEDCouplingFieldDiscretizationPerCell():_discr_per_cell(0)
1033 {
1034 }
1035
1036 MEDCouplingFieldDiscretizationPerCell::~MEDCouplingFieldDiscretizationPerCell()
1037 {
1038   if(_discr_per_cell)
1039     _discr_per_cell->decrRef();
1040 }
1041
1042 /*!
1043  * This constructor deep copies ParaMEDMEM::DataArrayInt instance from other (if any).
1044  */
1045 MEDCouplingFieldDiscretizationPerCell::MEDCouplingFieldDiscretizationPerCell(const MEDCouplingFieldDiscretizationPerCell& other, const int *startCellIds, const int *endCellIds):_discr_per_cell(0)
1046 {
1047   DataArrayInt *arr=other._discr_per_cell;
1048   if(arr)
1049     {
1050       if(startCellIds==0 && endCellIds==0)
1051         _discr_per_cell=arr->deepCpy();
1052       else
1053         _discr_per_cell=arr->selectByTupleIdSafe(startCellIds,endCellIds);
1054     }
1055 }
1056
1057 MEDCouplingFieldDiscretizationPerCell::MEDCouplingFieldDiscretizationPerCell(const MEDCouplingFieldDiscretizationPerCell& other, int beginCellIds, int endCellIds, int stepCellIds):_discr_per_cell(0)
1058 {
1059   DataArrayInt *arr=other._discr_per_cell;
1060   if(arr)
1061     {
1062       _discr_per_cell=arr->selectByTupleId2(beginCellIds,endCellIds,stepCellIds);
1063     }
1064 }
1065
1066 void MEDCouplingFieldDiscretizationPerCell::updateTime() const
1067 {
1068   if(_discr_per_cell)
1069     updateTimeWith(*_discr_per_cell);
1070 }
1071
1072 std::size_t MEDCouplingFieldDiscretizationPerCell::getHeapMemorySize() const
1073 {
1074   std::size_t ret=0;
1075   if(_discr_per_cell)
1076     ret+=_discr_per_cell->getHeapMemorySize();
1077   return ret;
1078 }
1079
1080 void MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception)
1081 {
1082   if(!_discr_per_cell)
1083     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell has no discretization per cell !");
1084   if(!mesh)
1085     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween : NULL input mesh or DataArray !");
1086   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1087   if(nbOfTuples!=mesh->getNumberOfCells())
1088     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell has a discretization per cell but it's not matching the underlying mesh !");
1089 }
1090
1091 bool MEDCouplingFieldDiscretizationPerCell::isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const
1092 {
1093   if(!other)
1094     {
1095       reason="other spatial discretization is NULL, and this spatial discretization (PerCell) is defined.";
1096       return false;
1097     }
1098   const MEDCouplingFieldDiscretizationPerCell *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationPerCell *>(other);
1099   if(!otherC)
1100     {
1101       reason="Spatial discretization of this is ON_GAUSS, which is not the case of other.";
1102       return false;
1103     }
1104   if(_discr_per_cell==0)
1105     return otherC->_discr_per_cell==0;
1106   if(otherC->_discr_per_cell==0)
1107     return false;
1108   bool ret=_discr_per_cell->isEqualIfNotWhy(*otherC->_discr_per_cell,reason);
1109   if(!ret)
1110     reason.insert(0,"Field discretization per cell DataArrayInt given the discid per cell :");
1111   return ret;
1112 }
1113
1114 bool MEDCouplingFieldDiscretizationPerCell::isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const
1115 {
1116   const MEDCouplingFieldDiscretizationPerCell *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationPerCell *>(other);
1117   if(!otherC)
1118     return false;
1119   if(_discr_per_cell==0)
1120     return otherC->_discr_per_cell==0;
1121   if(otherC->_discr_per_cell==0)
1122     return false;
1123   return _discr_per_cell->isEqualWithoutConsideringStr(*otherC->_discr_per_cell);
1124 }
1125
1126 /*!
1127  * This method is typically the first step of renumbering. The impact on _discr_per_cell is necessary here.
1128  * virtualy by this method.
1129  */
1130 void MEDCouplingFieldDiscretizationPerCell::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
1131 {
1132   int nbCells=_discr_per_cell->getNumberOfTuples();
1133   const int *array=old2NewBg;
1134   if(check)
1135     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
1136   //
1137   DataArrayInt *dpc=_discr_per_cell->renumber(array);
1138   _discr_per_cell->decrRef();
1139   _discr_per_cell=dpc;
1140   //
1141   if(check)
1142     free(const_cast<int *>(array));
1143 }
1144
1145 void MEDCouplingFieldDiscretizationPerCell::buildDiscrPerCellIfNecessary(const MEDCouplingMesh *mesh)
1146 {
1147   if(!mesh)
1148     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::buildDiscrPerCellIfNecessary : NULL input mesh !");
1149   if(!_discr_per_cell)
1150     {
1151       _discr_per_cell=DataArrayInt::New();
1152       int nbTuples=mesh->getNumberOfCells();
1153       _discr_per_cell->alloc(nbTuples,1);
1154       int *ptr=_discr_per_cell->getPointer();
1155       std::fill(ptr,ptr+nbTuples,DFT_INVALID_LOCID_VALUE);
1156     }
1157 }
1158
1159 void MEDCouplingFieldDiscretizationPerCell::checkNoOrphanCells() const throw(INTERP_KERNEL::Exception)
1160 {
1161   if(!_discr_per_cell)
1162     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::checkNoOrphanCells : no discretization defined !");
1163   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> test=_discr_per_cell->getIdsEqual(DFT_INVALID_LOCID_VALUE);
1164   if(test->getNumberOfTuples()!=0)
1165     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::checkNoOrphanCells : presence of orphan cells !");
1166 }
1167
1168 /*!
1169  * This method is useful when 'this' describes a field discretization with several gauss discretization on a \b same cell type.
1170  * For example same NORM_TRI3 cells having 6 gauss points and others with 12 gauss points.
1171  * This method returns 2 arrays with same size : the return value and 'locIds' output parameter.
1172  * 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.
1173  * The return vector contains a set of newly created instance to deal with.
1174  * The returned vector represents a \b partition of cells ids with a gauss discretization set.
1175  * 
1176  * If no descretization is set in 'this' and exception will be thrown.
1177  */
1178 std::vector<DataArrayInt *> MEDCouplingFieldDiscretizationPerCell::splitIntoSingleGaussDicrPerCellType(std::vector<int>& locIds) const throw(INTERP_KERNEL::Exception)
1179 {
1180   if(!_discr_per_cell)
1181     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::splitIntoSingleGaussDicrPerCellType : no descretization set !");
1182   return _discr_per_cell->partitionByDifferentValues(locIds);
1183 }
1184
1185 const DataArrayInt *MEDCouplingFieldDiscretizationPerCell::getArrayOfDiscIds() const
1186 {
1187   return _discr_per_cell;
1188 }
1189
1190 void MEDCouplingFieldDiscretizationPerCell::setArrayOfDiscIds(const DataArrayInt *adids) throw(INTERP_KERNEL::Exception)
1191 {
1192   if(adids!=_discr_per_cell)
1193     {
1194       if(_discr_per_cell)
1195         _discr_per_cell->decrRef();
1196       _discr_per_cell=const_cast<DataArrayInt *>(adids);
1197       if(_discr_per_cell)
1198         _discr_per_cell->incrRef();
1199       declareAsNew();
1200     }
1201 }
1202
1203 MEDCouplingFieldDiscretizationGauss::MEDCouplingFieldDiscretizationGauss()
1204 {
1205 }
1206
1207 MEDCouplingFieldDiscretizationGauss::MEDCouplingFieldDiscretizationGauss(const MEDCouplingFieldDiscretizationGauss& other, const int *startCellIds, const int *endCellIds):MEDCouplingFieldDiscretizationPerCell(other,startCellIds,endCellIds),_loc(other._loc)
1208 {
1209 }
1210
1211 MEDCouplingFieldDiscretizationGauss::MEDCouplingFieldDiscretizationGauss(const MEDCouplingFieldDiscretizationGauss& other, int beginCellIds, int endCellIds, int stepCellIds):MEDCouplingFieldDiscretizationPerCell(other,beginCellIds,endCellIds,stepCellIds),_loc(other._loc)
1212 {
1213 }
1214
1215 TypeOfField MEDCouplingFieldDiscretizationGauss::getEnum() const
1216 {
1217   return TYPE;
1218 }
1219
1220 bool MEDCouplingFieldDiscretizationGauss::isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const
1221 {
1222   if(!other)
1223     {
1224       reason="other spatial discretization is NULL, and this spatial discretization (Gauss) is defined.";
1225       return false;
1226     }
1227   const MEDCouplingFieldDiscretizationGauss *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationGauss *>(other);
1228   if(!otherC)
1229     {
1230       reason="Spatial discrtization of this is ON_GAUSS, which is not the case of other.";
1231       return false;
1232     }
1233   if(!MEDCouplingFieldDiscretizationPerCell::isEqualIfNotWhy(other,eps,reason))
1234     return false;
1235   if(_loc.size()!=otherC->_loc.size())
1236     {
1237       reason="Gauss spatial discretization : localization sizes differ";
1238       return false;
1239     }
1240   std::size_t sz=_loc.size();
1241   for(std::size_t i=0;i<sz;i++)
1242     if(!_loc[i].isEqual(otherC->_loc[i],eps))
1243       {
1244         std::ostringstream oss; oss << "Gauss spatial discretization : Localization #" << i << " differ from this to other.";
1245         reason=oss.str();
1246         return false;
1247       }
1248   return true;
1249 }
1250
1251 bool MEDCouplingFieldDiscretizationGauss::isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const
1252 {
1253   const MEDCouplingFieldDiscretizationGauss *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationGauss *>(other);
1254   if(!otherC)
1255     return false;
1256   if(!MEDCouplingFieldDiscretizationPerCell::isEqualWithoutConsideringStr(other,eps))
1257     return false;
1258   if(_loc.size()!=otherC->_loc.size())
1259     return false;
1260   std::size_t sz=_loc.size();
1261   for(std::size_t i=0;i<sz;i++)
1262     if(!_loc[i].isEqual(otherC->_loc[i],eps))
1263       return false;
1264   return true;
1265 }
1266
1267 /*!
1268  * This method is simply called by MEDCouplingFieldDiscretization::deepCpy. It performs the deep copy of \a this.
1269  *
1270  * \sa MEDCouplingFieldDiscretization::deepCpy.
1271  */
1272 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationGauss::clone() const
1273 {
1274   return new MEDCouplingFieldDiscretizationGauss(*this);
1275 }
1276
1277 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationGauss::clonePart(const int *startCellIds, const int *endCellIds) const
1278 {
1279   return new MEDCouplingFieldDiscretizationGauss(*this,startCellIds,endCellIds);
1280 }
1281
1282 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationGauss::clonePartRange(int beginCellIds, int endCellIds, int stepCellIds) const
1283 {
1284   return new MEDCouplingFieldDiscretizationGauss(*this,beginCellIds,endCellIds,stepCellIds);
1285 }
1286
1287 std::string MEDCouplingFieldDiscretizationGauss::getStringRepr() const
1288 {
1289   std::ostringstream oss; oss << REPR << "." << std::endl;
1290   if(_discr_per_cell)
1291     {
1292       if(_discr_per_cell->isAllocated())
1293         {
1294           oss << "Discretization per cell : ";
1295           std::copy(_discr_per_cell->begin(),_discr_per_cell->end(),std::ostream_iterator<int>(oss,", "));
1296           oss << std::endl;
1297         }
1298     }
1299   oss << "Presence of " << _loc.size() << " localizations." << std::endl;
1300   int i=0;
1301   for(std::vector<MEDCouplingGaussLocalization>::const_iterator it=_loc.begin();it!=_loc.end();it++,i++)
1302     {
1303       oss << "+++++ Localization #" << i << " +++++" << std::endl;
1304       oss << (*it).getStringRepr();
1305       oss << "++++++++++" << std::endl;
1306     }
1307   return oss.str();
1308 }
1309
1310 std::size_t MEDCouplingFieldDiscretizationGauss::getHeapMemorySize() const
1311 {
1312   std::size_t ret=_loc.capacity()*sizeof(MEDCouplingGaussLocalization);
1313   for(std::vector<MEDCouplingGaussLocalization>::const_iterator it=_loc.begin();it!=_loc.end();it++)
1314     ret+=(*it).getHeapMemorySize();
1315   return MEDCouplingFieldDiscretizationPerCell::getHeapMemorySize()+ret;
1316 }
1317
1318 const char *MEDCouplingFieldDiscretizationGauss::getRepr() const
1319 {
1320   return REPR;
1321 }
1322
1323 /*!
1324  * mesh is not used here. It is not a bug !
1325  */
1326 int MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode(const MEDCouplingMesh *mesh, const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
1327 {
1328   if(!_discr_per_cell || !_discr_per_cell->isAllocated() || _discr_per_cell->getNumberOfComponents()!=1)
1329     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode");
1330   if(code.size()%3!=0)
1331     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode : invalid input code !");
1332   int nbOfSplit=(int)idsPerType.size();
1333   int nbOfTypes=(int)code.size()/3;
1334   int ret=0;
1335   for(int i=0;i<nbOfTypes;i++)
1336     {
1337       int nbOfEltInChunk=code[3*i+1];
1338       if(nbOfEltInChunk<0)
1339         throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode : invalid input code ! presence of negative value in a type !");
1340       int pos=code[3*i+2];
1341       if(pos!=-1)
1342         {
1343           if(pos<0 || pos>=nbOfSplit)
1344             {
1345               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode : input code points to pos " << pos << " in typeid " << i << " ! Should be in [0," << nbOfSplit << ") !";
1346               throw INTERP_KERNEL::Exception(oss.str().c_str());
1347             }
1348           const DataArrayInt *ids(idsPerType[pos]);
1349           if(!ids || !ids->isAllocated() || ids->getNumberOfComponents()!=1 || ids->getNumberOfTuples()!=nbOfEltInChunk || ids->getMinValueInArray()<0)
1350             {
1351               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode : input pfl chunck at pos " << pos << " should have " << i << " tuples and one component and with ids all >=0 !";
1352               throw INTERP_KERNEL::Exception(oss.str().c_str());
1353             }
1354         }
1355       ret+=nbOfEltInChunk;
1356     }
1357   if(ret!=_discr_per_cell->getNumberOfTuples())
1358     {
1359       std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getNumberOfTuplesExpectedRegardingCode : input code points to " << ret << " cells whereas discretization percell array lgth is " <<  _discr_per_cell->getNumberOfTuples() << " !";
1360     }
1361   return getNumberOfTuples(0);//0 is not an error ! It is to be sure that input mesh is not used
1362 }
1363
1364 int MEDCouplingFieldDiscretizationGauss::getNumberOfTuples(const MEDCouplingMesh *) const throw(INTERP_KERNEL::Exception)
1365 {
1366   int ret=0;
1367   if (_discr_per_cell == 0)
1368     throw INTERP_KERNEL::Exception("Discretization is not initialized!");
1369   const int *dcPtr=_discr_per_cell->getConstPointer();
1370   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1371   int maxSz=(int)_loc.size();
1372   for(const int *w=dcPtr;w!=dcPtr+nbOfTuples;w++)
1373     {
1374       if(*w>=0 && *w<maxSz)
1375         ret+=_loc[*w].getNumberOfGaussPt();
1376       else
1377         {
1378           std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getNumberOfTuples : At cell #" << std::distance(dcPtr,w) << " localization id is " << *w << " should be in [0," << maxSz << ") !";
1379           throw INTERP_KERNEL::Exception(oss.str().c_str());
1380         }
1381     }
1382   return ret;
1383 }
1384
1385 int MEDCouplingFieldDiscretizationGauss::getNumberOfMeshPlaces(const MEDCouplingMesh *mesh) const
1386 {
1387   if(!mesh)
1388     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getNumberOfMeshPlaces : NULL input mesh !");
1389   return mesh->getNumberOfCells();
1390 }
1391
1392 /*!
1393  * This method is redevelopped for performance reasons, but it is equivalent to a call to MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField
1394  * and a call to DataArrayDouble::computeOffsets2 on the returned array.
1395  */
1396 DataArrayInt *MEDCouplingFieldDiscretizationGauss::getOffsetArr(const MEDCouplingMesh *mesh) const
1397 {
1398   if(!mesh)
1399     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getOffsetArr : NULL input mesh !");
1400   int nbOfTuples=mesh->getNumberOfCells();
1401   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1402   ret->alloc(nbOfTuples+1,1);
1403   int *retPtr=ret->getPointer();
1404   const int *start=_discr_per_cell->getConstPointer();
1405   if(_discr_per_cell->getNumberOfTuples()!=nbOfTuples)
1406     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getOffsetArr : mismatch between the mesh and the discretization ids array length !");
1407   int maxPossible=(int)_loc.size();
1408   retPtr[0]=0;
1409   for(int i=0;i<nbOfTuples;i++,start++)
1410     {
1411       if(*start>=0 && *start<maxPossible)
1412         retPtr[i+1]=retPtr[i]+_loc[*start].getNumberOfGaussPt();
1413       else
1414         {
1415           std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getOffsetArr : At position #" << i << " the locid = " << *start << " whereas it should be in [0," << maxPossible << ") !";
1416           throw INTERP_KERNEL::Exception(oss.str().c_str());
1417         }
1418     }
1419   return ret.retn();
1420 }
1421
1422 void MEDCouplingFieldDiscretizationGauss::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArray *>& arrays,
1423                                                                 const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
1424 {
1425   if(!mesh)
1426     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::renumberArraysForCell : NULL input mesh !");
1427   const int *array=old2NewBg;
1428   if(check)
1429     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+mesh->getNumberOfCells());
1430   int nbOfCells=_discr_per_cell->getNumberOfTuples();
1431   int nbOfTuples=getNumberOfTuples(0);
1432   const int *dcPtr=_discr_per_cell->getConstPointer();
1433   int *array2=new int[nbOfTuples];//stores the final conversion array old2New to give to arrays in renumberInPlace.
1434   int *array3=new int[nbOfCells];//store for each cell in present dcp array (already renumbered) the offset needed by each cell in new numbering.
1435   array3[0]=0;
1436   for(int i=1;i<nbOfCells;i++)
1437     array3[i]=array3[i-1]+_loc[dcPtr[i-1]].getNumberOfGaussPt();
1438   int j=0;
1439   for(int i=0;i<nbOfCells;i++)
1440     {
1441       int nbOfGaussPt=_loc[dcPtr[array[i]]].getNumberOfGaussPt();
1442       for(int k=0;k<nbOfGaussPt;k++,j++)
1443         array2[j]=array3[array[i]]+k;
1444     }
1445   delete [] array3;
1446   for(std::vector<DataArray *>::const_iterator it=arrays.begin();it!=arrays.end();it++)
1447     if(*it)
1448       (*it)->renumberInPlace(array2);
1449   delete [] array2;
1450   if(check)
1451     free(const_cast<int*>(array));
1452 }
1453
1454 DataArrayDouble *MEDCouplingFieldDiscretizationGauss::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const
1455 {
1456   if(!mesh)
1457     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getLocalizationOfDiscValues : NULL input mesh !");
1458   checkNoOrphanCells();
1459   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> umesh=mesh->buildUnstructured();//in general do nothing
1460   int nbOfTuples=getNumberOfTuples(mesh);
1461   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
1462   int spaceDim=mesh->getSpaceDimension();
1463   ret->alloc(nbOfTuples,spaceDim);
1464   std::vector< int > locIds;
1465   std::vector<DataArrayInt *> parts=splitIntoSingleGaussDicrPerCellType(locIds);
1466   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > parts2(parts.size());
1467   std::copy(parts.begin(),parts.end(),parts2.begin());
1468   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=buildNbOfGaussPointPerCellField();
1469   offsets->computeOffsets();
1470   const int *ptrOffsets=offsets->getConstPointer();
1471   const double *coords=umesh->getCoords()->getConstPointer();
1472   const int *connI=umesh->getNodalConnectivityIndex()->getConstPointer();
1473   const int *conn=umesh->getNodalConnectivity()->getConstPointer();
1474   double *valsToFill=ret->getPointer();
1475   for(std::size_t i=0;i<parts2.size();i++)
1476     {
1477       INTERP_KERNEL::GaussCoords calculator;
1478       //
1479       const MEDCouplingGaussLocalization& cli=_loc[locIds[i]];//curLocInfo
1480       INTERP_KERNEL::NormalizedCellType typ=cli.getType();
1481       const std::vector<double>& wg=cli.getWeights();
1482       calculator.addGaussInfo(typ,INTERP_KERNEL::CellModel::GetCellModel(typ).getDimension(),
1483                                   &cli.getGaussCoords()[0],(int)wg.size(),&cli.getRefCoords()[0],
1484                                   INTERP_KERNEL::CellModel::GetCellModel(typ).getNumberOfNodes());
1485       //
1486       int nbt=parts2[i]->getNumberOfTuples();
1487       for(const int *w=parts2[i]->getConstPointer();w!=parts2[i]->getConstPointer()+nbt;w++)
1488         calculator.calculateCoords(cli.getType(),coords,spaceDim,conn+connI[*w]+1,valsToFill+spaceDim*(ptrOffsets[*w]));
1489     }
1490   ret->copyStringInfoFrom(*umesh->getCoords());
1491   return ret.retn();
1492 }
1493
1494 void MEDCouplingFieldDiscretizationGauss::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *tupleIdsBg, const int *tupleIdsEnd,
1495                                                                              DataArrayInt *&cellRestriction, DataArrayInt *&trueTupleRestriction) const throw(INTERP_KERNEL::Exception)
1496 {
1497   if(!mesh)
1498     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::computeMeshRestrictionFromTupleIds : NULL input mesh !");
1499   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=DataArrayInt::New(); tmp->alloc((int)std::distance(tupleIdsBg,tupleIdsEnd),1);
1500   std::copy(tupleIdsBg,tupleIdsEnd,tmp->getPointer());
1501   tmp->sort(true);
1502   tmp=tmp->buildUnique();
1503   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=buildNbOfGaussPointPerCellField();
1504   nbOfNodesPerCell->computeOffsets2();
1505   nbOfNodesPerCell->searchRangesInListOfIds(tmp,cellRestriction,trueTupleRestriction);
1506 }
1507
1508 /*!
1509  * Empty : not a bug
1510  */
1511 void MEDCouplingFieldDiscretizationGauss::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
1512 {
1513 }
1514
1515 void MEDCouplingFieldDiscretizationGauss::getTinySerializationIntInformation(std::vector<int>& tinyInfo) const
1516 {
1517   int val=-1;
1518   if(_discr_per_cell)
1519     val=_discr_per_cell->getNumberOfTuples();
1520   tinyInfo.push_back(val);
1521   tinyInfo.push_back((int)_loc.size());
1522   if(_loc.empty())
1523     tinyInfo.push_back(-1);
1524   else
1525     tinyInfo.push_back(_loc[0].getDimension());
1526   for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++)
1527     (*iter).pushTinySerializationIntInfo(tinyInfo);
1528 }
1529
1530 void MEDCouplingFieldDiscretizationGauss::getTinySerializationDbleInformation(std::vector<double>& tinyInfo) const
1531 {
1532   for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++)
1533     (*iter).pushTinySerializationDblInfo(tinyInfo);
1534 }
1535
1536 void MEDCouplingFieldDiscretizationGauss::getSerializationIntArray(DataArrayInt *& arr) const
1537 {
1538   arr=0;
1539   if(_discr_per_cell)
1540     arr=_discr_per_cell;
1541 }
1542
1543 void MEDCouplingFieldDiscretizationGauss::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *& arr)
1544 {
1545   int val=tinyInfo[0];
1546   if(val>=0)
1547     {
1548       _discr_per_cell=DataArrayInt::New();
1549       _discr_per_cell->alloc(val,1);
1550     }
1551   else
1552     _discr_per_cell=0;
1553   arr=_discr_per_cell;
1554   int nbOfLoc=tinyInfo[1];
1555   _loc.clear();
1556   int dim=tinyInfo[2];
1557   int delta=-1;
1558   if(nbOfLoc>0)
1559     delta=((int)tinyInfo.size()-3)/nbOfLoc;
1560   for(int i=0;i<nbOfLoc;i++)
1561     {
1562       std::vector<int> tmp(tinyInfo.begin()+3+i*delta,tinyInfo.begin()+3+(i+1)*delta);
1563       MEDCouplingGaussLocalization elt=MEDCouplingGaussLocalization::BuildNewInstanceFromTinyInfo(dim,tmp);
1564       _loc.push_back(elt);
1565     }
1566 }
1567
1568 void MEDCouplingFieldDiscretizationGauss::finishUnserialization(const std::vector<double>& tinyInfo)
1569 {
1570   double *tmp=new double[tinyInfo.size()];
1571   std::copy(tinyInfo.begin(),tinyInfo.end(),tmp);
1572   const double *work=tmp;
1573   for(std::vector<MEDCouplingGaussLocalization>::iterator iter=_loc.begin();iter!=_loc.end();iter++)
1574     work=(*iter).fillWithValues(work);
1575   delete [] tmp;
1576 }
1577
1578 double MEDCouplingFieldDiscretizationGauss::getIJK(const MEDCouplingMesh *mesh, const DataArrayDouble *da,
1579                                                    int cellId, int nodeIdInCell, int compoId) const throw(INTERP_KERNEL::Exception)
1580 {
1581   int offset=getOffsetOfCell(cellId);
1582   return da->getIJ(offset+nodeIdInCell,compoId);
1583 }
1584
1585 void MEDCouplingFieldDiscretizationGauss::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception)
1586 {
1587   if(!mesh || !da)
1588     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::checkCoherencyBetween : NULL input mesh or DataArray !");
1589   MEDCouplingFieldDiscretizationPerCell::checkCoherencyBetween(mesh,da);
1590   for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++)
1591     (*iter).checkCoherency();
1592   int nbOfDesc=(int)_loc.size();
1593   int nbOfCells=mesh->getNumberOfCells();
1594   const int *dc=_discr_per_cell->getConstPointer();
1595   for(int i=0;i<nbOfCells;i++)
1596     {
1597       if(dc[i]>=nbOfDesc)
1598         {
1599           std::ostringstream oss; oss << "Cell # " << i << " of mesh \"" << mesh->getName() << "\" has an undefined gauss location ! Should never happend !";
1600           throw INTERP_KERNEL::Exception(oss.str().c_str());
1601         }
1602       if(dc[i]<0)
1603         {
1604           std::ostringstream oss; oss << "Cell # " << i << " of mesh \"" << mesh->getName() << "\" has no gauss location !";
1605           throw INTERP_KERNEL::Exception(oss.str().c_str());
1606         }
1607       if(mesh->getTypeOfCell(i)!=_loc[dc[i]].getType())
1608         {
1609           std::ostringstream oss; oss << "Types of mesh and gauss location mismatch for cell # " << i;
1610           throw INTERP_KERNEL::Exception(oss.str().c_str());
1611         }
1612     }
1613   int nbOfTuples=getNumberOfTuples(mesh);
1614   if(nbOfTuples!=da->getNumberOfTuples())
1615     {
1616       std::ostringstream oss; oss << "Invalid number of tuples in the array : expecting " << nbOfTuples << " !";
1617       throw INTERP_KERNEL::Exception(oss.str().c_str());
1618     }
1619 }
1620
1621 MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationGauss::getMeasureField(const MEDCouplingMesh *mesh, bool isAbs) const
1622 {
1623   if(!mesh)
1624     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getMeasureField : mesh instance specified is NULL !");
1625   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> vol=mesh->getMeasureField(isAbs);
1626   const double *volPtr=vol->getArray()->begin();
1627   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_GAUSS_PT);
1628   ret->setMesh(mesh);
1629   ret->setDiscretization(const_cast<MEDCouplingFieldDiscretizationGauss *>(this));
1630   if(!_discr_per_cell)
1631     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getMeasureField : no discr per cell array not defined ! spatial localization is incorrect !");
1632   _discr_per_cell->checkAllocated();
1633   if(_discr_per_cell->getNumberOfComponents()!=1)
1634     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::getMeasureField : no discr per cell array defined but with nb of components different from 1 !");
1635   if(_discr_per_cell->getNumberOfTuples()!=vol->getNumberOfTuples())
1636     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 !");
1637   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offset=getOffsetArr(mesh);
1638   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New(); arr->alloc(getNumberOfTuples(mesh),1);
1639   ret->setArray(arr);
1640   double *arrPtr=arr->getPointer();
1641   const int *offsetPtr=offset->getConstPointer();
1642   int maxGaussLoc=(int)_loc.size();
1643   std::vector<int> locIds;
1644   std::vector<DataArrayInt *> ids=splitIntoSingleGaussDicrPerCellType(locIds);
1645   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ids2(ids.size()); std::copy(ids.begin(),ids.end(),ids2.begin());
1646   for(std::size_t i=0;i<locIds.size();i++)
1647     {
1648       const DataArrayInt *curIds=ids[i];
1649       int locId=locIds[i];
1650       if(locId>=0 && locId<maxGaussLoc)
1651         {
1652           const MEDCouplingGaussLocalization& loc=_loc[locId];
1653           int nbOfGaussPt=loc.getNumberOfGaussPt();
1654           INTERP_KERNEL::AutoPtr<double> weights=new double[nbOfGaussPt];
1655           double sum=std::accumulate(loc.getWeights().begin(),loc.getWeights().end(),0.);
1656           std::transform(loc.getWeights().begin(),loc.getWeights().end(),(double *)weights,std::bind2nd(std::multiplies<double>(),1./sum));
1657           for(const int *cellId=curIds->begin();cellId!=curIds->end();cellId++)
1658             for(int j=0;j<nbOfGaussPt;j++)
1659               arrPtr[offsetPtr[*cellId]+j]=weights[j]*volPtr[*cellId];
1660         }
1661       else
1662         {
1663           std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::getMeasureField : Presence of localization id " << locId << " in cell #" << curIds->getIJ(0,0) << " ! Must be in [0," << maxGaussLoc << ") !";
1664           throw INTERP_KERNEL::Exception(oss.str().c_str());
1665         }
1666     }
1667   ret->synchronizeTimeWithSupport();
1668   return ret.retn();
1669 }
1670
1671 void MEDCouplingFieldDiscretizationGauss::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
1672 {
1673   throw INTERP_KERNEL::Exception("Not implemented yet !");
1674 }
1675
1676 void MEDCouplingFieldDiscretizationGauss::getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const
1677 {
1678   throw INTERP_KERNEL::Exception("getValueOnPos(i,j,k) : Not applyable for Gauss points !");
1679 }
1680
1681 DataArrayDouble *MEDCouplingFieldDiscretizationGauss::getValueOnMulti(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, int nbOfPoints) const
1682 {
1683   throw INTERP_KERNEL::Exception("getValueOnMulti : Not implemented yet for gauss points !");
1684 }
1685
1686 MEDCouplingMesh *MEDCouplingFieldDiscretizationGauss::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
1687 {
1688   if(!mesh)
1689     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildSubMeshData : NULL input mesh !");
1690   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diSafe=computeTupleIdsToSelectFromCellIds(mesh,start,end);
1691   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPart(start,end);
1692   di=diSafe.retn();
1693   return ret.retn();
1694 }
1695
1696 /*!
1697  * This method is strictly equivalent to MEDCouplingFieldDiscretizationGauss::buildSubMeshData except that it is optimized for input defined as a range of cell ids.
1698  * 
1699  * \param [out] beginOut Valid only if \a di is NULL
1700  * \param [out] endOut Valid only if \a di is NULL
1701  * \param [out] stepOut Valid only if \a di is NULL
1702  * \param [out] di is an array returned that specifies entity ids (nodes, cells, Gauss points... ) in array if no output range is foundable.
1703  *
1704  * \sa MEDCouplingFieldDiscretizationGauss::buildSubMeshData
1705  */
1706 MEDCouplingMesh *MEDCouplingFieldDiscretizationGauss::buildSubMeshDataRange(const MEDCouplingMesh *mesh, int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt *&di) const
1707 {
1708   if(stepCellIds!=1)//even for stepCellIds==-1 the output will not be a range
1709     return MEDCouplingFieldDiscretization::buildSubMeshDataRange(mesh,beginCellIds,endCellIds,stepCellIds,beginOut,endOut,stepOut,di);
1710   if(!mesh)
1711     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildSubMeshDataRange : NULL input mesh !");
1712   if(!_discr_per_cell)
1713     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildSubMeshDataRange : no discretization array set !");
1714   di=0; beginOut=0; endOut=0; stepOut=stepCellIds;
1715   const char msg[]="MEDCouplingFieldDiscretizationGauss::buildSubMeshDataRange : cell #";
1716   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1717   const int *w=_discr_per_cell->begin();
1718   int nbMaxOfLocId=(int)_loc.size();
1719   for(int i=0;i<nbOfTuples;i++,w++)
1720     {
1721       if(*w!=DFT_INVALID_LOCID_VALUE)
1722         {
1723           if(*w>=0 && *w<nbMaxOfLocId)
1724             {
1725               int delta=_loc[*w].getNumberOfGaussPt();
1726               if(i<beginCellIds)
1727                 beginOut+=delta;
1728               endOut+=delta;
1729               if(i>=endCellIds)
1730                 break;
1731             }
1732           else
1733             { std::ostringstream oss; oss << msg << i << " has invalid id (" << *w << ") ! Should be in [0," << nbMaxOfLocId << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
1734         }
1735       else
1736         { std::ostringstream oss; oss << msg << i << " is detected as orphan !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
1737     }
1738   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPartRange(beginCellIds,endCellIds,stepCellIds);
1739   return ret.retn();
1740 }
1741
1742 /*!
1743  * This method returns a tuple ids selection from cell ids selection [start;end).
1744  * This method is called by MEDCouplingFieldDiscretizationGauss::buildSubMeshData to return parameter \b di.
1745  *
1746  * \return a newly allocated array containing ids to select into the DataArrayDouble of the field.
1747  * 
1748  */
1749 DataArrayInt *MEDCouplingFieldDiscretizationGauss::computeTupleIdsToSelectFromCellIds(const MEDCouplingMesh *mesh, const int *startCellIds, const int *endCellIds) const
1750 {
1751   if(!mesh)
1752     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::computeTupleIdsToSelectFromCellIds : null mesh !");
1753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=buildNbOfGaussPointPerCellField();//check of _discr_per_cell not NULL pointer
1754   int nbOfCells=mesh->getNumberOfCells();
1755   if(_discr_per_cell->getNumberOfTuples()!=nbOfCells)
1756     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::computeTupleIdsToSelectFromCellIds : mismatch of nb of tuples of cell ids array and number of cells !");
1757   nbOfNodesPerCell->computeOffsets2();
1758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> sel=DataArrayInt::New(); sel->useArray(startCellIds,false,CPP_DEALLOC,(int)std::distance(startCellIds,endCellIds),1);
1759   return sel->buildExplicitArrByRanges(nbOfNodesPerCell);
1760 }
1761
1762 /*!
1763  * No implementation needed !
1764  */
1765 void MEDCouplingFieldDiscretizationGauss::renumberValuesOnNodes(double , const int *, int newNbOfNodes, DataArrayDouble *) const
1766 {
1767 }
1768
1769 void MEDCouplingFieldDiscretizationGauss::renumberValuesOnCells(double epsOnVals, const MEDCouplingMesh *mesh, const int *old2New, int newSz, DataArrayDouble *arr) const
1770 {
1771   throw INTERP_KERNEL::Exception("Not implemented yet !");
1772 }
1773
1774 void MEDCouplingFieldDiscretizationGauss::renumberValuesOnCellsR(const MEDCouplingMesh *mesh, const int *new2old, int newSz, DataArrayDouble *arr) const
1775 {
1776   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 !");
1777 }
1778
1779 void MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnType(const MEDCouplingMesh *mesh, INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
1780                                                                      const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
1781 {
1782   if(!mesh)
1783     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnType : NULL input mesh !");
1784   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1785   if((int)cm.getDimension()!=mesh->getMeshDimension())
1786     {
1787       std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnType : mismatch of dimensions ! MeshDim==" << mesh->getMeshDimension();
1788       oss << " whereas Type '" << cm.getRepr() << "' has dimension " << cm.getDimension() << " !";
1789       throw INTERP_KERNEL::Exception(oss.str().c_str());
1790     }
1791   buildDiscrPerCellIfNecessary(mesh);
1792   int id=(int)_loc.size();
1793   MEDCouplingGaussLocalization elt(type,refCoo,gsCoo,wg);
1794   _loc.push_back(elt);
1795   int *ptr=_discr_per_cell->getPointer();
1796   int nbCells=mesh->getNumberOfCells();
1797   for(int i=0;i<nbCells;i++)
1798     if(mesh->getTypeOfCell(i)==type)
1799       ptr[i]=id;
1800   zipGaussLocalizations();
1801 }
1802
1803 void MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnCells(const MEDCouplingMesh *mesh, const int *begin, const int *end, const std::vector<double>& refCoo,
1804                                                                       const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
1805 {
1806   if(!mesh)
1807     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnCells : NULL input mesh !");
1808   buildDiscrPerCellIfNecessary(mesh);
1809   if(std::distance(begin,end)<1)
1810     throw INTERP_KERNEL::Exception("Size of [begin,end) must be equal or greater than 1 !");
1811   INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(*begin);
1812   MEDCouplingGaussLocalization elt(type,refCoo,gsCoo,wg);
1813   int id=(int)_loc.size();
1814   int *ptr=_discr_per_cell->getPointer();
1815   for(const int *w=begin+1;w!=end;w++)
1816     {
1817       if(mesh->getTypeOfCell(*w)!=type)
1818         {
1819           std::ostringstream oss; oss << "The cell with id " << *w << " has been detected to be incompatible in the [begin,end) array specified !";
1820           throw INTERP_KERNEL::Exception(oss.str().c_str());
1821         }
1822     }
1823   //
1824   for(const int *w2=begin;w2!=end;w2++)
1825     ptr[*w2]=id;
1826   //
1827   _loc.push_back(elt);
1828   zipGaussLocalizations();
1829 }
1830
1831 void MEDCouplingFieldDiscretizationGauss::clearGaussLocalizations() throw(INTERP_KERNEL::Exception)
1832 {
1833   if(_discr_per_cell)
1834     {
1835       _discr_per_cell->decrRef();
1836       _discr_per_cell=0;
1837     }
1838   _loc.clear();
1839 }
1840
1841 void MEDCouplingFieldDiscretizationGauss::setGaussLocalization(int locId, const MEDCouplingGaussLocalization& loc) throw(INTERP_KERNEL::Exception)
1842 {
1843   if(locId<0)
1844     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::setGaussLocalization : localization id has to be >=0 !");
1845   int sz=(int)_loc.size();
1846   MEDCouplingGaussLocalization gLoc(INTERP_KERNEL::NORM_ERROR);
1847   if(locId>=sz)
1848     _loc.resize(locId+1,gLoc);
1849   _loc[locId]=loc;
1850 }
1851
1852 void MEDCouplingFieldDiscretizationGauss::resizeLocalizationVector(int newSz) throw(INTERP_KERNEL::Exception)
1853 {
1854   if(newSz<0)
1855     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::resizeLocalizationVector : new size has to be >=0 !");
1856   MEDCouplingGaussLocalization gLoc(INTERP_KERNEL::NORM_ERROR);
1857   _loc.resize(newSz,gLoc);
1858 }
1859
1860 MEDCouplingGaussLocalization& MEDCouplingFieldDiscretizationGauss::getGaussLocalization(int locId) throw(INTERP_KERNEL::Exception)
1861 {
1862   checkLocalizationId(locId);
1863   return _loc[locId];
1864 }
1865
1866 int MEDCouplingFieldDiscretizationGauss::getNbOfGaussLocalization() const throw(INTERP_KERNEL::Exception)
1867 {
1868   return (int)_loc.size();
1869 }
1870
1871 int MEDCouplingFieldDiscretizationGauss::getGaussLocalizationIdOfOneCell(int cellId) const throw(INTERP_KERNEL::Exception)
1872 {
1873   if(!_discr_per_cell)
1874     throw INTERP_KERNEL::Exception("No Gauss localization still set !");
1875   int locId=_discr_per_cell->begin()[cellId];
1876   if(locId<0)
1877     throw INTERP_KERNEL::Exception("No Gauss localization set for the specified cell !");
1878   return locId;
1879 }
1880
1881 int MEDCouplingFieldDiscretizationGauss::getGaussLocalizationIdOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
1882 {
1883   std::set<int> ret=getGaussLocalizationIdsOfOneType(type);
1884   if(ret.empty())
1885     throw INTERP_KERNEL::Exception("No gauss discretization found for the specified type !");
1886   if(ret.size()>1)
1887     throw INTERP_KERNEL::Exception("Several gauss discretizations have been found for the specified type !");
1888   return *ret.begin();
1889 }
1890
1891 std::set<int> MEDCouplingFieldDiscretizationGauss::getGaussLocalizationIdsOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
1892 {
1893   if(!_discr_per_cell)
1894     throw INTERP_KERNEL::Exception("No Gauss localization still set !");
1895   std::set<int> ret;
1896   int id=0;
1897   for(std::vector<MEDCouplingGaussLocalization>::const_iterator iter=_loc.begin();iter!=_loc.end();iter++,id++)
1898     if((*iter).getType()==type)
1899       ret.insert(id);
1900   return ret;
1901 }
1902
1903 void MEDCouplingFieldDiscretizationGauss::getCellIdsHavingGaussLocalization(int locId, std::vector<int>& cellIds) const throw(INTERP_KERNEL::Exception)
1904 {
1905   if(locId<0 || locId>=(int)_loc.size())
1906     throw INTERP_KERNEL::Exception("Invalid locId given : must be in range [0:getNbOfGaussLocalization()) !");
1907   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1908   const int *ptr=_discr_per_cell->getConstPointer();
1909   for(int i=0;i<nbOfTuples;i++)
1910     if(ptr[i]==locId)
1911       cellIds.push_back(i);
1912 }
1913
1914 const MEDCouplingGaussLocalization& MEDCouplingFieldDiscretizationGauss::getGaussLocalization(int locId) const throw(INTERP_KERNEL::Exception)
1915 {
1916   checkLocalizationId(locId);
1917   return _loc[locId];
1918 }
1919
1920 void MEDCouplingFieldDiscretizationGauss::checkLocalizationId(int locId) const throw(INTERP_KERNEL::Exception)
1921 {
1922   if(locId<0 || locId>=(int)_loc.size())
1923     throw INTERP_KERNEL::Exception("Invalid locId given : must be in range [0:getNbOfGaussLocalization()) !");
1924 }
1925
1926 int MEDCouplingFieldDiscretizationGauss::getOffsetOfCell(int cellId) const throw(INTERP_KERNEL::Exception)
1927 {
1928   int ret=0;
1929   const int *start=_discr_per_cell->getConstPointer();
1930   for(const int *w=start;w!=start+cellId;w++)
1931     ret+=_loc[*w].getNumberOfGaussPt();
1932   return ret;
1933 }
1934
1935 /*!
1936  * This method do the assumption that there is no orphan cell. If there is an exception is thrown.
1937  * This method makes the assumption too that '_discr_per_cell' is defined. If not an exception is thrown.
1938  * This method returns a newly created array with number of tuples equals to '_discr_per_cell->getNumberOfTuples' and number of components equal to 1.
1939  * The i_th tuple in returned array is the number of gauss point if the corresponding cell.
1940  */
1941 DataArrayInt *MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField() const throw(INTERP_KERNEL::Exception)
1942 {
1943   if(!_discr_per_cell)
1944     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField : no discretization array set !");
1945   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1946   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1947   const int *w=_discr_per_cell->begin();
1948   ret->alloc(nbOfTuples,1);
1949   int *valsToFill=ret->getPointer();
1950   int nbMaxOfLocId=(int)_loc.size();
1951   for(int i=0;i<nbOfTuples;i++,w++)
1952     if(*w!=DFT_INVALID_LOCID_VALUE)
1953       {
1954         if(*w>=0 && *w<nbMaxOfLocId)
1955           valsToFill[i]=_loc[*w].getNumberOfGaussPt();
1956         else
1957           {
1958             std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField : cell #" << i << " has invalid id (" << *w << ") ! Should be in [0," << nbMaxOfLocId << ") !";
1959             throw INTERP_KERNEL::Exception(oss.str().c_str());
1960           }
1961       }
1962     else
1963       {
1964         std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField : cell #" << i << " is detected as orphan !";
1965         throw INTERP_KERNEL::Exception(oss.str().c_str());
1966       }
1967   return ret.retn();
1968 }
1969
1970 void MEDCouplingFieldDiscretizationGauss::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
1971 {
1972   stream << "Gauss points spatial discretization.";
1973 }
1974
1975 /*!
1976  * This method makes the assumption that _discr_per_cell is set.
1977  * This method reduces as much as possible number size of _loc.
1978  * This method is useful when several set on same cells has been done and that some Gauss Localization are no more used.
1979  */
1980 void MEDCouplingFieldDiscretizationGauss::zipGaussLocalizations()
1981 {
1982   const int *start=_discr_per_cell->begin();
1983   int nbOfTuples=_discr_per_cell->getNumberOfTuples();
1984   INTERP_KERNEL::AutoPtr<int> tmp=new int[_loc.size()];
1985   std::fill((int *)tmp,(int *)tmp+_loc.size(),-2);
1986   for(const int *w=start;w!=start+nbOfTuples;w++)
1987     if(*w>=0)
1988       tmp[*w]=1;
1989   int fid=0;
1990   for(int i=0;i<(int)_loc.size();i++)
1991     if(tmp[i]!=-2)
1992       tmp[i]=fid++;
1993   if(fid==(int)_loc.size())
1994     return;
1995   // zip needed
1996   int *start2=_discr_per_cell->getPointer();
1997   for(int *w2=start2;w2!=start2+nbOfTuples;w2++)
1998     if(*w2>=0)
1999       *w2=tmp[*w2];
2000   std::vector<MEDCouplingGaussLocalization> tmpLoc;
2001   for(int i=0;i<(int)_loc.size();i++)
2002     if(tmp[i]!=-2)
2003       tmpLoc.push_back(_loc[tmp[i]]);
2004   _loc=tmpLoc;
2005 }
2006
2007 MEDCouplingFieldDiscretizationGaussNE::MEDCouplingFieldDiscretizationGaussNE()
2008 {
2009 }
2010
2011 TypeOfField MEDCouplingFieldDiscretizationGaussNE::getEnum() const
2012 {
2013   return TYPE;
2014 }
2015
2016 /*!
2017  * This method is simply called by MEDCouplingFieldDiscretization::deepCpy. It performs the deep copy of \a this.
2018  *
2019  * \sa MEDCouplingFieldDiscretization::deepCpy.
2020  */
2021 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationGaussNE::clone() const
2022 {
2023   return new MEDCouplingFieldDiscretizationGaussNE(*this);
2024 }
2025
2026 std::string MEDCouplingFieldDiscretizationGaussNE::getStringRepr() const
2027 {
2028   return std::string(REPR);
2029 }
2030
2031 const char *MEDCouplingFieldDiscretizationGaussNE::getRepr() const
2032 {
2033   return REPR;
2034 }
2035
2036 bool MEDCouplingFieldDiscretizationGaussNE::isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const
2037 {
2038   if(!other)
2039     {
2040       reason="other spatial discretization is NULL, and this spatial discretization (GaussNE) is defined.";
2041       return false;
2042     }
2043   const MEDCouplingFieldDiscretizationGaussNE *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationGaussNE *>(other);
2044   bool ret=otherC!=0;
2045   if(!ret)
2046     reason="Spatial discrtization of this is ON_GAUSS_NE, which is not the case of other.";
2047   return ret;
2048 }
2049
2050 int MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode(const MEDCouplingMesh *mesh, const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
2051 {
2052   if(code.size()%3!=0)
2053     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : invalid input code !");
2054   int nbOfSplit=(int)idsPerType.size();
2055   int nbOfTypes=(int)code.size()/3;
2056   int ret=0;
2057   for(int i=0;i<nbOfTypes;i++)
2058     {
2059       int nbOfEltInChunk=code[3*i+1];
2060       if(nbOfEltInChunk<0)
2061         throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : invalid input code ! presence of negative value in a type !");
2062       int pos=code[3*i+2];
2063       if(pos!=-1)
2064         {
2065           if(pos<0 || pos>=nbOfSplit)
2066             {
2067               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : input code points to pos " << pos << " in typeid " << i << " ! Should be in [0," << nbOfSplit << ") !";
2068               throw INTERP_KERNEL::Exception(oss.str().c_str());
2069             }
2070           const DataArrayInt *ids(idsPerType[pos]);
2071           if(!ids || !ids->isAllocated() || ids->getNumberOfComponents()!=1 || ids->getNumberOfTuples()!=nbOfEltInChunk || ids->getMinValueInArray()<0)
2072             {
2073               std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : input pfl chunck at pos " << pos << " should have " << i << " tuples and one component and with ids all >=0 !";
2074               throw INTERP_KERNEL::Exception(oss.str().c_str());
2075             }
2076         }
2077       ret+=nbOfEltInChunk;
2078     }
2079   if(!mesh)
2080     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : NULL input mesh !");
2081   if(ret!=mesh->getNumberOfCells())
2082     {
2083       std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuplesExpectedRegardingCode : input code points to " << ret << " number of cells should be " <<  mesh->getNumberOfCells() << " !";
2084     }
2085   return getNumberOfTuples(mesh);
2086 }
2087
2088 int MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuples(const MEDCouplingMesh *mesh) const throw(INTERP_KERNEL::Exception)
2089 {
2090   if(!mesh)
2091     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfTuples : NULL input mesh !");
2092   int ret=0;
2093   int nbOfCells=mesh->getNumberOfCells();
2094   for(int i=0;i<nbOfCells;i++)
2095     {
2096       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2097       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2098       if(cm.isDynamic())
2099         throw INTERP_KERNEL::Exception("Not implemented yet Gauss node on elements for polygons and polyedrons !");
2100       ret+=cm.getNumberOfNodes();
2101     }
2102   return ret;
2103 }
2104
2105 int MEDCouplingFieldDiscretizationGaussNE::getNumberOfMeshPlaces(const MEDCouplingMesh *mesh) const
2106 {
2107   if(!mesh)
2108     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getNumberOfMeshPlaces : NULL input mesh !");
2109   return mesh->getNumberOfCells();
2110 }
2111
2112 DataArrayInt *MEDCouplingFieldDiscretizationGaussNE::getOffsetArr(const MEDCouplingMesh *mesh) const
2113 {
2114   if(!mesh)
2115     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getOffsetArr : NULL input mesh !");
2116   int nbOfTuples=mesh->getNumberOfCells();
2117   DataArrayInt *ret=DataArrayInt::New();
2118   ret->alloc(nbOfTuples+1,1);
2119   int *retPtr=ret->getPointer();
2120   retPtr[0]=0;
2121   for(int i=0;i<nbOfTuples;i++)
2122     {
2123       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2124       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2125       if(cm.isDynamic())
2126         throw INTERP_KERNEL::Exception("Not implemented yet Gauss node on elements for polygons and polyedrons !");
2127       retPtr[i+1]=retPtr[i]+cm.getNumberOfNodes();
2128     }
2129   return ret;
2130 }
2131
2132 void MEDCouplingFieldDiscretizationGaussNE::renumberArraysForCell(const MEDCouplingMesh *mesh, const std::vector<DataArray *>& arrays,
2133                                                                   const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2134 {
2135   if(!mesh)
2136     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::renumberArraysForCell : NULL input mesh !");
2137   const int *array=old2NewBg;
2138   if(check)
2139     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+mesh->getNumberOfCells());
2140   int nbOfCells=mesh->getNumberOfCells();
2141   int nbOfTuples=getNumberOfTuples(mesh);
2142   int *array2=new int[nbOfTuples];//stores the final conversion array old2New to give to arrays in renumberInPlace.
2143   int *array3=new int[nbOfCells];//store for each cell in after renumbering the offset needed by each cell in new numbering.
2144   array3[0]=0;
2145   for(int i=1;i<nbOfCells;i++)
2146     {
2147       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell((int)std::distance(array,std::find(array,array+nbOfCells,i-1)));
2148       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2149       array3[i]=array3[i-1]+cm.getNumberOfNodes();
2150     }
2151   int j=0;
2152   for(int i=0;i<nbOfCells;i++)
2153     {
2154       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2155       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2156       for(int k=0;k<(int)cm.getNumberOfNodes();k++,j++)
2157         array2[j]=array3[array[i]]+k;
2158     }
2159   delete [] array3;
2160   for(std::vector<DataArray *>::const_iterator it=arrays.begin();it!=arrays.end();it++)
2161     if(*it)
2162       (*it)->renumberInPlace(array2);
2163   delete [] array2;
2164   if(check)
2165     free(const_cast<int *>(array));
2166 }
2167
2168 DataArrayDouble *MEDCouplingFieldDiscretizationGaussNE::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const
2169 {
2170   if(!mesh)
2171     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getLocalizationOfDiscValues : NULL input mesh !");
2172   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
2173   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> umesh=mesh->buildUnstructured();//in general do nothing
2174   int nbOfTuples=getNumberOfTuples(umesh);
2175   int spaceDim=mesh->getSpaceDimension();
2176   ret->alloc(nbOfTuples,spaceDim);
2177   const double *coords=umesh->getCoords()->begin();
2178   const int *connI=umesh->getNodalConnectivityIndex()->getConstPointer();
2179   const int *conn=umesh->getNodalConnectivity()->getConstPointer();
2180   int nbCells=umesh->getNumberOfCells();
2181   double *retPtr=ret->getPointer();
2182   for(int i=0;i<nbCells;i++,connI++)
2183     for(const int *w=conn+connI[0]+1;w!=conn+connI[1];w++)
2184       if(*w>=0)
2185         retPtr=std::copy(coords+(*w)*spaceDim,coords+((*w)+1)*spaceDim,retPtr);
2186   return ret.retn();
2187 }
2188
2189 /*!
2190  * Reimplemented from MEDCouplingFieldDiscretization::integral for performance reason. The default implementation is valid too for GAUSS_NE spatial discretization.
2191  */
2192 void MEDCouplingFieldDiscretizationGaussNE::integral(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, bool isWAbs, double *res) const throw(INTERP_KERNEL::Exception)
2193 {
2194   if(!mesh || !arr)
2195     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::integral : input mesh or array is null !");
2196   int nbOfCompo=arr->getNumberOfComponents();
2197   std::fill(res,res+nbOfCompo,0.);
2198   //
2199   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> vol=mesh->getMeasureField(isWAbs);
2200   std::set<INTERP_KERNEL::NormalizedCellType> types=mesh->getAllGeoTypes();
2201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=mesh->computeNbOfNodesPerCell();
2202   nbOfNodesPerCell->computeOffsets2();
2203   const double *arrPtr=arr->begin(),*volPtr=vol->getArray()->begin();
2204   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
2205     {
2206       std::size_t wArrSz=-1;
2207       const double *wArr=GetWeightArrayFromGeometricType(*it,wArrSz);
2208       INTERP_KERNEL::AutoPtr<double> wArr2=new double[wArrSz];
2209       double sum=std::accumulate(wArr,wArr+wArrSz,0.);
2210       std::transform(wArr,wArr+wArrSz,(double *)wArr2,std::bind2nd(std::multiplies<double>(),1./sum));      
2211       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=mesh->giveCellsWithType(*it);
2212       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->buildExplicitArrByRanges(nbOfNodesPerCell);
2213       const int *ptIds2=ids2->begin(),*ptIds=ids->begin();
2214       int nbOfCellsWithCurGeoType=ids->getNumberOfTuples();
2215       for(int i=0;i<nbOfCellsWithCurGeoType;i++,ptIds++,ptIds2+=wArrSz)
2216         {
2217           for(int k=0;k<nbOfCompo;k++)
2218             {
2219               double tmp=0.;
2220               for(std::size_t j=0;j<wArrSz;j++)
2221                 tmp+=arrPtr[nbOfCompo*ptIds2[j]+k]*wArr2[j];
2222               res[k]+=tmp*volPtr[*ptIds];
2223             }
2224         }
2225     }
2226 }
2227
2228 const double *MEDCouplingFieldDiscretizationGaussNE::GetWeightArrayFromGeometricType(INTERP_KERNEL::NormalizedCellType geoType, std::size_t& lgth) throw(INTERP_KERNEL::Exception)
2229 {
2230   switch(geoType)
2231     {
2232     case INTERP_KERNEL::NORM_SEG2:
2233       lgth=(int)sizeof(FGP_SEG2)/sizeof(double);
2234       return FGP_SEG2;
2235     case INTERP_KERNEL::NORM_SEG3:
2236       lgth=(int)sizeof(FGP_SEG3)/sizeof(double);
2237       return FGP_SEG3;
2238     case INTERP_KERNEL::NORM_SEG4:
2239       lgth=(int)sizeof(FGP_SEG4)/sizeof(double);
2240       return FGP_SEG4;
2241     case INTERP_KERNEL::NORM_TRI3:
2242       lgth=(int)sizeof(FGP_TRI3)/sizeof(double);
2243       return FGP_TRI3;
2244     case INTERP_KERNEL::NORM_TRI6:
2245       lgth=(int)sizeof(FGP_TRI6)/sizeof(double);
2246       return FGP_TRI6;
2247     case INTERP_KERNEL::NORM_TRI7:
2248       lgth=(int)sizeof(FGP_TRI7)/sizeof(double);
2249       return FGP_TRI7;
2250     case INTERP_KERNEL::NORM_QUAD4:
2251       lgth=(int)sizeof(FGP_QUAD4)/sizeof(double);
2252       return FGP_QUAD4;
2253     case INTERP_KERNEL::NORM_QUAD9:
2254       lgth=(int)sizeof(FGP_QUAD9)/sizeof(double);
2255       return FGP_QUAD9;
2256     case INTERP_KERNEL::NORM_TETRA4:
2257       lgth=(int)sizeof(FGP_TETRA4)/sizeof(double);
2258       return FGP_TETRA4;
2259     case INTERP_KERNEL::NORM_PENTA6:
2260       lgth=(int)sizeof(FGP_PENTA6)/sizeof(double);
2261       return FGP_PENTA6;
2262     case INTERP_KERNEL::NORM_HEXA8:
2263       lgth=(int)sizeof(FGP_HEXA8)/sizeof(double);
2264       return FGP_HEXA8;
2265     case INTERP_KERNEL::NORM_HEXA27:
2266       lgth=(int)sizeof(FGP_HEXA27)/sizeof(double);
2267       return FGP_HEXA27;
2268     case INTERP_KERNEL::NORM_PYRA5:
2269       lgth=(int)sizeof(FGP_PYRA5)/sizeof(double);
2270       return FGP_PYRA5;
2271     default:
2272       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 !");
2273     }
2274 }
2275
2276 const double *MEDCouplingFieldDiscretizationGaussNE::GetRefCoordsFromGeometricType(INTERP_KERNEL::NormalizedCellType geoType, std::size_t& lgth) throw(INTERP_KERNEL::Exception)
2277 {
2278   switch(geoType)
2279     {
2280     case INTERP_KERNEL::NORM_SEG2:
2281       lgth=(int)sizeof(REF_SEG2)/sizeof(double);
2282       return REF_SEG2;
2283     case INTERP_KERNEL::NORM_SEG3:
2284       lgth=(int)sizeof(REF_SEG3)/sizeof(double);
2285       return REF_SEG3;
2286     case INTERP_KERNEL::NORM_SEG4:
2287       lgth=(int)sizeof(REF_SEG4)/sizeof(double);
2288       return REF_SEG4;
2289     case INTERP_KERNEL::NORM_TRI3:
2290       lgth=(int)sizeof(REF_TRI3)/sizeof(double);
2291       return REF_TRI3;
2292     case INTERP_KERNEL::NORM_TRI6:
2293       lgth=(int)sizeof(REF_TRI6)/sizeof(double);
2294       return REF_TRI6;
2295     case INTERP_KERNEL::NORM_TRI7:
2296       lgth=(int)sizeof(REF_TRI7)/sizeof(double);
2297       return REF_TRI7;
2298     case INTERP_KERNEL::NORM_QUAD4:
2299       lgth=(int)sizeof(REF_QUAD4)/sizeof(double);
2300       return REF_QUAD4;
2301     case INTERP_KERNEL::NORM_QUAD8:
2302       lgth=(int)sizeof(REF_QUAD8)/sizeof(double);
2303       return REF_QUAD8;
2304     case INTERP_KERNEL::NORM_QUAD9:
2305       lgth=(int)sizeof(REF_QUAD9)/sizeof(double);
2306       return REF_QUAD9;
2307     case INTERP_KERNEL::NORM_TETRA4:
2308       lgth=(int)sizeof(REF_TETRA4)/sizeof(double);
2309       return REF_TETRA4;
2310     case INTERP_KERNEL::NORM_TETRA10:
2311       lgth=(int)sizeof(REF_TETRA10)/sizeof(double);
2312       return REF_TETRA10;
2313     case INTERP_KERNEL::NORM_PENTA6:
2314       lgth=(int)sizeof(REF_PENTA6)/sizeof(double);
2315       return REF_PENTA6;
2316     case INTERP_KERNEL::NORM_PENTA15:
2317       lgth=(int)sizeof(REF_PENTA15)/sizeof(double);
2318       return REF_PENTA15;
2319     case INTERP_KERNEL::NORM_HEXA8:
2320       lgth=(int)sizeof(REF_HEXA8)/sizeof(double);
2321       return REF_HEXA8;
2322     case INTERP_KERNEL::NORM_HEXA20:
2323       lgth=(int)sizeof(REF_HEXA20)/sizeof(double);
2324       return REF_HEXA20;
2325     case INTERP_KERNEL::NORM_HEXA27:
2326       lgth=(int)sizeof(REF_HEXA27)/sizeof(double);
2327       return REF_HEXA27;
2328     case INTERP_KERNEL::NORM_PYRA5:
2329       lgth=(int)sizeof(REF_PYRA5)/sizeof(double);
2330       return REF_PYRA5;
2331     case INTERP_KERNEL::NORM_PYRA13:
2332       lgth=(int)sizeof(REF_PYRA13)/sizeof(double);
2333       return REF_PYRA13;
2334     default:
2335       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 !");
2336     }
2337 }
2338
2339 void MEDCouplingFieldDiscretizationGaussNE::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *tupleIdsBg, const int *tupleIdsEnd,
2340                                                                                DataArrayInt *&cellRestriction, DataArrayInt *&trueTupleRestriction) const throw(INTERP_KERNEL::Exception)
2341 {
2342   if(!mesh)
2343     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::computeMeshRestrictionFromTupleIds : NULL input mesh !");
2344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=DataArrayInt::New(); tmp->alloc((int)std::distance(tupleIdsBg,tupleIdsEnd),1);
2345   std::copy(tupleIdsBg,tupleIdsEnd,tmp->getPointer());
2346   tmp->sort(true);
2347   tmp=tmp->buildUnique();
2348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=mesh->computeNbOfNodesPerCell();
2349   nbOfNodesPerCell->computeOffsets2();
2350   nbOfNodesPerCell->searchRangesInListOfIds(tmp,cellRestriction,trueTupleRestriction);
2351 }
2352
2353 void MEDCouplingFieldDiscretizationGaussNE::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
2354 {
2355 }
2356
2357 double MEDCouplingFieldDiscretizationGaussNE::getIJK(const MEDCouplingMesh *mesh, const DataArrayDouble *da,
2358                                                      int cellId, int nodeIdInCell, int compoId) const throw(INTERP_KERNEL::Exception)
2359 {
2360   if(!mesh)
2361     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getIJK : NULL input mesh !");
2362   int offset=0;
2363   for(int i=0;i<cellId;i++)
2364     {
2365       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2366       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2367       offset+=cm.getNumberOfNodes();
2368     }
2369   return da->getIJ(offset+nodeIdInCell,compoId);
2370 }
2371
2372 void MEDCouplingFieldDiscretizationGaussNE::checkCoherencyBetween(const MEDCouplingMesh *mesh, const DataArray *da) const throw(INTERP_KERNEL::Exception)
2373 {
2374   int nbOfTuples=getNumberOfTuples(mesh);
2375   if(nbOfTuples!=da->getNumberOfTuples())
2376     {
2377       std::ostringstream oss; oss << "Invalid number of tuples in the array : expecting " << nbOfTuples << " !";
2378       throw INTERP_KERNEL::Exception(oss.str().c_str());
2379     }
2380 }
2381
2382 MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationGaussNE::getMeasureField(const MEDCouplingMesh *mesh, bool isAbs) const
2383 {
2384   if(!mesh)
2385     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::getMeasureField : mesh instance specified is NULL !");
2386   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> vol=mesh->getMeasureField(isAbs);
2387   const double *volPtr=vol->getArray()->begin();
2388   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_GAUSS_NE);
2389   ret->setMesh(mesh);
2390   //
2391   std::set<INTERP_KERNEL::NormalizedCellType> types=mesh->getAllGeoTypes();
2392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=mesh->computeNbOfNodesPerCell();
2393   int nbTuples=nbOfNodesPerCell->accumulate(0);
2394   nbOfNodesPerCell->computeOffsets2();
2395   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New(); arr->alloc(nbTuples,1);
2396   ret->setArray(arr);
2397   double *arrPtr=arr->getPointer();
2398   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
2399     {
2400       std::size_t wArrSz=-1;
2401       const double *wArr=GetWeightArrayFromGeometricType(*it,wArrSz);
2402       INTERP_KERNEL::AutoPtr<double> wArr2=new double[wArrSz];
2403       double sum=std::accumulate(wArr,wArr+wArrSz,0.);
2404       std::transform(wArr,wArr+wArrSz,(double *)wArr2,std::bind2nd(std::multiplies<double>(),1./sum));      
2405       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=mesh->giveCellsWithType(*it);
2406       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->buildExplicitArrByRanges(nbOfNodesPerCell);
2407       const int *ptIds2=ids2->begin(),*ptIds=ids->begin();
2408       int nbOfCellsWithCurGeoType=ids->getNumberOfTuples();
2409       for(int i=0;i<nbOfCellsWithCurGeoType;i++,ptIds++)
2410         for(std::size_t j=0;j<wArrSz;j++,ptIds2++)
2411           arrPtr[*ptIds2]=wArr2[j]*volPtr[*ptIds];
2412     }
2413   ret->synchronizeTimeWithSupport();
2414   return ret.retn();
2415 }
2416
2417 void MEDCouplingFieldDiscretizationGaussNE::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
2418 {
2419   throw INTERP_KERNEL::Exception("Not implemented yet !");
2420 }
2421
2422 void MEDCouplingFieldDiscretizationGaussNE::getValueOnPos(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, int i, int j, int k, double *res) const
2423 {
2424   throw INTERP_KERNEL::Exception("getValueOnPos(i,j,k) : Not applyable for Gauss points !");
2425 }
2426
2427 DataArrayDouble *MEDCouplingFieldDiscretizationGaussNE::getValueOnMulti(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, int nbOfPoints) const
2428 {
2429   throw INTERP_KERNEL::Exception("getValueOnMulti : Not implemented for Gauss NE !");
2430 }
2431
2432 MEDCouplingMesh *MEDCouplingFieldDiscretizationGaussNE::buildSubMeshData(const MEDCouplingMesh *mesh, const int *start, const int *end, DataArrayInt *&di) const
2433 {
2434   if(!mesh)
2435     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::buildSubMeshData : NULL input mesh !");
2436   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diSafe=computeTupleIdsToSelectFromCellIds(mesh,start,end);
2437   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPart(start,end);
2438   di=diSafe.retn();
2439   return ret.retn();
2440 }
2441
2442 /*!
2443  * This method is strictly equivalent to MEDCouplingFieldDiscretizationGauss::buildSubMeshData except that it is optimized for input defined as a range of cell ids.
2444  * 
2445  * \param [out] beginOut Valid only if \a di is NULL
2446  * \param [out] endOut Valid only if \a di is NULL
2447  * \param [out] stepOut Valid only if \a di is NULL
2448  * \param [out] di is an array returned that specifies entity ids (nodes, cells, Gauss points... ) in array if no output range is foundable.
2449  *
2450  * \sa MEDCouplingFieldDiscretizationGauss::buildSubMeshData
2451  */
2452 MEDCouplingMesh *MEDCouplingFieldDiscretizationGaussNE::buildSubMeshDataRange(const MEDCouplingMesh *mesh, int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt *&di) const
2453 {
2454   if(stepCellIds!=1)//even for stepCellIds==-1 the output will not be a range
2455     return MEDCouplingFieldDiscretization::buildSubMeshDataRange(mesh,beginCellIds,endCellIds,stepCellIds,beginOut,endOut,stepOut,di);
2456   if(!mesh)
2457     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::buildSubMeshDataRange : NULL input mesh !");
2458   int nbOfCells=mesh->getNumberOfCells();
2459   di=0; beginOut=0; endOut=0; stepOut=stepCellIds;
2460   const char msg[]="MEDCouplingFieldDiscretizationGaussNE::buildSubMeshDataRange : cell #";
2461   for(int i=0;i<nbOfCells;i++)
2462     {
2463       INTERP_KERNEL::NormalizedCellType type=mesh->getTypeOfCell(i);
2464       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2465       if(cm.isDynamic())
2466         { std::ostringstream oss; oss << msg << i << " presence of dynamic cell (polygons and polyedrons) ! Not implemented !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
2467       int delta=cm.getNumberOfNodes();
2468       if(i<beginCellIds)
2469         beginOut+=delta;
2470       endOut+=delta;
2471       if(i>=endCellIds)
2472         break;
2473     }
2474   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> ret=mesh->buildPartRange(beginCellIds,endCellIds,stepCellIds);
2475   return ret.retn();
2476 }
2477
2478
2479 /*!
2480  * This method returns a tuple ids selection from cell ids selection [start;end).
2481  * This method is called by MEDCouplingFieldDiscretizationGaussNE::buildSubMeshData to return parameter \b di.
2482  *
2483  * \return a newly allocated array containing ids to select into the DataArrayDouble of the field.
2484  * 
2485  */
2486 DataArrayInt *MEDCouplingFieldDiscretizationGaussNE::computeTupleIdsToSelectFromCellIds(const MEDCouplingMesh *mesh, const int *startCellIds, const int *endCellIds) const
2487 {
2488   if(!mesh)
2489     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGaussNE::computeTupleIdsToSelectFromCellIds : null mesh !");
2490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nbOfNodesPerCell=mesh->computeNbOfNodesPerCell();
2491   nbOfNodesPerCell->computeOffsets2();
2492   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> sel=DataArrayInt::New(); sel->useArray(startCellIds,false,CPP_DEALLOC,(int)std::distance(startCellIds,endCellIds),1);
2493   return sel->buildExplicitArrByRanges(nbOfNodesPerCell);
2494 }
2495
2496 /*!
2497  * No implementation needed !
2498  */
2499 void MEDCouplingFieldDiscretizationGaussNE::renumberValuesOnNodes(double , const int *, int newNbOfNodes, DataArrayDouble *) const
2500 {
2501 }
2502
2503 void MEDCouplingFieldDiscretizationGaussNE::renumberValuesOnCells(double epsOnVals, const MEDCouplingMesh *mesh, const int *old2New, int newSz, DataArrayDouble *arr) const
2504 {
2505   throw INTERP_KERNEL::Exception("Not implemented yet !");
2506 }
2507
2508 void MEDCouplingFieldDiscretizationGaussNE::renumberValuesOnCellsR(const MEDCouplingMesh *mesh, const int *new2old, int newSz, DataArrayDouble *arr) const
2509 {
2510   throw INTERP_KERNEL::Exception("Not implemented yet !");
2511 }
2512
2513 void MEDCouplingFieldDiscretizationGaussNE::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2514 {
2515   stream << "Gauss points on nodes per element spatial discretization.";
2516 }
2517
2518 MEDCouplingFieldDiscretizationGaussNE::MEDCouplingFieldDiscretizationGaussNE(const MEDCouplingFieldDiscretizationGaussNE& other):MEDCouplingFieldDiscretization(other)
2519 {
2520 }
2521
2522 TypeOfField MEDCouplingFieldDiscretizationKriging::getEnum() const
2523 {
2524   return TYPE;
2525 }
2526
2527 const char *MEDCouplingFieldDiscretizationKriging::getRepr() const
2528 {
2529   return REPR;
2530 }
2531
2532 /*!
2533  * This method is simply called by MEDCouplingFieldDiscretization::deepCpy. It performs the deep copy of \a this.
2534  *
2535  * \sa MEDCouplingFieldDiscretization::deepCpy.
2536  */
2537 MEDCouplingFieldDiscretization *MEDCouplingFieldDiscretizationKriging::clone() const
2538 {
2539   return new MEDCouplingFieldDiscretizationKriging;
2540 }
2541
2542 std::string MEDCouplingFieldDiscretizationKriging::getStringRepr() const
2543 {
2544   return std::string(REPR);
2545 }
2546
2547 void MEDCouplingFieldDiscretizationKriging::checkCompatibilityWithNature(NatureOfField nat) const throw(INTERP_KERNEL::Exception)
2548 {
2549   if(nat!=ConservativeVolumic)
2550     throw INTERP_KERNEL::Exception("Invalid nature for Kriging field : expected ConservativeVolumic !");
2551 }
2552
2553 bool MEDCouplingFieldDiscretizationKriging::isEqualIfNotWhy(const MEDCouplingFieldDiscretization *other, double eps, std::string& reason) const
2554 {
2555   if(!other)
2556     {
2557       reason="other spatial discretization is NULL, and this spatial discretization (Kriginig) is defined.";
2558       return false;
2559     }
2560   const MEDCouplingFieldDiscretizationKriging *otherC=dynamic_cast<const MEDCouplingFieldDiscretizationKriging *>(other);
2561   bool ret=otherC!=0;
2562   if(!ret)
2563     reason="Spatial discrtization of this is ON_NODES_KR, which is not the case of other.";
2564   return ret;
2565 }
2566
2567 MEDCouplingFieldDouble *MEDCouplingFieldDiscretizationKriging::getMeasureField(const MEDCouplingMesh *mesh, bool isAbs) const
2568 {
2569   if(!mesh)
2570     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::getMeasureField : mesh instance specified is NULL !");
2571   throw INTERP_KERNEL::Exception("getMeasureField on FieldDiscretizationKriging : not implemented yet !");
2572 }
2573
2574 void MEDCouplingFieldDiscretizationKriging::getValueOn(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, double *res) const
2575 {
2576   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res2=MEDCouplingFieldDiscretizationKriging::getValueOnMulti(arr,mesh,loc,1);
2577   std::copy(res2->begin(),res2->end(),res);
2578 }
2579
2580 DataArrayDouble *MEDCouplingFieldDiscretizationKriging::getValueOnMulti(const DataArrayDouble *arr, const MEDCouplingMesh *mesh, const double *loc, int nbOfTargetPoints) const
2581 {
2582   if(!arr || !arr->isAllocated())
2583     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::getValueOnMulti : input array is null or not allocated !");
2584   int nbOfRows(getNumberOfMeshPlaces(mesh));
2585   if(arr->getNumberOfTuples()!=nbOfRows)
2586     {
2587       std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationKriging::getValueOnMulti : input array does not have correct number of tuples ! Excepted " << nbOfRows << " having " << arr->getNumberOfTuples() << " !";
2588       throw INTERP_KERNEL::Exception(oss.str().c_str());
2589     }
2590   int nbCols(-1),nbCompo(arr->getNumberOfComponents());
2591   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> m(computeEvaluationMatrixOnGivenPts(mesh,loc,nbOfTargetPoints,nbCols));
2592   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
2593   ret->alloc(nbOfTargetPoints,nbCompo);
2594   INTERP_KERNEL::matrixProduct(m->begin(),nbOfTargetPoints,nbCols,arr->begin(),nbOfRows,nbCompo,ret->getPointer());
2595   return ret.retn();
2596 }
2597
2598 void MEDCouplingFieldDiscretizationKriging::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2599 {
2600   stream << "Kriging spatial discretization.";
2601 }
2602
2603 /*!
2604  * Returns the matrix of size nbRows = \a nbOfTargetPoints and \a nbCols = \a nbCols. This matrix is useful if 
2605  * 
2606  * \return the new result matrix to be deallocated by the caller.
2607  */
2608 DataArrayDouble *MEDCouplingFieldDiscretizationKriging::computeEvaluationMatrixOnGivenPts(const MEDCouplingMesh *mesh, const double *loc, int nbOfTargetPoints, int& nbCols) const
2609 {
2610   int isDrift(-1),nbRows(-1);
2611   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixInv(computeInverseMatrix(mesh,isDrift,nbRows));
2612   //
2613   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getLocalizationOfDiscValues(mesh);
2614   int nbOfPts(coords->getNumberOfTuples()),dimension(coords->getNumberOfComponents());
2615   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> locArr=DataArrayDouble::New();
2616   locArr->useArray(loc,false,CPP_DEALLOC,nbOfTargetPoints,dimension);
2617   nbCols=nbOfPts;
2618   //
2619   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrix2=coords->buildEuclidianDistanceDenseMatrixWith(locArr);
2620   operateOnDenseMatrix(mesh->getSpaceDimension(),nbOfTargetPoints*nbOfPts,matrix2->getPointer());
2621   //
2622   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrix3=DataArrayDouble::New();
2623   matrix3->alloc(nbOfTargetPoints*nbRows,1);
2624   double *work=matrix3->getPointer();
2625   const double *workCst(matrix2->begin()),*workCst2(loc);
2626   for(int i=0;i<nbOfTargetPoints;i++,workCst+=nbOfPts,workCst2+=isDrift-1)
2627     {
2628       for(int j=0;j<nbOfPts;j++)
2629         work[i*nbRows+j]=workCst[j];
2630       work[i*nbRows+nbOfPts]=1.0;
2631       for(int j=0;j<isDrift-1;j++)
2632         work[i*nbRows+(nbOfPts+1+j)]=workCst2[j];
2633     }
2634   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
2635   ret->alloc(nbOfTargetPoints,nbRows);
2636   INTERP_KERNEL::matrixProduct(matrix3->begin(),nbOfTargetPoints,nbRows,matrixInv->begin(),nbRows,nbRows,ret->getPointer());
2637   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret2(DataArrayDouble::New());
2638   ret2->alloc(nbOfTargetPoints*nbOfPts,1);
2639   workCst=ret->begin(); work=ret2->getPointer();
2640   for(int i=0;i<nbOfTargetPoints;i++,workCst+=nbRows)
2641     work=std::copy(workCst,workCst+nbOfPts,work);
2642   return ret2.retn();
2643 }
2644
2645 /*!
2646  * This method returns the square matrix of size \a matSz that is the inverse of the kriging matrix. The returned matrix can returned all the coeffs of kriging
2647  * when multiplied by the vector of values attached to each point.
2648  * 
2649  * \param [out] isDrift return if drift coefficients are present in the returned vector of coefficients. If different from 0 there is presence of drift coefficients.
2650  * \param [out] matSz the size of returned square matrix
2651  * \return the new result matrix to be deallocated by the caller.
2652  */
2653 DataArrayDouble *MEDCouplingFieldDiscretizationKriging::computeInverseMatrix(const MEDCouplingMesh *mesh, int& isDrift, int& matSz) const
2654 {
2655   if(!mesh)
2656     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::computeVectorOfCoefficients : NULL input mesh !");
2657   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getLocalizationOfDiscValues(mesh);
2658   int nbOfPts=coords->getNumberOfTuples();
2659   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrix=coords->buildEuclidianDistanceDenseMatrix();
2660   operateOnDenseMatrix(mesh->getSpaceDimension(),nbOfPts*nbOfPts,matrix->getPointer());
2661   // Drift
2662   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixWithDrift=performDrift(matrix,coords,isDrift);
2663   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixInv=DataArrayDouble::New();
2664   matSz=nbOfPts+isDrift;
2665   matrixInv->alloc(matSz*matSz,1);
2666   INTERP_KERNEL::inverseMatrix(matrixWithDrift->getConstPointer(),matSz,matrixInv->getPointer());
2667   return matrixInv.retn();
2668 }
2669
2670 /*!
2671  * 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
2672  * number of tuples should be equal to the number of representing points in \a mesh.
2673  * 
2674  * \param [in] mesh is the sources of nodes on which kriging will be done regarding the parameters and the value of \c this->getSpaceDimension()
2675  * \param [in] arr input field DataArrayDouble whose number of tuples must be equal to the number of nodes in \a mesh
2676  * \param [out] isDrift return if drift coefficients are present in the returned vector of coefficients. If different from 0 there is presence of drift coefficients.
2677  *              Whatever the value of \a isDrift the number of tuples of returned DataArrayDouble  will be equal to \c arr->getNumberOfTuples() + \a isDrift.
2678  * \return a newly allocated array containing coefficients including or not drift coefficient at the end depending the value of \a isDrift parameter.
2679  */
2680 DataArrayDouble *MEDCouplingFieldDiscretizationKriging::computeVectorOfCoefficients(const MEDCouplingMesh *mesh, const DataArrayDouble *arr, int& isDrift) const
2681 {
2682   int nbRows(-1);
2683   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> matrixInv(computeInverseMatrix(mesh,isDrift,nbRows));
2684   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> KnewiK=DataArrayDouble::New();
2685   KnewiK->alloc(nbRows*1,1);
2686   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2=DataArrayDouble::New();
2687   arr2->alloc(nbRows*1,1);
2688   double *work=std::copy(arr->begin(),arr->end(),arr2->getPointer());
2689   std::fill(work,work+isDrift,0.);
2690   INTERP_KERNEL::matrixProduct(matrixInv->getConstPointer(),nbRows,nbRows,arr2->getConstPointer(),nbRows,1,KnewiK->getPointer());
2691   return KnewiK.retn();
2692 }
2693
2694 /*!
2695  * 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.
2696  *
2697  * \param [in] spaceDimension space dimension of the input mesh on which the Kriging has to be performed
2698  * \param [in] nbOfElems is the result of the product of nb of rows and the nb of columns of matrix \a matrixPtr
2699  * \param [in,out] matrixPtr is the dense matrix whose on each values the operation will be applied
2700  */
2701 void MEDCouplingFieldDiscretizationKriging::operateOnDenseMatrix(int spaceDimension, int nbOfElems, double *matrixPtr) const
2702 {
2703   switch(spaceDimension)
2704     {
2705     case 1:
2706       {
2707         for(int i=0;i<nbOfElems;i++)
2708           {
2709             double val=matrixPtr[i];
2710             matrixPtr[i]=val*val*val;
2711           }
2712         break;
2713       }
2714     case 2:
2715       {
2716         for(int i=0;i<nbOfElems;i++)
2717           {
2718             double val=matrixPtr[i];
2719             if(val!=0.)
2720               matrixPtr[i]=val*val*log(val);
2721           }
2722         break;
2723       }
2724     case 3:
2725       {
2726         //nothing here : it is not a bug g(h)=h with spaceDim 3.
2727         break;
2728       }
2729     default:
2730       throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::operateOnDenseMatrix : only dimension 1, 2 and 3 implemented !");
2731     }
2732 }
2733
2734 /*!
2735  * Starting from a square matrix \a matr, this method returns a newly allocated dense square matrix whose \a matr is included in returned matrix
2736  * in the top left corner, and in the remaining returned matrix the parameters to take into account about the kriging drift.
2737  * For the moment only linear srift is implemented.
2738  *
2739  * \param [in] arr the position of points were input mesh geometry is considered for Kriging
2740  * \param [in] matr input matrix whose drift part will be added
2741  * \param [out] delta the difference between the size of the output matrix and the input matrix \a matr.
2742  * \return a newly allocated matrix bigger than input matrix \a matr.
2743  */
2744 DataArrayDouble *MEDCouplingFieldDiscretizationKriging::performDrift(const DataArrayDouble *matr, const DataArrayDouble *arr, int& delta) const
2745 {
2746   int spaceDimension=arr->getNumberOfComponents();
2747   delta=spaceDimension+1;
2748   int szOfMatrix=arr->getNumberOfTuples();
2749   if(szOfMatrix*szOfMatrix!=matr->getNumberOfTuples())
2750     throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationKriging::performDrift : invalid size");
2751   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
2752   ret->alloc((szOfMatrix+delta)*(szOfMatrix+delta),1);
2753   const double *srcWork=matr->getConstPointer();
2754   const double *srcWork2=arr->getConstPointer();
2755   double *destWork=ret->getPointer();
2756   for(int i=0;i<szOfMatrix;i++)
2757     {
2758       destWork=std::copy(srcWork,srcWork+szOfMatrix,destWork);
2759       srcWork+=szOfMatrix;
2760       *destWork++=1.;
2761       destWork=std::copy(srcWork2,srcWork2+spaceDimension,destWork);
2762       srcWork2+=spaceDimension;
2763     }
2764   std::fill(destWork,destWork+szOfMatrix,1.); destWork+=szOfMatrix;
2765   std::fill(destWork,destWork+spaceDimension+1,0.); destWork+=spaceDimension+1;
2766   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arrNoI=arr->toNoInterlace();
2767   srcWork2=arrNoI->getConstPointer();
2768   for(int i=0;i<spaceDimension;i++)
2769     {
2770       destWork=std::copy(srcWork2,srcWork2+szOfMatrix,destWork);
2771       srcWork2+=szOfMatrix;
2772       std::fill(destWork,destWork+spaceDimension+1,0.);
2773       destWork+=spaceDimension+1;
2774     }
2775   //
2776   return ret.retn();
2777 }