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