Salome HOME
Merge remote-tracking branch 'origin/abn/bug_fixes' into V8_5_BR
[tools/medcoupling.git] / src / MEDLoader / MEDFileBlowStrEltUp.cxx
1 // Copyright (C) 2007-2017  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 "MEDFileBlowStrEltUp.hxx"
22 #include "MEDCouplingFieldDouble.hxx"
23 #include "MEDFileFieldVisitor.hxx"
24 #include "MEDCouplingPartDefinition.hxx"
25 #include "MCAuto.txx"
26 #include <numeric>
27
28 using namespace MEDCoupling;
29
30 const char MEDFileBlowStrEltUp::MED_BALL_STR[]="MED_BALL";
31
32 MEDFileBlowStrEltUp::MEDFileBlowStrEltUp(const MEDFileFields *fsOnlyOnSE, const MEDFileMeshes *ms, const MEDFileStructureElements *ses)
33 {
34   if(!fsOnlyOnSE || !ms || !ses)
35     throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp constructor : NULL input pointer !");
36   _ms.takeRef(ms); _ses.takeRef(ses);
37   std::vector< std::pair<std::string,std::string> > ps;
38   fsOnlyOnSE->getMeshSENames(ps);
39   std::size_t sz(ps.size());
40   _elts.resize(sz);
41   for(std::size_t i=0;i<sz;i++)
42     {
43       const std::pair<std::string,std::string>& p(ps[i]);
44       MCAuto<MEDFileFields> f(fsOnlyOnSE->partOfThisLyingOnSpecifiedMeshSEName(p.first,p.second));
45       _elts[i]=f;
46     }
47   for(std::size_t i=0;i<sz;i++)
48     {
49       const std::pair<std::string,std::string>& p(ps[i]);
50       MEDFileMesh *mesh(_ms->getMeshWithName(p.first));
51       if(!mesh)
52         throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp : NULL mesh !");
53       MEDFileUMesh *umesh(dynamic_cast<MEDFileUMesh *>(mesh));
54       if(!umesh)
55         throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp : Blow up of Stru Elt not managed yet for unstructured meshes !");
56     }
57 }
58
59 /*!
60  * \param [in] mesh - The mesh containing structure element called \a seName. After the call of this method the Structure elements parts will be removed.
61  * \param [out] mOut - the physical mesh of the structure element \a seName in mesh \a mesh
62  * \param [out] fsOut - the list of var attribute of structure element \a seName - \b WARNING no time steps here
63  */
64 MCAuto<MEDFileEltStruct4Mesh> MEDFileBlowStrEltUp::dealWithSEInMesh(const std::string& seName, MEDFileUMesh *mesh, MCAuto<MEDFileUMesh>& mOut, MCAuto<MEDFileFields>& fsOut) const
65 {
66   if(!mesh)
67     throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithSEInMesh : null pointer !");
68   if(seName==MED_BALL_STR)
69     {
70       MCAuto<MEDFileEltStruct4Mesh> ret(dealWithMEDBALLInMesh(mesh,mOut,fsOut));
71       mesh->killStructureElements();
72       return ret;
73     }
74   throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithSEInMesh : only MED_BALL is managed for the moment, but if you are interested please send spec to anthony.geay@edf.fr !");
75 }
76
77 MCAuto<MEDFileEltStruct4Mesh> MEDFileBlowStrEltUp::dealWithMEDBALLInMesh(const MEDFileUMesh *mesh, MCAuto<MEDFileUMesh>& mOut, MCAuto<MEDFileFields>& fsOut) const
78 {
79   mOut=MEDFileUMesh::New(); fsOut=MEDFileFields::New();
80   const std::vector< MCAuto<MEDFileEltStruct4Mesh> >& strs(mesh->getAccessOfUndergroundEltStrs());
81   MCAuto<MEDFileEltStruct4Mesh> zeStr;
82   for(std::vector< MCAuto<MEDFileEltStruct4Mesh> >::const_iterator it=strs.begin();it!=strs.end();it++)
83     {
84       if((*it)->getGeoTypeName()==MED_BALL_STR)
85         {
86           zeStr=*it;
87           break;
88         }
89     }
90   if(zeStr.isNull())
91     {
92       std::ostringstream oss; oss << "MEDFileBlowStrEltUp::dealWithMEDBALLInMesh : no geo type with name " <<  MED_BALL_STR << " in " << mesh->getName() << " !";
93       throw INTERP_KERNEL::Exception(oss.str());
94     }
95   const DataArrayDouble *coo(mesh->getCoords());
96   if(!coo)
97     throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLInMesh : null coords !");
98   MCAuto<DataArrayInt> conn(zeStr->getConn());
99   if(conn.isNull())
100     throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLInMesh : null connectivity !");
101   conn->checkAllocated();
102   if(conn->getNumberOfComponents()!=1)
103     throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLInMesh : excepted to be single compo !");
104   int nbCells(conn->getNumberOfTuples());
105   MCAuto<DataArrayDouble> connOut(coo->selectByTupleIdSafe(conn->begin(),conn->end()));
106   MCAuto<MEDCouplingUMesh> mcOut(MEDCouplingUMesh::Build0DMeshFromCoords(connOut));
107   mcOut->setName(BuildNewMeshName(mesh->getName(),MED_BALL_STR));
108   mOut->setMeshAtLevel(0,mcOut);
109   const DataArrayInt *ff1(mesh->getFamilyFieldAtLevel(1));
110   if(ff1)
111     {
112       MCAuto<DataArrayInt> ff1o(ff1->selectByTupleIdSafe(conn->begin(),conn->end()));
113       mOut->setFamilyFieldArr(1,ff1o);
114     }
115   const DataArrayInt *nf1(mesh->getNumberFieldAtLevel(1));
116   if(nf1)
117     {
118       MCAuto<DataArrayInt> nf1o(nf1->selectByTupleIdSafe(conn->begin(),conn->end()));
119       mOut->setRenumFieldArr(1,nf1o);
120     }
121   MCAuto<MEDFileUMeshPerTypeCommon> md(zeStr->getMeshDef());
122   const DataArrayInt *ff0(md->getFam());
123   if(ff0)
124     mOut->setFamilyFieldArr(0,const_cast<DataArrayInt *>(ff0));
125   const DataArrayInt *nf0(md->getNum());
126   if(nf0)
127     mOut->setRenumFieldArr(0,const_cast<DataArrayInt *>(nf0));
128   mOut->copyFamGrpMapsFrom(*mesh);
129   const std::vector< MCAuto<DataArray> >& vars(zeStr->getVars());
130   for(std::vector< MCAuto<DataArray> >::const_iterator it=vars.begin();it!=vars.end();it++)
131     {
132       const DataArray *elt(*it);
133       if(!elt)
134         continue;
135       {
136         const DataArrayDouble *eltC(dynamic_cast<const DataArrayDouble *>(elt));
137         if(eltC)
138           {
139             MCAuto<MEDFileFieldMultiTS> fmts(MEDFileFieldMultiTS::New());
140             MCAuto<MEDFileField1TS> f1ts(MEDFileField1TS::New());
141             MCAuto<MEDCouplingFieldDouble> f(MEDCouplingFieldDouble::New(ON_NODES));
142             f->setMesh(mcOut);
143             f->setArray(const_cast<DataArrayDouble *>(eltC));
144             f->setName(eltC->getName());
145             f1ts->setFieldNoProfileSBT(f);
146             fmts->pushBackTimeStep(f1ts);
147             fsOut->pushField(fmts);
148           }
149       }
150     }
151   return zeStr;
152 }
153
154 /*!
155  * \param [in] fs - fields lying all on same mesh and on same structure element
156  * \param [in] zeStr - ze structure of current structure element
157  * \param [in] varAtt - fields containing var att of current structure element. WARNING at this stage the number of iteration are equal to one for each field in \a varAtt
158  * \param [out] zeOutputs - ze fields that are the concatenation of fields in \a fs transformed and those in \a varAtt normalized in time space
159  */
160 void MEDFileBlowStrEltUp::dealWithSEInFields(const std::string& seName, const MEDFileFields *fs, const MEDFileEltStruct4Mesh *zeStr, const MEDFileFields *varAtt, MEDFileFields *zeOutputs) const
161 {
162   if(!fs)
163     throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithSEInFields : null pointer !");
164   if(seName==MED_BALL_STR)
165     {
166       dealWithMEDBALLSInFields(fs,zeStr,varAtt,zeOutputs);
167       return ;
168     }
169   throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithSEInFields : only MED_BALL is managed for the moment, but if you are interested please send spec to anthony.geay@edf.fr !");
170 }
171
172 void MEDFileBlowStrEltUp::dealWithMEDBALLSInFields(const MEDFileFields *fs, const MEDFileEltStruct4Mesh *zeStr, const MEDFileFields *varAtt, MEDFileFields *zeOutputs) const
173 {
174   int nbf(fs->getNumberOfFields());
175   std::vector< MCAuto<MEDFileAnyTypeFieldMultiTS> > elts0;
176   std::vector< MEDFileAnyTypeFieldMultiTS * > elts1;
177   std::string zeMeshName;
178   for(int i=0;i<nbf;i++)
179     {
180       MCAuto<MEDFileAnyTypeFieldMultiTS> elt(fs->getFieldAtPos(i));
181       MCAuto<MEDFileAnyTypeFieldMultiTS> eltOut(elt->buildNewEmpty());
182       int nbTS(elt->getNumberOfTS());
183       for(int j=0;j<nbTS;j++)
184         {
185           MCAuto<MEDFileAnyTypeField1TS> eltt(elt->getTimeStepAtPos(j));
186           MCAuto<MEDFileAnyTypeField1TS> elttOut(eltt->deepCopy());
187           std::string meshName(eltt->getMeshName());
188           zeMeshName=BuildNewMeshName(meshName,MED_BALL_STR);
189           elttOut->setMeshName(zeMeshName);
190           elttOut->convertMedBallIntoClassic();
191           eltOut->pushBackTimeStep(elttOut);
192         }
193       elts0.push_back(eltOut); elts1.push_back(eltOut);
194     }
195   //
196   const MEDFileMesh *zeCurrentMesh(_ms->getMeshWithName(zeMeshName));
197   //
198   std::size_t ii(0);
199   std::vector< std::vector<MEDFileAnyTypeFieldMultiTS *> > sp(MEDFileAnyTypeFieldMultiTS::SplitIntoCommonTimeSeries(elts1));
200   for(std::vector< std::vector<MEDFileAnyTypeFieldMultiTS *> >::const_iterator it0=sp.begin();it0!=sp.end();it0++,ii++)
201     {
202       std::vector< MCAuto<MEDFileFastCellSupportComparator> > fsc;
203       std::vector< std::vector<MEDFileAnyTypeFieldMultiTS *> > sp2(MEDFileAnyTypeFieldMultiTS::SplitPerCommonSupport(*it0,zeCurrentMesh,fsc));
204       std::size_t jj(0);
205       for(std::vector< std::vector<MEDFileAnyTypeFieldMultiTS *> >::const_iterator it1=sp2.begin();it1!=sp2.end();it1++,jj++)
206         {
207           for(std::vector<MEDFileAnyTypeFieldMultiTS *>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
208             zeOutputs->pushField(*it2);
209           // The most exciting part. Users that put profiles on struct elements part of fields. Reduce var att.
210           if((*it1).size()<1)
211             throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLSInFields : take a deep breath !");
212           MCAuto<MEDFileAnyTypeField1TS> zeGuideForPfl;// This var is the reference for pfl management.
213           {
214             if(!(*it1)[0])
215               throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLSInFields : take a deep breath 2 !");
216             int pdm((*it1)[0]->getNumberOfTS());
217             if(pdm<1)
218               throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLSInFields : take a deep breath 3 !");
219             zeGuideForPfl=(*it1)[0]->getTimeStepAtPos(0);
220           }
221           if(zeGuideForPfl.isNull())
222             throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLSInFields : take a deep breath 4 !");
223           std::vector<std::string> pfls(zeGuideForPfl->getPflsReallyUsed());
224           if(pfls.size()>=2)
225             throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLSInFields : drink less coffee");
226           MCAuto<DataArrayInt> pflMyLove;
227           if(pfls.size()==1)
228             pflMyLove.takeRef(zeGuideForPfl->getProfile(pfls[0]));
229           // Yeah we have pfls
230           std::vector<double> t2s;
231           std::vector< std::pair<int,int> > t1s((*it1)[0]->getTimeSteps(t2s));
232           std::size_t nbTS3(t2s.size());
233           int nbf2(varAtt->getNumberOfFields());
234           for(int i=0;i<nbf2;i++)
235             {
236               MCAuto<MEDFileAnyTypeFieldMultiTS> elt(varAtt->getFieldAtPos(i));
237               int nbTS2(elt->getNumberOfTS());
238               if(nbTS2!=1)
239                 throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLSInFields : internal error ! The dealWithMEDBALLInMesh is expected to return a single TS !");
240               MCAuto<MEDFileAnyTypeField1TS> elt2(elt->getTimeStepAtPos(0));
241               MCAuto<MEDFileAnyTypeFieldMultiTS> elt4(elt->buildNewEmpty());
242               for(std::size_t j=0;j<nbTS3;j++)
243                 {
244                   MCAuto<MEDFileAnyTypeField1TS> elt3(elt2->deepCopy());
245                   elt3->setTime(t1s[j].first,t1s[j].second,t2s[j]);
246                   elt3->setName(BuildVarAttName(ii,sp.size(),jj,sp2.size(),elt3->getName()));
247                   if(pflMyLove.isNotNull())
248                     elt3->makeReduction(INTERP_KERNEL::NORM_ERROR,ON_NODES,pflMyLove);
249                   elt4->pushBackTimeStep(elt3);
250                 }
251               zeOutputs->pushField(elt4);
252             }
253         }
254     }
255 }
256
257 void MEDFileBlowStrEltUp::generate(MEDFileMeshes *msOut, MEDFileFields *allZeOutFields)
258 {
259   for(std::vector< MCAuto<MEDFileFields> >::iterator elt=_elts.begin();elt!=_elts.end();elt++)
260     {
261       std::vector< std::pair<std::string,std::string> > ps;
262       (*elt)->getMeshSENames(ps);
263       if(ps.size()!=1)
264         throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::generateMeshes : internal error !");
265       MEDFileMesh *mesh(_ms->getMeshWithName(ps[0].first));
266       if(!mesh)
267         throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::generateMeshes : NULL mesh !");
268       MEDFileUMesh *umesh(dynamic_cast<MEDFileUMesh *>(mesh));
269       if(!umesh)
270         throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::generateMeshes : Blow up of Stru Elt not managed yet for unstructured meshes !");
271       //
272       MCAuto<MEDFileFields> classicalSEFields(splitFieldsPerLoc(*elt,umesh,msOut,allZeOutFields));
273       if(classicalSEFields.isNotNull())
274         {
275           MCAuto<MEDFileUMesh> mOut;
276           MCAuto<MEDFileFields> fsOut1;
277           MCAuto<MEDFileEltStruct4Mesh> zeStr(dealWithSEInMesh(ps[0].second,umesh,mOut,fsOut1));
278           msOut->pushMesh(mOut);
279           dealWithSEInFields(ps[0].second,classicalSEFields,zeStr,fsOut1,allZeOutFields);
280         }
281     }
282 }
283
284 std::string MEDFileBlowStrEltUp::BuildNewMeshName(const std::string& meshName, const std::string& seName)
285 {
286   std::ostringstream mNameOut;
287   mNameOut << meshName << "_" << seName;
288   return mNameOut.str();
289 }
290
291 std::string MEDFileBlowStrEltUp::BuildVarAttName(std::size_t iPart, std::size_t totINbParts, std::size_t jPart, std::size_t totJNbParts, const std::string& name)
292 {
293   if(totINbParts==1 && totJNbParts==1)
294     return name;
295   std::ostringstream oss;
296   oss << name << "@" << iPart << "@" << jPart;
297   return oss.str();
298 }
299
300 void MEDFileBlowStrEltUp::DealWithSE(MEDFileFields *fs, MEDFileMeshes *ms, const MEDFileStructureElements *ses)
301 {
302   MCAuto<MEDFileFields> fsSEOnly(fs->partOfThisOnStructureElements());
303   fs->killStructureElements();
304   MEDFileBlowStrEltUp bu(fsSEOnly,ms,ses);
305   bu.generate(ms,fs);
306   fs->killStructureElementsInGlobs();
307 }
308
309 //
310
311 class FieldWalker2
312 {
313 public:
314   FieldWalker2(const MEDFileFieldPerMeshPerTypePerDisc *pmptpd);
315   std::string getLoc() const { return _loc; }
316   std::string getPfl() const { return _pfl; }
317   bool isClassic() const { return _is_classic; }
318   bool operator!=(const FieldWalker2& other) const;
319   bool operator==(const FieldWalker2& other) const;
320   const SlicePartDefinition *getPartDef() const { return _pd; }
321 private:
322   std::string _loc;
323   std::string _pfl;
324   bool _is_classic;
325   MCAuto<SlicePartDefinition> _pd;
326 };
327
328 class LocInfo
329 {
330 public:
331   LocInfo() { }
332   LocInfo(const std::vector<FieldWalker2>& fw);
333   bool operator==(const LocInfo& other) const { return _locs==other._locs && _pfl==other._pfl; }
334   void push(const std::string& loc, const std::string& pfl) { checkUniqueLoc(loc); _locs.push_back(loc); _pfl.push_back(pfl); }
335   MCAuto<MEDFileUMesh> generateNonClassicalData(int zePos, const MEDFileUMesh *mesh, const MEDFileFieldGlobsReal *globs) const;
336   const PartDefinition *getPartDef() const { return _pd; }
337 private:
338   void checkUniqueLoc(const std::string& loc) const;
339   static MCAuto<DataArrayDouble> BuildMeshFromAngleVrille(INTERP_KERNEL::NormalizedCellType gt, const DataArrayDouble *angleDeVrille, const std::string& pfl, const MEDFileFieldLoc& loc, const MEDFileEltStruct4Mesh *zeStr, const MEDFileUMesh *mesh, const MEDFileUMesh *section, const MEDFileFieldGlobsReal *globs);
340   static MCAuto<DataArrayDouble> BuildMeshFromEpaisseur(INTERP_KERNEL::NormalizedCellType gt, const DataArrayDouble *thikness, const std::string& pfl, const MEDFileFieldLoc& loc, const MEDFileEltStruct4Mesh *zeStr, const MEDFileUMesh *mesh, const MEDFileUMesh *section, const MEDFileFieldGlobsReal *globs);
341   static MCAuto<DataArrayDouble> BuildMeshPipeSEG3(const DataArrayDouble *angle, const DataArrayDouble *scale, const std::string& pfl, const MEDFileFieldLoc& loc, const MEDFileEltStruct4Mesh *zeStr, const MEDFileUMesh *mesh, const MEDFileUMesh *section, const MEDFileFieldGlobsReal *globs);
342   static MCAuto<MEDCouplingUMesh> BuildMeshCommon(INTERP_KERNEL::NormalizedCellType gt, const std::string& pfl, const MEDFileFieldLoc& loc, const MEDFileEltStruct4Mesh *zeStr, const MEDFileUMesh *mesh, const MEDFileUMesh *section, const MEDFileFieldGlobsReal *globs, MCAuto<DataArrayDouble>& ptsForLoc);
343   static MCAuto<DataArrayDouble> BuildMeshFromStructure(INTERP_KERNEL::NormalizedCellType gt, const std::string& pfl, const MEDFileFieldLoc& loc, const MEDFileEltStruct4Mesh *zeStr, const MEDFileUMesh *mesh, const MEDFileUMesh *section, const MEDFileFieldGlobsReal *globs);
344 public:
345   static const char ANGLE_DE_VRILLE[];
346   static const char ANGLE[];
347   static const char SCALE[];
348   static const char EPAISSEUR[];
349 private:
350   std::vector<std::string> _locs;
351   std::vector<std::string> _pfl;
352   MCAuto<PartDefinition> _pd;
353 };
354
355 const char LocInfo::ANGLE_DE_VRILLE[]="ANGLE DE VRILLE";
356
357 const char LocInfo::ANGLE[]="ANGLE";
358
359 const char LocInfo::SCALE[]="SCALE";
360
361 const char LocInfo::EPAISSEUR[]="EPAISSEUR";
362
363 LocInfo::LocInfo(const std::vector<FieldWalker2>& fw)
364 {
365   std::size_t sz(fw.size());
366   _locs.resize(sz); _pfl.resize(sz);
367   if(sz>0)
368     _pd=fw[0].getPartDef()->deepCopy();
369   for(std::size_t i=0;i<sz;i++)
370     {
371       _locs[i]=fw[i].getLoc();
372       _pfl[i]=fw[i].getPfl();
373       if(i>0)
374         _pd=(*_pd)+(*(fw[i].getPartDef()));
375     }
376 }
377
378 void LocInfo::checkUniqueLoc(const std::string& loc) const
379 {
380   if(std::find(_locs.begin(),_locs.end(),loc)!=_locs.end())
381     {
382       std::ostringstream oss; oss << "LocInfo::checkUniqueLoc : loc \"" << loc << "\" already exists !";
383       throw INTERP_KERNEL::Exception(oss.str());
384     }
385 }
386
387 MCAuto<MEDCouplingUMesh> LocInfo::BuildMeshCommon(INTERP_KERNEL::NormalizedCellType gt, const std::string& pfl, const MEDFileFieldLoc& loc, const MEDFileEltStruct4Mesh *zeStr, const MEDFileUMesh *mesh, const MEDFileUMesh *section, const MEDFileFieldGlobsReal *globs, MCAuto<DataArrayDouble>& ptsForLoc)
388 {
389   MCAuto<DataArrayInt> conn(zeStr->getConn());
390   conn=conn->deepCopy(); conn->rearrange(1);
391   MCAuto<MEDCouplingUMesh> geoMesh;
392   {
393     MCAuto<MEDCoupling1SGTUMesh> umesh(MEDCoupling1SGTUMesh::New("",gt));
394     umesh->setCoords(mesh->getCoords());
395     umesh->setNodalConnectivity(conn);
396     geoMesh=umesh->buildUnstructured();
397   }
398   //
399   if(!pfl.empty())
400     {
401       const DataArrayInt *pflArr(globs->getProfile(pfl));
402       geoMesh=geoMesh->buildPartOfMySelf(pflArr->begin(),pflArr->end(),true);
403     }
404   //
405   MCAuto<MEDCouplingFieldDouble> fakeF(MEDCouplingFieldDouble::New(ON_GAUSS_PT));
406   fakeF->setMesh(geoMesh);
407   fakeF->setGaussLocalizationOnType(gt,loc.getRefCoords(),loc.getGaussCoords(),loc.getGaussWeights());
408   ptsForLoc=fakeF->getLocalizationOfDiscr();
409   //
410   return geoMesh;
411 }
412
413 MCAuto<DataArrayDouble> LocInfo::BuildMeshFromAngleVrille(INTERP_KERNEL::NormalizedCellType gt, const DataArrayDouble *angleDeVrille, const std::string& pfl, const MEDFileFieldLoc& loc, const MEDFileEltStruct4Mesh *zeStr, const MEDFileUMesh *mesh, const MEDFileUMesh *section, const MEDFileFieldGlobsReal *globs)
414 {
415   MCAuto<DataArrayDouble> ptsForLoc;
416   MCAuto<MEDCouplingUMesh> geoMesh(BuildMeshCommon(gt,pfl,loc,zeStr,mesh,section,globs,ptsForLoc));
417   //
418   MCConstAuto<DataArrayDouble> angleVrille;
419   if(!pfl.empty())
420     {
421       const DataArrayInt *pflArr(globs->getProfile(pfl));
422       angleVrille=angleDeVrille->selectByTupleIdSafe(pflArr->begin(),pflArr->end());
423     }
424   else
425     angleVrille.takeRef(angleDeVrille);
426   //
427   MCAuto<MEDCouplingFieldDouble> dir(geoMesh->buildDirectionVectorField());
428   MCAuto<DataArrayDouble> rot(dir->getArray()->fromCartToSpher());
429   int nbCompo(ptsForLoc->getNumberOfComponents());
430   MCAuto<DataArrayDouble> secPts(section->getCoords()->changeNbOfComponents(nbCompo,0.));
431   int nbSecPts(secPts->getNumberOfTuples()),nbCells(geoMesh->getNumberOfCells()),nbg(loc.getGaussWeights().size());
432   {
433     const int TAB[3]={2,0,1};
434     std::vector<int> v(TAB,TAB+3);
435     secPts=secPts->keepSelectedComponents(v);
436   }
437   const double CENTER[3]={0.,0.,0.},AX0[3]={0.,0.,1.};
438   double AX1[3]; AX1[2]=0.;
439   std::vector< MCAuto<DataArrayDouble> > arrs(nbCells*nbg);
440   for(int j=0;j<nbCells;j++)
441     {
442       MCAuto<DataArrayDouble> p(secPts->deepCopy());
443       double ang0(rot->getIJ(j,2));
444       DataArrayDouble::Rotate3DAlg(CENTER,AX0,ang0,nbSecPts,p->begin(),p->getPointer());
445       AX1[0]=-sin(ang0); AX1[1]=cos(ang0);// rot Oy around OZ
446       double ang1(M_PI/2.-rot->getIJ(j,1));
447       DataArrayDouble::Rotate3DAlg(CENTER,AX1,-ang1,nbSecPts,p->begin(),p->getPointer());
448       DataArrayDouble::Rotate3DAlg(CENTER,dir->getArray()->begin()+j*3,angleVrille->getIJ(j,0),nbSecPts,p->begin(),p->getPointer());
449       for(int l=0;l<nbg;l++)
450         {
451           MCAuto<DataArrayDouble> p2(p->deepCopy());
452           for(int k=0;k<nbCompo;k++)
453             p2->applyLin(1.,ptsForLoc->getIJ(j*nbg+l,k),k);
454           arrs[j*nbg+l]=p2;
455         }
456     }
457   std::vector<const DataArrayDouble *> arrs2(VecAutoToVecOfCstPt(arrs));
458   MCAuto<DataArrayDouble> resu(DataArrayDouble::Aggregate(arrs2));
459   return resu;
460 }
461
462 MCAuto<DataArrayDouble> LocInfo::BuildMeshFromEpaisseur(INTERP_KERNEL::NormalizedCellType gt, const DataArrayDouble *thikness, const std::string& pfl, const MEDFileFieldLoc& loc, const MEDFileEltStruct4Mesh *zeStr, const MEDFileUMesh *mesh, const MEDFileUMesh *section, const MEDFileFieldGlobsReal *globs)
463 {
464 #if __cplusplus >= 201103L
465   MCAuto<DataArrayDouble> ptsForLoc;
466   MCAuto<MEDCouplingUMesh> geoMesh(BuildMeshCommon(gt,pfl,loc,zeStr,mesh,section,globs,ptsForLoc));
467   int nbSecPts(section->getNumberOfNodes()),nbCells(geoMesh->getNumberOfCells()),nbg(loc.getGaussWeights().size());
468   MCConstAuto<DataArrayDouble> zeThikness;
469   if(!pfl.empty())
470     {
471       const DataArrayInt *pflArr(globs->getProfile(pfl));
472       zeThikness=thikness->selectByTupleIdSafe(pflArr->begin(),pflArr->end());
473     }
474   else
475     zeThikness.takeRef(thikness);
476   MCAuto<DataArrayDouble> orthoArr;
477   {
478     MCAuto<MEDCouplingFieldDouble> ortho(geoMesh->buildOrthogonalField());
479     orthoArr.takeRef(ortho->getArray());
480   }
481   int nbCompo(orthoArr->getNumberOfComponents());
482   MCAuto<DataArrayDouble> secPts(section->getCoords()->duplicateEachTupleNTimes(nbCompo));
483   secPts->rearrange(nbCompo);
484   std::vector< MCAuto<DataArrayDouble> > arrs(nbCells*nbg);
485   for(int j=0;j<nbCells;j++)
486     {
487       double thck(zeThikness->getIJ(j,0)),eccentricity(zeThikness->getIJ(j,1));
488       MCAuto<DataArrayDouble> fact(DataArrayDouble::New()),fact2(DataArrayDouble::New()); fact->alloc(1,nbCompo); fact2->alloc(1,nbCompo);
489       std::copy(orthoArr->begin()+j*nbCompo,orthoArr->begin()+(j+1)*nbCompo,fact->getPointer());
490       std::copy(orthoArr->begin()+j*nbCompo,orthoArr->begin()+(j+1)*nbCompo,fact2->getPointer());
491       std::for_each(fact2->rwBegin(),fact2->rwEnd(),[eccentricity](double& val){ val*=eccentricity; });
492       std::transform(fact->begin(),fact->end(),fact->getPointer(),[thck](const double& val){ return val*thck/2.; });
493       MCAuto<DataArrayDouble> p(DataArrayDouble::Multiply(secPts,fact));
494       p=DataArrayDouble::Add(p,fact2);
495       for(int l=0;l<nbg;l++)
496         {
497           MCAuto<DataArrayDouble> p2(p->deepCopy());
498           for(int k=0;k<nbCompo;k++)
499             p2->applyLin(1.,ptsForLoc->getIJ(j*nbg+l,k),k);
500           arrs[j*nbg+l]=p2;
501         }
502     }
503   std::vector<const DataArrayDouble *> arrs2(VecAutoToVecOfCstPt(arrs));
504   MCAuto<DataArrayDouble> resu(DataArrayDouble::Aggregate(arrs2));
505   return resu;
506 #else
507   throw INTERP_KERNEL::Exception("Broken news : 10% off for C++11 compiler :)");
508 #endif
509 }
510
511 MCAuto<DataArrayDouble> LocInfo::BuildMeshPipeSEG3(const DataArrayDouble *angle, const DataArrayDouble *scale, const std::string& pfl, const MEDFileFieldLoc& loc, const MEDFileEltStruct4Mesh *zeStr, const MEDFileUMesh *mesh, const MEDFileUMesh *section, const MEDFileFieldGlobsReal *globs)
512 {
513 #if __cplusplus >= 201103L
514   static const char MSG1[]="BuildMeshPipeSEG3 : not recognized pattern ! Send mail to anthony.geay@edf.fr with corresponding MED file !";
515   MCAuto<DataArrayDouble> ptsForLoc;
516   MCAuto<MEDCouplingUMesh> geoMesh(BuildMeshCommon(INTERP_KERNEL::NORM_SEG3,pfl,loc,zeStr,mesh,section,globs,ptsForLoc));
517   int nbSecPts(section->getNumberOfNodes()),nbCells(geoMesh->getNumberOfCells()),nbg(loc.getGaussWeights().size());
518   MCConstAuto<DataArrayDouble> zeAngle,zeScale;
519   if(!pfl.empty())
520     {
521       const DataArrayInt *pflArr(globs->getProfile(pfl));
522       zeAngle=angle->selectByTupleIdSafe(pflArr->begin(),pflArr->end());
523       zeScale=scale->selectByTupleIdSafe(pflArr->begin(),pflArr->end());
524     }
525   else
526     {
527       zeAngle.takeRef(angle);
528       zeScale.takeRef(scale);
529     }
530   if(zeAngle->getNumberOfComponents()!=3 || zeScale->getNumberOfComponents()!=2 || nbg!=3)
531     throw INTERP_KERNEL::Exception(MSG1);
532   MCAuto<MEDCouplingFieldDouble> dir;
533   {
534     MCAuto<MEDCouplingUMesh> geoMesh2(geoMesh->deepCopy());
535     geoMesh2->convertQuadraticCellsToLinear();
536     dir=geoMesh2->buildDirectionVectorField();
537   }
538   MCAuto<DataArrayDouble> rot(dir->getArray()->fromCartToSpher());
539   int nbCompo(ptsForLoc->getNumberOfComponents());
540   MCAuto<DataArrayDouble> secPts(section->getCoords()->changeNbOfComponents(nbCompo,0.));
541   {
542     const int TAB[3]={2,0,1};
543     std::vector<int> v(TAB,TAB+3);
544     secPts=secPts->keepSelectedComponents(v);
545   }
546   const double CENTER[3]={0.,0.,0.},AX0[3]={0.,0.,1.};
547   double AX1[3]; AX1[2]=0.;
548   std::vector< MCAuto<DataArrayDouble> > arrs(nbCells*nbg);
549   for(int j=0;j<nbCells;j++)
550     {
551       constexpr int DIM=3;
552       MCAuto<DataArrayDouble> p(secPts->deepCopy());
553       double ang0(rot->getIJ(j,2));
554       double rmin(zeScale->getIJ(j,0)),rmax(zeScale->getIJ(j,1));
555       {
556         auto pt(p->rwBegin());
557         for(int i=0;i<nbSecPts;i++)
558           {
559             auto nrm(sqrt(std::accumulate(pt,pt+DIM,0.,[](double sum, double v) { return sum+v*v; } )));
560             auto sca((rmin+2.*(nrm-0.5)*(rmax-rmin))/nrm);
561             std::for_each(pt,pt+3,[sca](double& val) { val*=sca; } );
562             std::advance(pt,DIM);
563           }
564       }
565       DataArrayDouble::Rotate3DAlg(CENTER,AX0,ang0,nbSecPts,p->begin(),p->getPointer());
566       AX1[0]=-sin(ang0); AX1[1]=cos(ang0);// rot Oy around OZ
567       double ang1(M_PI/2.-rot->getIJ(j,1));
568       DataArrayDouble::Rotate3DAlg(CENTER,AX1,-ang1,nbSecPts,p->begin(),p->getPointer());
569       for(int l=0;l<3;l++)
570         {
571           MCAuto<DataArrayDouble> p3(p->deepCopy());
572           DataArrayDouble::Rotate3DAlg(CENTER,dir->getArray()->begin()+j*3,zeAngle->getIJ(j,l),nbSecPts,p3->begin(),p3->getPointer());
573           MCAuto<DataArrayDouble> p2(p3->deepCopy());
574           for(int k=0;k<nbCompo;k++)
575             p2->applyLin(1.,ptsForLoc->getIJ(j*nbg+l,k),k);
576           arrs[j*nbg+l]=p2;
577         }
578     }
579   std::vector<const DataArrayDouble *> arrs2(VecAutoToVecOfCstPt(arrs));
580   MCAuto<DataArrayDouble> resu(DataArrayDouble::Aggregate(arrs2));
581   return resu;
582 #else
583   throw INTERP_KERNEL::Exception("Broken news : 10% off for C++11 compiler :)");
584 #endif
585 }
586
587 MCAuto<DataArrayDouble> LocInfo::BuildMeshFromStructure(INTERP_KERNEL::NormalizedCellType gt, const std::string& pfl, const MEDFileFieldLoc& loc, const MEDFileEltStruct4Mesh *zeStr, const MEDFileUMesh *mesh, const MEDFileUMesh *section, const MEDFileFieldGlobsReal *globs)
588 {
589   static const char MSG1[]="BuildMeshFromStructure : not recognized pattern ! Send mail to anthony.geay@edf.fr with corresponding MED file !";
590   const std::vector< MCAuto<DataArray> >& vars(zeStr->getVars());
591   if(vars.size()==1)
592     {
593       MCAuto<DataArray> zeArr(vars[0]);
594       if(zeArr.isNull())
595         throw INTERP_KERNEL::Exception(MSG1);
596       MCAuto<DataArrayDouble> zeArr2(DynamicCast<DataArray,DataArrayDouble>(zeArr));
597       if(zeArr2.isNull())
598         throw INTERP_KERNEL::Exception(MSG1);
599       if(zeArr2->getName()==ANGLE_DE_VRILLE || zeArr2->getName()==ANGLE)
600         return BuildMeshFromAngleVrille(gt,zeArr2,pfl,loc,zeStr,mesh,section,globs);
601       if(zeArr2->getName()==EPAISSEUR || zeArr2->getName()==SCALE)
602         return BuildMeshFromEpaisseur(gt,zeArr2,pfl,loc,zeStr,mesh,section,globs);
603     }
604   if(vars.size()==2)
605     {
606       MCAuto<DataArray> zeArr0(vars[0]),zeArr1(vars[1]);
607       if(zeArr0.isNull() || zeArr1.isNull())
608         throw INTERP_KERNEL::Exception(MSG1);
609       MCAuto<DataArrayDouble> zeArr00(DynamicCastSafe<DataArray,DataArrayDouble>(zeArr0)),zeArr11(DynamicCastSafe<DataArray,DataArrayDouble>(zeArr1));
610       switch(gt)
611       {
612         case INTERP_KERNEL::NORM_SEG3:
613           {
614             MCAuto<DataArrayDouble> angle,scale;
615             if(zeArr00->getName()==ANGLE)
616               angle=zeArr00;
617             if(zeArr00->getName()==SCALE)
618               scale=zeArr00;
619             if(zeArr11->getName()==ANGLE)
620               angle=zeArr11;
621             if(zeArr11->getName()==SCALE)
622               scale=zeArr11;
623             if(angle.isNull() || scale.isNull())
624               throw INTERP_KERNEL::Exception(MSG1);
625             return BuildMeshPipeSEG3(angle,scale,pfl,loc,zeStr,mesh,section,globs);
626           }
627         default:
628           throw INTERP_KERNEL::Exception(MSG1);
629       }
630     }
631   throw INTERP_KERNEL::Exception(MSG1);
632 }
633
634 MCAuto<MEDFileUMesh> LocInfo::generateNonClassicalData(int zePos, const MEDFileUMesh *mesh, const MEDFileFieldGlobsReal *globs) const
635 {
636   static const char MSG1[]="LocInfo::generateNonClassicalData : no spec for GAUSS on StructureElement with more than one cell !";
637   std::size_t sz(_locs.size());
638   std::vector< MCAuto<DataArrayDouble> > arrs(sz);
639   for(std::size_t i=0;i<sz;i++)
640     {
641       const MEDFileFieldLoc& loc(globs->getLocalization(_locs[i]));
642       const MEDFileGTKeeper *gtk(loc.getUndergroundGTKeeper());
643       const MEDFileGTKeeperDyn *gtk2(dynamic_cast<const MEDFileGTKeeperDyn *>(gtk));
644       if(!gtk2)
645         throw INTERP_KERNEL::Exception("LocInfo::generateNonClassicalData : internal error !");
646       const MEDFileUMesh *meshLoc(gtk2->getMesh()),*section(gtk2->getSection());
647       const MEDFileStructureElement *se(gtk2->getSE());
648       INTERP_KERNEL::NormalizedCellType gt;
649       {
650         std::vector<int> nel(meshLoc->getNonEmptyLevels());
651         if(nel.size()!=1)
652           throw INTERP_KERNEL::Exception(MSG1);
653         if(nel[0]!=0)
654           throw INTERP_KERNEL::Exception(MSG1);
655         MCAuto<MEDCouplingUMesh> um(meshLoc->getMeshAtLevel(0));
656         if(um->getNumberOfCells()!=1)
657           throw INTERP_KERNEL::Exception(MSG1);
658         gt=um->getTypeOfCell(0);
659         std::vector<int> v;
660         um->getNodeIdsOfCell(0,v);
661         std::size_t sz2(v.size());
662         for(std::size_t j=0;j<sz2;j++)
663           if(v[j]!=j)
664             throw INTERP_KERNEL::Exception(MSG1);
665       }
666       const std::vector< MCAuto<MEDFileEltStruct4Mesh> >& strs(mesh->getAccessOfUndergroundEltStrs());
667       MCAuto<MEDFileEltStruct4Mesh> zeStr;
668       for(std::vector< MCAuto<MEDFileEltStruct4Mesh> >::const_iterator it=strs.begin();it!=strs.end();it++)
669         {
670           if((*it)->getGeoTypeName()==se->getName())
671             {
672               zeStr=*it;
673               break;
674             }
675         }
676       if(zeStr.isNull())
677         {
678           std::ostringstream oss; oss << "LocInfo::generateNonClassicalData :  : no geo type with name " <<  se->getName() << " in " << mesh->getName() << " !";
679           throw INTERP_KERNEL::Exception(oss.str());
680         }
681       arrs[i]=BuildMeshFromStructure(gt,_pfl[i],loc,zeStr,mesh,section,globs);
682     }
683   std::vector<const DataArrayDouble *> arrs2(VecAutoToVecOfCstPt(arrs));
684   MCAuto<DataArrayDouble> resu(DataArrayDouble::Aggregate(arrs2));
685   MCAuto<MEDFileUMesh> ret(MEDFileUMesh::New());
686   ret->setCoords(resu);
687   std::ostringstream meshName; meshName << mesh->getName() << "_on_" << sz << "_sections" << "_" << zePos;
688   ret->setName(meshName.str());
689   return ret;
690 }
691
692 FieldWalker2::FieldWalker2(const MEDFileFieldPerMeshPerTypePerDisc *pmptpd)
693 {
694   _loc=pmptpd->getLocalization();
695   _pfl=pmptpd->getProfile();
696   _is_classic=pmptpd->getType()!=ON_GAUSS_PT;
697   _pd=SlicePartDefinition::New(pmptpd->getStart(),pmptpd->getEnd(),1);
698 }
699
700 bool FieldWalker2::operator!=(const FieldWalker2& other) const
701 {
702   return !((*this)==other);
703 }
704
705 bool FieldWalker2::operator==(const FieldWalker2& other) const
706 {
707   bool ret2(false);
708   {
709     std::string tmp;
710     ret2=_pd->isEqual(other._pd,tmp);
711   }
712   bool ret(_loc==other._loc && _pfl==other._pfl && _is_classic==other._is_classic && ret2);
713   return ret;
714 }
715
716 class FieldWalker1
717 {
718 public:
719   FieldWalker1(const MEDFileAnyTypeField1TSWithoutSDA *ts):_ts(ts),_pm_pt(0),_nb_mesh(0) { }
720   void newMeshEntry(const MEDFileFieldPerMesh *fpm);
721   void endMeshEntry(const MEDFileFieldPerMesh *fpm) { }
722   void newPerMeshPerTypeEntry(const MEDFileFieldPerMeshPerTypeCommon *pmpt);
723   void endPerMeshPerTypeEntry(const MEDFileFieldPerMeshPerTypeCommon *pmpt);
724   void newPerMeshPerTypePerDisc(const MEDFileFieldPerMeshPerTypePerDisc *pmptpd);
725   void checkOK(const FieldWalker1& other) const;
726   bool isClassical() const;
727   std::vector<FieldWalker2> getNonClassicalData() const { return _fw; }
728 private:
729   const MEDFileAnyTypeField1TSWithoutSDA *_ts;
730   const MEDFileFieldPerMeshPerTypeDyn *_pm_pt;
731   std::vector<FieldWalker2> _fw;
732   int _nb_mesh;
733 };
734
735 void FieldWalker1::newMeshEntry(const MEDFileFieldPerMesh *fpm)
736 {
737   if(_nb_mesh++==1)
738     throw INTERP_KERNEL::Exception("FieldWalker1::newMeshEntry : multi mesh not supported !");
739 }
740
741 void FieldWalker1::newPerMeshPerTypeEntry(const MEDFileFieldPerMeshPerTypeCommon *pmpt)
742 {
743   if(_pm_pt)
744     throw INTERP_KERNEL::Exception("FieldWalker1::newPerMeshPerTypeEntry : multi SE loc not managed yet !");
745   const MEDFileFieldPerMeshPerTypeDyn *pmpt2(dynamic_cast<const MEDFileFieldPerMeshPerTypeDyn *>(pmpt));
746   if(!pmpt2)
747     throw INTERP_KERNEL::Exception("newPerMeshPerTypeEntry : internal error !");
748   _pm_pt=pmpt2;
749 }
750
751 void FieldWalker1::endPerMeshPerTypeEntry(const MEDFileFieldPerMeshPerTypeCommon *)
752 {
753   isClassical();
754 }
755
756 void FieldWalker1::newPerMeshPerTypePerDisc(const MEDFileFieldPerMeshPerTypePerDisc *pmptpd)
757 {
758   _fw.push_back(FieldWalker2(pmptpd));
759 }
760
761 void FieldWalker1::checkOK(const FieldWalker1& other) const
762 {
763   std::size_t sz(_fw.size());
764   if(other._fw.size()!=sz)
765     throw INTERP_KERNEL::Exception("checkOK : not OK because size are not the same !");
766   for(std::size_t i=0;i<sz;i++)
767     if(_fw[i]!=other._fw[i])
768       throw INTERP_KERNEL::Exception("checkOK : not OK because an element mismatches !");
769 }
770
771 bool FieldWalker1::isClassical() const
772 {
773   if(_fw.empty())
774     throw INTERP_KERNEL::Exception("FieldWalker1::endPerMeshPerTypeEntry : internal error !");
775   std::size_t ic(0),inc(0);
776   for(std::vector<FieldWalker2>::const_iterator it=_fw.begin();it!=_fw.end();it++)
777     {
778       if((*it).isClassic())
779         ic++;
780       else
781         inc++;
782     }
783   if(ic!=0 && inc!=0)
784     throw INTERP_KERNEL::Exception("FieldWalker1::endPerMeshPerTypeEntry : mix is not allowed yet !");
785   return inc==0;
786 }
787
788 class FieldWalker
789 {
790 public:
791   FieldWalker(const MEDFileAnyTypeFieldMultiTSWithoutSDA *f):_f(f) { }
792   void newTimeStepEntry(const MEDFileAnyTypeField1TSWithoutSDA *ts);
793   void endTimeStepEntry(const MEDFileAnyTypeField1TSWithoutSDA *ts);
794   void newMeshEntry(const MEDFileFieldPerMesh *fpm);
795   void endMeshEntry(const MEDFileFieldPerMesh *fpm);
796   void newPerMeshPerTypeEntry(const MEDFileFieldPerMeshPerTypeCommon *pmpt);
797   void endPerMeshPerTypeEntry(const MEDFileFieldPerMeshPerTypeCommon *pmpt);
798   void newPerMeshPerTypePerDisc(const MEDFileFieldPerMeshPerTypePerDisc *pmptpd);
799 public:
800   bool isEmpty() const;
801   bool isClassical() const;
802   const MEDFileAnyTypeFieldMultiTSWithoutSDA *field() const { return _f; }
803   std::vector<FieldWalker2> getNonClassicalData() const { return _fw_prev->getNonClassicalData(); }
804 private:
805   const MEDFileAnyTypeFieldMultiTSWithoutSDA *_f;
806   mutable INTERP_KERNEL::AutoCppPtr<FieldWalker1> _fw;
807   mutable INTERP_KERNEL::AutoCppPtr<FieldWalker1> _fw_prev;
808 };
809
810 bool FieldWalker::isEmpty() const
811 {
812   return _fw_prev.isNull();
813 }
814
815 bool FieldWalker::isClassical() const
816 {
817   return _fw_prev->isClassical();
818 }
819
820 void FieldWalker::newTimeStepEntry(const MEDFileAnyTypeField1TSWithoutSDA *ts)
821 {
822   _fw=new FieldWalker1(ts);
823 }
824
825 void FieldWalker::endTimeStepEntry(const MEDFileAnyTypeField1TSWithoutSDA *ts)
826 {
827   if(_fw_prev.isNull())
828     _fw_prev=new FieldWalker1(*_fw);
829   else
830     _fw_prev->checkOK(*_fw);
831   _fw=0;
832 }
833
834 void FieldWalker::newMeshEntry(const MEDFileFieldPerMesh *fpm)
835 {
836   _fw->newMeshEntry(fpm);
837 }
838
839 void FieldWalker::endMeshEntry(const MEDFileFieldPerMesh *fpm)
840 {
841   _fw->endMeshEntry(fpm);
842 }
843
844 void FieldWalker::newPerMeshPerTypeEntry(const MEDFileFieldPerMeshPerTypeCommon *pmpt)
845 {
846   _fw->newPerMeshPerTypeEntry(pmpt);
847 }
848
849 void FieldWalker::endPerMeshPerTypeEntry(const MEDFileFieldPerMeshPerTypeCommon *pmpt)
850 {
851   _fw->endPerMeshPerTypeEntry(pmpt);
852 }
853
854 void FieldWalker::newPerMeshPerTypePerDisc(const MEDFileFieldPerMeshPerTypePerDisc *pmptpd)
855 {
856   _fw->newPerMeshPerTypePerDisc(pmptpd);
857 }
858
859 // this class splits fields into same
860 class LocSpliter : public MEDFileFieldVisitor
861 {
862 public:
863   LocSpliter(const MEDFileFieldGlobsReal *globs):_globs(globs),_fw(0) { }
864   MCAuto<MEDFileFields> getClassical() const { return _classical; }
865   void generateNonClassicalData(const MEDFileUMesh *mesh, std::vector< MCAuto<MEDFileFields> >& outFields, std::vector< MCAuto<MEDFileUMesh> >& outMeshes) const;
866 private:
867   void newFieldEntry(const MEDFileAnyTypeFieldMultiTSWithoutSDA *field);
868   void endFieldEntry(const MEDFileAnyTypeFieldMultiTSWithoutSDA *field);
869   //
870   void newTimeStepEntry(const MEDFileAnyTypeField1TSWithoutSDA *ts);
871   void endTimeStepEntry(const MEDFileAnyTypeField1TSWithoutSDA *ts);
872   //
873   void newMeshEntry(const MEDFileFieldPerMesh *fpm);
874   void endMeshEntry(const MEDFileFieldPerMesh *fpm);
875   //
876   void newPerMeshPerTypeEntry(const MEDFileFieldPerMeshPerTypeCommon *pmpt);
877   void endPerMeshPerTypeEntry(const MEDFileFieldPerMeshPerTypeCommon *pmpt);
878   //
879   void newPerMeshPerTypePerDisc(const MEDFileFieldPerMeshPerTypePerDisc *pmptpd);
880 private:
881   const MEDFileFieldGlobsReal *_globs;
882   std::vector< LocInfo > _locs;
883   std::vector< MCAuto<MEDFileFields> > _fields_on_locs;//size of _locs== size of _fields_on_locs
884   MCAuto<MEDFileFields> _classical;
885 private:
886   mutable INTERP_KERNEL::AutoCppPtr<FieldWalker> _fw;
887 };
888
889 void LocSpliter::newFieldEntry(const MEDFileAnyTypeFieldMultiTSWithoutSDA *field)
890 {
891   _fw=new FieldWalker(field);
892 }
893
894 void LocSpliter::endFieldEntry(const MEDFileAnyTypeFieldMultiTSWithoutSDA *field)
895 {
896   if(_fw->isEmpty())
897     return ;
898   MCAuto<MEDFileAnyTypeFieldMultiTS> f(MEDFileAnyTypeFieldMultiTS::BuildNewInstanceFromContent(const_cast<MEDFileAnyTypeFieldMultiTSWithoutSDA *>(field)));
899   if(_fw->isClassical())
900     {
901       if(_classical.isNull())
902         {
903           _classical=MEDFileFields::New();
904           _classical->shallowCpyGlobs(*_globs);
905         }
906       _classical->pushField(f);
907     }
908   else
909     {
910       std::vector<FieldWalker2> fw2(_fw->getNonClassicalData());
911       LocInfo elt(fw2);
912       std::vector< LocInfo >::iterator it(std::find(_locs.begin(),_locs.end(),elt));
913       if(it==_locs.end())
914         {
915           _locs.push_back(elt);
916           MCAuto<MEDFileFields> zeF(MEDFileFields::New());
917           zeF->shallowCpyGlobs(*_globs);
918           zeF->pushField(f);
919           _fields_on_locs.push_back(zeF);
920         }
921       else
922         {
923           MCAuto<MEDFileFields> zeF(_fields_on_locs[std::distance(_locs.begin(),it)]);
924           zeF->pushField(f);
925         }
926     }
927 }
928
929 void LocSpliter::generateNonClassicalData(const MEDFileUMesh *mesh, std::vector< MCAuto<MEDFileFields> >& outFields, std::vector< MCAuto<MEDFileUMesh> >& outMeshes) const
930 {
931   int i(0);
932   for(std::vector<LocInfo>::const_iterator it=_locs.begin();it!=_locs.end();it++,i++)
933     {
934       MCAuto<MEDFileUMesh> m((*it).generateNonClassicalData(i,mesh,_globs));
935       outMeshes.push_back(m);
936       MCAuto<MEDCouplingUMesh> mcm(MEDCouplingUMesh::Build0DMeshFromCoords(m->getCoords()));
937       mcm->setName(m->getName());
938       MCAuto<MEDFileFields> fs(_fields_on_locs[i]);
939       MCAuto<MEDFileFields> outFs(MEDFileFields::New());
940       for(int j=0;j<fs->getNumberOfFields();j++)
941         {
942           MCAuto<MEDFileAnyTypeFieldMultiTS> fmtsNC(fs->getFieldAtPos(j));
943           MCAuto<MEDFileFieldMultiTS> fmts(DynamicCastSafe<MEDFileAnyTypeFieldMultiTS,MEDFileFieldMultiTS>(fmtsNC));
944           MCAuto<MEDFileFieldMultiTS> outFmts(MEDFileFieldMultiTS::New());
945           for(int k=0;k<fmts->getNumberOfTS();k++)
946             {
947               MCAuto<MEDFileField1TS> outF1t(MEDFileField1TS::New());
948               MCAuto<MEDFileField1TS> f1ts(fmts->getTimeStepAtPos(k));
949               int t2,t3;
950               double t1(f1ts->getTime(t2,t3));
951               MCAuto<MEDCouplingFieldDouble> mcf(MEDCouplingFieldDouble::New(ON_NODES));
952               MCAuto<DataArrayDouble> arr,arr2;
953               arr.takeRef(f1ts->getUndergroundDataArray());
954               arr2=arr->selectPartDef((*it).getPartDef());
955               mcf->setArray(arr2);
956               mcf->setTime(t1,t2,t3);
957               mcf->setName(f1ts->getName());
958               mcf->setMesh(mcm);
959               outF1t->setFieldNoProfileSBT(mcf);
960               outFmts->pushBackTimeStep(outF1t);
961             }
962           outFs->pushField(outFmts);
963         }
964       outFields.push_back(outFs);
965     }
966 }
967
968 void LocSpliter::newTimeStepEntry(const MEDFileAnyTypeField1TSWithoutSDA *ts)
969 {
970   _fw->newTimeStepEntry(ts);
971 }
972
973 void LocSpliter::endTimeStepEntry(const MEDFileAnyTypeField1TSWithoutSDA *ts)
974 {
975   _fw->endTimeStepEntry(ts);
976 }
977
978 void LocSpliter::newMeshEntry(const MEDFileFieldPerMesh *fpm)
979 {
980   _fw->newMeshEntry(fpm);
981 }
982
983 void LocSpliter::endMeshEntry(const MEDFileFieldPerMesh *fpm)
984 {
985   _fw->endMeshEntry(fpm);
986 }
987
988 void LocSpliter::newPerMeshPerTypeEntry(const MEDFileFieldPerMeshPerTypeCommon *pmpt)
989 {
990   _fw->newPerMeshPerTypeEntry(pmpt);
991 }
992
993 void LocSpliter::endPerMeshPerTypeEntry(const MEDFileFieldPerMeshPerTypeCommon *pmpt)
994 {
995   _fw->endPerMeshPerTypeEntry(pmpt);
996 }
997
998 void LocSpliter::newPerMeshPerTypePerDisc(const MEDFileFieldPerMeshPerTypePerDisc *pmptpd)
999 {
1000   _fw->newPerMeshPerTypePerDisc(pmptpd);
1001 }
1002
1003 void MEDFileBlowStrEltUp::DealWithConflictNames(MEDFileAnyTypeFieldMultiTS *fmtsToAdd, const MEDFileFields *fs)
1004 {
1005   std::vector<std::string> fnames(fs->getFieldsNames());
1006   for(int i=0;i<1000;i++)
1007     {
1008       std::ostringstream oss; oss << fmtsToAdd->getName();
1009       if(i>=1)
1010         oss << "_" << i-1;
1011       if(std::find(fnames.begin(),fnames.end(),oss.str())==fnames.end())
1012         {
1013           fmtsToAdd->setName(oss.str());
1014           return ;
1015         }
1016     }
1017   throw INTERP_KERNEL::Exception("DealWithConflictNames : Eh eh interesting !");
1018 }
1019
1020 MCAuto<MEDFileFields> MEDFileBlowStrEltUp::splitFieldsPerLoc(const MEDFileFields *fields, const MEDFileUMesh *mesh, MEDFileMeshes *msOut, MEDFileFields *allZeOutFields)
1021 {
1022   LocSpliter ls(fields);
1023   fields->accept(ls);
1024   std::vector< MCAuto<MEDFileFields> > outFields;
1025   std::vector< MCAuto<MEDFileUMesh> > outMeshes;
1026   ls.generateNonClassicalData(mesh,outFields,outMeshes);
1027   for(std::vector< MCAuto<MEDFileFields> >::iterator it=outFields.begin();it!=outFields.end();it++)
1028     {
1029       for(int j=0;j<(*it)->getNumberOfFields();j++)
1030         {
1031           MCAuto<MEDFileAnyTypeFieldMultiTS> fmts((*it)->getFieldAtPos(j));
1032           //DealWithConflictNames(fmts,allZeOutFields);// uncomment to have a writable data structure
1033           allZeOutFields->pushField(fmts);
1034         }
1035     }
1036   for(std::vector< MCAuto<MEDFileUMesh> >::iterator it=outMeshes.begin();it!=outMeshes.end();it++)
1037     msOut->pushMesh(*it);
1038   return ls.getClassical();
1039 }