Salome HOME
Fix computation height of isocel triangle with base equal zero : NaN
[tools/medcoupling.git] / src / MEDLoader / MEDFileField.cxx
index 0193d138d7e5a3d400d046559b447f07b46b4313..dc81062983ab4c36394b02db050c007211927003 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2023  CEA, EDF
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -35,6 +35,7 @@
 #include <algorithm>
 #include <iterator>
 
+// From MEDLoader.cxx TU:
 extern INTERP_KERNEL::NormalizedCellType typmai2[MED_N_CELL_FIXED_GEO];
 extern med_geometry_type typmainoeud[1];
 extern med_geometry_type typmai3[INTERP_KERNEL::NORM_MAXTYPE];
@@ -234,7 +235,7 @@ void MEDFileFields::simpleRepr(int bkOffset, std::ostream& oss) const
   for(std::vector< MCAuto<MEDFileAnyTypeFieldMultiTSWithoutSDA> >::const_iterator it=_fields.begin();it!=_fields.end();it++,i++)
     {
       const MEDFileAnyTypeFieldMultiTSWithoutSDA *cur=(*it);
-      std::string chapter(17,'0'+i);
+      std::string chapter(17,(char)('0'+i));
       oss << startLine << chapter << std::endl;
       if(cur)
         {
@@ -273,7 +274,12 @@ try:MEDFileFieldGlobsReal(fid)
           }
         case MED_INT32:
           {
-            _fields[i]=MEDFileIntFieldMultiTSWithoutSDA::New(fid,fieldName,meshName,typcha,infos,nbOfStep,dtunit,loadAll,ms,entities);
+            _fields[i]=MEDFileInt32FieldMultiTSWithoutSDA::New(fid,fieldName,meshName,typcha,infos,nbOfStep,dtunit,loadAll,ms,entities);
+            break;
+          }
+        case MED_INT64:
+          {
+            _fields[i]=MEDFileInt64FieldMultiTSWithoutSDA::New(fid,fieldName,meshName,typcha,infos,nbOfStep,dtunit,loadAll,ms,entities);
             break;
           }
         case MED_FLOAT32:
@@ -285,13 +291,13 @@ try:MEDFileFieldGlobsReal(fid)
           {
             if(sizeof(med_int)==sizeof(int))
               {
-                _fields[i]=MEDFileIntFieldMultiTSWithoutSDA::New(fid,fieldName,meshName,typcha,infos,nbOfStep,dtunit,loadAll,ms,entities);
+                _fields[i]=MEDFileInt32FieldMultiTSWithoutSDA::New(fid,fieldName,meshName,typcha,infos,nbOfStep,dtunit,loadAll,ms,entities);
                 break;
               }
           }
         default:
           {
-            std::ostringstream oss; oss << "constructor MEDFileFields(fileName) : file \'" << FileNameFromFID(fid) << "\' at pos #" << i << " field has name \'" << fieldName << "\' but the type of field is not in [MED_FLOAT64, MED_INT32, MED_FLOAT32] !";
+            std::ostringstream oss; oss << "constructor MEDFileFields(fileName) : file \'" << FileNameFromFID(fid) << "\' at pos #" << i << " field has name \'" << fieldName << "\' but the type of field is not in [MED_FLOAT64, MED_INT32, MED_FLOAT32, MED_INT64] !";
             throw INTERP_KERNEL::Exception(oss.str());
           }
       }
@@ -848,17 +854,20 @@ MEDFileAnyTypeFieldMultiTS *MEDFileFields::getFieldAtPos(int i) const
     return 0;
   MCAuto<MEDFileAnyTypeFieldMultiTS> ret;
   const MEDFileFieldMultiTSWithoutSDA *fmtsC(dynamic_cast<const MEDFileFieldMultiTSWithoutSDA *>(fmts));
-  const MEDFileIntFieldMultiTSWithoutSDA *fmtsC2(dynamic_cast<const MEDFileIntFieldMultiTSWithoutSDA *>(fmts));
+  const MEDFileInt32FieldMultiTSWithoutSDA *fmtsC2(dynamic_cast<const MEDFileInt32FieldMultiTSWithoutSDA *>(fmts));
+  const MEDFileInt64FieldMultiTSWithoutSDA *fmtsC4(dynamic_cast<const MEDFileInt64FieldMultiTSWithoutSDA *>(fmts));
   const MEDFileFloatFieldMultiTSWithoutSDA *fmtsC3(dynamic_cast<const MEDFileFloatFieldMultiTSWithoutSDA *>(fmts));
   if(fmtsC)
     ret=MEDFileFieldMultiTS::New(*fmtsC,false);
   else if(fmtsC2)
