Back to index

salome-med  6.5.0
MEDCouplingMultiFields.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 #include "MEDCouplingMultiFields.hxx"
00021 #include "MEDCouplingFieldTemplate.hxx"
00022 #include "MEDCouplingFieldDouble.hxx"
00023 #include "MEDCouplingMesh.hxx"
00024 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
00025 
00026 #include <sstream>
00027 #include <algorithm>
00028 
00029 using namespace ParaMEDMEM;
00030 
00031 MEDCouplingMultiFields *MEDCouplingMultiFields::New(const std::vector<MEDCouplingFieldDouble *>& fs) throw(INTERP_KERNEL::Exception)
00032 {
00033   return new MEDCouplingMultiFields(fs);
00034 }
00035 
00036 MEDCouplingMultiFields *MEDCouplingMultiFields::New()
00037 {
00038   return new MEDCouplingMultiFields;
00039 }
00040 
00041 MEDCouplingMultiFields *MEDCouplingMultiFields::deepCpy() const
00042 {
00043   return new MEDCouplingMultiFields(*this);
00044 }
00045 
00046 bool MEDCouplingMultiFields::isEqual(const MEDCouplingMultiFields *other, double meshPrec, double valsPrec) const
00047 {
00048   std::size_t sz=_fs.size();
00049   if(sz!=other->_fs.size())
00050     return false;
00051   for(std::size_t i=0;i<sz;i++)
00052     {
00053       const MEDCouplingFieldDouble *f1=_fs[i];
00054       const MEDCouplingFieldDouble *f2=other->_fs[i];
00055       if(f1!=f2)
00056         {
00057           if(f1==0 || f2==0)
00058             return false;
00059           if(!_fs[i]->isEqual(other->_fs[i],meshPrec,valsPrec))
00060             return false;
00061         }
00062     }
00063   std::vector<int> refs1,refs2;
00064   std::vector<MEDCouplingMesh *> ms1=getDifferentMeshes(refs1);
00065   std::vector<MEDCouplingMesh *> ms2=other->getDifferentMeshes(refs2);
00066   if(ms1.size()!=ms2.size())
00067     return false;
00068   if(refs1!=refs2)
00069     return false;
00070   std::vector< std::vector<int> > refs3,refs4;
00071   std::vector<DataArrayDouble *> das1=getDifferentArrays(refs3);
00072   std::vector<DataArrayDouble *> das2=getDifferentArrays(refs4);
00073   if(das1.size()!=das2.size())
00074     return false;
00075   if(refs3!=refs4)
00076     return false;
00077   return true;
00078 }
00079 
00080 std::string MEDCouplingMultiFields::getName() const
00081 {
00082   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();
00083   for(;it!=_fs.end();it++)
00084     if((const MEDCouplingFieldDouble *)(*it))
00085       return (*it)->getName();
00086   return std::string();
00087 }
00088 
00089 std::string MEDCouplingMultiFields::getDescription() const
00090 {
00091   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();
00092   for(;it!=_fs.end();it++)
00093     if((const MEDCouplingFieldDouble *)(*it))
00094       return (*it)->getDescription();
00095   return std::string();
00096 }
00097 
00098 std::string MEDCouplingMultiFields::getTimeUnit() const
00099 {
00100   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();
00101   for(;it!=_fs.end();it++)
00102     if((const MEDCouplingFieldDouble *)(*it))
00103       return (*it)->getTimeUnit();
00104   return std::string();
00105 }
00106 
00107 double MEDCouplingMultiFields::getTimeResolution() const throw(INTERP_KERNEL::Exception)
00108 {
00109   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();
00110   for(;it!=_fs.end();it++)
00111     if((const MEDCouplingFieldDouble *)(*it))
00112       return (*it)->getTimeTolerance();
00113   throw INTERP_KERNEL::Exception("MEDCouplingMultiFields::getTimeResolution : no not null field !");
00114 }
00115 
00116 std::string MEDCouplingMultiFields::simpleRepr() const
00117 {
00118   std::ostringstream ret;
00119   ret << "MEDCouplingMultiFields with name : \"" << getName() << "\"\n";
00120   ret << "Description of MEDCouplingMultiFields is : \"" << getDescription() << "\"\n";
00121   ret << "Number of discretization : " << _fs.size() << "\n";
00122   ret << "Number of different meshes : ";
00123   std::vector<MEDCouplingMesh *> ms;
00124   std::vector<int> refms;
00125   try
00126     {
00127       ms=getDifferentMeshes(refms);
00128       ret << ms.size() << "\n";
00129     }
00130   catch(INTERP_KERNEL::Exception& e)
00131     { ret << "Current instance is INVALID !\n"; }
00132   return ret.str();
00133 }
00134 
00135 std::string MEDCouplingMultiFields::advancedRepr() const
00136 {
00137   return simpleRepr();
00138 }
00139 
00140 bool MEDCouplingMultiFields::isEqualWithoutConsideringStr(const MEDCouplingMultiFields *other, double meshPrec, double valsPrec) const
00141 {
00142   std::size_t sz=_fs.size();
00143   if(sz!=other->_fs.size())
00144     return false;
00145   for(std::size_t i=0;i<sz;i++)
00146     if(!_fs[i]->isEqualWithoutConsideringStr(other->_fs[i],meshPrec,valsPrec))
00147       return false;
00148   return true;
00149 }
00150 
00151 const MEDCouplingFieldDouble *MEDCouplingMultiFields::getFieldWithId(int id) const throw(INTERP_KERNEL::Exception)
00152 {
00153   if(id>=(int)_fs.size() || id < 0)
00154     throw INTERP_KERNEL::Exception("MEDCouplingMultiFields::getFieldWithId : invalid id outside boundaries !");
00155   return _fs[id];
00156 }
00157 
00158 std::vector<const MEDCouplingFieldDouble *> MEDCouplingMultiFields::getFields() const
00159 {
00160   std::vector<const MEDCouplingFieldDouble *> ret(_fs.size());
00161   std::copy(_fs.begin(),_fs.end(),ret.begin());
00162   return ret;
00163 }
00164 
00165 int MEDCouplingMultiFields::getNumberOfFields() const
00166 {
00167   return (int)_fs.size();
00168 }
00169 
00170 const MEDCouplingFieldDouble *MEDCouplingMultiFields::getFieldAtPos(int id) const throw(INTERP_KERNEL::Exception)
00171 {
00172   if(id<0 || id>=(int)_fs.size())
00173     {
00174       std::ostringstream oss; oss << "MEDCouplingMultiFields::getFieldAtPos : Invalid given pos : should be >=0 and < " << _fs.size() << " !";
00175       throw INTERP_KERNEL::Exception(oss.str().c_str());
00176     }
00177   return _fs[id];
00178 }
00179 
00180 void MEDCouplingMultiFields::updateTime() const
00181 {
00182   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();
00183   for(;it!=_fs.end();it++)
00184     if((const MEDCouplingFieldDouble *)(*it))
00185       (*it)->updateTime();
00186   it=_fs.begin();
00187   for(;it!=_fs.end();it++)
00188     if((const MEDCouplingFieldDouble *)(*it))
00189       updateTimeWith(*(*it));
00190 }
00191 
00192 std::vector<MEDCouplingMesh *> MEDCouplingMultiFields::getMeshes() const throw(INTERP_KERNEL::Exception)
00193 {
00194   std::vector<MEDCouplingMesh *> ms;
00195   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();it!=_fs.end();it++)
00196     {
00197       const MEDCouplingMesh *m=0;
00198       if((const MEDCouplingFieldDouble *)(*it))
00199         m=(*it)->getMesh();
00200       ms.push_back(const_cast<MEDCouplingMesh *>(m));
00201     }
00202   return ms;
00203 }
00204 
00205 std::vector<MEDCouplingMesh *> MEDCouplingMultiFields::getDifferentMeshes(std::vector<int>& refs) const throw(INTERP_KERNEL::Exception)
00206 {
00207   refs.resize(_fs.size());
00208   std::vector<MEDCouplingMesh *> ms;
00209   int id=0;
00210   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();it!=_fs.end();it++,id++)
00211     {
00212       const MEDCouplingMesh *m=0;
00213       if((const MEDCouplingFieldDouble *)(*it))
00214         m=(*it)->getMesh();
00215       if(m)
00216         {
00217           std::vector<MEDCouplingMesh *>::iterator it2=std::find(ms.begin(),ms.end(),m);
00218           if(it2==ms.end())
00219             {
00220               ms.push_back(const_cast<MEDCouplingMesh *>(m));
00221               refs[id]=(int)ms.size()-1;
00222             }
00223           else
00224             refs[id]=(int)std::distance(ms.begin(),it2);
00225         }
00226       else
00227         refs[id]=-1;
00228     }
00229   return ms;
00230 }
00231 
00232 std::vector<DataArrayDouble *> MEDCouplingMultiFields::getArrays() const throw(INTERP_KERNEL::Exception)
00233 {
00234   std::vector<DataArrayDouble *> tmp;
00235   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();it!=_fs.end();it++)
00236     {
00237       std::vector<DataArrayDouble *> tmp2=(*it)->getArrays();
00238       tmp.insert(tmp.end(),tmp2.begin(),tmp2.end());
00239     }
00240   return tmp;
00241 }
00242 
00243 std::vector<DataArrayDouble *> MEDCouplingMultiFields::getDifferentArrays(std::vector< std::vector<int> >& refs) const throw(INTERP_KERNEL::Exception)
00244 {
00245   refs.resize(_fs.size());
00246   int id=0;
00247   std::vector<DataArrayDouble *> ret;
00248   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();it!=_fs.end();it++,id++)
00249     {
00250       std::vector<DataArrayDouble *> tmp2;
00251       if((const MEDCouplingFieldDouble *)(*it))
00252         {
00253           tmp2=(*it)->getArrays();
00254           refs[id].resize(tmp2.size());
00255         }
00256       else
00257         refs[id].clear();
00258       int id2=0;
00259       for(std::vector<DataArrayDouble *>::const_iterator it2=tmp2.begin();it2!=tmp2.end();it2++,id2++)
00260         {
00261           if(*it2)
00262             {
00263               std::vector<DataArrayDouble *>::iterator it3=std::find(ret.begin(),ret.end(),*it2);
00264               if(it3==ret.end())
00265                 {
00266                   ret.push_back(*it2);
00267                   refs[id][id2]=(int)ret.size()-1;
00268                 }
00269               else
00270                 refs[id][id2]=(int)std::distance(ret.begin(),it3);
00271             }
00272           else
00273             refs[id][id2]=-1;
00274         }
00275     }
00276   return ret;
00277 }
00278 
00279 void MEDCouplingMultiFields::checkCoherency() const throw(INTERP_KERNEL::Exception)
00280 {
00281   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> >::const_iterator it=_fs.begin();
00282   for(;it!=_fs.end();it++)
00283     {
00284       if((const MEDCouplingFieldDouble *)(*it)==0)
00285         throw INTERP_KERNEL::Exception("MEDCouplingMultiFields::checkCoherency : There is an empty Field in array...");
00286       (*it)->checkCoherency();
00287     }
00288 }
00289 
00290 MEDCouplingMultiFields::MEDCouplingMultiFields(const std::vector<MEDCouplingFieldDouble *>& fs) throw(INTERP_KERNEL::Exception):_fs(fs.size())
00291 {
00292   int id=0;
00293   for(std::vector< MEDCouplingFieldDouble * >::const_iterator it=fs.begin();it!=fs.end();it++,id++)
00294     {
00295       if(*it)
00296         (*it)->incrRef();
00297       else
00298         throw INTERP_KERNEL::Exception("MEDCouplingMultiFields constructor : empty field found in vector !");
00299       (*it)->checkCoherency();
00300       _fs[id]=*it;
00301     }
00302 }
00303 
00304 
00308 MEDCouplingMultiFields::MEDCouplingMultiFields(const MEDCouplingMultiFields& other)
00309 {
00310   std::size_t sz=other._fs.size();
00311   _fs.resize(sz);
00312   std::vector<int> refs;
00313   std::vector< std::vector<int> > refs2;
00314   std::vector<MEDCouplingMesh *> ms=other.getDifferentMeshes(refs);
00315   std::size_t msLgh=ms.size();
00316   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> > ms2(msLgh);
00317   for(std::size_t i=0;i<msLgh;i++)
00318     ms2[i]=ms[i]->deepCpy();
00319   std::vector<DataArrayDouble *> das=other.getDifferentArrays(refs2);
00320   std::size_t dasLgth=das.size();
00321   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > das2(dasLgth);
00322   for(std::size_t i=0;i<dasLgth;i++)
00323     das2[i]=das[i]->deepCpy();
00324   for(std::size_t i=0;i<sz;i++)
00325     {
00326       if((const MEDCouplingFieldDouble *)other._fs[i])
00327         {
00328           MEDCouplingFieldTemplate *tmp=MEDCouplingFieldTemplate::New(other._fs[i]);
00329           _fs[i]=MEDCouplingFieldDouble::New(tmp,other._fs[i]->getTimeDiscretization());
00330           tmp->decrRef();
00331           if(refs[i]!=-1)
00332             _fs[i]->setMesh(ms2[refs[i]]);
00333           std::size_t nbOfArr=refs2[i].size();
00334           std::vector<DataArrayDouble *> tmp2(nbOfArr);
00335           for(std::size_t j=0;j<nbOfArr;j++)
00336             {
00337               if(refs2[i][j]!=-1)
00338                 tmp2[j]=das2[refs2[i][j]];
00339               else
00340                 tmp2[j]=0;
00341             }
00342           _fs[i]->setArrays(tmp2);
00343           std::vector<int> tinyInfo;
00344           std::vector<double> tinyInfo2;
00345           other._fs[i]->getTimeDiscretizationUnderGround()->getTinySerializationIntInformation2(tinyInfo);
00346           other._fs[i]->getTimeDiscretizationUnderGround()->getTinySerializationDbleInformation2(tinyInfo2);
00347           _fs[i]->getTimeDiscretizationUnderGround()->finishUnserialization2(tinyInfo,tinyInfo2);
00348         }
00349     }
00350 }
00351 
00352 MEDCouplingMultiFields::MEDCouplingMultiFields()
00353 {
00354 }
00355 
00356 void MEDCouplingMultiFields::getTinySerializationInformation(std::vector<int>& tinyInfo, std::vector<double>& tinyInfo2, int& nbOfDiffMeshes, int& nbOfDiffArr) const
00357 {
00358   std::vector<int> refs;
00359   std::vector<MEDCouplingMesh *> ms=getDifferentMeshes(refs);
00360   nbOfDiffMeshes=(int)ms.size();
00361   std::vector< std::vector<int> > refs2;
00362   std::vector<DataArrayDouble *> fs=getDifferentArrays(refs2);
00363   nbOfDiffArr=(int)fs.size();
00364   //
00365   std::size_t sz=refs.size();//==_fs.size()
00366   int sz2=0;
00367   for(std::size_t i=0;i<sz;i++)
00368     sz2+=(int)refs2[i].size();
00369   //
00370   tinyInfo2.clear();
00371   std::vector<int> doubleDaInd(sz);
00372   std::vector<int> timeDiscrInt;
00373   tinyInfo.resize(sz2+5*sz+3);
00374   tinyInfo[0]=(int)sz;
00375   tinyInfo[1]=sz2;
00376   for(std::size_t i=0;i<sz;i++)
00377     {
00378       std::vector<double> tmp;
00379       std::vector<int> tmp2;
00380       _fs[i]->getTimeDiscretizationUnderGround()->getTinySerializationDbleInformation2(tmp);
00381       _fs[i]->getTimeDiscretizationUnderGround()->getTinySerializationIntInformation2(tmp2);
00382       tinyInfo[3*sz+3+i]=(int)tmp.size();
00383       tinyInfo[4*sz+3+i]=(int)tmp2.size();
00384       tinyInfo2.insert(tinyInfo2.end(),tmp.begin(),tmp.end());
00385       timeDiscrInt.insert(timeDiscrInt.end(),tmp2.begin(),tmp2.end());
00386     }
00387   int sz3=(int)timeDiscrInt.size();
00388   tinyInfo[2]=sz3;
00389   //
00390   for(std::size_t i=0;i<sz;i++)
00391     tinyInfo[i+3]=refs[i];
00392   for(std::size_t i=0;i<sz;i++)
00393     tinyInfo[i+sz+3]=(int)refs2[i].size();
00394   for(std::size_t i=0;i<sz;i++)
00395     tinyInfo[i+2*sz+3]=(int)_fs[i]->getTimeDiscretization();
00396   int k=0;
00397   for(std::size_t i=0;i<sz;i++)
00398     for(std::vector<int>::const_iterator it=refs2[i].begin();it!=refs2[i].end();it++,k++)
00399       tinyInfo[5*sz+k+3]=*it;
00400   tinyInfo.insert(tinyInfo.end(),timeDiscrInt.begin(),timeDiscrInt.end());//tinyInfo has lgth==sz3+sz2+5*sz+3
00401 }
00402 
00403 void MEDCouplingMultiFields::finishUnserialization(const std::vector<int>& tinyInfoI, const std::vector<double>& tinyInfoD,
00404                                                    const std::vector<MEDCouplingFieldTemplate *>& ft, const std::vector<MEDCouplingMesh *>& ms,
00405                                                    const std::vector<DataArrayDouble *>& das)
00406 {
00407   int sz=tinyInfoI[0];
00408   _fs.resize(sz);
00409   int sz2=tinyInfoI[1];
00410   // dealing with ft with no mesh set.
00411   for(int i=0;i<sz;i++)
00412     {
00413       int meshId=tinyInfoI[3+i];
00414       if(meshId!=-1)
00415         ft[i]->setMesh(ms[meshId]);
00416     }
00417   // dealing with fieldtemplate->fielddouble
00418   int k=0;
00419   int offI=0;
00420   int offD=0;
00421   for(int i=0;i<sz;i++)
00422     {
00423       _fs[i]=MEDCouplingFieldDouble::New(ft[i],(TypeOfTimeDiscretization)tinyInfoI[2*sz+3+i]);
00424       int sz3=tinyInfoI[sz+i+3];
00425       std::vector<DataArrayDouble *> tmp(sz3);
00426       for(int j=0;j<sz3;j++,k++)
00427         {
00428           int daId=tinyInfoI[5*sz+k+3];
00429           if(daId!=-1)
00430             tmp[j]=das[daId];
00431           else
00432             tmp[j]=0;
00433         }
00434       _fs[i]->setArrays(tmp);
00435       // time discr tiny info
00436       int lgthI=tinyInfoI[4*sz+3+i];
00437       int lgthD=tinyInfoI[3*sz+3+i];
00438       //
00439       std::vector<int> tdInfoI(tinyInfoI.begin()+sz2+5*sz+3+offI,tinyInfoI.begin()+sz2+5*sz+3+offI+lgthI);
00440       std::vector<double> tdInfoD(tinyInfoD.begin()+offD,tinyInfoD.begin()+offD+lgthD);
00441       _fs[i]->getTimeDiscretizationUnderGround()->finishUnserialization2(tdInfoI,tdInfoD);
00442       //
00443       offI+=lgthI;
00444       offD+=lgthD;
00445     }
00446 }