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