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