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