Salome HOME
Overload of MEDLoader.ReadField method to ease access of medcoupling for new comers
[tools/medcoupling.git] / src / MEDLoader / MEDFileData.cxx
index 61f1429f310af06946731886c38affb4135dedb4..af66dda5b732f8dde5e2f91f3b6c119401255fe4 100644 (file)
@@ -1,9 +1,9 @@
-// Copyright (C) 2007-2012  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 // Author : Anthony Geay (CEA/DEN)
 
 #include "MEDFileData.hxx"
+#include "MEDLoaderBase.hxx"
+#include "MEDFileSafeCaller.txx"
+#include "MEDFileBlowStrEltUp.hxx"
 
-using namespace ParaMEDMEM;
+#include "InterpKernelAutoPtr.hxx"
 
-MEDFileData *MEDFileData::New(const char *fileName) throw(INTERP_KERNEL::Exception)
+using namespace MEDCoupling;
+
+MEDFileData *MEDFileData::New(const std::string& fileName)
 {
-  return new MEDFileData(fileName);
+  MEDFileUtilities::AutoFid fid(OpenMEDFileForRead(fileName));
+  return New(fid);
+}
+
+MEDFileData *MEDFileData::New(med_idt fid)
+{
+  return new MEDFileData(fid);
 }
 
 MEDFileData *MEDFileData::New()
@@ -32,33 +43,79 @@ MEDFileData *MEDFileData::New()
   return new MEDFileData;
 }
 
+MEDFileData *MEDFileData::deepCopy() const
+{
+  MCAuto<MEDFileFields> fields;
+  if(_fields.isNotNull())
+    fields=_fields->deepCopy();
+  MCAuto<MEDFileMeshes> meshes;
+  if(_meshes.isNotNull())
+    meshes=_meshes->deepCopy();
+  MCAuto<MEDFileParameters> params;
+  if(_params.isNotNull())
+    params=_params->deepCopy();
+  MCAuto<MEDFileData> ret(MEDFileData::New());
+  ret->_fields=fields; ret->_meshes=meshes; ret->_params=params;
+  return ret.retn();
+}
+
+std::size_t MEDFileData::getHeapMemorySizeWithoutChildren() const
+{
+  return _header.capacity();
+}
+
+std::vector<const BigMemoryObject *> MEDFileData::getDirectChildrenWithNull() const
+{
+  std::vector<const BigMemoryObject *> ret;
+  ret.push_back((const MEDFileFields *)_fields);
+  ret.push_back((const MEDFileMeshes *)_meshes);
+  ret.push_back((const MEDFileParameters *)_params);
+  ret.push_back((const MEDFileMeshSupports *)_mesh_supports);
+  ret.push_back((const MEDFileStructureElements *)_struct_elems);
+  return ret;
+
+}
+
+/** Return a borrowed reference (caller is not responsible for object destruction) */
 MEDFileFields *MEDFileData::getFields() const
 {
   return const_cast<MEDFileFields *>(static_cast<const MEDFileFields *>(_fields));
 }
 
+/** Return a borrowed reference (caller is not responsible for object destruction) */
 MEDFileMeshes *MEDFileData::getMeshes() const
 {
   return const_cast<MEDFileMeshes *>(static_cast<const MEDFileMeshes *>(_meshes));
 }
 
-void MEDFileData::setFields(MEDFileFields *fields) throw(INTERP_KERNEL::Exception)
+/** Return a borrowed reference (caller is not responsible for object destruction) */
+MEDFileParameters *MEDFileData::getParams() const
 {
-  if(!fields)
-    throw INTERP_KERNEL::Exception("MEDFileData::setFields : input pointer is null !");
-  fields->incrRef();
+  return const_cast<MEDFileParameters *>(static_cast<const MEDFileParameters *>(_params));
+}
+
+void MEDFileData::setFields(MEDFileFields *fields)
+{
+  if(fields)
+    fields->incrRef();
   _fields=fields;
 }
 
-void MEDFileData::setMeshes(MEDFileMeshes *meshes) throw(INTERP_KERNEL::Exception)
+void MEDFileData::setMeshes(MEDFileMeshes *meshes)
 {
-  if(!meshes)
-    throw INTERP_KERNEL::Exception("MEDFileData::setMeshes : input pointer is null !");
-  meshes->incrRef();
+  if(meshes)
+    meshes->incrRef();
   _meshes=meshes;
 }
 
-int MEDFileData::getNumberOfFields() const throw(INTERP_KERNEL::Exception)
+void MEDFileData::setParams(MEDFileParameters *params)
+{
+  if(params)
+    params->incrRef();
+  _params=params;
+}
+
+int MEDFileData::getNumberOfFields() const
 {
   const MEDFileFields *f=_fields;
   if(!f)
@@ -66,7 +123,7 @@ int MEDFileData::getNumberOfFields() const throw(INTERP_KERNEL::Exception)
   return f->getNumberOfFields();
 }
 
