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