PR: create flat elements on face groups (ASTER calculations)

This commit is contained in:
prascle 2011-03-30 15:48:07 +00:00
parent 5f35b29326
commit ecea4040f1
10 changed files with 247 additions and 8 deletions

View 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 );
};
};

View 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])

View 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);

View 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

View 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

View File

@ -1959,6 +1959,11 @@ void SMESHDS_Mesh::compactMesh()
}
void SMESHDS_Mesh::CleanDownWardConnectivity()
{
myGrid->CleanDownwardConnectivity();
}
void SMESHDS_Mesh::BuildDownWardConnectivity(bool withEdges)
{
myGrid->BuildDownwardConnectivity(withEdges);

View File

@ -445,6 +445,7 @@ public:
bool IsGroupOfSubShapes (const TopoDS_Shape& aSubShape) const;
virtual void compactMesh();
void CleanDownWardConnectivity();
void BuildDownWardConnectivity(bool withEdges);
~SMESHDS_Mesh();

View 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

View 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

View 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)