Salome HOME
Management of pfls
[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
24 using namespace MEDCoupling;
25
26 const char MEDFileBlowStrEltUp::MED_BALL_STR[]="MED_BALL";
27
28 MEDFileBlowStrEltUp::MEDFileBlowStrEltUp(const MEDFileFields *fsOnlyOnSE, const MEDFileMeshes *ms, const MEDFileStructureElements *ses)
29 {
30   if(!fsOnlyOnSE || !ms || !ses)
31     throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp constructor : NULL input pointer !");
32   _ms.takeRef(ms); _ses.takeRef(ses);
33   std::vector< std::pair<std::string,std::string> > ps;
34   fsOnlyOnSE->getMeshSENames(ps);
35   std::size_t sz(ps.size());
36   _elts.resize(sz);
37   for(std::size_t i=0;i<sz;i++)
38     {
39       const std::pair<std::string,std::string>& p(ps[i]);
40       MCAuto<MEDFileFields> f(fsOnlyOnSE->partOfThisLyingOnSpecifiedMeshSEName(p.first,p.second));
41       _elts[i]=f;
42     }
43   for(std::size_t i=0;i<sz;i++)
44     {
45       const std::pair<std::string,std::string>& p(ps[i]);
46       MEDFileMesh *mesh(_ms->getMeshWithName(p.first));
47       if(!mesh)
48         throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp : NULL mesh !");
49       MEDFileUMesh *umesh(dynamic_cast<MEDFileUMesh *>(mesh));
50       if(!umesh)
51         throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp : Blow up of Stru Elt not managed yet for unstructured meshes !");
52     }
53 }
54
55 /*!
56  * \param [in] mesh - The mesh containing structure element called \a seName. After the call of this method the Structure elements parts will be removed.
57  * \param [out] mOut - the physical mesh of the structure element \a seName in mesh \a mesh
58  * \param [out] fsOut - the list of var attribute of structure element \a seName - \b WARNING no time steps here
59  */
60 MCAuto<MEDFileEltStruct4Mesh> MEDFileBlowStrEltUp::dealWithSEInMesh(const std::string& seName, MEDFileUMesh *mesh, MCAuto<MEDFileUMesh>& mOut, MCAuto<MEDFileFields>& fsOut) const
61 {
62   if(!mesh)
63     throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithSEInMesh : null pointer !");
64   if(seName==MED_BALL_STR)
65     {
66       MCAuto<MEDFileEltStruct4Mesh> ret(dealWithMEDBALLInMesh(mesh,mOut,fsOut));
67       mesh->killStructureElements();
68       return ret;
69     }
70   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 !");
71 }
72
73 MCAuto<MEDFileEltStruct4Mesh> MEDFileBlowStrEltUp::dealWithMEDBALLInMesh(const MEDFileUMesh *mesh, MCAuto<MEDFileUMesh>& mOut, MCAuto<MEDFileFields>& fsOut) const
74 {
75   mOut=MEDFileUMesh::New(); fsOut=MEDFileFields::New();
76   const std::vector< MCAuto<MEDFileEltStruct4Mesh> >& strs(mesh->getAccessOfUndergroundEltStrs());
77   MCAuto<MEDFileEltStruct4Mesh> zeStr;
78   for(std::vector< MCAuto<MEDFileEltStruct4Mesh> >::const_iterator it=strs.begin();it!=strs.end();it++)
79     {
80       if((*it)->getGeoTypeName()==MED_BALL_STR)
81         {
82           zeStr=*it;
83           break;
84         }
85     }
86   if(zeStr.isNull())
87     {
88       std::ostringstream oss; oss << "MEDFileBlowStrEltUp::dealWithMEDBALLInMesh : no geo type with name " <<  MED_BALL_STR << " in " << mesh->getName() << " !";
89       throw INTERP_KERNEL::Exception(oss.str());
90     }
91   const DataArrayDouble *coo(mesh->getCoords());
92   if(!coo)
93     throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLInMesh : null coords !");
94   MCAuto<DataArrayInt> conn(zeStr->getConn());
95   if(conn.isNull())
96     throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLInMesh : null connectivity !");
97   conn->checkAllocated();
98   if(conn->getNumberOfComponents()!=1)
99     throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLInMesh : excepted to be single compo !");
100   int nbCells(conn->getNumberOfTuples());
101   MCAuto<DataArrayDouble> connOut(coo->selectByTupleIdSafe(conn->begin(),conn->end()));
102   MCAuto<MEDCouplingUMesh> mcOut(MEDCouplingUMesh::Build0DMeshFromCoords(connOut));
103   mcOut->setName(BuildNewMeshName(mesh->getName(),MED_BALL_STR));
104   mOut->setMeshAtLevel(0,mcOut);
105   const DataArrayInt *ff1(mesh->getFamilyFieldAtLevel(1));
106   if(ff1)
107     {
108       MCAuto<DataArrayInt> ff1o(ff1->selectByTupleIdSafe(conn->begin(),conn->end()));
109       mOut->setFamilyFieldArr(1,ff1o);
110     }
111   const DataArrayInt *nf1(mesh->getNumberFieldAtLevel(1));
112   if(nf1)
113     {
114       MCAuto<DataArrayInt> nf1o(nf1->selectByTupleIdSafe(conn->begin(),conn->end()));
115       mOut->setRenumFieldArr(1,nf1o);
116     }
117   MCAuto<MEDFileUMeshPerTypeCommon> md(zeStr->getMeshDef());
118   const DataArrayInt *ff0(md->getFam());
119   if(ff0)
120     mOut->setFamilyFieldArr(0,const_cast<DataArrayInt *>(ff0));
121   const DataArrayInt *nf0(md->getNum());
122   if(nf0)
123     mOut->setRenumFieldArr(0,const_cast<DataArrayInt *>(nf0));
124   mOut->copyFamGrpMapsFrom(*mesh);
125   const std::vector< MCAuto<DataArray> >& vars(zeStr->getVars());
126   for(std::vector< MCAuto<DataArray> >::const_iterator it=vars.begin();it!=vars.end();it++)
127     {
128       const DataArray *elt(*it);
129       if(!elt)
130         continue;
131       {
132         const DataArrayDouble *eltC(dynamic_cast<const DataArrayDouble *>(elt));
133         if(eltC)
134           {
135             MCAuto<MEDFileFieldMultiTS> fmts(MEDFileFieldMultiTS::New());
136             MCAuto<MEDFileField1TS> f1ts(MEDFileField1TS::New());
137             MCAuto<MEDCouplingFieldDouble> f(MEDCouplingFieldDouble::New(ON_NODES));
138             f->setMesh(mcOut);
139             f->setArray(const_cast<DataArrayDouble *>(eltC));
140             f->setName(eltC->getName());
141             f1ts->setFieldNoProfileSBT(f);
142             fmts->pushBackTimeStep(f1ts);
143             fsOut->pushField(fmts);
144           }
145       }
146     }
147   return zeStr;
148 }
149
150 /*!
151  * \param [in] fs - fields lying all on same mesh and on same structure element
152  * \param [in] zeStr - ze structure of current structure element
153  * \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
154  * \param [out] zeOutputs - ze fields that are the concatenation of fields in \a fs transformed and those in \a varAtt normalized in time space
155  */
156 void MEDFileBlowStrEltUp::dealWithSEInFields(const std::string& seName, const MEDFileFields *fs, const MEDFileEltStruct4Mesh *zeStr, const MEDFileFields *varAtt, MEDFileFields *zeOutputs) const
157 {
158   if(!fs)
159     throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithSEInFields : null pointer !");
160   if(seName==MED_BALL_STR)
161     {
162       dealWithMEDBALLSInFields(fs,zeStr,varAtt,zeOutputs);
163       return ;
164     }
165   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 !");
166 }
167
168 void MEDFileBlowStrEltUp::dealWithMEDBALLSInFields(const MEDFileFields *fs, const MEDFileEltStruct4Mesh *zeStr, const MEDFileFields *varAtt, MEDFileFields *zeOutputs) const
169 {
170   int nbf(fs->getNumberOfFields());
171   std::vector< MCAuto<MEDFileAnyTypeFieldMultiTS> > elts0;
172   std::vector< MEDFileAnyTypeFieldMultiTS * > elts1;
173   std::string zeMeshName;
174   for(int i=0;i<nbf;i++)
175     {
176       MCAuto<MEDFileAnyTypeFieldMultiTS> elt(fs->getFieldAtPos(i));
177       MCAuto<MEDFileAnyTypeFieldMultiTS> eltOut(elt->buildNewEmpty());
178       int nbTS(elt->getNumberOfTS());
179       for(int j=0;j<nbTS;j++)
180         {
181           MCAuto<MEDFileAnyTypeField1TS> eltt(elt->getTimeStepAtPos(j));
182           MCAuto<MEDFileAnyTypeField1TS> elttOut(eltt->deepCopy());
183           std::string meshName(eltt->getMeshName());
184           zeMeshName=BuildNewMeshName(meshName,MED_BALL_STR);
185           elttOut->setMeshName(zeMeshName);
186           elttOut->convertMedBallIntoClassic();
187           eltOut->pushBackTimeStep(elttOut);
188         }
189       elts0.push_back(eltOut); elts1.push_back(eltOut);
190     }
191   //
192   const MEDFileMesh *zeCurrentMesh(_ms->getMeshWithName(zeMeshName));
193   //
194   std::size_t ii(0);
195   std::vector< std::vector<MEDFileAnyTypeFieldMultiTS *> > sp(MEDFileAnyTypeFieldMultiTS::SplitIntoCommonTimeSeries(elts1));
196   for(std::vector< std::vector<MEDFileAnyTypeFieldMultiTS *> >::const_iterator it0=sp.begin();it0!=sp.end();it0++,ii++)
197     {
198       std::vector< MCAuto<MEDFileFastCellSupportComparator> > fsc;
199       std::vector< std::vector<MEDFileAnyTypeFieldMultiTS *> > sp2(MEDFileAnyTypeFieldMultiTS::SplitPerCommonSupport(*it0,zeCurrentMesh,fsc));
200       std::size_t jj(0);
201       for(std::vector< std::vector<MEDFileAnyTypeFieldMultiTS *> >::const_iterator it1=sp2.begin();it1!=sp2.end();it1++,jj++)
202         {
203           for(std::vector<MEDFileAnyTypeFieldMultiTS *>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
204             zeOutputs->pushField(*it2);
205           // The most exciting part. Users that put profiles on struct elements part of fields. Reduce var att.
206           if((*it1).size()<1)
207             throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLSInFields : take a deep breath !");
208           MCAuto<MEDFileAnyTypeField1TS> zeGuideForPfl;// This var is the reference for pfl management.
209           {
210             if(!(*it1)[0])
211               throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLSInFields : take a deep breath 2 !");
212             int pdm((*it1)[0]->getNumberOfTS());
213             if(pdm<1)
214               throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLSInFields : take a deep breath 3 !");
215             zeGuideForPfl=(*it1)[0]->getTimeStepAtPos(0);
216           }
217           if(zeGuideForPfl.isNull())
218             throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLSInFields : take a deep breath 4 !");
219           std::vector<std::string> pfls(zeGuideForPfl->getPflsReallyUsed());
220           if(pfls.size()>=2)
221             throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLSInFields : drink less coffee");
222           MCAuto<DataArrayInt> pflMyLove;
223           if(pfls.size()==1)
224             pflMyLove.takeRef(zeGuideForPfl->getProfile(pfls[0]));
225           // Yeah we have pfls
226           std::vector<double> t2s;
227           std::vector< std::pair<int,int> > t1s((*it1)[0]->getTimeSteps(t2s));
228           std::size_t nbTS3(t2s.size());
229           int nbf2(varAtt->getNumberOfFields());
230           for(int i=0;i<nbf2;i++)
231             {
232               MCAuto<MEDFileAnyTypeFieldMultiTS> elt(varAtt->getFieldAtPos(i));
233               int nbTS2(elt->getNumberOfTS());
234               if(nbTS2!=1)
235                 throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLSInFields : internal error ! The dealWithMEDBALLInMesh is expected to return a single TS !");
236               MCAuto<MEDFileAnyTypeField1TS> elt2(elt->getTimeStepAtPos(0));
237               MCAuto<MEDFileAnyTypeFieldMultiTS> elt4(elt->buildNewEmpty());
238               for(std::size_t j=0;j<nbTS3;j++)
239                 {
240                   MCAuto<MEDFileAnyTypeField1TS> elt3(elt2->deepCopy());
241                   elt3->setTime(t1s[j].first,t1s[j].second,t2s[j]);
242                   elt3->setName(BuildVarAttName(ii,sp.size(),jj,sp2.size(),elt3->getName()));
243                   if(pflMyLove.isNotNull())
244                     elt3->makeReduction(INTERP_KERNEL::NORM_ERROR,ON_NODES,pflMyLove);
245                   elt4->pushBackTimeStep(elt3);
246                 }
247               zeOutputs->pushField(elt4);
248             }
249         }
250     }
251 }
252
253 void MEDFileBlowStrEltUp::generate(MEDFileMeshes *msOut, MEDFileFields *allZeOutFields)
254 {
255   for(std::vector< MCAuto<MEDFileFields> >::iterator elt=_elts.begin();elt!=_elts.end();elt++)
256     {
257       std::vector< std::pair<std::string,std::string> > ps;
258       (*elt)->getMeshSENames(ps);
259       if(ps.size()!=1)
260         throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::generateMeshes : internal error !");
261       MEDFileMesh *mesh(_ms->getMeshWithName(ps[0].first));
262       if(!mesh)
263         throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::generateMeshes : NULL mesh !");
264       MEDFileUMesh *umesh(dynamic_cast<MEDFileUMesh *>(mesh));
265       if(!umesh)
266         throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::generateMeshes : Blow up of Stru Elt not managed yet for unstructured meshes !");
267       MCAuto<MEDFileUMesh> mOut;
268       MCAuto<MEDFileFields> fsOut1;
269       MCAuto<MEDFileEltStruct4Mesh> zeStr(dealWithSEInMesh(ps[0].second,umesh,mOut,fsOut1));
270       msOut->pushMesh(mOut);
271       dealWithSEInFields(ps[0].second,*elt,zeStr,fsOut1,allZeOutFields);
272     }
273 }
274
275 std::string MEDFileBlowStrEltUp::BuildNewMeshName(const std::string& meshName, const std::string& seName)
276 {
277   std::ostringstream mNameOut;
278   mNameOut << meshName << "_" << seName;
279   return mNameOut.str();
280 }
281
282 std::string MEDFileBlowStrEltUp::BuildVarAttName(std::size_t iPart, std::size_t totINbParts, std::size_t jPart, std::size_t totJNbParts, const std::string& name)
283 {
284   if(totINbParts==1 && totJNbParts==1)
285     return name;
286   std::ostringstream oss;
287   oss << name << "@" << iPart << "@" << jPart;
288   return oss.str();
289 }
290
291 void MEDFileBlowStrEltUp::DealWithSE(MEDFileFields *fs, MEDFileMeshes *ms, const MEDFileStructureElements *ses)
292 {
293   MCAuto<MEDFileFields> fsSEOnly(fs->partOfThisOnStructureElements());
294   fs->killStructureElements();
295   MEDFileBlowStrEltUp bu(fsSEOnly,ms,ses);
296   bu.generate(ms,fs);
297 }