1 // Copyright (C) 2007-2023 CEA, EDF
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDFileData.hxx"
22 #include "MEDLoaderBase.hxx"
23 #include "MEDFileSafeCaller.txx"
24 #include "MEDFileBlowStrEltUp.hxx"
26 #include "InterpKernelAutoPtr.hxx"
28 using namespace MEDCoupling;
30 MEDFileData *MEDFileData::New(const std::string& fileName)
32 MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
36 MEDFileData *MEDFileData::New(med_idt fid)
38 return new MEDFileData(fid);
41 MEDFileData *MEDFileData::New()
43 return new MEDFileData;
46 MEDFileData *MEDFileData::deepCopy() const
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;
62 std::size_t MEDFileData::getHeapMemorySizeWithoutChildren() const
64 return _header.capacity();
67 std::vector<const BigMemoryObject *> MEDFileData::getDirectChildrenWithNull() const
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);
79 /** Return a borrowed reference (caller is not responsible for object destruction) */
80 MEDFileFields *MEDFileData::getFields() const
82 return const_cast<MEDFileFields *>(static_cast<const MEDFileFields *>(_fields));
85 /** Return a borrowed reference (caller is not responsible for object destruction) */
86 MEDFileMeshes *MEDFileData::getMeshes() const
88 return const_cast<MEDFileMeshes *>(static_cast<const MEDFileMeshes *>(_meshes));
91 /** Return a borrowed reference (caller is not responsible for object destruction) */
92 MEDFileParameters *MEDFileData::getParams() const
94 return const_cast<MEDFileParameters *>(static_cast<const MEDFileParameters *>(_params));
97 void MEDFileData::setFields(MEDFileFields *fields)
104 void MEDFileData::setMeshes(MEDFileMeshes *meshes)
111 void MEDFileData::setParams(MEDFileParameters *params)
118 int MEDFileData::getNumberOfFields() const
120 const MEDFileFields *f=_fields;
122 throw INTERP_KERNEL::Exception("MEDFileData::getNumberOfFields : no fields set !");
123 return f->getNumberOfFields();
126 int MEDFileData::getNumberOfMeshes() const
128 const MEDFileMeshes *m=_meshes;
130 throw INTERP_KERNEL::Exception("MEDFileData::getNumberOfMeshes : no meshes set !");
131 return m->getNumberOfMeshes();
134 int MEDFileData::getNumberOfParams() const
136 const MEDFileParameters *p=_params;
138 throw INTERP_KERNEL::Exception("MEDFileData::getNumberOfParams : no params set !");
139 return p->getNumberOfParams();
142 std::string MEDFileData::simpleRepr() const
144 std::ostringstream oss;
145 oss << "(***************)\n(* MEDFileData *)\n(***************)\n\nFields part :\n*************\n\n";
146 const MEDFileFields *tmp=_fields;
149 tmp->simpleRepr(0,oss);
153 oss << "No fields set !!!\n\n";
154 oss << "Meshes part :\n*************\n\n";
155 const MEDFileMeshes *tmp2=_meshes;
158 tmp2->simpleReprWithoutHeader(oss);
161 oss << "No meshes set !!!\n\n";
162 oss << "Params part :\n*************\n\n";
163 const MEDFileParameters *tmp3=_params;
166 tmp3->simpleReprWithoutHeader(oss);
169 oss << "No params set !!!\n";
173 bool MEDFileData::changeMeshNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
176 MEDFileFields *fields=_fields;
178 ret=fields->changeMeshNames(modifTab) || ret;
179 MEDFileMeshes *meshes=_meshes;
181 ret=meshes->changeNames(modifTab) || ret;
185 bool MEDFileData::changeMeshName(const std::string& oldMeshName, const std::string& newMeshName)
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);
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)
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.
200 bool MEDFileData::unPolyzeMeshes()
202 MEDFileMeshes *ms=_meshes;
205 std::vector< MEDFileMesh * > meshesImpacted;
206 std::vector< DataArrayIdType * > renumParamsOfMeshImpacted;//same size as meshesImpacted
207 std::vector< std::vector<mcIdType> > oldCodeOfMeshImpacted,newCodeOfMeshImpacted;//same size as meshesImpacted
208 std::vector<MCAuto<DataArrayIdType> > memSaverIfThrow;//same size as meshesImpacted
209 for(int i=0;i<ms->getNumberOfMeshes();i++)
211 MEDFileMesh *m=ms->getMeshAtPos(i);
214 std::vector<mcIdType> oldCode,newCode;
215 DataArrayIdType *o2nRenumCell=0;
216 bool modif=m->unPolyze(oldCode,newCode,o2nRenumCell);
219 renumParamsOfMeshImpacted.push_back(o2nRenumCell); memSaverIfThrow.push_back(o2nRenumCell);
220 oldCodeOfMeshImpacted.push_back(oldCode);
221 newCodeOfMeshImpacted.push_back(newCode);
222 meshesImpacted.push_back(m);
225 if(!meshesImpacted.empty())
227 MEDFileFields *fs=_fields;
229 for(std::size_t i=0;i<meshesImpacted.size();i++)
230 fs->renumberEntitiesLyingOnMesh(meshesImpacted[i]->getName(),oldCodeOfMeshImpacted[i],newCodeOfMeshImpacted[i],renumParamsOfMeshImpacted[i]);
232 return !meshesImpacted.empty();
235 void MEDFileData::dealWithStructureElements()
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);
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.
248 MCAuto<MEDFileData> MEDFileData::Aggregate(const std::vector<const MEDFileData *>& mfds)
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,mcIdType> > > dts(sz);
256 for(std::vector<const MEDFileData *>::const_iterator it=mfds.begin();it!=mfds.end();it++,i++)
258 const MEDFileData *elt(*it);
260 throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : presence of NULL pointer !");
261 const MEDFileMeshes *meshes(elt->getMeshes());
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));
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));
271 throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : works only for unstructured meshes !");
273 dts[i]=umesh->getAllDistributionOfTypes();
275 MCAuto<MEDFileUMesh> agg_m(MEDFileUMesh::Aggregate(ms));
276 MCAuto<MEDFileMeshes> mss(MEDFileMeshes::New()); mss->pushMesh(agg_m);
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++)
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 !");
293 for(std::vector<std::string>::const_iterator it1=fieldNames.begin();it1!=fieldNames.end();it1++,i++)
295 MCAuto<MEDFileAnyTypeFieldMultiTS> fmts((*it)->getFields()->getFieldWithName(*it1));
297 throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : internal error 1 !");
298 vectOfFields2[i].push_back(fmts); vectOfFields[i].push_back(fmts);
302 for(std::vector<std::string>::const_iterator it1=fieldNames.begin();it1!=fieldNames.end();it1++,i++)
304 MCAuto<MEDFileAnyTypeFieldMultiTS> fmts(MEDFileAnyTypeFieldMultiTS::Aggregate(vectOfFields[i],dts));
305 fmts->setMeshName(agg_m->getName());
306 fss->pushField(fmts);
312 MEDFileData::MEDFileData()
316 MEDFileData::MEDFileData(med_idt 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);
326 catch(INTERP_KERNEL::Exception& e)
331 void MEDFileData::writeLL(med_idt fid) const
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);
346 std::string MEDFileData::getHeader() const
352 void MEDFileData::setHeader(const std::string& header)
357 void MEDFileData::readHeader(med_idt fid)
359 INTERP_KERNEL::AutoPtr<char> header(MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE));
360 int ret(MEDfileCommentRd(fid,header));
362 _header=MEDLoaderBase::buildStringFromFortran(header,MED_COMMENT_SIZE);
365 void MEDFileData::writeHeader(med_idt fid) const
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));