From ecea4040f1015e025650a0b4d7a16b0782c7a1cf Mon Sep 17 00:00:00 2001 From: prascle Date: Wed, 30 Mar 2011 15:48:07 +0000 Subject: [PATCH] PR: create flat elements on face groups (ASTER calculations) --- idl/SMESH_MeshEditor.idl | 12 +++ src/SMDS/SMDS_UnstructuredGrid.cxx | 19 ++-- src/SMDS/SMDS_UnstructuredGrid.hxx | 1 + src/SMESH/SMESH_MeshEditor.cxx | 148 ++++++++++++++++++++++++++++- src/SMESH/SMESH_MeshEditor.hxx | 2 + src/SMESHDS/SMESHDS_Mesh.cxx | 5 + src/SMESHDS/SMESHDS_Mesh.hxx | 1 + src/SMESH_I/SMESH_MeshEditor_i.cxx | 47 +++++++++ src/SMESH_I/SMESH_MeshEditor_i.hxx | 10 ++ src/SMESH_SWIG/smeshDC.py | 10 ++ 10 files changed, 247 insertions(+), 8 deletions(-) diff --git a/idl/SMESH_MeshEditor.idl b/idl/SMESH_MeshEditor.idl index 681c4ece7..85a57a142 100644 --- a/idl/SMESH_MeshEditor.idl +++ b/idl/SMESH_MeshEditor.idl @@ -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 ); }; }; diff --git a/src/SMDS/SMDS_UnstructuredGrid.cxx b/src/SMDS/SMDS_UnstructuredGrid.cxx index 869e6079c..03b5d2337 100644 --- a/src/SMDS/SMDS_UnstructuredGrid.cxx +++ b/src/SMDS/SMDS_UnstructuredGrid.cxx @@ -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]) diff --git a/src/SMDS/SMDS_UnstructuredGrid.hxx b/src/SMDS/SMDS_UnstructuredGrid.hxx index 2afe37800..78b7dd2da 100644 --- a/src/SMDS/SMDS_UnstructuredGrid.hxx +++ b/src/SMDS/SMDS_UnstructuredGrid.hxx @@ -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); diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index e7c1cf476..b65000907 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -10862,7 +10862,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectormyMesh->GetMeshDS(); - meshDS->BuildDownWardConnectivity(false); + meshDS->BuildDownWardConnectivity(true); CHRONO(50); SMDS_UnstructuredGrid *grid = meshDS->getGrid(); @@ -11286,6 +11286,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vectorCleanDownWardConnectivity(); // 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& 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 clonedNodes; + std::map 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 (anElem); + if (!aFace) + continue; + // MESSAGE("aFace=" << aFace->GetID()); + bool isQuad = aFace->IsQuadratic(); + vector 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 (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 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 diff --git a/src/SMESH/SMESH_MeshEditor.hxx b/src/SMESH/SMESH_MeshEditor.hxx index c4995b43d..48090ae4d 100644 --- a/src/SMESH/SMESH_MeshEditor.hxx +++ b/src/SMESH/SMESH_MeshEditor.hxx @@ -570,6 +570,8 @@ public: bool DoubleNodesOnGroupBoundaries( const std::vector& theElems, bool createJointElems); + bool CreateFlatElementsOnFacesGroups( const std::vector& 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 diff --git a/src/SMESHDS/SMESHDS_Mesh.cxx b/src/SMESHDS/SMESHDS_Mesh.cxx index 7d2986ffe..7e625ecde 100644 --- a/src/SMESHDS/SMESHDS_Mesh.cxx +++ b/src/SMESHDS/SMESHDS_Mesh.cxx @@ -1959,6 +1959,11 @@ void SMESHDS_Mesh::compactMesh() } +void SMESHDS_Mesh::CleanDownWardConnectivity() +{ + myGrid->CleanDownwardConnectivity(); +} + void SMESHDS_Mesh::BuildDownWardConnectivity(bool withEdges) { myGrid->BuildDownwardConnectivity(withEdges); diff --git a/src/SMESHDS/SMESHDS_Mesh.hxx b/src/SMESHDS/SMESHDS_Mesh.hxx index 55912f8d4..005b4fd5b 100644 --- a/src/SMESHDS/SMESHDS_Mesh.hxx +++ b/src/SMESHDS/SMESHDS_Mesh.hxx @@ -445,6 +445,7 @@ public: bool IsGroupOfSubShapes (const TopoDS_Shape& aSubShape) const; virtual void compactMesh(); + void CleanDownWardConnectivity(); void BuildDownWardConnectivity(bool withEdges); ~SMESHDS_Mesh(); diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index 218fe5a5d..d99983c95 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -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 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 diff --git a/src/SMESH_I/SMESH_MeshEditor_i.hxx b/src/SMESH_I/SMESH_MeshEditor_i.hxx index 1cd67ed84..3552dde40 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.hxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.hxx @@ -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 diff --git a/src/SMESH_SWIG/smeshDC.py b/src/SMESH_SWIG/smeshDC.py index 88591ffa7..79562f553 100644 --- a/src/SMESH_SWIG/smeshDC.py +++ b/src/SMESH_SWIG/smeshDC.py @@ -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)