Salome HOME
Add test for .mesh file format
[tools/medcoupling.git] / src / MEDLoader / MEDFileFieldInternal.cxx
index 2cb35d9631773c2636791f2ed628a120c4100291..84eb086ac2d9d224488311e16e785db60b9b8310 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017-2020  CEA/DEN, EDF R&D
+// Copyright (C) 2017-2024  CEA, EDF
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 #include "MEDCouplingFieldTemplate.hxx"
 #include "MEDCouplingFieldDouble.hxx"
 
+#include "MEDFilterEntity.hxx"
+
 #include "CellModel.hxx"
 
+// From MEDLOader.cxx TU
 extern med_geometry_type typmai[MED_N_CELL_FIXED_GEO];
 extern INTERP_KERNEL::NormalizedCellType typmai2[MED_N_CELL_FIXED_GEO];
 extern med_geometry_type typmai3[INTERP_KERNEL::NORM_MAXTYPE];
@@ -371,7 +374,8 @@ void MEDFileFieldPerMeshPerTypePerDisc::assignFieldNoProfile(mcIdType& start, mc
 
 /*!
  * Leaf method of field with profile assignment. This method is the most general one. No optimization is done here.
- * \param [in] pflName input containing name of profile if any. 0 if no profile (except for GAUSS_PT where a no profile can hide a profile when split by loc_id).
+ * \param [in] isPflAlone whether there are several profiles or not
+ * \param [in] start starting ID
  * \param [in] multiTypePfl is the end user profile specified in high level API
  * \param [in] idsInPfl is the selection into the \a multiTypePfl whole profile that corresponds to the current geometric type.
  * \param [in] locIds is the profile needed to be created for MED file format. It can be null if all cells of current geometric type are fetched in \a multiTypePfl.
@@ -589,47 +593,15 @@ void MEDFileFieldPerMeshPerTypePerDisc::goReadZeValuesInFile(med_idt fid, const
       INTERP_KERNEL::AutoPtr<char> pflname(MEDLoaderBase::buildEmptyString(MED_NAME_SIZE)),locname(MEDLoaderBase::buildEmptyString(MED_NAME_SIZE));
       med_int profilesize,nbi;
       med_int overallNval(MEDfieldnValueWithProfile(fid,fieldName.c_str(),iteration,order,menti,mgeoti,FromIdType<int>(_profile_it+1),MED_COMPACT_PFLMODE,pflname,&profilesize,locname,&nbi));
-      const SlicePartDefinition *spd(dynamic_cast<const SlicePartDefinition *>(pd));
-      if(spd)
-        {
-          mcIdType start,stop,step;
-          spd->getSlice(start,stop,step);
-          mcIdType nbOfEltsToLoad(DataArray::GetNumberOfItemGivenBES(start,stop,step,"MEDFileFieldPerMeshPerTypePerDisc::goReadZeValuesInFile"));
-          med_filter filter=MED_FILTER_INIT;
-          MEDFILESAFECALLERRD0(MEDfilterBlockOfEntityCr,(fid,/*nentity*/overallNval,/*nvaluesperentity*/nbi,/*nconstituentpervalue*/nbOfCompo,
-                                                         MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,MED_NO_PROFILE,
-                                                         /*start*/ToMedInt(start+1),/*stride*/ToMedInt(step),/*count*/1,/*blocksize*/ToMedInt(nbOfEltsToLoad),
-                                                         /*lastblocksize=useless because count=1*/0,&filter));
-          MEDFILESAFECALLERRD0(MEDfieldValueAdvancedRd,(fid,fieldName.c_str(),iteration,order,menti,mgeoti,&filter,startFeedingPtr));
-          MEDfilterClose(&filter);
-          return ;
-        }
-      const DataArrayPartDefinition *dpd(dynamic_cast<const DataArrayPartDefinition *>(pd));
-      if(dpd)
-        {
-          dpd->checkConsistencyLight();
-          MCAuto<DataArrayIdType> myIds(dpd->toDAI());
-          mcIdType a(myIds->getMinValueInArray()),b(myIds->getMaxValueInArray());
-          myIds=myIds->deepCopy();// WARNING deep copy here because _pd is modified by applyLin !!!
-          myIds->applyLin(1,-a);
-          mcIdType nbOfEltsToLoad(b-a+1);
-          med_filter filter=MED_FILTER_INIT;
-          {//TODO : manage int32 !
-            MCAuto<DataArrayDouble> tmp(DataArrayDouble::New());
-            tmp->alloc(nbOfEltsToLoad,nbOfCompo);
-            MEDFILESAFECALLERRD0(MEDfilterBlockOfEntityCr,(fid,/*nentity*/overallNval,/*nvaluesperentity*/nbi,/*nconstituentpervalue*/nbOfCompo,
-                                                           MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,MED_NO_PROFILE,
-                                                           /*start*/ToMedInt(a+1),/*stride*/1,/*count*/1,/*blocksize*/ToMedInt(nbOfEltsToLoad),
-                                                           /*lastblocksize=useless because count=1*/0,&filter));
-            MEDFILESAFECALLERRD0(MEDfieldValueAdvancedRd,(fid,fieldName.c_str(),iteration,order,menti,mgeoti,&filter,reinterpret_cast<unsigned char *>(tmp->getPointer())));
-            MCAuto<DataArrayDouble> feeder(DataArrayDouble::New());
-            feeder->useExternalArrayWithRWAccess(reinterpret_cast<double *>(startFeedingPtr),_nval,nbOfCompo);
-            feeder->setContigPartOfSelectedValues(0,tmp,myIds);
-          }
-          MEDfilterClose(&filter);
-        }
-      else
-        throw INTERP_KERNEL::Exception("Not implemented yet for not slices!");
+
+      {//TODO : manage int32 !
+        pd->checkConsistencyLight();
+        MEDFilterEntity filter;
+        filter.fill(fid,/*nentity*/overallNval,/*nvaluesperentity*/nbi,/*nconstituentpervalue*/nbOfCompo,
+                  MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,MED_NO_PROFILE,
+                  pd);
+        MEDFILESAFECALLERRD0(MEDfieldValueAdvancedRd,(fid,fieldName.c_str(),iteration,order,menti,mgeoti,filter.getPtr(),startFeedingPtr));
+      }
     }
 }
 