-int MEDFileData::getNumberOfMeshes() const throw(INTERP_KERNEL::Exception)
+int MEDFileData::getNumberOfMeshes() const
 {
   const MEDFileMeshes *m=_meshes;
   if(!m)
@@ -74,6 +131,14 @@ int MEDFileData::getNumberOfMeshes() const throw(INTERP_KERNEL::Exception)
   return m->getNumberOfMeshes();
 }
 
+int MEDFileData::getNumberOfParams() const
+{
+  const MEDFileParameters *p=_params;
+  if(!p)
+    throw INTERP_KERNEL::Exception("MEDFileData::getNumberOfParams : no params set !");
+  return p->getNumberOfParams();
+}
+
 std::string MEDFileData::simpleRepr() const
 {
   std::ostringstream oss;
@@ -93,11 +158,19 @@ std::string MEDFileData::simpleRepr() const
       tmp2->simpleReprWithoutHeader(oss);
     }
   else
-    oss << "No meshes set !!!\n";
+    oss << "No meshes set !!!\n\n";
+  oss << "Params part :\n*************\n\n";
+  const MEDFileParameters *tmp3=_params;
+  if(tmp3)
+    {
+      tmp3->simpleReprWithoutHeader(oss);
+    }
+  else
+    oss << "No params set !!!\n";
   return oss.str();
 }
 
