Salome HOME
PR: create flat elements on face groups (ASTER calculations)
authorprascle <prascle>
Wed, 30 Mar 2011 15:48:07 +0000 (15:48 +0000)
committerprascle <prascle>
Wed, 30 Mar 2011 15:48:07 +0000 (15:48 +0000)
idl/SMESH_MeshEditor.idl
src/SMDS/SMDS_UnstructuredGrid.cxx
src/SMDS/SMDS_UnstructuredGrid.hxx
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_MeshEditor.hxx
src/SMESHDS/SMESHDS_Mesh.cxx
src/SMESHDS/SMESHDS_Mesh.hxx
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.hxx
src/SMESH_SWIG/smeshDC.py

index 681c4ece785ccfc581e496885d5e7dc6cf799de3..85a57a1423af30c7f36e405f2379aa621a26a36c 100644 (file)
@@ -1010,6 +1010,8 @@ module SMESH
 
     /*!
      * \brief Double nodes on shared faces between groups of volumes and create flat elements on demand.
+     * Flat elements are mainly used by some types of mechanic calculations.
+     *
      * The list of groups must describe a partition of the mesh volumes.
      * The nodes of the internal faces at the boundaries of the groups are doubled.
      * In option, the internal faces are replaced by flat elements.
@@ -1021,6 +1023,16 @@ module SMESH
     boolean DoubleNodesOnGroupBoundaries( in ListOfGroups theDomains,
                                           in boolean createJointElems );
 
+    /*!
+     * \brief Double nodes on some external faces and create flat elements.
+     * Flat elements are mainly used by some types of mechanic calculations.
+     *
+     * Each group of the list must be constituted of faces.
+     * Triangles are transformed in prisms, and quadrangles in hexahedrons.
+     * \param theGroupsOfFaces - list of groups of faces
+     * \return TRUE if operation has been completed successfully, FALSE otherwise
+     */
+    boolean CreateFlatElementsOnFacesGroups( in ListOfGroups theGroupsOfFaces ); 
   };
 };
 
index 869e6079c8b5ea75511650a3249fd00ac74dd0d9..03b5d2337c676987b8237dffd32df6ebedf38ced 100644 (file)
@@ -322,6 +322,17 @@ void SMDS_UnstructuredGrid::setCellIdToDownId(int vtkCellId, int downId)
   _cellIdToDownId[vtkCellId] = downId;
 }
 
