Salome HOME
Useful ConvertMEDFileTo30 tool to change version of a file.
[tools/medcoupling.git] / src / MEDLoader / MEDFileData.cxx
1 // Copyright (C) 2007-2016  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 (CEA/DEN)
20
21 #include "MEDFileData.hxx"
22
23 using namespace MEDCoupling;
24
25 MEDFileData *MEDFileData::New(const std::string& fileName)
26 {
27   MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
28   return New(fid);
29 }
30
31 MEDFileData *MEDFileData::New(med_idt fid)
32 {
33   return new MEDFileData(fid);
34 }
35
36 MEDFileData *MEDFileData::New()
37 {
38   return new MEDFileData;
39 }
40
41 MEDFileData *MEDFileData::deepCopy() const
42 {
43   MCAuto<MEDFileFields> fields;
44   if((const MEDFileFields *)_fields)
45     fields=_fields->deepCopy();
46   MCAuto<MEDFileMeshes> meshes;
47   if((const MEDFileMeshes *)_meshes)
48     meshes=_meshes->deepCopy();
49   MCAuto<MEDFileParameters> params;
50   if((const MEDFileParameters *)_params)
51     params=_params->deepCopy();
52   MCAuto<MEDFileData> ret(MEDFileData::New());
53   ret->_fields=fields; ret->_meshes=meshes; ret->_params=params;
54   return ret.retn();
55 }
56
57 std::size_t MEDFileData::getHeapMemorySizeWithoutChildren() const
58 {
59   return 0;
60 }
61
62 std::vector<const BigMemoryObject *> MEDFileData::getDirectChildrenWithNull() const
63 {
64   std::vector<const BigMemoryObject *> ret;
65   ret.push_back((const MEDFileFields *)_fields);
66   ret.push_back((const MEDFileMeshes *)_meshes);
67   ret.push_back((const MEDFileParameters *)_params);
68   return ret;
69
70 }
71
72 /** Return a borrowed reference (caller is not responsible for object destruction) */
73 MEDFileFields *MEDFileData::getFields() const
74 {
75   return const_cast<MEDFileFields *>(static_cast<const MEDFileFields *>(_fields));
76 }
77
78 /** Return a borrowed reference (caller is not responsible for object destruction) */
79 MEDFileMeshes *MEDFileData::getMeshes() const
80 {
81   return const_cast<MEDFileMeshes *>(static_cast<const MEDFileMeshes *>(_meshes));
82 }
83
84 /** Return a borrowed reference (caller is not responsible for object destruction) */
85 MEDFileParameters *MEDFileData::getParams() const
86 {
87   return const_cast<MEDFileParameters *>(static_cast<const MEDFileParameters *>(_params));
88 }
89
90 void MEDFileData::setFields(MEDFileFields *fields)
91 {
92   if(fields)
93     fields->incrRef();
94   _fields=fields;
95 }
96
97 void MEDFileData::setMeshes(MEDFileMeshes *meshes)
98 {
99   if(meshes)
100     meshes->incrRef();
101   _meshes=meshes;
102 }
103
104 void MEDFileData::setParams(MEDFileParameters *params)
105 {
106   if(params)
107     params->incrRef();
108   _params=params;
109 }
110
111 int MEDFileData::getNumberOfFields() const
112 {
113   const MEDFileFields *f=_fields;
114   if(!f)
115     throw INTERP_KERNEL::Exception("MEDFileData::getNumberOfFields : no fields set !");
116   return f->getNumberOfFields();
117 }
118
119 int MEDFileData::getNumberOfMeshes() const
120 {
121   const MEDFileMeshes *m=_meshes;
122   if(!m)
123     throw INTERP_KERNEL::Exception("MEDFileData::getNumberOfMeshes : no meshes set !");
124   return m->getNumberOfMeshes();
125 }
126
127 int MEDFileData::getNumberOfParams() const
128 {
129   const MEDFileParameters *p=_params;
130   if(!p)
131     throw INTERP_KERNEL::Exception("MEDFileData::getNumberOfParams : no params set !");
132   return p->getNumberOfParams();
133 }
134
135 std::string MEDFileData::simpleRepr() const
136 {
137   std::ostringstream oss;
138   oss << "(***************)\n(* MEDFileData *)\n(***************)\n\nFields part :\n*************\n\n";
139   const MEDFileFields *tmp=_fields;
140   if(tmp)
141     {
142       tmp->simpleRepr(0,oss);
143       oss << std::endl;
144     }
145   else
146     oss << "No fields set !!!\n\n";
147   oss << "Meshes part :\n*************\n\n";
148   const MEDFileMeshes *tmp2=_meshes;
149   if(tmp2)
150     {
151       tmp2->simpleReprWithoutHeader(oss);
152     }
153   else
154     oss << "No meshes set !!!\n\n";
155   oss << "Params part :\n*************\n\n";
156   const MEDFileParameters *tmp3=_params;
157   if(tmp3)
158     {
159       tmp3->simpleReprWithoutHeader(oss);
160     }
161   else
162     oss << "No params set !!!\n";
163   return oss.str();
164 }
165
166 bool MEDFileData::changeMeshNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
167 {
168   bool ret=false;
169   MEDFileFields *fields=_fields;
170   if(fields)
171     ret=fields->changeMeshNames(modifTab) || ret;
172   MEDFileMeshes *meshes=_meshes;
173   if(meshes)
174     ret=meshes->changeNames(modifTab) || ret;
175   return ret;
176 }
177
178 bool MEDFileData::changeMeshName(const std::string& oldMeshName, const std::string& newMeshName)
179 {
180   std::string oldName(oldMeshName);
181   std::vector< std::pair<std::string,std::string> > v(1);
182   v[0].first=oldName; v[0].second=newMeshName;
183   return changeMeshNames(v);
184 }
185
186 /*!
187  * This method performs unpolyzation in meshes in \a this and if it leads to a modification to one or more than one meshes in \a this 
188  * the fields are automatically renumbered (for those impacted, that is to say here fields on cells and fields on gauss points on impacted fields)
189  *
190  * \return If true is returned it means that some meshes in \a this has been modified and eventually fields have been renumbered.
191  *         \n If false \a this remains unchanged.
192  */
193 bool MEDFileData::unPolyzeMeshes()
194 {
195   MEDFileMeshes *ms=_meshes;
196   if(!ms)
197     return false;
198   std::vector< MEDFileMesh * > meshesImpacted;
199   std::vector< DataArrayInt * > renumParamsOfMeshImpacted;//same size as meshesImpacted
200   std::vector< std::vector<int> > oldCodeOfMeshImpacted,newCodeOfMeshImpacted;//same size as meshesImpacted
201   std::vector<MCAuto<DataArrayInt> > memSaverIfThrow;//same size as meshesImpacted
202   for(int i=0;i<ms->getNumberOfMeshes();i++)
203     {
204       MEDFileMesh *m=ms->getMeshAtPos(i);
205       if(m)
206         {
207           std::vector<int> oldCode,newCode;
208           DataArrayInt *o2nRenumCell=0;
209           bool modif=m->unPolyze(oldCode,newCode,o2nRenumCell);
210           if(!modif)
211             continue;
212           renumParamsOfMeshImpacted.push_back(o2nRenumCell); memSaverIfThrow.push_back(o2nRenumCell);
213           oldCodeOfMeshImpacted.push_back(oldCode);
214           newCodeOfMeshImpacted.push_back(newCode);
215           meshesImpacted.push_back(m);
216         }
217     }
218   if(!meshesImpacted.empty())
219     {
220       MEDFileFields *fs=_fields;
221       if(fs)
222         for(std::size_t i=0;i<meshesImpacted.size();i++)
223           fs->renumberEntitiesLyingOnMesh(meshesImpacted[i]->getName(),oldCodeOfMeshImpacted[i],newCodeOfMeshImpacted[i],renumParamsOfMeshImpacted[i]);
224     }
225   return !meshesImpacted.empty();
226 }
227
228 /*!
229  * Precondition : all instances in \a mfds should have a single mesh with fields on it. If there is an instance with not exactly one mesh an exception will be thrown.
230  * You can invoke MEDFileFields::partOfThisLyingOnSpecifiedMeshName method to make it work.
231  */
232 MCAuto<MEDFileData> MEDFileData::Aggregate(const std::vector<const MEDFileData *>& mfds)
233 {
234   if(mfds.empty())
235     throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : empty vector !");
236   std::size_t sz(mfds.size()),i(0);
237   MCAuto<MEDFileData> ret(MEDFileData::New());
238   std::vector<const MEDFileUMesh *> ms(sz);
239   std::vector< std::vector< std::pair<int,int> > > dts(sz);
240   for(std::vector<const MEDFileData *>::const_iterator it=mfds.begin();it!=mfds.end();it++,i++)
241     {
242       const MEDFileData *elt(*it);
243       if(!elt)
244         throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : presence of NULL pointer !");
245       const MEDFileMeshes *meshes(elt->getMeshes());
246       if(!meshes)
247         throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : presence of an instance with no meshes attached on it !");
248       if(meshes->getNumberOfMeshes()!=1)
249         throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : all instances in input vector must lie on exactly one mesh ! To have it you can invoke partOfThisLyingOnSpecifiedMeshName method.");
250       const MEDFileMesh *mesh(meshes->getMeshAtPos(0));
251       if(!mesh)
252         throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : presence of null mesh in a MEDFileData instance among input vector !");
253       const MEDFileUMesh *umesh(dynamic_cast<const MEDFileUMesh *>(mesh));
254       if(!umesh)
255         throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : works only for unstructured meshes !");
256       ms[i]=umesh;
257       dts[i]=umesh->getAllDistributionOfTypes();
258     }
259   MCAuto<MEDFileUMesh> agg_m(MEDFileUMesh::Aggregate(ms));
260   MCAuto<MEDFileMeshes> mss(MEDFileMeshes::New()); mss->pushMesh(agg_m);
261   ret->setMeshes(mss);
262   // fields
263   std::vector<std::string> fieldNames(mfds[0]->getFields()->getFieldsNames());
264   std::set<std::string> fieldNamess(fieldNames.begin(),fieldNames.end());
265   if(fieldNames.size()!=fieldNamess.size())
266     throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : field names must be different each other !");
267   std::vector< std::vector<const MEDFileAnyTypeFieldMultiTS *> > vectOfFields(fieldNames.size());
268   std::vector< std::vector< MCAuto< MEDFileAnyTypeFieldMultiTS > > > vectOfFields2(fieldNames.size());
269   MCAuto<MEDFileFields> fss(MEDFileFields::New());
270   for(std::vector<const MEDFileData *>::const_iterator it=mfds.begin();it!=mfds.end();it++)
271     {
272       std::vector<std::string> fieldNames0((*it)->getFields()->getFieldsNames());
273       std::set<std::string> fieldNamess0(fieldNames0.begin(),fieldNames0.end());
274       if(fieldNamess!=fieldNamess0)
275         throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : field names must be the same for all input instances !");
276       i=0;
277       for(std::vector<std::string>::const_iterator it1=fieldNames.begin();it1!=fieldNames.end();it1++,i++)
278         {
279           MCAuto<MEDFileAnyTypeFieldMultiTS> fmts((*it)->getFields()->getFieldWithName(*it1));
280           if(fmts.isNull())
281             throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : internal error 1 !");
282           vectOfFields2[i].push_back(fmts); vectOfFields[i].push_back(fmts);
283         }
284     }
285   i=0;
286   for(std::vector<std::string>::const_iterator it1=fieldNames.begin();it1!=fieldNames.end();it1++,i++)
287     {
288       MCAuto<MEDFileAnyTypeFieldMultiTS> fmts(MEDFileAnyTypeFieldMultiTS::Aggregate(vectOfFields[i],dts));
289       fmts->setMeshName(agg_m->getName());
290       fss->pushField(fmts);
291     }
292   ret->setFields(fss);
293   return ret;
294 }
295
296 MEDFileData::MEDFileData()
297 {
298 }
299
300 MEDFileData::MEDFileData(med_idt fid)
301 try
302 {
303     _fields=MEDFileFields::New(fid);
304     _meshes=MEDFileMeshes::New(fid);
305     _params=MEDFileParameters::New(fid);
306 }
307 catch(INTERP_KERNEL::Exception& e)
308 {
309     throw e;
310 }
311
312 void MEDFileData::writeLL(med_idt fid) const
313 {
314   const MEDFileMeshes *ms(_meshes);
315   if(ms)
316     ms->writeLL(fid);
317   const MEDFileFields *fs(_fields);
318   if(fs)
319     fs->writeLL(fid);
320   const MEDFileParameters *ps(_params);
321   if(ps)
322     ps->writeLL(fid);
323 }