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