+void SMDS_UnstructuredGrid::CleanDownwardConnectivity()
+{
+  for (int i = 0; i < _downArray.size(); i++)
+    {
+      if (_downArray[i])
+        delete _downArray[i];
+      _downArray[i] = 0;
+    }
+  _cellIdToDownId.clear();
+}
+
 /*! Build downward connectivity: to do only when needed because heavy memory load.
  *  Downward connectivity is no more valid if vtkUnstructuredGrid is modified.
  *
@@ -333,13 +344,7 @@ void SMDS_UnstructuredGrid::BuildDownwardConnectivity(bool withEdges)
 
   // --- erase previous data if any
 
-  for (int i = 0; i < _downArray.size(); i++)
-    {
-      if (_downArray[i])
-        delete _downArray[i];
-      _downArray[i] = 0;
-    }
-  _cellIdToDownId.clear();
+  this->CleanDownwardConnectivity();
 
   // --- create SMDS_Downward structures (in _downArray vector[vtkCellType])
 
index 2afe37800ecc6863c6c6d8ad40cc20cd2b848a55..78b7dd2dabb95644dd64581f081c9f8cf23ee12f 100644 (file)
@@ -61,6 +61,7 @@ public:
 
   int CellIdToDownId(int vtkCellId);
   void setCellIdToDownId(int vtkCellId, int downId);
+  void CleanDownwardConnectivity();
   void BuildDownwardConnectivity(bool withEdges);
   int GetNeighbors(int* neighborsVtkIds, int* downIds, unsigned char* downTypes, int vtkId);
   int GetParentVolumes(int* volVtkIds, int vtkId);
index e7c1cf476a4558a030ea1713940f45d03b490fcd..b6500090727efb0f6adb2cbe7807f11e860f1ec4 100644 (file)
@@ -10862,7 +10862,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   MESSAGE("----------------------------------------------");
 
   SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
-  meshDS->BuildDownWardConnectivity(false);
+  meshDS->BuildDownWardConnectivity(true);
   CHRONO(50);
   SMDS_UnstructuredGrid *grid = meshDS->getGrid();
 
@@ -11286,6 +11286,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
         }
     }
 
+  meshDS->CleanDownWardConnectivity(); // Mesh has been modified, downward connectivity is no more usable, free memory
   grid->BuildLinks();
 
   CHRONOSTOP(50);
@@ -11293,6 +11294,151 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   return true;
 }
 
+/*!
+ * \brief Double nodes on some external faces and create flat elements.
+ * Flat elements are mainly used by some types of mechanic calculations.
+ *
+ * Each group of the list must be constituted of faces.
+ * Triangles are transformed in prisms, and quadrangles in hexahedrons.
+ * @param theElems - list of groups of faces, where a group of faces is a set of
+ * SMDS_MeshElements sorted by Id.
+ * @return TRUE if operation has been completed successfully, FALSE otherwise
+ */
+bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSortedElemSet>& theElems)
+{
+  MESSAGE("-------------------------------------------------");
+  MESSAGE("SMESH_MeshEditor::CreateFlatElementsOnFacesGroups");
+  MESSAGE("-------------------------------------------------");
+
+  SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
+
+  // --- For each group of faces
+  //     duplicate the nodes, create a flat element based on the face
+  //     replace the nodes of the faces by their clones
+
+  std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> clonedNodes;
+  std::map<const SMDS_MeshNode*, const SMDS_MeshNode*> intermediateNodes;
+  clonedNodes.clear();
+  intermediateNodes.clear();
+
+  for (int idom = 0; idom < theElems.size(); idom++)
+    {
+      const TIDSortedElemSet& domain = theElems[idom];
+      TIDSortedElemSet::const_iterator elemItr = domain.begin();
+      for (; elemItr != domain.end(); ++elemItr)
+        {
+          SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr;
+          SMDS_MeshFace* aFace = dynamic_cast<SMDS_MeshFace*> (anElem);
+          if (!aFace)
+            continue;
+          // MESSAGE("aFace=" << aFace->GetID());
+          bool isQuad = aFace->IsQuadratic();
+          vector<const SMDS_MeshNode*> ln0, ln1, ln2, ln3, ln4;
+
+          // --- clone the nodes, create intermediate nodes for non medium nodes of a quad face
+
+          SMDS_ElemIteratorPtr nodeIt = aFace->nodesIterator();
+          while (nodeIt->more())
+            {
+              const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*> (nodeIt->next());
+              bool isMedium = isQuad && (aFace->IsMediumNode(node));
+              if (isMedium)
+                ln2.push_back(node);
+              else
+                ln0.push_back(node);
+
+              const SMDS_MeshNode* clone = 0;
+              if (!clonedNodes.count(node))
+                {
+                  clone = meshDS->AddNode(node->X(), node->Y(), node->Z());
+                  clonedNodes[node] = clone;
+                }
+              else
+                clone = clonedNodes[node];
+
+              if (isMedium)
+                ln3.push_back(clone);
+              else
+                ln1.push_back(clone);
+
+              const SMDS_MeshNode* inter = 0;
+              if (isQuad && (!isMedium))
+                {
+                  if (!intermediateNodes.count(node))
+                    {
+                      inter = meshDS->AddNode(node->X(), node->Y(), node->Z());
+                      intermediateNodes[node] = inter;
+                    }
+                  else
+                    inter = intermediateNodes[node];
+                  ln4.push_back(inter);
+                }
+            }
+
+          // --- extrude the face
+
+          vector<const SMDS_MeshNode*> ln;
+          SMDS_MeshVolume* vol = 0;
+          vtkIdType aType = aFace->GetVtkType();
+          switch (aType)
+          {
+            case VTK_TRIANGLE:
+              vol = meshDS->AddVolume(ln0[2], ln0[1], ln0[0], ln1[2], ln1[1], ln1[0]);
+              // MESSAGE("vol prism " << vol->GetID());
+              ln.push_back(ln1[0]);
+              ln.push_back(ln1[1]);
+              ln.push_back(ln1[2]);
+              break;
+            case VTK_QUAD:
+              vol = meshDS->AddVolume(ln0[3], ln0[2], ln0[1], ln0[0], ln1[3], ln1[2], ln1[1], ln1[0]);
+              // MESSAGE("vol hexa " << vol->GetID());
+              ln.push_back(ln1[0]);
+              ln.push_back(ln1[1]);
+              ln.push_back(ln1[2]);
+              ln.push_back(ln1[3]);
+              break;
+            case VTK_QUADRATIC_TRIANGLE:
+              vol = meshDS->AddVolume(ln1[0], ln1[1], ln1[2], ln0[0], ln0[1], ln0[2], ln3[0], ln3[1], ln3[2],
+                                      ln2[0], ln2[1], ln2[2], ln4[0], ln4[1], ln4[2]);
+              // MESSAGE("vol quad prism " << vol->GetID());
+              ln.push_back(ln1[0]);
+              ln.push_back(ln1[1]);
+              ln.push_back(ln1[2]);
+              ln.push_back(ln3[0]);
+              ln.push_back(ln3[1]);
+              ln.push_back(ln3[2]);
+              break;
+            case VTK_QUADRATIC_QUAD:
+//              vol = meshDS->AddVolume(ln0[0], ln0[1], ln0[2], ln0[3], ln1[0], ln1[1], ln1[2], ln1[3],
+//                                      ln2[0], ln2[1], ln2[2], ln2[3], ln3[0], ln3[1], ln3[2], ln3[3],
+//                                      ln4[0], ln4[1], ln4[2], ln4[3]);
+              vol = meshDS->AddVolume(ln1[0], ln1[1], ln1[2], ln1[3], ln0[0], ln0[1], ln0[2], ln0[3],
+                                      ln3[0], ln3[1], ln3[2], ln3[3], ln2[0], ln2[1], ln2[2], ln2[3],
+                                      ln4[0], ln4[1], ln4[2], ln4[3]);
+              // MESSAGE("vol quad hexa " << vol->GetID());
+              ln.push_back(ln1[0]);
+              ln.push_back(ln1[1]);
+              ln.push_back(ln1[2]);
+              ln.push_back(ln1[3]);
+              ln.push_back(ln3[0]);
+              ln.push_back(ln3[1]);
+              ln.push_back(ln3[2]);
+              ln.push_back(ln3[3]);
+              break;
+            case VTK_POLYGON:
+              break;
+            default:
+              break;
+          }
+
+          // --- modify the face
+
+          aFace->ChangeNodes(&ln[0], ln.size());
+        }
+    }
+  return true;
+}
+
 //================================================================================
 /*!
  * \brief Generates skin mesh (containing 2D cells) from 3D mesh
index c4995b43d0d3695d862f0ccc773f8e860428884c..48090ae4d2cc30a9b757f7ba740faaff663b9ee2 100644 (file)
@@ -570,6 +570,8 @@ public:
   bool DoubleNodesOnGroupBoundaries( const std::vector<TIDSortedElemSet>& theElems,
                                      bool createJointElems);
 
+  bool CreateFlatElementsOnFacesGroups( const std::vector<TIDSortedElemSet>& theElems );
+
   /*!
    * \brief Generated skin mesh (containing 2D cells) from 3D mesh
    * The created 2D mesh elements based on nodes of free faces of boundary volumes
index 7d2986ffefbd513e7c02a9c33782d3616e84dcf2..7e625ecdef7ba8a9b3ed8e5493c4ea6740d69b6d 100644 (file)
@@ -1959,6 +1959,11 @@ void SMESHDS_Mesh::compactMesh()
 
 }
 
+void SMESHDS_Mesh::CleanDownWardConnectivity()
+{
+  myGrid->CleanDownwardConnectivity();
+}
+
 void SMESHDS_Mesh::BuildDownWardConnectivity(bool withEdges)
 {
   myGrid->BuildDownwardConnectivity(withEdges);
index 55912f8d4487b333bba4f7f26a38fb6902d9ec67..005b4fd5b7f2be298d14798e707995b463b217f7 100644 (file)
@@ -445,6 +445,7 @@ public:
   bool IsGroupOfSubShapes (const TopoDS_Shape& aSubShape) const;
 
   virtual void compactMesh();
+  void CleanDownWardConnectivity();
   void BuildDownWardConnectivity(bool withEdges);
 
   ~SMESHDS_Mesh();
index 218fe5a5dc5c0e2475cd49db299b7ff6b6262373..d99983c95634e6f5e738c13f7adb487c94da4f23 100644 (file)
@@ -5632,6 +5632,53 @@ CORBA::Boolean SMESH_MeshEditor_i::DoubleNodesOnGroupBoundaries( const SMESH::Li
   return aResult;
 }
 
+//================================================================================
+/*!
+ * \brief Double nodes on some external faces and create flat elements.
+ * Flat elements are mainly used by some types of mechanic calculations.
+ *
+ * Each group of the list must be constituted of faces.
+ * Triangles are transformed in prisms, and quadrangles in hexahedrons.
+ * @param theGroupsOfFaces - list of groups of faces
+ * @return TRUE if operation has been completed successfully, FALSE otherwise
+ */
+//================================================================================
+
+CORBA::Boolean SMESH_MeshEditor_i::CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces )
+{
+  initData();
+
+  ::SMESH_MeshEditor aMeshEditor( myMesh );
+
+  SMESHDS_Mesh* aMeshDS = GetMeshDS();
+
+  vector<TIDSortedElemSet> faceGroups;
+  faceGroups.clear();
+
+  for ( int i = 0, n = theGroupsOfFaces.length(); i < n; i++ )
+  {
+    SMESH::SMESH_GroupBase_var aGrp = theGroupsOfFaces[ i ];
+    if ( !CORBA::is_nil( aGrp ) && ( aGrp->GetType() != SMESH::NODE ) )
+    {
+      TIDSortedElemSet faceGroup;
+      faceGroup.clear();
+      faceGroups.push_back(faceGroup);
+      SMESH::long_array_var anIDs = aGrp->GetIDs();
+      arrayToSet( anIDs, aMeshDS, faceGroups[ i ], SMDSAbs_All );
+    }
+  }
+
+  bool aResult = aMeshEditor.CreateFlatElementsOnFacesGroups( faceGroups );
+  // TODO publish the groups of flat elements in study
+
+  storeResult( aMeshEditor) ;
+  myMesh->GetMeshDS()->Modified();
+
+  // Update Python script
+  TPythonDump() << "isDone = " << this << ".CreateFlatElementsOnFacesGroups( " << &theGroupsOfFaces << " )";
+  return aResult;
+}
+
 // issue 20749 ===================================================================
 /*!
  * \brief Creates missing boundary elements
index 1cd67ed849e8e492235bcb7e24d29723b1df3997..3552dde40df820f76edf3714c438bc922b6a8884 100644 (file)
@@ -704,6 +704,16 @@ public:
    */
   CORBA::Boolean DoubleNodesOnGroupBoundaries( const SMESH::ListOfGroups& theDomains,
                                                CORBA::Boolean createJointElems );
