PR: doubleNodesOnGroupBoundaries in progress

This commit is contained in:
prascle 2011-03-09 08:42:21 +00:00
parent 044bc6d891
commit 293e2534c0
6 changed files with 148 additions and 66 deletions

View File

@ -843,7 +843,7 @@ SMESH_GroupObj::SMESH_GroupObj( SMESH::SMESH_GroupBase_ptr theGroup,
SMESH_GroupObj::~SMESH_GroupObj() SMESH_GroupObj::~SMESH_GroupObj()
{ {
if ( MYDEBUG ) MESSAGE("~SMESH_GroupObj"); if ( MYDEBUG ) MESSAGE("~SMESH_GroupObj");
myGroupServer->UnRegister(); myGroupServer->Destroy();
} }
//================================================================================= //=================================================================================
@ -973,7 +973,7 @@ SMESH_subMeshObj::SMESH_subMeshObj( SMESH::SMESH_subMesh_ptr theSubMesh,
SMESH_subMeshObj::~SMESH_subMeshObj() SMESH_subMeshObj::~SMESH_subMeshObj()
{ {
if ( MYDEBUG ) MESSAGE( "~SMESH_subMeshObj" ); if ( MYDEBUG ) MESSAGE( "~SMESH_subMeshObj" );
mySubMeshServer->UnRegister(); mySubMeshServer->Destroy();
} }
//================================================================================= //=================================================================================

View File

@ -27,6 +27,24 @@ vector<int> SMDS_Downward::_cellDimension;
*/ */
int SMDS_Downward::getCellDimension(unsigned char cellType) int SMDS_Downward::getCellDimension(unsigned char cellType)
{ {
if (_cellDimension.empty())
{
_cellDimension.resize(VTK_MAXTYPE + 1, 0);
_cellDimension[VTK_LINE] = 1;
_cellDimension[VTK_QUADRATIC_EDGE] = 1;
_cellDimension[VTK_TRIANGLE] = 2;
_cellDimension[VTK_QUADRATIC_TRIANGLE] = 2;
_cellDimension[VTK_QUAD] = 2;
_cellDimension[VTK_QUADRATIC_QUAD] = 2;
_cellDimension[VTK_TETRA] = 3;
_cellDimension[VTK_QUADRATIC_TETRA] = 3;
_cellDimension[VTK_HEXAHEDRON] = 3;
_cellDimension[VTK_QUADRATIC_HEXAHEDRON] = 3;
_cellDimension[VTK_WEDGE] = 3;
_cellDimension[VTK_QUADRATIC_WEDGE] = 3;
_cellDimension[VTK_PYRAMID] = 3;
_cellDimension[VTK_QUADRATIC_PYRAMID] = 3;
}
return _cellDimension[cellType]; return _cellDimension[cellType];
} }

View File

@ -813,15 +813,15 @@ int SMDS_UnstructuredGrid::GetNeighbors(int* neighborsVtkIds, int* downIds, unsi
{ {
int vtkType = this->GetCellType(vtkId); int vtkType = this->GetCellType(vtkId);
int cellDim = SMDS_Downward::getCellDimension(vtkType); int cellDim = SMDS_Downward::getCellDimension(vtkType);
if (cellDim != 3) if (cellDim <2)
return 0; // TODO voisins des faces ou edges return 0; // TODO voisins des edges = edges connectees
int cellId = this->_cellIdToDownId[vtkId]; int cellId = this->_cellIdToDownId[vtkId];
int nbCells = _downArray[vtkType]->getNumberOfDownCells(cellId); int nbCells = _downArray[vtkType]->getNumberOfDownCells(cellId);
const int *downCells = _downArray[vtkType]->getDownCells(cellId); const int *downCells = _downArray[vtkType]->getDownCells(cellId);
const unsigned char* downTyp = _downArray[vtkType]->getDownTypes(cellId); const unsigned char* downTyp = _downArray[vtkType]->getDownTypes(cellId);
// --- iteration on faces of the 3D cell. // --- iteration on faces of the 3D cell (or edges on the 2D cell).
int nb = 0; int nb = 0;
for (int i = 0; i < nbCells; i++) for (int i = 0; i < nbCells; i++)
@ -832,7 +832,8 @@ int SMDS_UnstructuredGrid::GetNeighbors(int* neighborsVtkIds, int* downIds, unsi
const int *upCells = _downArray[cellType]->getUpCells(downId); const int *upCells = _downArray[cellType]->getUpCells(downId);
const unsigned char* upTypes = _downArray[cellType]->getUpTypes(downId); const unsigned char* upTypes = _downArray[cellType]->getUpTypes(downId);
// --- max 2 upCells, one is this cell, the other is a neighbor // ---for a volume, max 2 upCells, one is this cell, the other is a neighbor
// for a face, number of neighbors (connected faces) not known
for (int j = 0; j < nbUp; j++) for (int j = 0; j < nbUp; j++)
{ {
@ -884,11 +885,10 @@ void SMDS_UnstructuredGrid::ModifyCellNodes(int vtkVolId, std::map<int, int> loc
} }
} }
/*! Create a volume (prism or hexahedron) by duplication of a face. /*! reorder the nodes of a face
* the nodes of the new face are already created.
* @param vtkVolId vtk id of a volume containing the face, to get an orientation for the face. * @param vtkVolId vtk id of a volume containing the face, to get an orientation for the face.
* @param localClonedNodeIds map old node id to new node id. * @param orderedNodes list of nodes to reorder (in out)
* @return vtk id of the new volume. * @return size of the list
*/ */
int SMDS_UnstructuredGrid::getOrderedNodesOfFace(int vtkVolId, std::vector<vtkIdType>& orderedNodes) int SMDS_UnstructuredGrid::getOrderedNodesOfFace(int vtkVolId, std::vector<vtkIdType>& orderedNodes)
{ {

View File

@ -10626,11 +10626,16 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
SMDS_UnstructuredGrid *grid = meshDS->getGrid(); SMDS_UnstructuredGrid *grid = meshDS->getGrid();
// --- build the list of faces shared by 2 domains (group of elements), with their domain and volume indexes // --- build the list of faces shared by 2 domains (group of elements), with their domain and volume indexes
// build the list of cells with only a node or an edge on the border, with their domain and volume indexes
// build the list of nodes shared by 2 or more domains, with their domain indexes // build the list of nodes shared by 2 or more domains, with their domain indexes
std::map<DownIdType, std::map<int,int>, DownIdCompare> faceDomains; // 2x(id domain --> id volume) std::map<DownIdType, std::map<int,int>, DownIdCompare> faceDomains; // face --> (id domain --> id volume)
std::map<int, std::map<int,int> > nodeDomains; //oldId -> (domainId -> newId) std::map<int,int>celldom; // cell vtkId --> domain
std::map<DownIdType, std::map<int,int>, DownIdCompare> cellDomains; // oldNode --> (id domain --> id cell)
std::map<int, std::map<int,int> > nodeDomains; // oldId --> (domainId --> newId)
faceDomains.clear(); faceDomains.clear();
celldom.clear();
cellDomains.clear();
nodeDomains.clear(); nodeDomains.clear();
std::map<int,int> emptyMap; std::map<int,int> emptyMap;
emptyMap.clear(); emptyMap.clear();
@ -10667,6 +10672,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
if (!faceDomains[face].count(idom)) if (!faceDomains[face].count(idom))
{ {
faceDomains[face][idom] = vtkId; // volume associated to face in this domain faceDomains[face][idom] = vtkId; // volume associated to face in this domain
celldom[vtkId] = idom;
} }
} }
} }
@ -10674,15 +10680,23 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
} }
MESSAGE("Number of shared faces " << faceDomains.size()); MESSAGE("Number of shared faces " << faceDomains.size());
std::map<DownIdType, std::map<int, int>, DownIdCompare>::iterator itface;
// --- for each shared face, get the nodes // --- explore the shared faces domain by domain,
// for each node, for each domain of the face, create a clone of the node // explore the nodes of the face and see if they belong to a cell in the domain,
// which has only a node or an edge on the border (not a shared face)
std::map<DownIdType, std::map<int,int>, DownIdCompare>::iterator itface = faceDomains.begin(); for (int idomain = 0; idomain < theElems.size(); idomain++)
{
const TIDSortedElemSet& domain = theElems[idomain];
itface = faceDomains.begin();
for (; itface != faceDomains.end(); ++itface) for (; itface != faceDomains.end(); ++itface)
{ {
DownIdType face = itface->first;
std::map<int, int> domvol = itface->second; std::map<int, int> domvol = itface->second;
if (!domvol.count(idomain))
continue;
DownIdType face = itface->first;
//MESSAGE(" --- face " << face.cellId);
std::set<int> oldNodes; std::set<int> oldNodes;
oldNodes.clear(); oldNodes.clear();
grid->GetNodeIds(oldNodes, face.cellId, face.cellType); grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
@ -10690,20 +10704,67 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
for (; itn != oldNodes.end(); ++itn) for (; itn != oldNodes.end(); ++itn)
{ {
int oldId = *itn; int oldId = *itn;
//MESSAGE(" node " << oldId);
std::set<int> cells;
cells.clear();
vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId);
for (int i=0; i<l.ncells; i++)
{
int vtkId = l.cells[i];
const SMDS_MeshElement* anElem = GetMeshDS()->FindElement(GetMeshDS()->fromVtkToSmds(vtkId));
if (!domain.count(anElem))
continue;
int vtkType = grid->GetCellType(vtkId);
int downId = grid->CellIdToDownId(vtkId);
DownIdType aCell(downId, vtkType);
if (celldom.count(vtkId))
continue;
cellDomains[aCell][idomain] = vtkId;
celldom[vtkId] = idomain;
}
}
}
}
// --- explore the shared faces domain by domain, to duplicate the nodes in a coherent way
// for each shared face, get the nodes
// for each node, for each domain of the face, create a clone of the node
for (int idomain = 0; idomain < theElems.size(); idomain++)
{
itface = faceDomains.begin();
for (; itface != faceDomains.end(); ++itface)
{
std::map<int, int> domvol = itface->second;
if (!domvol.count(idomain))
continue;
DownIdType face = itface->first;
//MESSAGE(" --- face " << face.cellId);
std::set<int> oldNodes;
oldNodes.clear();
grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
std::set<int>::iterator itn = oldNodes.begin();
for (; itn != oldNodes.end(); ++itn)
{
int oldId = *itn;
//MESSAGE(" node " << oldId);
if (!nodeDomains.count(oldId)) if (!nodeDomains.count(oldId))
nodeDomains[oldId] = emptyMap; // create an empty entry for node nodeDomains[oldId] = emptyMap; // create an empty entry for node
if (nodeDomains[oldId].empty())
nodeDomains[oldId][idomain] = oldId; // keep the old node in the first domain
std::map<int, int>::iterator itdom = domvol.begin(); std::map<int, int>::iterator itdom = domvol.begin();
for (; itdom != domvol.end(); ++itdom) for (; itdom != domvol.end(); ++itdom)
{ {
int idom = itdom->first; int idom = itdom->first;
if ( nodeDomains[oldId].empty() ) //MESSAGE(" domain " << idom);
nodeDomains[oldId][idom] = oldId; // keep the old node in the first domain if (!nodeDomains[oldId].count(idom))
else
{ {
double *coords = grid->GetPoint(oldId); double *coords = grid->GetPoint(oldId);
SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]); SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]);
int newId = newNode->getVtkId(); int newId = newNode->getVtkId();
nodeDomains[oldId][idom] = newId; // cloned node for other domains nodeDomains[oldId][idom] = newId; // cloned node for other domains
//MESSAGE(" newNode " << newId);
}
} }
} }
} }
@ -10723,7 +10784,6 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
std::set<int>::iterator itn; std::set<int>::iterator itn;
oldNodes.clear(); oldNodes.clear();
grid->GetNodeIds(oldNodes, face.cellId, face.cellType); grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
std::map<int,int> localClonedNodeIds;
std::map<int,int> domvol = itface->second; std::map<int,int> domvol = itface->second;
std::map<int,int>::iterator itdom = domvol.begin(); std::map<int,int>::iterator itdom = domvol.begin();
@ -10731,24 +10791,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
int vtkVolId = itdom->second; int vtkVolId = itdom->second;
itdom++; itdom++;
int dom2 = itdom->first; int dom2 = itdom->first;
meshDS->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains);
localClonedNodeIds.clear();
for (itn = oldNodes.begin(); itn != oldNodes.end(); ++itn)
{
int oldId = *itn;
int refid = oldId;
if (nodeDomains[oldId].count(dom1))
refid = nodeDomains[oldId][dom1];
else
MESSAGE("--- problem domain node " << dom1 << " " << oldId);
int newid = oldId;
if (nodeDomains[oldId].count(dom2))
newid = nodeDomains[oldId][dom2];
else
MESSAGE("--- problem domain node " << dom2 << " " << oldId);
localClonedNodeIds[oldId] = newid;
}
meshDS->extrudeVolumeFromFace(vtkVolId, localClonedNodeIds);
} }
} }
@ -10756,6 +10799,8 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
// get node id's of the face // get node id's of the face
// replace old nodes by new nodes in volumes, and update inverse connectivity // replace old nodes by new nodes in volumes, and update inverse connectivity
MESSAGE("cellDomains " << cellDomains.size());
faceDomains.insert(cellDomains.begin(), cellDomains.end());
itface = faceDomains.begin(); itface = faceDomains.begin();
for( ; itface != faceDomains.end();++itface ) for( ; itface != faceDomains.end();++itface )
{ {

View File

@ -1977,23 +1977,38 @@ bool SMESHDS_Mesh::ModifyCellNodes(int vtkVolId, std::map<int,int> localClonedNo
} }
/*! Create a volume (prism or hexahedron) by duplication of a face. /*! Create a volume (prism or hexahedron) by duplication of a face.
* the nodes of the new face are already created. * Designed for use in creation of flat elements separating volume domains.
* @param vtkVolId vtk id of a volume containing the face, to get an orientation for the face. * A face separating two domains is shared by two volume cells.
* @param localClonedNodeIds map old node id to new node id. The old nodes define the face in the volume. * All the nodes are already created (for the two faces).
* Each original Node is associated to corresponding nodes in the domains.
* Some nodes may be duplicated for more than two domains, when domain separations intersect.
* In that case, even some of the nodes to use for the original face may be changed.
* @param vtkVolId: vtk id of a volume containing the face, to get an orientation for the face.
* @param domain1: domain of the original face
* @param domain2: domain of the duplicated face
* @param originalNodes: the vtk node ids of the original face
* @param nodeDomains: map(original id --> map(domain --> duplicated node id))
* @return ok if success. * @return ok if success.
*/ */
bool SMESHDS_Mesh::extrudeVolumeFromFace(int vtkVolId, std::map<int,int>& localClonedNodeIds) bool SMESHDS_Mesh::extrudeVolumeFromFace(int vtkVolId,
int domain1,
int domain2,
std::set<int>& originalNodes,
std::map<int,std::map<int,int> >& nodeDomains)
{ {
//MESSAGE("extrudeVolumeFromFace " << vtkVolId); //MESSAGE("extrudeVolumeFromFace " << vtkVolId);
vector<vtkIdType> orderedNodes; vector<vtkIdType> orderedOriginals;
orderedNodes.clear(); orderedOriginals.clear();
map<int, int>::const_iterator it = localClonedNodeIds.begin(); set<int>::const_iterator it = originalNodes.begin();
for (; it != localClonedNodeIds.end(); ++it) for (; it != originalNodes.end(); ++it)
orderedNodes.push_back(it->first); orderedOriginals.push_back(*it);
int nbNodes = myGrid->getOrderedNodesOfFace(vtkVolId, orderedNodes); int nbNodes = myGrid->getOrderedNodesOfFace(vtkVolId, orderedOriginals);
vector<vtkIdType> orderedNodes;
for (int i=0; i<nbNodes; i++) for (int i=0; i<nbNodes; i++)
orderedNodes.push_back(localClonedNodeIds[orderedNodes[i]]); orderedNodes.push_back(nodeDomains[orderedOriginals[i]][domain1]);
for (int i=0; i<nbNodes; i++)
orderedNodes.push_back(nodeDomains[orderedOriginals[i]][domain2]);
SMDS_MeshVolume *vol = this->AddVolumeFromVtkIds(orderedNodes); SMDS_MeshVolume *vol = this->AddVolumeFromVtkIds(orderedNodes);
// TODO update subshape list of elements and nodes // TODO update subshape list of elements and nodes

View File

@ -401,7 +401,11 @@ public:
std::vector<const SMDS_MeshNode*> nodes, std::vector<const SMDS_MeshNode*> nodes,
std::vector<int> quantities); std::vector<int> quantities);
bool ModifyCellNodes(int smdsVolId, std::map<int,int> localClonedNodeIds); bool ModifyCellNodes(int smdsVolId, std::map<int,int> localClonedNodeIds);
bool extrudeVolumeFromFace(int vtkVolId, std::map<int,int>& localClonedNodeIds); bool extrudeVolumeFromFace(int vtkVolId,
int domain1,
int domain2,
std::set<int>& originalNodes,
std::map<int,std::map<int,int> >& nodeDomains);
void Renumber (const bool isNodes, const int startID=1, const int deltaID=1); void Renumber (const bool isNodes, const int startID=1, const int deltaID=1);
void SetNodeInVolume(SMDS_MeshNode * aNode, const TopoDS_Shell & S); void SetNodeInVolume(SMDS_MeshNode * aNode, const TopoDS_Shell & S);