-bool MEDFileData::changeMeshNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
+bool MEDFileData::changeMeshNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
 {
   bool ret=false;
   MEDFileFields *fields=_fields;
@@ -109,7 +182,7 @@ bool MEDFileData::changeMeshNames(const std::vector< std::pair<std::string,std::
   return ret;
 }
 
-bool MEDFileData::changeMeshName(const char *oldMeshName, const char *newMeshName) throw(INTERP_KERNEL::Exception)
+bool MEDFileData::changeMeshName(const std::string& oldMeshName, const std::string& newMeshName)
 {
   std::string oldName(oldMeshName);
   std::vector< std::pair<std::string,std::string> > v(1);
@@ -124,7 +197,7 @@ bool MEDFileData::changeMeshName(const char *oldMeshName, const char *newMeshNam
  * \return If true is returned it means that some meshes in \a this has been modified and eventually fields have been renumbered.
  *         \n If false \a this remains unchanged.
  */
-bool MEDFileData::unPolyzeMeshes() throw(INTERP_KERNEL::Exception)
+bool MEDFileData::unPolyzeMeshes()
 {
   MEDFileMeshes *ms=_meshes;
   if(!ms)
@@ -132,7 +205,7 @@ bool MEDFileData::unPolyzeMeshes() throw(INTERP_KERNEL::Exception)
   std::vector< MEDFileMesh * > meshesImpacted;
   std::vector< DataArrayInt * > renumParamsOfMeshImpacted;//same size as meshesImpacted
   std::vector< std::vector<int> > oldCodeOfMeshImpacted,newCodeOfMeshImpacted;//same size as meshesImpacted
-  std::vector<MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > memSaverIfThrow;//same size as meshesImpacted
+  std::vector<MCAuto<DataArrayInt> > memSaverIfThrow;//same size as meshesImpacted
   for(int i=0;i<ms->getNumberOfMeshes();i++)
     {
       MEDFileMesh *m=ms->getMeshAtPos(i);
@@ -159,29 +232,139 @@ bool MEDFileData::unPolyzeMeshes() throw(INTERP_KERNEL::Exception)
   return !meshesImpacted.empty();
 }
 
+void MEDFileData::dealWithStructureElements()
+{
+  if(_struct_elems.isNull())
+    throw INTERP_KERNEL::Exception("MEDFileData::dealWithStructureElements : no structure elements in this !");
+  if(_meshes.isNull() || _fields.isNull())
+    throw INTERP_KERNEL::Exception("MEDFileData::dealWithStructureElements : meshes and fields must be not null !");
+  MEDFileBlowStrEltUp::DealWithSE(_fields,_meshes,_struct_elems);
+}
+
+/*!
+ * 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.
+ * You can invoke MEDFileFields::partOfThisLyingOnSpecifiedMeshName method to make it work.
+ */
+MCAuto<MEDFileData> MEDFileData::Aggregate(const std::vector<const MEDFileData *>& mfds)
+{
+  if(mfds.empty())
+    throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : empty vector !");
+  std::size_t sz(mfds.size()),i(0);
+  MCAuto<MEDFileData> ret(MEDFileData::New());
+  std::vector<const MEDFileUMesh *> ms(sz);
+  std::vector< std::vector< std::pair<int,int> > > dts(sz);
+  for(std::vector<const MEDFileData *>::const_iterator it=mfds.begin();it!=mfds.end();it++,i++)
+    {
+      const MEDFileData *elt(*it);
+      if(!elt)
+        throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : presence of NULL pointer !");
+      const MEDFileMeshes *meshes(elt->getMeshes());
+      if(!meshes)
+        throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : presence of an instance with no meshes attached on it !");
+      if(meshes->getNumberOfMeshes()!=1)
+        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.");
+      const MEDFileMesh *mesh(meshes->getMeshAtPos(0));
+      if(!mesh)
+        throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : presence of null mesh in a MEDFileData instance among input vector !");
+      const MEDFileUMesh *umesh(dynamic_cast<const MEDFileUMesh *>(mesh));
+      if(!umesh)
+        throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : works only for unstructured meshes !");
+      ms[i]=umesh;
+      dts[i]=umesh->getAllDistributionOfTypes();
+    }
+  MCAuto<MEDFileUMesh> agg_m(MEDFileUMesh::Aggregate(ms));
+  MCAuto<MEDFileMeshes> mss(MEDFileMeshes::New()); mss->pushMesh(agg_m);
+  ret->setMeshes(mss);
+  // fields
+  std::vector<std::string> fieldNames(mfds[0]->getFields()->getFieldsNames());
+  std::set<std::string> fieldNamess(fieldNames.begin(),fieldNames.end());
+  if(fieldNames.size()!=fieldNamess.size())
+    throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : field names must be different each other !");
+  std::vector< std::vector<const MEDFileAnyTypeFieldMultiTS *> > vectOfFields(fieldNames.size());
+  std::vector< std::vector< MCAuto< MEDFileAnyTypeFieldMultiTS > > > vectOfFields2(fieldNames.size());
+  MCAuto<MEDFileFields> fss(MEDFileFields::New());
+  for(std::vector<const MEDFileData *>::const_iterator it=mfds.begin();it!=mfds.end();it++)
+    {
+      std::vector<std::string> fieldNames0((*it)->getFields()->getFieldsNames());
+      std::set<std::string> fieldNamess0(fieldNames0.begin(),fieldNames0.end());
+      if(fieldNamess!=fieldNamess0)
+        throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : field names must be the same for all input instances !");
+      i=0;
+      for(std::vector<std::string>::const_iterator it1=fieldNames.begin();it1!=fieldNames.end();it1++,i++)
+        {
+          MCAuto<MEDFileAnyTypeFieldMultiTS> fmts((*it)->getFields()->getFieldWithName(*it1));
+          if(fmts.isNull())
+            throw INTERP_KERNEL::Exception("MEDFileData::Aggregate : internal error 1 !");
+          vectOfFields2[i].push_back(fmts); vectOfFields[i].push_back(fmts);
+        }
+    }
+  i=0;
+  for(std::vector<std::string>::const_iterator it1=fieldNames.begin();it1!=fieldNames.end();it1++,i++)
+    {
+      MCAuto<MEDFileAnyTypeFieldMultiTS> fmts(MEDFileAnyTypeFieldMultiTS::Aggregate(vectOfFields[i],dts));
+      fmts->setMeshName(agg_m->getName());
+      fss->pushField(fmts);
+    }
+  ret->setFields(fss);
+  return ret;
+}
+
 MEDFileData::MEDFileData()
 {
 }
 
-MEDFileData::MEDFileData(const char *fileName) throw(INTERP_KERNEL::Exception)
+MEDFileData::MEDFileData(med_idt fid)
 try
-  {
-    _fields=MEDFileFields::New(fileName);
-    _meshes=MEDFileMeshes::New(fileName);
-  }
+{
+  readHeader(fid);
+  _mesh_supports=MEDFileMeshSupports::New(fid);
+  _struct_elems=MEDFileStructureElements::New(fid,_mesh_supports);
+  _fields=MEDFileFields::NewWithDynGT(fid,_struct_elems,true);
+  _meshes=MEDFileMeshes::New(fid);
+  _params=MEDFileParameters::New(fid);
+}
 catch(INTERP_KERNEL::Exception& e)
-  {
+{
     throw e;
-  }
-
-void MEDFileData::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
-{
-  med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
-  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
-  const MEDFileMeshes *ms=_meshes;
-  if(ms)
-    ms->write(fid);
-  const MEDFileFields *fs=_fields;
-  if(fs)
-    fs->writeLL(fid);
+}
+
+void MEDFileData::writeLL(med_idt fid) const
+{
+  writeHeader(fid);
+  if(_meshes.isNotNull())
+    _meshes->writeLL(fid);
+  if(_fields.isNotNull())
+    _fields->writeLL(fid);
+  if(_params.isNotNull())
+    _params->writeLL(fid);
+  if(_mesh_supports.isNotNull())
+    _mesh_supports->writeLL(fid);
+  if(_struct_elems.isNotNull())
+    _struct_elems->writeLL(fid);
+}
+
+std::string MEDFileData::getHeader() const
+{
+  return _header;
+}
+
+
+void MEDFileData::setHeader(const std::string& header)
+{
+  _header=header;
+}
+
+void MEDFileData::readHeader(med_idt fid)
+{
+  INTERP_KERNEL::AutoPtr<char> header(MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE));
+  int ret(MEDfileCommentRd(fid,header));
+  if(ret==0)
+    _header=MEDLoaderBase::buildStringFromFortran(header,MED_COMMENT_SIZE);
+}
+
+void MEDFileData::writeHeader(med_idt fid) const
+{
+  INTERP_KERNEL::AutoPtr<char> header(MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE));
+  MEDLoaderBase::safeStrCpy(_header.c_str(),MED_COMMENT_SIZE,header,_too_long_str);
+  MEDFILESAFECALLERWR0(MEDfileCommentWr,(fid,header));
 }