+  /*!
+   * \brief Double nodes on some external faces and create flat elements.
+   * Flat elements are mainly used by some types of mechanic calculations.
+   *
+   * Each group of the list must be constituted of faces.
+   * Triangles are transformed in prisms, and quadrangles in hexahedrons.
+   * @param theGroupsOfFaces - list of groups of faces
+   * @return TRUE if operation has been completed successfully, FALSE otherwise
+   */
+  CORBA::Boolean CreateFlatElementsOnFacesGroups( const SMESH::ListOfGroups& theGroupsOfFaces );
 
   /*!
    * \brief Generated skin mesh (containing 2D cells) from 3D mesh
index 88591ffa79330365461999ac3f6012c6e9f849f2..79562f553cb2f502e4dc55d498e286f240d75459 100644 (file)
@@ -4169,6 +4169,16 @@ class Mesh:
     def DoubleNodesOnGroupBoundaries(self, theDomains, createJointElems ):
        return self.editor.DoubleNodesOnGroupBoundaries( theDomains, createJointElems )
 
+    ## Double nodes on some external faces and create flat elements.
+    # Flat elements are mainly used by some types of mechanic calculations.
+    #
+    # Each group of the list must be constituted of faces.
+    # Triangles are transformed in prisms, and quadrangles in hexahedrons.
+    # @param theGroupsOfFaces - list of groups of faces
+    # @return TRUE if operation has been completed successfully, FALSE otherwise
+    def CreateFlatElementsOnFacesGroups(self, theGroupsOfFaces ):
+        return self.editor.CreateFlatElementsOnFacesGroups( theGroupsOfFaces )
+
     def _valueFromFunctor(self, funcType, elemId):
         fn = self.smeshpyD.GetFunctor(funcType)
         fn.SetMesh(self.mesh)