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()
{
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()
{
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)
{
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];
}

View File

@ -813,15 +813,15 @@ int SMDS_UnstructuredGrid::GetNeighbors(int* neighborsVtkIds, int* downIds, unsi
{
int vtkType = this->GetCellType(vtkId);
int cellDim = SMDS_Downward::getCellDimension(vtkType);
if (cellDim != 3)
return 0; // TODO voisins des faces ou edges
if (cellDim <2)
return 0; // TODO voisins des edges = edges connectees
int cellId = this->_cellIdToDownId[vtkId];
int nbCells = _downArray[vtkType]->getNumberOfDownCells(cellId);
const int *downCells = _downArray[vtkType]->getDownCells(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;
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 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++)
{
@ -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.
* the nodes of the new face are already created.
/*! reorder the nodes of a 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.
* @return vtk id of the new volume.
* @param orderedNodes list of nodes to reorder (in out)
* @return size of the list
*/
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();
// --- 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
std::map<DownIdType, std::map<int,int>, DownIdCompare> faceDomains; // 2x(id domain --> id volume)
std::map<int, std::map<int,int> > nodeDomains; //oldId -> (domainId -> newId)
std::map<DownIdType, std::map<int,int>, DownIdCompare> faceDomains; // face --> (id domain --> id volume)
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();
celldom.clear();
cellDomains.clear();
nodeDomains.clear();
std::map<int,int> emptyMap;
emptyMap.clear();
@ -10667,6 +10672,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
if (!faceDomains[face].count(idom))
{
faceDomains[face][idom] = vtkId; // volume associated to face in this domain
celldom[vtkId] = idom;
}
}
}
@ -10674,36 +10680,91 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
}
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,
// 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)
for (int idomain = 0; idomain < theElems.size(); idomain++)
{
const TIDSortedElemSet& domain = theElems[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);
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
std::map<DownIdType, std::map<int,int>, DownIdCompare>::iterator itface = faceDomains.begin();
for( ; itface != faceDomains.end();++itface )
for (int idomain = 0; idomain < theElems.size(); idomain++)
{
DownIdType face = itface->first;
std::map<int,int> domvol = itface->second;
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)
itface = faceDomains.begin();
for (; itface != faceDomains.end(); ++itface)
{
int oldId = *itn;
if (!nodeDomains.count(oldId))
nodeDomains[oldId] = emptyMap; // create an empty entry for node
std::map<int,int>::iterator itdom = domvol.begin();
for(; itdom != domvol.end(); ++itdom)
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 idom = itdom->first;
if ( nodeDomains[oldId].empty() )
nodeDomains[oldId][idom] = oldId; // keep the old node in the first domain
else
int oldId = *itn;
//MESSAGE(" node " << oldId);
if (!nodeDomains.count(oldId))
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();
for (; itdom != domvol.end(); ++itdom)
{
double *coords = grid->GetPoint(oldId);
SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]);
int newId = newNode->getVtkId();
nodeDomains[oldId][idom] = newId; // cloned node for other domains
int idom = itdom->first;
//MESSAGE(" domain " << idom);
if (!nodeDomains[oldId].count(idom))
{
double *coords = grid->GetPoint(oldId);
SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]);
int newId = newNode->getVtkId();
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;
oldNodes.clear();
grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
std::map<int,int> localClonedNodeIds;
std::map<int,int> domvol = itface->second;
std::map<int,int>::iterator itdom = domvol.begin();
@ -10731,24 +10791,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
int vtkVolId = itdom->second;
itdom++;
int dom2 = itdom->first;
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);
meshDS->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains);
}
}
@ -10756,6 +10799,8 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
// get node id's of the face
// 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();
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.
* 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 localClonedNodeIds map old node id to new node id. The old nodes define the face in the volume.
* Designed for use in creation of flat elements separating volume domains.
* A face separating two domains is shared by two volume cells.
* 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.
*/
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);
vector<vtkIdType> orderedNodes;
orderedNodes.clear();
map<int, int>::const_iterator it = localClonedNodeIds.begin();
for (; it != localClonedNodeIds.end(); ++it)
orderedNodes.push_back(it->first);
vector<vtkIdType> orderedOriginals;
orderedOriginals.clear();
set<int>::const_iterator it = originalNodes.begin();
for (; it != originalNodes.end(); ++it)
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++)
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);
// TODO update subshape list of elements and nodes

View File

@ -401,7 +401,11 @@ public:
std::vector<const SMDS_MeshNode*> nodes,
std::vector<int> quantities);
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 SetNodeInVolume(SMDS_MeshNode * aNode, const TopoDS_Shell & S);