Salome HOME
d261867686ec8fbb85741bc74a69fe90e443b66c
[modules/med.git] / src / MEDCoupling / MEDCouplingMultiFields.cxx
1 // Copyright (C) 2007-2012  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 "MEDCouplingMultiFields.hxx"
22 #include "MEDCouplingFieldTemplate.hxx"
23 #include "MEDCouplingFieldDouble.hxx"
24 #include "MEDCouplingMesh.hxx"
25 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
26
27 #include <sstream>
28 #include <algorithm>
29
30 using namespace ParaMEDMEM;
31
32 MEDCouplingMultiFields *MEDCouplingMultiFields::New(const std::vector<MEDCouplingFieldDouble *>& fs) throw(INTERP_KERNEL::Exception)
33 {
34   return new MEDCouplingMultiFields(fs);
35 }
36
37 MEDCouplingMultiFields *MEDCouplingMultiFields::New()
38 {
39   return new MEDCouplingMultiFields;
40 }
41
42 MEDCouplingMultiFields *MEDCouplingMultiFields::deepCpy() const
43 {
44   return new MEDCouplingMultiFields(*this);
45 }
46
47 bool MEDCouplingMultiFields::isEqual(const MEDCouplingMultiFields *other, double meshPrec, double valsPrec) const
48 {
49   std::size_t sz=_fs.size();
50   if(sz!=other->_fs.size())
51     return false;
52   for(std::size_t i=0;i<sz;i++)
53     {
54       const MEDCouplingFieldDouble *f1=_fs[i];
55       const MEDCouplingFieldDouble *f2=other->_fs[i];
56       if(f1!=f2)
57         {
58           if(f1==0 || f2==0)
59             return false;
60           if(!_fs[i]->isEqual(other->_fs[i],meshPrec,valsPrec))
61             return false;
62         }
63     }
64   std::vector<int> refs1,refs2;
65   std::vector<MEDCouplingMesh *> ms1=getDifferentMeshes(refs1);
66   std::vector<MEDCouplingMesh *> ms2=other->getDifferentMeshes(refs2);
67   if(ms1.size()!=ms2.size())
68     return false;
69   if(refs1!=refs2)
70     return false;
71   std::vector< std::vector<int> > refs3,refs4;
72   std::vector<DataArrayDouble *> das1=getDifferentArrays(refs3);
73   std::vector<DataArrayDouble *> das2=getDifferentArrays(refs4);
74   if(das1.size()!=das2.size())
75     return false;
76   if(refs3!=refs4)
77     return false;
78   return true;
79 }
80
81 std::string MEDCouplingMultiFields::getName() const
82 {
83   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();
84   for(;it!=_fs.end();it++)
85     if((const MEDCouplingFieldDouble *)(*it))
86       return (*it)->getName();
87   return std::string();
88 }
89
90 std::string MEDCouplingMultiFields::getDescription() const
91 {
92   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();
93   for(;it!=_fs.end();it++)
94     if((const MEDCouplingFieldDouble *)(*it))
95       return (*it)->getDescription();
96   return std::string();
97 }
98
99 std::string MEDCouplingMultiFields::getTimeUnit() const
100 {
101   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();
102   for(;it!=_fs.end();it++)
103     if((const MEDCouplingFieldDouble *)(*it))
104       return (*it)->getTimeUnit();
105   return std::string();
106 }
107
108 double MEDCouplingMultiFields::getTimeResolution() const throw(INTERP_KERNEL::Exception)
109 {
110   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();
111   for(;it!=_fs.end();it++)
112     if((const MEDCouplingFieldDouble *)(*it))
113       return (*it)->getTimeTolerance();
114   throw INTERP_KERNEL::Exception("MEDCouplingMultiFields::getTimeResolution : no not null field !");
115 }
116
117 std::string MEDCouplingMultiFields::simpleRepr() const
118 {
119   std::ostringstream ret;
120   ret << "MEDCouplingMultiFields with name : \"" << getName() << "\"\n";
121   ret << "Description of MEDCouplingMultiFields is : \"" << getDescription() << "\"\n";
122   ret << "Number of discretization : " << _fs.size() << "\n";
123   ret << "Number of different meshes : ";
124   std::vector<MEDCouplingMesh *> ms;
125   std::vector<int> refms;
126   try
127     {
128       ms=getDifferentMeshes(refms);
129       ret << ms.size() << "\n";
130     }
131   catch(INTERP_KERNEL::Exception& e)
132     { ret << "Current instance is INVALID !\n"; }
133   return ret.str();
134 }
135
136 std::string MEDCouplingMultiFields::advancedRepr() const
137 {
138   return simpleRepr();
139 }
140
141 bool MEDCouplingMultiFields::isEqualWithoutConsideringStr(const MEDCouplingMultiFields *other, double meshPrec, double valsPrec) const
142 {
143   std::size_t sz=_fs.size();
144   if(sz!=other->_fs.size())
145     return false;
146   for(std::size_t i=0;i<sz;i++)
147     if(!_fs[i]->isEqualWithoutConsideringStr(other->_fs[i],meshPrec,valsPrec))
148       return false;
149   return true;
150 }
151
152 const MEDCouplingFieldDouble *MEDCouplingMultiFields::getFieldWithId(int id) const throw(INTERP_KERNEL::Exception)
153 {
154   if(id>=(int)_fs.size() || id < 0)
155     throw INTERP_KERNEL::Exception("MEDCouplingMultiFields::getFieldWithId : invalid id outside boundaries !");
156   return _fs[id];
157 }
158
159 std::vector<const MEDCouplingFieldDouble *> MEDCouplingMultiFields::getFields() const
160 {
161   std::vector<const MEDCouplingFieldDouble *> ret(_fs.size());
162   std::copy(_fs.begin(),_fs.end(),ret.begin());
163   return ret;
164 }
165
166 int MEDCouplingMultiFields::getNumberOfFields() const
167 {
168   return (int)_fs.size();
169 }
170
171 const MEDCouplingFieldDouble *MEDCouplingMultiFields::getFieldAtPos(int id) const throw(INTERP_KERNEL::Exception)
172 {
173   if(id<0 || id>=(int)_fs.size())
174     {
175       std::ostringstream oss; oss << "MEDCouplingMultiFields::getFieldAtPos : Invalid given pos : should be >=0 and < " << _fs.size() << " !";
176       throw INTERP_KERNEL::Exception(oss.str().c_str());
177     }
178   return _fs[id];
179 }
180
181 void MEDCouplingMultiFields::updateTime() const
182 {
183   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();
184   for(;it!=_fs.end();it++)
185     if((const MEDCouplingFieldDouble *)(*it))
186       (*it)->updateTime();
187   it=_fs.begin();
188   for(;it!=_fs.end();it++)
189     if((const MEDCouplingFieldDouble *)(*it))
190       updateTimeWith(*(*it));
191 }
192
193 std::size_t MEDCouplingMultiFields::getHeapMemorySize() const
194 {
195   std::vector<int> tmp;
196   std::vector< std::vector<int> > tmp2;
197   std::vector<MEDCouplingMesh *> ms=getDifferentMeshes(tmp);
198   std::vector<DataArrayDouble *> arrs=getDifferentArrays(tmp2);
199   std::size_t ret=0;
200   for(std::vector<MEDCouplingMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
201     if(*it)
202       ret+=(*it)->getHeapMemorySize();
203   for(std::vector<DataArrayDouble *>::const_iterator it=arrs.begin();it!=arrs.end();it++)
204     if(*it)
205       ret+=(*it)->getHeapMemorySize();
206   return ret;
207 }
208
209 std::vector<MEDCouplingMesh *> MEDCouplingMultiFields::getMeshes() const throw(INTERP_KERNEL::Exception)
210 {
211   std::vector<MEDCouplingMesh *> ms;
212   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();it!=_fs.end();it++)
213     {
214       const MEDCouplingMesh *m=0;
215       if((const MEDCouplingFieldDouble *)(*it))
216         m=(*it)->getMesh();
217       ms.push_back(const_cast<MEDCouplingMesh *>(m));
218     }
219   return ms;
220 }
221
222 std::vector<MEDCouplingMesh *> MEDCouplingMultiFields::getDifferentMeshes(std::vector<int>& refs) const throw(INTERP_KERNEL::Exception)
223 {
224   refs.resize(_fs.size());
225   std::vector<MEDCouplingMesh *> ms;
226   int id=0;
227   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();it!=_fs.end();it++,id++)
228     {
229       const MEDCouplingMesh *m=0;
230       if((const MEDCouplingFieldDouble *)(*it))
231         m=(*it)->getMesh();
232       if(m)
233         {
234           std::vector<MEDCouplingMesh *>::iterator it2=std::find(ms.begin(),ms.end(),m);
235           if(it2==ms.end())
236             {
237               ms.push_back(const_cast<MEDCouplingMesh *>(m));
238               refs[id]=(int)ms.size()-1;
239             }
240           else
241             refs[id]=(int)std::distance(ms.begin(),it2);
242         }
243       else
244         refs[id]=-1;
245     }
246   return ms;
247 }
248
249 std::vector<DataArrayDouble *> MEDCouplingMultiFields::getArrays() const throw(INTERP_KERNEL::Exception)
250 {
251   std::vector<DataArrayDouble *> tmp;
252   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();it!=_fs.end();it++)
253     {
254       std::vector<DataArrayDouble *> tmp2=(*it)->getArrays();
255       tmp.insert(tmp.end(),tmp2.begin(),tmp2.end());
256     }
257   return tmp;
258 }
259
260 std::vector<DataArrayDouble *> MEDCouplingMultiFields::getDifferentArrays(std::vector< std::vector<int> >& refs) const throw(INTERP_KERNEL::Exception)
261 {
262   refs.resize(_fs.size());
263   int id=0;
264   std::vector<DataArrayDouble *> ret;
265   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();it!=_fs.end();it++,id++)
266     {
267       std::vector<DataArrayDouble *> tmp2;
268       if((const MEDCouplingFieldDouble *)(*it))
269         {
270           tmp2=(*it)->getArrays();
271           refs[id].resize(tmp2.size());
272         }
273       else
274         refs[id].clear();
275       int id2=0;
276       for(std::vector<DataArrayDouble *>::const_iterator it2=tmp2.begin();it2!=tmp2.end();it2++,id2++)
277         {
278           if(*it2)
279             {
280               std::vector<DataArrayDouble *>::iterator it3=std::find(ret.begin(),ret.end(),*it2);
281               if(it3==ret.end())
282                 {
283                   ret.push_back(*it2);
284                   refs[id][id2]=(int)ret.size()-1;
285                 }
286               else
287                 refs[id][id2]=(int)std::distance(ret.begin(),it3);
288             }
289           else
290             refs[id][id2]=-1;
291         }
292     }
293   return ret;
294 }
295
296 void MEDCouplingMultiFields::checkCoherency() const throw(INTERP_KERNEL::Exception)
297 {
298   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();
299   for(;it!=_fs.end();it++)
300     {
301       if((const MEDCouplingFieldDouble *)(*it)==0)
302         throw INTERP_KERNEL::Exception("MEDCouplingMultiFields::checkCoherency : There is an empty Field in array...");
303       (*it)->checkCoherency();
304     }
305 }
306
307 MEDCouplingMultiFields::MEDCouplingMultiFields(const std::vector<MEDCouplingFieldDouble *>& fs) throw(INTERP_KERNEL::Exception):_fs(fs.size())
308 {
309   int id=0;
310   for(std::vector< MEDCouplingFieldDouble * >::const_iterator it=fs.begin();it!=fs.end();it++,id++)
311     {
312       if(*it)
313         (*it)->incrRef();
314       else
315         throw INTERP_KERNEL::Exception("MEDCouplingMultiFields constructor : empty field found in vector !");
316       (*it)->checkCoherency();
317       _fs[id]=*it;
318     }
319 }
320
321
322 /*!
323  * Performs deepCpy.
324  */
325 MEDCouplingMultiFields::MEDCouplingMultiFields(const MEDCouplingMultiFields& other)
326 {
327   std::size_t sz=other._fs.size();
328   _fs.resize(sz);
329   std::vector<int> refs;
330   std::vector< std::vector<int> > refs2;
331   std::vector<MEDCouplingMesh *> ms=other.getDifferentMeshes(refs);
332   std::size_t msLgh=ms.size();
333   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> > ms2(msLgh);
334   for(std::size_t i=0;i<msLgh;i++)
335     ms2[i]=ms[i]->deepCpy();
336   std::vector<DataArrayDouble *> das=other.getDifferentArrays(refs2);
337   std::size_t dasLgth=das.size();
338   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > das2(dasLgth);
339   for(std::size_t i=0;i<dasLgth;i++)
340     das2[i]=das[i]->deepCpy();
341   for(std::size_t i=0;i<sz;i++)
342     {
343       if((const MEDCouplingFieldDouble *)other._fs[i])
344         {
345           MEDCouplingFieldTemplate *tmp=MEDCouplingFieldTemplate::New(other._fs[i]);
346           _fs[i]=MEDCouplingFieldDouble::New(tmp,other._fs[i]->getTimeDiscretization());
347           tmp->decrRef();
348           if(refs[i]!=-1)
349             _fs[i]->setMesh(ms2[refs[i]]);
350           std::size_t nbOfArr=refs2[i].size();
351           std::vector<DataArrayDouble *> tmp2(nbOfArr);
352           for(std::size_t j=0;j<nbOfArr;j++)
353             {
354               if(refs2[i][j]!=-1)
355                 tmp2[j]=das2[refs2[i][j]];
356               else
357                 tmp2[j]=0;
358             }
359           _fs[i]->setArrays(tmp2);
360           std::vector<int> tinyInfo;
361           std::vector<double> tinyInfo2;
362           other._fs[i]->getTimeDiscretizationUnderGround()->getTinySerializationIntInformation2(tinyInfo);
363           other._fs[i]->getTimeDiscretizationUnderGround()->getTinySerializationDbleInformation2(tinyInfo2);
364           _fs[i]->getTimeDiscretizationUnderGround()->finishUnserialization2(tinyInfo,tinyInfo2);
365         }
366     }
367 }
368
369 MEDCouplingMultiFields::MEDCouplingMultiFields()
370 {
371 }
372
373 void MEDCouplingMultiFields::getTinySerializationInformation(std::vector<int>& tinyInfo, std::vector<double>& tinyInfo2, int& nbOfDiffMeshes, int& nbOfDiffArr) const
374 {
375   std::vector<int> refs;
376   std::vector<MEDCouplingMesh *> ms=getDifferentMeshes(refs);
377   nbOfDiffMeshes=(int)ms.size();
378   std::vector< std::vector<int> > refs2;
379   std::vector<DataArrayDouble *> fs=getDifferentArrays(refs2);
380   nbOfDiffArr=(int)fs.size();
381   //
382   std::size_t sz=refs.size();//==_fs.size()
383   int sz2=0;
384   for(std::size_t i=0;i<sz;i++)
385     sz2+=(int)refs2[i].size();
386   //
387   tinyInfo2.clear();
388   std::vector<int> doubleDaInd(sz);
389   std::vector<int> timeDiscrInt;
390   tinyInfo.resize(sz2+5*sz+3);
391   tinyInfo[0]=(int)sz;
392   tinyInfo[1]=sz2;
393   for(std::size_t i=0;i<sz;i++)
394     {
395       std::vector<double> tmp;
396       std::vector<int> tmp2;
397       _fs[i]->getTimeDiscretizationUnderGround()->getTinySerializationDbleInformation2(tmp);
398       _fs[i]->getTimeDiscretizationUnderGround()->getTinySerializationIntInformation2(tmp2);
399       tinyInfo[3*sz+3+i]=(int)tmp.size();
400       tinyInfo[4*sz+3+i]=(int)tmp2.size();
401       tinyInfo2.insert(tinyInfo2.end(),tmp.begin(),tmp.end());
402       timeDiscrInt.insert(timeDiscrInt.end(),tmp2.begin(),tmp2.end());
403     }
404   int sz3=(int)timeDiscrInt.size();
405   tinyInfo[2]=sz3;
406   //
407   for(std::size_t i=0;i<sz;i++)
408     tinyInfo[i+3]=refs[i];
409   for(std::size_t i=0;i<sz;i++)
410     tinyInfo[i+sz+3]=(int)refs2[i].size();
411   for(std::size_t i=0;i<sz;i++)
412     tinyInfo[i+2*sz+3]=(int)_fs[i]->getTimeDiscretization();
413   int k=0;
414   for(std::size_t i=0;i<sz;i++)
415     for(std::vector<int>::const_iterator it=refs2[i].begin();it!=refs2[i].end();it++,k++)
416       tinyInfo[5*sz+k+3]=*it;
417   tinyInfo.insert(tinyInfo.end(),timeDiscrInt.begin(),timeDiscrInt.end());//tinyInfo has lgth==sz3+sz2+5*sz+3
418 }
419
420 void MEDCouplingMultiFields::finishUnserialization(const std::vector<int>& tinyInfoI, const std::vector<double>& tinyInfoD,
421                                                    const std::vector<MEDCouplingFieldTemplate *>& ft, const std::vector<MEDCouplingMesh *>& ms,
422                                                    const std::vector<DataArrayDouble *>& das)
423 {
424   int sz=tinyInfoI[0];
425   _fs.resize(sz);
426   int sz2=tinyInfoI[1];
427   // dealing with ft with no mesh set.
428   for(int i=0;i<sz;i++)
429     {
430       int meshId=tinyInfoI[3+i];
431       if(meshId!=-1)
432         ft[i]->setMesh(ms[meshId]);
433     }
434   // dealing with fieldtemplate->fielddouble
435   int k=0;
436   int offI=0;
437   int offD=0;
438   for(int i=0;i<sz;i++)
439     {
440       _fs[i]=MEDCouplingFieldDouble::New(ft[i],(TypeOfTimeDiscretization)tinyInfoI[2*sz+3+i]);
441       int sz3=tinyInfoI[sz+i+3];
442       std::vector<DataArrayDouble *> tmp(sz3);
443       for(int j=0;j<sz3;j++,k++)
444         {
445           int daId=tinyInfoI[5*sz+k+3];
446           if(daId!=-1)
447             tmp[j]=das[daId];
448           else
449             tmp[j]=0;
450         }
451       _fs[i]->setArrays(tmp);
452       // time discr tiny info
453       int lgthI=tinyInfoI[4*sz+3+i];
454       int lgthD=tinyInfoI[3*sz+3+i];
455       //
456       std::vector<int> tdInfoI(tinyInfoI.begin()+sz2+5*sz+3+offI,tinyInfoI.begin()+sz2+5*sz+3+offI+lgthI);
457       std::vector<double> tdInfoD(tinyInfoD.begin()+offD,tinyInfoD.begin()+offD+lgthD);
458       _fs[i]->getTimeDiscretizationUnderGround()->finishUnserialization2(tdInfoI,tdInfoD);
459       //
460       offI+=lgthI;
461       offD+=lgthD;
462     }
463 }