Salome HOME
fd4dd281f277511ec0cc86d6b7c815ac54167907
[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   for(int i=0;i<nbf;i++)
174     {
175       MCAuto<MEDFileAnyTypeFieldMultiTS> elt(fs->getFieldAtPos(i));
176       MCAuto<MEDFileAnyTypeFieldMultiTS> eltOut(elt->buildNewEmpty());
177       int nbTS(elt->getNumberOfTS());
178       for(int j=0;j<nbTS;j++)
179         {
180           MCAuto<MEDFileAnyTypeField1TS> eltt(elt->getTimeStepAtPos(j));
181           MCAuto<MEDFileAnyTypeField1TS> elttOut(eltt->deepCopy());
182           std::string meshName(eltt->getMeshName());
183           elttOut->setMeshName(BuildNewMeshName(meshName,MED_BALL_STR));
184           elttOut->convertMedBallIntoClassic();
185           eltOut->pushBackTimeStep(elttOut);
186         }
187       elts0.push_back(eltOut); elts1.push_back(eltOut);
188     }
189   //
190   std::size_t ii(0);
191   std::vector< std::vector<MEDFileAnyTypeFieldMultiTS *> > sp(MEDFileAnyTypeFieldMultiTS::SplitIntoCommonTimeSeries(elts1));
192   for(std::vector< std::vector<MEDFileAnyTypeFieldMultiTS *> >::const_iterator it0=sp.begin();it0!=sp.end();it0++,ii++)
193     {
194       for(std::vector<MEDFileAnyTypeFieldMultiTS *>::const_iterator it1=(*it0).begin();it1!=(*it0).end();it1++)
195         zeOutputs->pushField(*it1);
196       std::vector<double> t2s;
197       std::vector< std::pair<int,int> > t1s((*it0)[0]->getTimeSteps(t2s));
198       std::size_t nbTS3(t2s.size());
199       int nbf2(varAtt->getNumberOfFields());
200       for(int i=0;i<nbf2;i++)
201         {
202           MCAuto<MEDFileAnyTypeFieldMultiTS> elt(varAtt->getFieldAtPos(i));
203           int nbTS2(elt->getNumberOfTS());
204           if(nbTS2!=1)
205             throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::dealWithMEDBALLSInFields : internal error ! The dealWithMEDBALLInMesh is expected to return a single TS !");
206           MCAuto<MEDFileAnyTypeField1TS> elt2(elt->getTimeStepAtPos(0));
207           MCAuto<MEDFileAnyTypeFieldMultiTS> elt4(elt->buildNewEmpty());
208           for(std::size_t j=0;j<nbTS3;j++)
209             {
210               MCAuto<MEDFileAnyTypeField1TS> elt3(elt2->deepCopy());
211               elt3->setTime(t1s[j].first,t1s[j].second,t2s[j]);
212               elt3->setName(BuildVarAttName(ii,sp.size(),elt3->getName()));
213               elt4->pushBackTimeStep(elt3);
214             }
215           zeOutputs->pushField(elt4);
216         }
217     }
218   
219 }
220
221 void MEDFileBlowStrEltUp::generate(MEDFileMeshes *msOut, MEDFileFields *allZeOutFields)
222 {
223   for(std::vector< MCAuto<MEDFileFields> >::iterator elt=_elts.begin();elt!=_elts.end();elt++)
224     {
225       std::vector< std::pair<std::string,std::string> > ps;
226       (*elt)->getMeshSENames(ps);
227       if(ps.size()!=1)
228         throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::generateMeshes : internal error !");
229       MEDFileMesh *mesh(_ms->getMeshWithName(ps[0].first));
230       if(!mesh)
231         throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::generateMeshes : NULL mesh !");
232       MEDFileUMesh *umesh(dynamic_cast<MEDFileUMesh *>(mesh));
233       if(!umesh)
234         throw INTERP_KERNEL::Exception("MEDFileBlowStrEltUp::generateMeshes : Blow up of Stru Elt not managed yet for unstructured meshes !");
235       MCAuto<MEDFileUMesh> mOut;
236       MCAuto<MEDFileFields> fsOut1;
237       MCAuto<MEDFileEltStruct4Mesh> zeStr(dealWithSEInMesh(ps[0].second,umesh,mOut,fsOut1));
238       msOut->pushMesh(mOut);
239       dealWithSEInFields(ps[0].second,*elt,zeStr,fsOut1,allZeOutFields);
240     }
241 }
242
243 std::string MEDFileBlowStrEltUp::BuildNewMeshName(const std::string& meshName, const std::string& seName)
244 {
245   std::ostringstream mNameOut;
246   mNameOut << meshName << "_" << seName;
247   return mNameOut.str();
248 }
249
250 std::string MEDFileBlowStrEltUp::BuildVarAttName(std::size_t iPart, std::size_t totNbParts, const std::string& name)
251 {
252   if(totNbParts==1)
253     return name;
254   std::ostringstream oss;
255   oss << name << "@" << iPart;
256   return oss.str();
257 }
258
259 void MEDFileBlowStrEltUp::DealWithSE(MEDFileFields *fs, MEDFileMeshes *ms, const MEDFileStructureElements *ses)
260 {
261   MCAuto<MEDFileFields> fsSEOnly(fs->partOfThisOnStructureElements());
262   fs->killStructureElements();
263   MEDFileBlowStrEltUp bu(fsSEOnly,ms,ses);
264   bu.generate(ms,fs);
265 }