@@ -743,9 +715,10 @@ void MEDFileFieldPerMeshPerTypePerDisc::loadBigArray(med_idt fid, const MEDFileF
       goReadZeValuesInFile(fid,fieldName,nbOfCompo,iteration,order,menti,mgeoti,reinterpret_cast<unsigned char*>(startFeeding));
       return ;
     }
-  throw INTERP_KERNEL::Exception("Error on array reading ! Unrecognized type of field ! Should be in FLOAT64 FLOAT32 or INT32 !");
+  throw INTERP_KERNEL::Exception("Error on array reading ! Unrecognized type of field ! Should be in FLOAT64 FLOAT32 INT32 or INT64 !");
 }
 
+
 /*!
  * Set a \c this->_start **and** \c this->_end keeping the same delta between the two.
  */
@@ -799,6 +772,11 @@ INTERP_KERNEL::NormalizedCellType MEDFileFieldPerMeshPerTypePerDisc::getGeoType(
   return _father->getGeoType();
 }
 
+INTERP_KERNEL::NormalizedCellType MEDFileFieldPerMeshPerTypePerDisc::getGeoTypeStatic() const
+{
+  return _father->getGeoTypeStatic();
+}
+
 void MEDFileFieldPerMeshPerTypePerDisc::fillTypesOfFieldAvailable(std::set<TypeOfField>& types) const
 {
   types.insert(_type);
@@ -914,8 +892,6 @@ void MEDFileFieldPerMeshPerTypePerDisc::fillValues(int discId, mcIdType& startEn
 
 void MEDFileFieldPerMeshPerTypePerDisc::writeLL(med_idt fid, const MEDFileFieldNameScope& nasc) const
 {
-  TypeOfField type=getType();
-  INTERP_KERNEL::NormalizedCellType geoType(getGeoType());
   med_geometry_type mgeoti;
   med_entity_type menti;
   _father->entriesForMEDfile(getType(),mgeoti,menti);
@@ -1778,6 +1754,11 @@ INTERP_KERNEL::NormalizedCellType MEDFileFieldPerMeshPerType::getGeoType() const
   return _geo_type;
 }
 
+INTERP_KERNEL::NormalizedCellType MEDFileFieldPerMeshPerType::getGeoTypeStatic() const
+{
+  return _geo_type;
+}
+
 void MEDFileFieldPerMeshPerType::entriesForMEDfile(TypeOfField mct, med_geometry_type& gt, med_entity_type& ent) const
 {
   ent=MEDFileFieldPerMeshPerTypeCommon::ConvertIntoMEDFileType(mct,_geo_type,gt);
@@ -1930,6 +1911,11 @@ INTERP_KERNEL::NormalizedCellType MEDFileFieldPerMeshPerTypeDyn::getGeoType() co
   throw INTERP_KERNEL::Exception("not implemented yet !");
 }
 
+INTERP_KERNEL::NormalizedCellType MEDFileFieldPerMeshPerTypeDyn::getGeoTypeStatic() const
+{
+  return _se->getGeoType();
+}
+
 void MEDFileFieldPerMeshPerTypeDyn::simpleRepr(int bkOffset, std::ostream& oss, int id) const
 {
   const char startLine[]="  ## ";
@@ -1975,6 +1961,11 @@ MEDFileFieldPerMesh *MEDFileFieldPerMesh::NewOnRead(med_idt fid, MEDFileAnyTypeF
   return new MEDFileFieldPerMesh(fid,fath,meshCsit,meshIteration,meshOrder,nasc,mm,entities);
 }
 
+MEDFileFieldPerMesh *MEDFileFieldPerMesh::NewOnRead(med_idt fid, MEDFileAnyTypeField1TSWithoutSDA *fath, int meshCsit, int meshIteration, int meshOrder, const MEDFileFieldNameScope& nasc, const PartDefinition *pd, const MEDFileEntities *entities)
+{
+  return new MEDFileFieldPerMesh(fid,fath,meshCsit,meshIteration,meshOrder,nasc,pd,entities);
+}
+
 MEDFileFieldPerMesh *MEDFileFieldPerMesh::New(MEDFileAnyTypeField1TSWithoutSDA *fath, const MEDCouplingMesh *mesh)
 {
   return new MEDFileFieldPerMesh(fath,mesh);
@@ -3035,7 +3026,7 @@ DataArray *MEDFileFieldPerMesh::finishField4(const std::vector<std::pair<mcIdTyp
 
 /// @cond INTERNAL
 
-class MFFPMIter
+class MFFPMIter  // MEDFileFieldPerMeshIterator
 {
 public:
   static MFFPMIter *NewCell(const MEDFileEntities *entities);
@@ -3137,6 +3128,9 @@ MEDFileFieldPerMesh::MEDFileFieldPerMesh(med_idt fid, MEDFileAnyTypeField1TSWith
   INTERP_KERNEL::AutoPtr<char> locName(MEDLoaderBase::buildEmptyString(MED_NAME_SIZE));
   const MEDFileUMesh *mmu(dynamic_cast<const MEDFileUMesh *>(mm));
   INTERP_KERNEL::AutoCppPtr<MFFPMIter> iter0(MFFPMIter::NewCell(entities));
+
+  // for each geometric type inside my mesh, check if there is a field profile ie if the field is defined on this type of cells (whether the discretization is on cells or on gauss_ne)
+  // and if this is the case, retrieve the part to be read and build a new MedFileField from it
   for(iter0->begin();!iter0->finished();iter0->next())
     {
       med_int nbProfile (MEDfield23nProfile(fid,nasc.getName().c_str(),getIteration(),getOrder(),MED_CELL        ,typmai[iter0->current()],meshCsit+1,meshName,pflName,locName));
@@ -3155,8 +3149,13 @@ MEDFileFieldPerMesh::MEDFileFieldPerMesh(med_idt fid, MEDFileAnyTypeField1TSWith
             setMeshName(name1);
         }
     }
+
+
+  // entities are pairs of a field discretization and geometric type
+  // if no entities have been passed, then it means we can consider nodes by default
   if(MFFPMIter::IsPresenceOfNode(entities))
     {
+      // if there is a profile on nodes for the current field, retrieve the part to be read and build a new MedFileField from it
       med_int nbProfile(MEDfield23nProfile(fid,nasc.getName().c_str(),getIteration(),getOrder(),MED_NODE,MED_NONE,meshCsit+1,meshName,pflName,locName));
       if(nbProfile>0)
         {
@@ -3200,6 +3199,41 @@ MEDFileFieldPerMesh::MEDFileFieldPerMesh(med_idt fid, MEDFileAnyTypeField1TSWith
     }
 }
 
+MEDFileFieldPerMesh::MEDFileFieldPerMesh(med_idt fid, MEDFileAnyTypeField1TSWithoutSDA *fath, int meshCsit, int meshIteration, int meshOrder, const MEDFileFieldNameScope& nasc, const PartDefinition *pd, const MEDFileEntities *entities):_mesh_iteration(meshIteration),_mesh_order(meshOrder),
+    _father(fath)
+{
+  INTERP_KERNEL::AutoPtr<char> meshName(MEDLoaderBase::buildEmptyString(MED_NAME_SIZE));
+  INTERP_KERNEL::AutoPtr<char> pflName(MEDLoaderBase::buildEmptyString(MED_NAME_SIZE));
+  INTERP_KERNEL::AutoPtr<char> locName(MEDLoaderBase::buildEmptyString(MED_NAME_SIZE));
+  INTERP_KERNEL::AutoCppPtr<MFFPMIter> iter0(MFFPMIter::NewCell(entities));
+  for(iter0->begin();!iter0->finished();iter0->next())
+    {
+      med_int nbProfile (MEDfield23nProfile(fid,nasc.getName().c_str(),getIteration(),getOrder(),MED_CELL        ,typmai[iter0->current()],meshCsit+1,meshName,pflName,locName));
+      std::string name0(MEDLoaderBase::buildStringFromFortran(meshName,MED_NAME_SIZE+1));
+      med_int nbProfile2(MEDfield23nProfile(fid,nasc.getName().c_str(),getIteration(),getOrder(),MED_NODE_ELEMENT,typmai[iter0->current()],meshCsit+1,meshName,pflName,locName));
+      std::string name1(MEDLoaderBase::buildStringFromFortran(meshName,MED_NAME_SIZE+1));
+      if(nbProfile>0 || nbProfile2>0)
+        {
+          _field_pm_pt.push_back(MEDFileFieldPerMeshPerType::NewOnRead(fid,this,ON_CELLS,typmai2[iter0->current()],nasc,pd));
+          if(nbProfile>0)
+            setMeshName(name0);
+          else
+            setMeshName(name1);
+        }
+    }
+
+  if(MFFPMIter::IsPresenceOfNode(entities))
+    {
+      med_int nbProfile(MEDfield23nProfile(fid,nasc.getName().c_str(),getIteration(),getOrder(),MED_NODE,MED_NONE,meshCsit+1,meshName,pflName,locName));
+      if(nbProfile>0)
+        {
+          _field_pm_pt.push_back(MEDFileFieldPerMeshPerType::NewOnRead(fid,this,ON_NODES,INTERP_KERNEL::NORM_ERROR,nasc,pd));
+          setMeshName(MEDLoaderBase::buildStringFromFortran(meshName,MED_NAME_SIZE));
+        }
+    }
+}
+
+
 MEDFileFieldPerMesh::MEDFileFieldPerMesh(MEDFileAnyTypeField1TSWithoutSDA *fath, const MEDCouplingMesh *mesh):_father(fath)
 {
   copyTinyInfoFrom(mesh);