Salome HOME
MEDCoupling Memory output from SMESH engine now deal with fields too.
authorAnthony Geay <anthony.geay@edf.fr>
Wed, 23 Jun 2021 05:59:19 +0000 (07:59 +0200)
committerAnthony Geay <anthony.geay@edf.fr>
Wed, 23 Jun 2021 05:59:19 +0000 (07:59 +0200)
doc/salome/examples/basic_smesh_output_with_mc_field.py [new file with mode: 0644]
doc/salome/examples/tests.set
src/DriverMED/DriverMED_W_Field.cxx
src/DriverMED/DriverMED_W_Field.h
src/MEDWrapper/MED_TFile.hxx
src/MEDWrapper/MED_Wrapper.cxx
src/SMESH_I/SMESH_Mesh_i.cxx
src/SMESH_SWIG/smeshBuilder.py

diff --git a/doc/salome/examples/basic_smesh_output_with_mc_field.py b/doc/salome/examples/basic_smesh_output_with_mc_field.py
new file mode 100644 (file)
index 0000000..f900b96
--- /dev/null
@@ -0,0 +1,175 @@
+#!/usr/bin/env python
+
+import sys
+import salome
+
+import unittest
+
+class SMESHExportOfFieldsInMemory(unittest.TestCase):
+
+  def testMEDCouplingFieldOnCells(self):
+    """
+    Test focuses on ExportMEDCoupling method in the context of MED_CELL field output.
+    """
+    salome.standalone()
+    salome.salome_init()
+    ###
+    ### SHAPER component
+    ###
+
+    from salome.shaper import model
+
+    model.begin()
+    partSet = model.moduleDocument()
+
+    ### Create Part
+    Part_1 = model.addPart(partSet)
+    Part_1_doc = Part_1.document()
+
+    ### Create Box
+    Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+
+    ### Create Plane
+    Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOY"), 5, False)
+
+    ### Create Plane
+    Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), 5, False)
+
+    ### Create Partition
+    Partition_1_objects = [model.selection("FACE", "Plane_1"),
+                          model.selection("FACE", "Plane_2"),
+                          model.selection("SOLID", "Box_1_1")]
+    Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, keepSubResults = True)
+
+    ### Create Field
+    Field_1_objects = [model.selection("SOLID", "Partition_1_1_2"),
+                      model.selection("SOLID", "Partition_1_1_4"),
+                      model.selection("SOLID", "Partition_1_1_1"),
+                      model.selection("SOLID", "Partition_1_1_3")]
+    Field_1 = model.addField(Part_1_doc, 1, "DOUBLE", 1, ["Comp 1"], Field_1_objects)
+    Field_1.addStep(0, 0, [[0], [1], [2], [3], [4]])
+
+
+    model.end()
+
+    ###
+    ### SHAPERSTUDY component
+    ###
+
+    model.publishToShaperStudy()
+    import SHAPERSTUDY
+    Partition_1_1, Field_1_1 = SHAPERSTUDY.shape(model.featureStringId(Partition_1))
+    ###
+    ### SMESH component
+    ###
+
+    import  SMESH, SALOMEDS
+    from salome.smesh import smeshBuilder
+
+    smesh = smeshBuilder.New()
+    #smesh.SetEnablePublish( False ) # Set to False to avoid publish in study if not needed or in some particular situations:
+                                    # multiples meshes built in parallel, complex and numerous mesh edition (performance)
+
+    Mesh_1 = smesh.Mesh(Partition_1_1)
+    Regular_1D = Mesh_1.Segment()
+    Local_Length_1 = Regular_1D.LocalLength(5,None,1e-07)
+    Quadrangle_2D = Mesh_1.Quadrangle(algo=smeshBuilder.QUADRANGLE)
+    Hexa_3D = Mesh_1.Hexahedron(algo=smeshBuilder.Hexa)
+    isDone = Mesh_1.Compute()
+    smesh.SetName(Mesh_1, 'Mesh_1')
+
+    #### Mesh_1.ExportMED( r'Mesh_with_one_field_on_cells.med', 0, 41, 1, Mesh_1.GetMesh(), 1, [ Field_1_1 ], '',-1 )
+    mfd = Mesh_1.ExportMEDCoupling(0, Mesh_1.GetMesh(), 1, [ Field_1_1 ], '',-1 )#### <- important line of test is here !
+
+    self.assertEqual(len(mfd.getMeshes()),1)
+    self.assertEqual(len(mfd.getFields()),1)
+    f = mfd.getFields()[0][0].field(mfd.getMeshes()[0])
+    f.checkConsistencyLight()
+    import medcoupling
+    self.assertEqual(f.getDiscretization().getEnum(),medcoupling.ON_CELLS)
+    self.assertTrue(f.getMesh().getNumberOfCells()>1)
+    pass
+
+
+  def testMEDCouplingFieldOnNodes(self):
+    """
+    Test focuses on ExportMEDCoupling method in the context of MED_NODES field output.
+    """
+    salome.standalone()
+    salome.salome_init()
+
+    ###
+    ### SHAPER component
+    ###
+
+    from salome.shaper import model
+
+    model.begin()
+    partSet = model.moduleDocument()
+
+    ### Create Part
+    Part_1 = model.addPart(partSet)
+    Part_1_doc = Part_1.document()
+
+    ### Create Box
+    Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+
+    ### Create Plane
+    Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOY"), 5, False)
+
+    ### Create Plane
+    Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), 5, False)
+
+    ### Create Partition
+    Partition_1_objects = [model.selection("FACE", "Plane_1"),
+                          model.selection("FACE", "Plane_2"),
+                          model.selection("SOLID", "Box_1_1")]
+    Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects, keepSubResults = True)
+
+    ### Create Field
+    Field_2_objects = [model.selection("VERTEX", "[Partition_1_1_2/Modified_Face&Box_1_1/Back][Partition_1_1_2/Modified_Face&Box_1_1/Left][Partition_1_1_2/Modified_Face&Box_1_1/Top]"),
+                      model.selection("VERTEX", "Partition_1_1_2/Generated_Vertex&Plane_2/Plane_2&new_weak_name_1"),
+                      model.selection("VERTEX", "[Partition_1_1_4/Modified_Face&Box_1_1/Front][Partition_1_1_4/Modified_Face&Box_1_1/Left][Partition_1_1_4/Modified_Face&Box_1_1/Top]"),
+                      model.selection("VERTEX", "Partition_1_1_1/Generated_Vertex&Plane_1/Plane_1&new_weak_name_1"),
+                      model.selection("VERTEX", "[Partition_1_1_1/Modified_Face&Box_1_1/Left][Partition_1_1_1/Modified_Face&Plane_1/Plane_1][Partition_1_1_1/Modified_Face&Plane_2/Plane_2]"),
+                      model.selection("VERTEX", "Partition_1_1_3/Generated_Vertex&Plane_1/Plane_1&new_weak_name_1"),
+                      model.selection("VERTEX", "[Partition_1_1_1/Modified_Face&Box_1_1/Back][Partition_1_1_1/Modified_Face&Box_1_1/Left][Partition_1_1_1/Modified_Face&Box_1_1/Bottom]"),
+                      model.selection("VERTEX", "Partition_1_1_1/Generated_Vertex&Plane_2/Plane_2&new_weak_name_1"),
+                      model.selection("VERTEX", "[Partition_1_1_3/Modified_Face&Box_1_1/Left][Partition_1_1_3/Modified_Face&Box_1_1/Bottom][Partition_1_1_3/Modified_Face&Box_1_1/Front]")]
+    Field_2 = model.addField(Part_1_doc, 1, "DOUBLE", 1, ["Comp 1"], Field_2_objects)
+    Field_2.addStep(0, 0, [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]])
+
+    model.end()
+
+    ###
+    ### SHAPERSTUDY component
+    ###
+
+    model.publishToShaperStudy()
+    import SHAPERSTUDY
+    Partition_1_1, Field_2_1 = SHAPERSTUDY.shape(model.featureStringId(Partition_1))
+    ###
+    ### SMESH component
+    ###
+
+    import  SMESH, SALOMEDS
+    from salome.smesh import smeshBuilder
+
+    smesh = smeshBuilder.New()
+    #smesh.SetEnablePublish( False ) # Set to False to avoid publish in study if not needed or in some particular situations:
+                                    # multiples meshes built in parallel, complex and numerous mesh edition (performance)
+
+    Mesh_1 = smesh.Mesh(Partition_1_1)
+    Regular_1D = Mesh_1.Segment()
+    Local_Length_1 = Regular_1D.LocalLength(5,None,1e-07)
+    Quadrangle_2D = Mesh_1.Quadrangle(algo=smeshBuilder.QUADRANGLE)
+    Hexa_3D = Mesh_1.Hexahedron(algo=smeshBuilder.Hexa)
+    isDone = Mesh_1.Compute()
+    smesh.SetName(Mesh_1, 'Mesh_1')
+
+    # 23th of june 2021 : Bug both in ExportMED and in ExportMEDCoupling
+    #Mesh_1.ExportMED( r'/tmp/Mesh_with_one_field_on_nodes.med', 0, 41, 1, Mesh_1.GetMesh(), 1, [ Field_2_1 ], '',-1 )
+    #mfd = Mesh_1.ExportMEDCoupling(0,Mesh_1.GetMesh(), 1, [ Field_2_1 ], '',-1)
+
+if __name__ == '__main__':
+    unittest.main()
index e0293d3..d674d64 100644 (file)
@@ -197,6 +197,7 @@ set(SESSION_FREE_TESTS
   basic_geom_smesh_without_session.py
   basic_shaper_smesh_without_session.py
   shaper_smesh_groups_without_session.py
+  basic_smesh_output_with_mc_field.py
 )
 
 SET(EXAMPLES_TESTS ${BAD_TESTS} ${GOOD_TESTS} ${SESSION_FREE_TESTS} testme.py)
