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