-    ret=MEDFileIntFieldMultiTS::New(*fmtsC2,false);
+    ret=MEDFileInt32FieldMultiTS::New(*fmtsC2,false);
+  else if(fmtsC4)
+    ret=MEDFileInt64FieldMultiTS::New(*fmtsC4,false);
   else if(fmtsC3)
     ret=MEDFileFloatFieldMultiTS::New(*fmtsC3,false);
   else
     {
-      std::ostringstream oss; oss << "MEDFileFields::getFieldAtPos : At pos #" << i << " field is neither double (FLOAT64) nor float (FLOAT32) nor integer (INT32) !";
+      std::ostringstream oss; oss << "MEDFileFields::getFieldAtPos : At pos #" << i << " field is neither double (FLOAT64) nor float (FLOAT32) nor integer (INT32) nor integer (INT64) !";
       throw INTERP_KERNEL::Exception(oss.str());
     }
   ret->shallowCpyGlobs(*this);
@@ -1068,6 +1077,125 @@ void MEDFileFields::getMeshSENames(std::vector< std::pair<std::string,std::strin
 void MEDFileFields::blowUpSE(MEDFileMeshes *ms, const MEDFileStructureElements *ses)
 {
   MEDFileBlowStrEltUp::DealWithSE(this,ms,ses);
+  this->aggregateFieldsOnSameMeshes(ms);
+}
+
+/*!
+ * This method is dedicated to explosed Structured Elements that can lead to exotic situation.
+ * Especially when there are several structured elements for a same field.
+ * 
+ * This method looks into meshes into \a ms if there is presence of multiple mesh having same name.
+ * If so, these meshes are aggregated in the same order than \a ms.
+ * The fields in \a this lying on the same meshName are also aggregated in the same order than \a this.
+ */
+void MEDFileFields::aggregateFieldsOnSameMeshes(MEDFileMeshes *ms)
+{
+  if(!ms)
+    THROW_IK_EXCEPTION("MEDFileFields::aggregateFieldsOnSameMeshes : ms is nullptr !");
+  //
+  std::vector<std::string> msNames(ms->getMeshesNames());
+  std::set<std::string> msNamesSet(msNames.begin(),msNames.end());
+  if(msNames.size() == msNamesSet.size())
+    return ;
+  //
+  std::map<std::string,std::vector< MCAuto<MEDFileAnyTypeFieldMultiTSWithoutSDA>> > fsByName;
+  for(auto fmts : _fields)
+  {
+    fsByName[fmts->getMeshName()].push_back(fmts);
+  }
+  std::vector<std::string> fieldsNamesToBeAggregated;
+  std::vector< MCAuto<MEDFileAnyTypeFieldMultiTSWithoutSDA> > otherFields;
+  std::set<std::string> expectedMeshNamesToMerge;
+  for(auto fieldsWithSame : fsByName)
+  {
+    if(fieldsWithSame.second.size() > 1)
+    {
+      fieldsNamesToBeAggregated.push_back(fieldsWithSame.first);
+      std::set< std::string > zeMeshNames;
+      for(auto fmtsWithSameName : fieldsWithSame.second)
+        zeMeshNames.insert(fmtsWithSameName->getMeshName());
+      if(zeMeshNames.size()!=1)
+        THROW_IK_EXCEPTION("MEDFileFields::aggregateFieldsOnSameMeshes : Presence of multiple MultiTS instances with same name but lying on same meshName. Looks bad !");
+      std::string meshNameToMerge = *zeMeshNames.begin();
+      if(expectedMeshNamesToMerge.find(meshNameToMerge) != expectedMeshNamesToMerge.end())
+        THROW_IK_EXCEPTION("MEDFileFields::aggregateFieldsOnSameMeshes : unexpected situation ! Error in implementation !");
+      expectedMeshNamesToMerge.insert(*zeMeshNames.begin());
+    }
+    else
+    {
+      otherFields.push_back(fieldsWithSame.second.front());
+    }
+  }
+  for(auto fieldNameToBeAggregated : fieldsNamesToBeAggregated)
+  {
+    auto base_fs = fsByName[fieldNameToBeAggregated].front();
+    auto fieldsToBeAggregated = fsByName[fieldNameToBeAggregated];
+    std::vector< std::vector< std::pair<int,mcIdType> > > dtsToAggregate;
+    std::vector< MCAuto<MEDFileAnyTypeFieldMultiTS> > eltsToAggregate;
+    for(auto fieldToBeAggregated : fieldsToBeAggregated)
+    {
+      std::vector< std::pair<std::pair<INTERP_KERNEL::NormalizedCellType,int>,std::pair<mcIdType,mcIdType> > > entries;
+      int iteration,order;
+      {
+        auto dtits = fieldToBeAggregated->getIterations();
+        iteration = dtits.front().first;
+        order = dtits.front().second;
+      }
+      fieldToBeAggregated->getUndergroundDataArrayExt(iteration,order,entries);
+      std::vector< std::pair<int,mcIdType> > dtsToPush;
+      for(auto entry : entries)
+        dtsToPush.push_back({entry.first.first,entry.second.second-entry.second.first});
+      dtsToAggregate.push_back(dtsToPush);
+      MCAuto<MEDFileAnyTypeFieldMultiTS> eltToAggregate = MEDFileAnyTypeFieldMultiTS::BuildNewInstanceFromContent(fieldToBeAggregated);
+      eltsToAggregate.push_back(eltToAggregate);
+    }
+    MCAuto<MEDFileAnyTypeFieldMultiTS> gg = MEDFileAnyTypeFieldMultiTS::Aggregate(FromVecAutoToVecOfConst(eltsToAggregate),dtsToAggregate);
+    gg->setMeshName(base_fs->getMeshName());
+    otherFields.push_back(gg->getContent());
+  }
+  // now deal with meshes
+  std::map<std::string,std::vector< MEDFileMesh *> > msByName;
+  for(auto iMesh = 0 ; iMesh < ms->getNumberOfMeshes() ; ++iMesh)
+  {
+    auto curMesh = ms->getMeshAtPos(iMesh);
+    msByName[curMesh->getName()].push_back(curMesh);
+  }
+  std::set<std::string> meshesNamesToBeAggregated;
+  std::vector< MCAuto<MEDFileMesh> > otherMeshes;
+  for(auto msWithSameName : msByName)
+  {
+    if(msWithSameName.second.size()>1)
+      meshesNamesToBeAggregated.insert(msWithSameName.first);
+    else
+    {
+      otherMeshes.push_back( MCAuto<MEDFileMesh>::TakeRef(msWithSameName.second.front()) );
+    }
+  }
+  if(meshesNamesToBeAggregated != expectedMeshNamesToMerge)
+    THROW_IK_EXCEPTION("MEDFileFields::aggregateFieldsOnSameMeshes : mismatch between meshes to be aggregated and meshnames into fields to be aggregated");
+  std::vector<const DataArrayDouble *> coos;
+  for(auto meshNameToBeAggregated : meshesNamesToBeAggregated)
+  {
+    for(auto curMesh : msByName[meshNameToBeAggregated])
+    {
+      if(!curMesh->getNonEmptyLevels().empty())
+        THROW_IK_EXCEPTION("MEDFileFields::aggregateFieldsOnSameMeshes : only meshes without cells supported.");
+      MEDFileUMesh *curMeshU(dynamic_cast<MEDFileUMesh *>(curMesh));
+      if(!curMeshU)
+        THROW_IK_EXCEPTION("MEDFileFields::aggregateFieldsOnSameMeshes : only unstructured mesh supported.");
+      coos.push_back(curMeshU->getCoords());
+    }
+    MCAuto<DataArrayDouble> coo=DataArrayDouble::Aggregate(coos);
+    MCAuto<MEDFileUMesh> gg = MEDFileUMesh::New();
+    gg->setName(meshNameToBeAggregated);
+    gg->setCoords(coo);
+    otherMeshes.push_back(DynamicCast<MEDFileUMesh,MEDFileMesh>(gg));
+  }
+  // until this point nothing has changed in \a this nor in \a ms as if a const method.
+  ms->resize(0);
+  for(auto mesh : otherMeshes)
+    ms->pushMesh(mesh);
+  _fields = otherFields;
 }
 
 MCAuto<MEDFileFields> MEDFileFields::partOfThisOnStructureElements() const