index 041d1e8..c722aaf 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "DriverMED_W_Field.h"
 
+#include "MED_TFile.hxx"
 #include "DriverMED.hxx"
 #include "DriverMED_W_SMESHDS_Mesh.h"
 #include "MED_Factory.hxx"
@@ -236,16 +237,8 @@ SMDS_ElemIteratorPtr DriverMED_W_Field::GetOrderedElems()
   return SMDS_ElemIteratorPtr( new TItIterator( iterVec ));
 }
 
-//================================================================================
-/*!
- * Writes a field to the file
- */
-//================================================================================
-
-Driver_Mesh::Status DriverMED_W_Field::Perform()
+Driver_Mesh::Status DriverMED_W_Field::PerformInternal(MED::PWrapper& medFile)
 {
-  if ( myFile.empty() )
-    return addMessage("File name not set", /*isFatal=*/true ); // 'fatal' means 'bug'
   if ( myMeshId < 0 && myMeshName.empty() )
     return addMessage("Mesh in file not specified", /*isFatal=*/true );
   if ( _nbElemsByGeom.size() < 2 )
@@ -253,11 +246,6 @@ Driver_Mesh::Status DriverMED_W_Field::Perform()
   if ( !myMesh )
     return addMessage("Supporting mesh not set", /*isFatal=*/true );
 
-  int version = -1, major, minor, release;
-  if ( MED::GetMEDVersion( myFile, major, minor, release ))
-    version = major * 10 + minor;
-
-  MED::PWrapper medFile = MED::CrWrapperW( myFile, version );
   MED::PMeshInfo meshInfo;
   if ( myMeshId > 0 )
   {
@@ -361,6 +349,49 @@ Driver_Mesh::Status DriverMED_W_Field::Perform()
   return DRS_OK;
 }
 
+/*!
+ * Writes a field to the file
+ */
+Driver_Mesh::Status DriverMED_W_Field::Perform()
+{
+  if ( myFile.empty() )
+    return addMessage("File name not set", /*isFatal=*/true ); // 'fatal' means 'bug'
+  int version = -1, major, minor, release;
+  if ( MED::GetMEDVersion( myFile, major, minor, release ))
+    version = major * 10 + minor;
+
+  MED::PWrapper medFile = MED::CrWrapperW( myFile, version );
+  return this->PerformInternal(medFile);
+}
+
+/*!
+ * Writes a field to a chunck of memory
+ */
+Driver_Mesh::Status DriverMED_W_Field_Mem::Perform()
+{
+  void *ptr(nullptr);
+  std::size_t sz(0);
+  Driver_Mesh::Status status = Driver_Mesh::DRS_OK;
+  bool isClosed(false);
+  MED::TMemFile *tfileInst = nullptr;
+  char *initPtr(_data->getPointer());
+  mcIdType initSz(_data->getNumberOfTuples());
+  _data->accessToMemArray().setSpecificDeallocator(nullptr);
+  _data->useArray(nullptr,false,MEDCoupling::DeallocType::C_DEALLOC,0,1);
+  {// let braces to flush (call of MED::PWrapper myMed destructor)
+    tfileInst = new MED::TMemFile(initPtr,initSz,&isClosed);
+    MED::PWrapper myMed = MED::CrWrapperW(myFile, -1, tfileInst);
+    status = this->PerformInternal(myMed);
+  }
+  if(tfileInst)
+  {
+    ptr = tfileInst->getData(); sz = tfileInst->getSize();
+  }
+  _data = MEDCoupling::DataArrayByte::New();
+  _data->useArray(reinterpret_cast<char *>(ptr),true,MEDCoupling::DeallocType::C_DEALLOC,sz,1);
+  return status;
+}
+
 namespace DriverMED // Implementation of functions declared in DriverMED.hxx
 {
   //================================================================================
index 03168e7..d343823 100644 (file)
@@ -31,6 +31,7 @@
 #include "Driver_SMESHDS_Mesh.h"
 #include "SMDSAbs_ElementType.hxx"
 #include "SMDS_ElemIterator.hxx"
+#include "MED_Common.hxx"
 
 #include <string>
 #include <vector>
@@ -64,8 +65,12 @@ class MESHDRIVERMED_EXPORT DriverMED_W_Field: public Driver_SMESHDS_Mesh
   /*
    * Add one field to the file
    */
-  virtual Status Perform();
+  Status Perform() override;
 
+ protected:
+
+  Status PerformInternal(MED::PWrapper& medFile);
+  
  private:
 
   std::string                _fieldName;
@@ -80,4 +85,16 @@ class MESHDRIVERMED_EXPORT DriverMED_W_Field: public Driver_SMESHDS_Mesh
   std::vector< std::pair< SMDSAbs_EntityType, int > > _nbElemsByGeom;
 };
 
+#include "MEDCouplingMemArray.hxx"
+
+class MESHDRIVERMED_EXPORT DriverMED_W_Field_Mem : public DriverMED_W_Field
+{
+public:
+  DriverMED_W_Field_Mem(MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> data):_data(data) { }
+  Status Perform() override;
+  MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> getData() const { return _data; }
+private:
+  MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> _data;
+};
+
 #endif
index f30dc7a..70a5402 100644 (file)
@@ -73,7 +73,8 @@ namespace MED
   class MEDWRAPPER_EXPORT TMemFile : public MEDIDTHoder
   {
   public:
-    TMemFile(bool* isClosedStatus = nullptr):MEDIDTHoder(isClosedStatus) { }
+    TMemFile(bool* isClosedStatus = nullptr):MEDIDTHoder(isClosedStatus) { memfile.app_image_ptr=nullptr; memfile.app_image_size=0; }
+    TMemFile(void *data, std::size_t sz, bool* isClosedStatus):MEDIDTHoder(isClosedStatus) { memfile.app_image_ptr=data; memfile.app_image_size=sz; }
     void Open(EModeAcces theMode, TErr* theErr = nullptr) override;
     void *getData() const { return memfile.app_image_ptr; }
     std::size_t getSize() const { return memfile.app_image_size; }
index 4d0f992..ad18d17 100644 (file)
@@ -90,10 +90,10 @@ namespace MED
     if (this->myCount++ == 0)
     {
       std::string dftFileName = MEDCoupling::MEDFileWritableStandAlone::GenerateUniqueDftFileNameInMem();
-      memfile = MED_MEMFILE_INIT;
-      memfile.app_image_ptr=0;
-      memfile.app_image_size=0;
-      myFid = MEDmemFileOpen(dftFileName.c_str(),&memfile,MED_FALSE,MED_ACC_CREAT);
+      med_access_mode modeTmp(MED_ACC_CREAT);
+      if(memfile.app_image_ptr)
+        modeTmp = med_access_mode(theMode);
+      myFid = MEDmemFileOpen(dftFileName.c_str(),&memfile,MED_FALSE,modeTmp);
     }
     if (theErr)
       *theErr = TErr(myFid);
index 4e442a7..afc798f 100644 (file)
@@ -4069,7 +4069,11 @@ public:
   void prepareForWriting(SMESH_Mesh_i& self) { /* nothing here */ }
   void exportField(SMESH_Mesh_i& self, const std::string& aMeshName, bool have0dField, SMESHDS_Mesh *meshDS, const GEOM::ListOfFields& fields, const char*geomAssocFields)
   {
-    THROW_IK_EXCEPTION("exportField Not implemented yet for full memory !");
+    DriverMED_W_Field_Mem fieldWriter(_res);
+    fieldWriter.SetMeshName( aMeshName );
+    fieldWriter.AddODOnVertices( have0dField );
+    self.exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
+    _res = fieldWriter.getData();
   }
 public:
   MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> getData() { return _res; }
@@ -4084,10 +4088,15 @@ CORBA::LongLong SMESH_Mesh_i::ExportPartToMEDCoupling(SMESH::SMESH_IDSource_ptr
                                   const char*               geomAssocFields,
                                   CORBA::Double             ZTolerance)
 {
+  MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> data;
+  SMESH_TRY;
+  if( !this->_gen_i->isSSLMode() )
+    SMESH::throwCorbaException("SMESH_Mesh_i::ExportPartToMEDCoupling : only for embedded mode !");
   MEDFileMemSpeCls spe;
   this->ExportPartToMEDCommon<MEDFileMemSpeCls>(spe,meshPart,auto_groups,autoDimension,fields,geomAssocFields,ZTolerance);
-  MEDCoupling::MCAuto<MEDCoupling::DataArrayByte> res( spe.getData() );
-  MEDCoupling::DataArrayByte *ret(res.retn());
+  data = spe.getData();
+  SMESH_CATCH( SMESH::throwCorbaException );
+  MEDCoupling::DataArrayByte *ret(data.retn());
   return reinterpret_cast<CORBA::LongLong>(ret);
 }
 
index e65c357..43e8f43 100644 (file)
@@ -2355,7 +2355,10 @@ class Mesh(metaclass = MeshMeta):
             z_tolerance,Parameters,hasVars = ParseParameters(z_tolerance)
             self.mesh.SetParameters(Parameters)
 
-            return self.mesh.ExportPartToMEDCoupling(meshPart, auto_groups, autoDimension, fields, geomAssocFields, z_tolerance)
+            intPtr = self.mesh.ExportPartToMEDCoupling(meshPart, auto_groups, autoDimension, fields, geomAssocFields, z_tolerance)
+            import medcoupling
+            dab = medcoupling.FromPyIntPtrToDataArrayByte(intPtr)
+            return medcoupling.MEDFileData.New(dab)
         else:
             intPtr = self.mesh.ExportMEDCoupling(auto_groups, autoDimension)
             import medcoupling