Salome HOME
On the road of last imps for MEDReader
[modules/med.git] / src / MEDLoader / MEDFileFieldOverView.cxx
1 // Copyright (C) 2007-2013  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.
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 "MEDFileFieldOverView.hxx"
22 #include "MEDFileField.hxx"
23 #include "MEDFileMesh.hxx"
24
25 #include "CellModel.hxx"
26
27 using namespace ParaMEDMEM;
28
29 MEDFileMeshStruct *MEDFileMeshStruct::New(const MEDFileMesh *mesh)
30 {
31   return new MEDFileMeshStruct(mesh);
32 }
33
34 std::size_t MEDFileMeshStruct::getHeapMemorySize() const
35 {
36   return 0;
37 }
38
39 MEDFileMeshStruct::MEDFileMeshStruct(const MEDFileMesh *mesh):_mesh(mesh)
40 {
41   std::vector<int> levs=mesh->getNonEmptyLevels();
42   _name=mesh->getName();
43   _nb_nodes=mesh->getNumberOfNodes();
44   _geo_types_distrib.resize(levs.size());
45   for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
46     {
47       MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> mLev=mesh->getGenMeshAtLevel(*lev);
48       _geo_types_distrib[-(*lev)]=mLev->getDistributionOfTypes();
49     }
50 }
51
52 int MEDFileMeshStruct::getNumberOfElemsOfGeoType(INTERP_KERNEL::NormalizedCellType t) const throw(INTERP_KERNEL::Exception)
53 {
54   for(std::vector< std::vector<int> >::const_iterator it1=_geo_types_distrib.begin();it1!=_geo_types_distrib.end();it1++)
55     {
56       std::size_t sz=(*it1).size();
57       if(sz%3!=0)
58         throw INTERP_KERNEL::Exception("MEDFileMeshStruct::getNumberOfElemsOfGeoType : internal error in code !");
59       std::size_t nbGeo=sz/3;
60       for(std::size_t i=0;i<nbGeo;i++)
61         if((*it1)[3*i]==(int)t)
62           return (*it1)[3*i+1];
63     }
64   throw INTERP_KERNEL::Exception("The specified geometric type is not present in the mesh structure !");
65 }
66
67 //=
68
69 MEDFileField1TSStructItem2::MEDFileField1TSStructItem2(INTERP_KERNEL::NormalizedCellType a, const std::pair<int,int>& b, const std::string& c, const std::string& d):_geo_type(a),_start_end(b),_pfl(DataArrayInt::New()),_loc(d),_nb_of_entity(-1)
70 {
71   _pfl->setName(c.c_str());
72 }
73
74 void MEDFileField1TSStructItem2::checkWithMeshStructForCells(MEDFileMeshStruct *mst, const MEDFileFieldGlobs *globs) throw(INTERP_KERNEL::Exception)
75 {
76   int nbOfEnt=mst->getNumberOfElemsOfGeoType(_geo_type);
77   checkInRange(nbOfEnt,1,globs);
78 }
79
80 void MEDFileField1TSStructItem2::checkWithMeshStructForGaussNE(MEDFileMeshStruct *mst, const MEDFileFieldGlobs *globs) throw(INTERP_KERNEL::Exception)
81 {
82   int nbOfEnt=mst->getNumberOfElemsOfGeoType(_geo_type);
83   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(_geo_type);
84   checkInRange(nbOfEnt,(int)cm.getNumberOfNodes(),globs);
85 }
86
87 void MEDFileField1TSStructItem2::checkWithMeshStructForGaussPT(MEDFileMeshStruct *mst, const MEDFileFieldGlobs *globs) throw(INTERP_KERNEL::Exception)
88 {
89   if(!globs)
90     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::checkWithMeshStructForGaussPT : no globals specified !");
91   if(_loc.empty())
92     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::checkWithMeshStructForGaussPT : no localization specified !");
93   const MEDFileFieldLoc& loc=globs->getLocalization(_loc.c_str());
94   int nbOfEnt=mst->getNumberOfElemsOfGeoType(_geo_type);
95   checkInRange(nbOfEnt,loc.getNumberOfGaussPoints(),globs);
96 }
97
98 /*!
99  * \param [in] nbOfEntity - number of entity that can be either cells or nodes. Not other possiblity.
100  * \param [in] nip - number of integration points. 1 for ON_CELLS and NO_NODES
101  */
102 void MEDFileField1TSStructItem2::checkInRange(int nbOfEntity, int nip, const MEDFileFieldGlobs *globs) throw(INTERP_KERNEL::Exception)
103 {
104   _nb_of_entity=nbOfEntity;
105   if(_pfl->getName().empty())
106     {
107       if(nbOfEntity!=(_start_end.second-_start_end.first)/nip)
108         throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::checkInRange : Mismatch between number of entities and size of node field !");
109       return ;
110     }
111   else
112     {
113       if(!globs)
114         throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::checkInRange : Presence of a profile on field whereas no globals found in file !");
115       const DataArrayInt *pfl=globs->getProfile(_pfl->getName().c_str());
116       if(!pfl)
117         throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::checkInRange : Presence of a profile on field whereas no such profile found in file !");
118       if(!pfl->checkAllIdsInRange(0,nbOfEntity))
119         throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem2::checkInRange : The profile specified is invalid !");
120     }
121 }
122
123 bool MEDFileField1TSStructItem2::operator==(const MEDFileField1TSStructItem2& other) const throw(INTERP_KERNEL::Exception)
124 {
125   return _geo_type==other._geo_type && _start_end==other._start_end && _pfl->getName()==other._pfl->getName();
126 }
127
128 //=
129
130 MEDFileField1TSStructItem::MEDFileField1TSStructItem(TypeOfField a, const std::vector< MEDFileField1TSStructItem2 >& b):_type(a),_items(b)
131 {
132 }
133
134 void MEDFileField1TSStructItem::checkWithMeshStruct(MEDFileMeshStruct *mst, const MEDFileFieldGlobs *globs) throw(INTERP_KERNEL::Exception)
135 {
136   switch(_type)
137     {
138     case ON_NODES:
139       {
140         int nbOfEnt=mst->getNumberOfNodes();
141         if(_items.size()!=1)
142           throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem::checkWithMeshStruct : for nodes field only one subdivision supported !");
143         _items[0].checkInRange(nbOfEnt,1,globs);
144         break ;
145       }
146     case ON_CELLS:
147       {
148         for(std::vector< MEDFileField1TSStructItem2 >::iterator it=_items.begin();it!=_items.end();it++)
149           (*it).checkWithMeshStructForCells(mst,globs);
150         break;
151       }
152     case ON_GAUSS_NE:
153       {
154         for(std::vector< MEDFileField1TSStructItem2 >::iterator it=_items.begin();it!=_items.end();it++)
155           (*it).checkWithMeshStructForGaussNE(mst,globs);
156         break;
157       }
158     case ON_GAUSS_PT:
159       {
160         for(std::vector< MEDFileField1TSStructItem2 >::iterator it=_items.begin();it!=_items.end();it++)
161           (*it).checkWithMeshStructForGaussPT(mst,globs);
162         break;
163       }
164     default:
165       throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem::checkWithMeshStruct : not managed field type !");
166     }
167 }
168
169 bool MEDFileField1TSStructItem::operator==(const MEDFileField1TSStructItem& other) const throw(INTERP_KERNEL::Exception)
170 {
171   if(_type!=other._type)
172     return false;
173   if(_items.size()!=other._items.size())
174     return false;
175   for(std::size_t i=0;i<_items.size();i++)
176     if(!(_items[i]==other._items[i]))
177       return false;
178   return true;
179 }
180
181 bool MEDFileField1TSStructItem::isEntityCell() const
182 {
183   if(_type==ON_NODES)
184     return false;
185   else
186     return true;
187 }
188
189 class CmpGeo
190 {
191 public:
192   CmpGeo(INTERP_KERNEL::NormalizedCellType geoTyp):_geo_type(geoTyp) { }
193   bool operator()(const std::pair< INTERP_KERNEL::NormalizedCellType, std::vector<std::size_t> > & v) const { return _geo_type==v.first; }
194 private:
195   INTERP_KERNEL::NormalizedCellType _geo_type;
196 };
197
198 MEDFileField1TSStructItem MEDFileField1TSStructItem::simplifyMeOnCellEntity(const MEDFileFieldGlobs *globs) const throw(INTERP_KERNEL::Exception)
199 {
200   if(!isEntityCell())
201     throw INTERP_KERNEL::Exception("MEDFileField1TSStructItem::simplifyMeOnCellEntity : must be on ON_CELLS, ON_GAUSS_NE or ON_GAUSS_PT !");
202   std::vector< std::pair< INTERP_KERNEL::NormalizedCellType, std::vector<std::size_t> > > m;
203   std::size_t i=0;
204   for(std::vector< MEDFileField1TSStructItem2 >::const_iterator it=_items.begin();it!=_items.end();it++,i++)
205     {
206       std::vector< std::pair< INTERP_KERNEL::NormalizedCellType, std::vector<std::size_t> > >::iterator it0(std::find_if(m.begin(),m.end(),CmpGeo((*it).getGeo())));
207       if(it0==m.end())
208         m.push_back(std::pair< INTERP_KERNEL::NormalizedCellType, std::vector<std::size_t> >((*it).getGeo(),std::vector<std::size_t>(1,i)));
209       (*it0).second.push_back(i);
210     }
211   if(m.size()==_items.size())
212     {
213       MEDFileField1TSStructItem ret(*this);
214       ret._type=ON_CELLS;
215       return ret;
216     }
217   return *this;
218 }
219
220 //=
221
222 MEDFileField1TSStruct *MEDFileField1TSStruct::New(const MEDFileAnyTypeField1TS *ref) throw(INTERP_KERNEL::Exception)
223 {
224   return new MEDFileField1TSStruct(ref);
225 }
226
227 MEDFileField1TSStruct::MEDFileField1TSStruct(const MEDFileAnyTypeField1TS *ref)
228 {
229   _already_checked.push_back(BuildItemFrom(ref));
230 }
231
232 void MEDFileField1TSStruct::checkWithMeshStruct(MEDFileMeshStruct *mst, const MEDFileFieldGlobs *globs) throw(INTERP_KERNEL::Exception)
233 {
234   if(_already_checked.empty())
235     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct::checkWithMeshStruct : not correctly initialized !");
236   _already_checked.back().checkWithMeshStruct(mst,globs);
237 }
238
239 bool MEDFileField1TSStruct::isEqualConsideringThePast(const MEDFileAnyTypeField1TS *other) throw(INTERP_KERNEL::Exception)
240 {
241   MEDFileField1TSStructItem b(BuildItemFrom(other));
242   for(std::vector<MEDFileField1TSStructItem>::const_iterator it=_already_checked.begin();it!=_already_checked.end();it++)
243     {
244       if((*it)==b)
245         return true;
246     }
247   return false;
248 }
249
250 bool MEDFileField1TSStruct::isSupportSameAs(const MEDFileAnyTypeField1TS *other) throw(INTERP_KERNEL::Exception)
251 {
252   if(_already_checked.empty())
253     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct::isSupportSameAs : no ref !");
254   MEDFileField1TSStructItem b(BuildItemFrom(other));
255   if(!_already_checked[0].isEntityCell() || !b.isEntityCell())
256     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct::isSupportSameAs : only available on cell entities !");
257   return false;
258 }
259
260 std::size_t MEDFileField1TSStruct::getHeapMemorySize() const
261 {
262   return 0;
263 }
264
265 MEDFileField1TSStructItem MEDFileField1TSStruct::BuildItemFrom(const MEDFileAnyTypeField1TS *ref)
266 {
267   TypeOfField atype;
268   std::vector< MEDFileField1TSStructItem2 > anItems;
269   //
270   std::vector< std::vector<std::string> > pfls,locs;
271   std::vector< std::vector<TypeOfField> > typesF;
272   std::vector<INTERP_KERNEL::NormalizedCellType> geoTypes;
273   std::vector< std::vector<std::pair<int,int> > > strtEnds=ref->getFieldSplitedByType(0,geoTypes,typesF,pfls,locs);
274   std::size_t nbOfGeoTypes(geoTypes.size());
275   if(nbOfGeoTypes==0)
276     throw INTERP_KERNEL::Exception("MEDFileField1TSStruct : not null by empty ref  !");
277   bool isFirst=true;
278   for(std::size_t i=0;i<nbOfGeoTypes;i++)
279     {
280       std::size_t sz=typesF.size();
281       if(strtEnds[i].size()<1 || sz<1 || pfls[i].size()<1)
282         throw INTERP_KERNEL::Exception("MEDFileField1TSStruct : internal error #1 !");
283       //
284       if(isFirst)
285         atype=typesF[i][0];
286       isFirst=false;
287       //
288       for(std::size_t j=0;j<sz;j++)
289         {
290           if(atype!=typesF[i][j])
291             anItems.push_back(MEDFileField1TSStructItem2(geoTypes[i],strtEnds[i][j],pfls[i][j],locs[i][j]));
292           else
293             throw INTERP_KERNEL::Exception("MEDFileField1TSStruct : can be applied only on single spatial discretization fields ! Call SplitPerDiscretization method !");
294         }
295     }
296   return MEDFileField1TSStructItem(atype,anItems);
297 }
298
299 //=
300
301 MEDFileFastCellSupportComparator *MEDFileFastCellSupportComparator::New(const MEDFileMesh *m, const MEDFileAnyTypeFieldMultiTS *ref) throw(INTERP_KERNEL::Exception)
302 {
303   return new MEDFileFastCellSupportComparator(m,ref);
304 }
305
306 MEDFileFastCellSupportComparator::MEDFileFastCellSupportComparator(const MEDFileMesh *m, const MEDFileAnyTypeFieldMultiTS *ref)
307 {
308   _mesh_comp=MEDFileMeshStruct::New(m);
309   int nbPts=ref->getNumberOfTS();
310   _f1ts_cmps.resize(nbPts);
311   for(int i=0;i<nbPts;i++)
312     {
313       MEDCouplingAutoRefCountObjectPtr<MEDFileAnyTypeField1TS> elt=ref->getTimeStepAtPos(i);
314       _f1ts_cmps[i]=MEDFileField1TSStruct::New(elt);
315       _f1ts_cmps[i]->checkWithMeshStruct(_mesh_comp,elt->contentNotNull());
316     }
317 }
318
319 std::size_t MEDFileFastCellSupportComparator::getHeapMemorySize() const
320 {
321   /*std::size_t part1=sizeof(MEDFileFastCellSupportComparator)+_mesh_name.capacity()+_already_passed_code1.capacity()*sizeof(std::vector<int>)+_already_passed_code2.capacity()*sizeof(void*)+_m_geo_types_distrib.capacity()*sizeof(std::vector<int>);
322   std::size_t part2=0;
323   for(std::vector< std::vector<int> >::const_iterator it=_already_passed_code1.begin();it!=_already_passed_code1.end();it++)
324     part2+=(*it).capacity()*(sizeof(int)+sizeof(const DataArrayInt *));
325   for(std::vector< std::vector<int> >::const_iterator it2=_m_geo_types_distrib.begin();it2!=_m_geo_types_distrib.end();it2++)
326     part2+=(*it2).capacity()*sizeof(int);
327     return part1+part2;*/
328   return 0;
329 }
330
331 bool MEDFileFastCellSupportComparator::isEqual(const MEDFileAnyTypeFieldMultiTS *other) throw(INTERP_KERNEL::Exception)
332 {
333   int nbPts=other->getNumberOfTS();
334   if(nbPts!=(int)_f1ts_cmps.size())
335     {
336       std::ostringstream oss; oss << "MEDFileFastCellSupportComparator::isEqualRegardingPast : unexpected nb of time steps in  input ! Should be " << _f1ts_cmps.size() << " it is in reality " << nbPts << " !";
337       throw INTERP_KERNEL::Exception(oss.str().c_str());
338     }
339   for(int i=0;i<nbPts;i++)
340     {
341       MEDCouplingAutoRefCountObjectPtr<MEDFileAnyTypeField1TS> elt=other->getTimeStepAtPos(i);
342       if(!_f1ts_cmps[i]->isEqualConsideringThePast(elt))
343         if(!_f1ts_cmps[i]->isSupportSameAs(elt))
344           return false;
345     }
346   return true;
347 }