1 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + This file is part of enGrid. +
5 // + Copyright 2008-2014 enGits GmbH +
7 // + enGrid is free software: you can redistribute it and/or modify +
8 // + it under the terms of the GNU General Public License as published by +
9 // + the Free Software Foundation, either version 3 of the License, or +
10 // + (at your option) any later version. +
12 // + enGrid is distributed in the hope that it will be useful, +
13 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
14 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
15 // + GNU General Public License for more details. +
17 // + You should have received a copy of the GNU General Public License +
18 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
20 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22 #ifndef MESHPARTITION_H
23 #define MESHPARTITION_H
27 #include "egvtkobject.h"
29 class MeshPartition
: public EgVtkObject
32 private: // attributes
35 vtkUnstructuredGrid
* m_Grid
; ///< the grid underlying this mesh partition
36 QVector
<vtkIdType
> m_Cells
; ///< all cells of the mesh partition
37 QVector
<int> m_LCells
; ///< inverse indexing for the cells
38 QVector
<vtkIdType
> m_Nodes
; ///< all nodes of the mesh partition
39 QVector
<int> m_LNodes
; ///< inverse indexing for the nodes
40 QVector
<QVector
<int> > m_N2C
; ///< node to cell information
41 QVector
<QVector
<int> > m_N2BC
; ///< node to boundary code information
42 QVector
<QVector
<int> > m_N2N
; ///< node to node information
43 QVector
<QVector
<int> > m_C2C
; ///< cell to cell information
45 int m_CellsStamp
; ///< "time"-stamp
46 int m_LCellsStamp
; ///< "time"-stamp
47 int m_NodesStamp
; ///< "time"-stamp
48 int m_LNodesStamp
; ///< "time"-stamp
49 int m_N2NStamp
; ///< "time"-stamp
50 int m_N2CStamp
; ///< "time"-stamp
51 int m_N2BCStamp
; ///< "time"-stamp
52 int m_C2CStamp
; ///< "time"-stamp
54 bool m_TrackGrid
; ///< flag to determine if grid should be tracked (make sure that all cells are always included)
55 unsigned long int m_GridMTime
; ///< VTK's modification time of the underlying grid
59 void createNodeToBC();
61 void resetTimeStamps();
73 /// Create an empty (undefined) mesh partition
77 * Create a mesh partition with the grid set. Optionally all cells can be selected.
78 * @param grid the grid to use
79 * @param use_all_cells if set to true all cells will be selected;
81 MeshPartition(vtkUnstructuredGrid
*grid
, bool use_all_cells
= false);
84 * Create a mesh partition from a global volume definition
85 * @param volume_name the name of the volume
87 MeshPartition(QString volume_name
);
91 * @param a pointer to the grid
92 * @param use_all_cells if set to true all cells will be selected;
94 void setGrid(vtkUnstructuredGrid
*grid
, bool use_all_cells
= false);
97 * Set the grid and make sure all cells are always included (automatic tracking).
98 * @param a pointer to the grid
100 void trackGrid(vtkUnstructuredGrid
*grid
);
103 * Access to the grid.
104 * @return a pointer to the grid
106 vtkUnstructuredGrid
* getGrid() const { return m_Grid
; }
109 * Define the mesh partition by defining its cells.
110 * @param cls the cells of the subset
113 void setCells(const C
& cls
);
116 * Define the mesh partition by defining its nodes.
117 * @param nds the nodes of the subset
120 void setNodes(const C
& nds
);
123 * Define the mesh partition by defining boundary codes.
124 * @param bcs the boundary codes of the subset
127 void setBCs(const C
& bcs
);
130 * Define the mesh partition by defining all its cells.
135 * Define the mesh partition by giving a symbolic volume name.
136 * The grid will be changed to the default (main) grid that is currently loaded into ENGRID.
137 * @param volume_name the symbolic volume name
139 void setVolume(QString volume_name
);
142 * Define the mesh partition as the remainder of an existing partition.
143 * @param part the existing partition
145 void setRemainder(const MeshPartition
& part
);
147 const QVector
<vtkIdType
>& getCells() const; ///< Access to the cell indices
148 const QVector
<int>& getLocalCells(); ///< Access to the local cell indices
149 const QVector
<vtkIdType
>& getNodes(); ///< Access to the node indices
150 const QVector
<int>& getLocalNodes(); ///< Access to the local node indices
151 const QVector
<QVector
<int> >& getN2N(); ///< Access to the local node to node structure
152 const QVector
<QVector
<int> >& getN2C(); ///< Access to the local node to cell structure
153 const QVector
<QVector
<int> >& getC2C(); ///< Access to the local cell to cell structure
155 void setVolumeOrientation(); ///< change the face orientation to match the volume definition
156 void setOriginalOrientation(); ///< change the orientation to match the original orientation
159 * Copy the partition to a VTK grid.
160 * @param new_grid the grid to copy the partition to (will be resized accordingly).
162 void extractToVtkGrid(vtkUnstructuredGrid
*new_grid
);
165 * Add another partition to this one.
166 * At the moment overlapping partitions on two different grids will not be handled well.
167 * If both partitions do not have the same underlying grid the grid will be extended in order
168 * to add the other partition.
169 * @param part the partition to add
170 * @param tol the tolerance to identify duplicate nodes
171 * (negative values denote a relative tolerance -- relative to the smallest edge length)
173 void addPartition(const MeshPartition
& part
, double tol
= -1e-3);
176 * compute the smallest edge length of the partition
177 * @return the smallest edge length
179 double getSmallestEdgeLength() const;
182 * Get the number of nodes in the partition.
183 * @return the number of nodes
185 int getNumberOfNodes();
188 * Get the number of cells in the partition.
189 * @return the number of cells
191 int getNumberOfCells();
194 * Get the average length of all surface edges connected to this node.
195 * @param id_node the node ID of the node in question
196 * @return the average length of all connected surface edges
198 double getAverageSurfaceEdgeLength(vtkIdType id_node
);
201 * @brief compute the minimal and maximal edge length of a surface stencil
202 * A surface stencil consists of all surface elements which have a single node in common.
203 * @param id_node the node in common
204 * @param l_min on return this will hold the minimal edge length
205 * @param l_max on return this will hold the maximal edge length
207 void computeMinAndMaxSurfaceStencilEdgeLengths(vtkIdType id_node
, double &l_min
, double &l_max
);
210 * @brief get the minimal edge length of a surface stencil
211 * A surface stencil consists of all surface elements which have a single node in common.
212 * @param id_node the node in common
213 * @return the minimal edge length
215 double getMinSurfaceStencilEdgeLength(vtkIdType id_node
);
218 * @brief get the maximal edge length of a surface stencil
219 * A surface stencil consists of all surface elements which have a single node in common.
220 * @param id_node the node in common
221 * @return the maximal edge length
223 double getMaxSurfaceStencilEdgeLength(vtkIdType id_node
);
225 vtkIdType
getVolumeCell(vtkIdType id_face
);
227 int localNode(vtkIdType id_node
);
228 vtkIdType
globalNode(int i
);
229 int localCell(vtkIdType id_cell
);
230 vtkIdType
globalCell(int i
);
233 int n2nLSize(int i_nodes
);
234 int n2nLL(int i_nodes
, int j
);
235 vtkIdType
n2nLG(int i_nodes
, int j
);
236 int n2nGSize(vtkIdType id_node
);
237 int n2nGL(vtkIdType id_node
, int j
);
238 vtkIdType
n2nGG(vtkIdType id_node
, int j
);
239 int n2cLSize(int i_nodes
);
240 int n2cLL(int i_nodes
, int j
);
241 vtkIdType
n2cLG(int i_nodes
, int j
);
242 int n2cGSize(vtkIdType id_node
);
243 int n2cGL(vtkIdType id_node
, int j
);
244 vtkIdType
n2cGG(vtkIdType id_node
, int j
);
245 int c2cLSize(int i_cells
);
246 int c2cLL(int i_cells
, int j
);
247 vtkIdType
c2cLG(int i_cells
, int j
);
248 int c2cGSize(vtkIdType id_cell
);
249 int c2cGL(vtkIdType id_cell
, int j
);
250 vtkIdType
c2cGG(vtkIdType id_cell
, int j
);
251 int n2bcLSize(int i_nodes
);
252 int n2bcL(int i_nodes
, int j
);
253 int n2bcGSize(vtkIdType id_node
);
254 int n2bcG(vtkIdType id_node
, int j
);
256 bool hasNeighNode(vtkIdType id_node
, vtkIdType id_neigh
);
257 bool hasBC(vtkIdType id_node
, int bc
);
260 * Compute the normal vector of a node.
261 * @param id_node the global ID of the node
262 * @return the normalised normal vector
264 vec3_t
globalNormal(vtkIdType id_node
);
266 template <typename C
>
267 void getGlobalN2N(vtkIdType id_node
, C
& cont
);
269 int getNumberOfFeatureNeighbours(vtkIdType id_node
);
271 template <typename C
>
272 void getEdgeFaces(vtkIdType id_node1
, vtkIdType id_node2
, C
&edge_faces
);
274 int getEdgeType(vtkIdType id_node1
, vtkIdType id_node2
);
277 * @brief compute topological distance between two nodes
278 * @param id_node1 index of the first node
279 * @param id_node2 index of the second node
280 * @param max_dist maximal search distance
281 * @param restriction_type (0: no restriction, 1: only surface nodes, 2: only edge nodes)
282 * @return the number of edges for the shortest connection between the two nodes
284 int computeTopoDistance(vtkIdType id_node1
, vtkIdType id_node2
, int max_dist
, int restriction_type
);
286 template <typename C
>
287 void getCommonNodes(vtkIdType id_cell1
, vtkIdType id_cell2
, C
&common_nodes
);
293 inline void MeshPartition::setCells(const C
& cls
)
295 m_Cells
.resize(cls
.size());
296 qCopy(cls
.begin(), cls
.end(), m_Cells
.begin());
301 inline void MeshPartition::setNodes(const C
& nds
)
303 QList
<vtkIdType
> cls
;
304 QVector
<bool> node_inside(m_Grid
->GetNumberOfPoints(), false);
305 foreach (vtkIdType id_node
, nds
) {
306 node_inside
[id_node
] = true;
308 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
309 vtkIdType N_pts
, *pts
;
310 m_Grid
->GetCellPoints(id_cell
, N_pts
, pts
);
311 bool append_cell
= true;
312 for (int i
= 0; i
< N_pts
; ++i
) {
313 if (!node_inside
[pts
[i
]]) {
326 inline void MeshPartition::setBCs(const C
& bcs
)
328 QList
<vtkIdType
> cls
;
329 EG_VTKDCC(vtkIntArray
, cell_code
, m_Grid
, "cell_code");
330 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
331 foreach (int bc
, bcs
) {
332 if (cell_code
->GetValue(id_cell
) == bc
) {
341 inline void MeshPartition::setAllCells()
343 QVector
<vtkIdType
> all_cells
;
344 getAllCells(all_cells
, m_Grid
);
345 this->setCells(all_cells
);
348 inline void MeshPartition::checkCells()
350 if (m_Grid
->GetMTime() > m_GridMTime
) {
352 m_GridMTime
= m_Grid
->GetMTime();
356 inline void MeshPartition::checkNodes()
361 if (m_CellsStamp
> m_NodesStamp
) {
362 getNodesFromCells(m_Cells
, m_Nodes
, m_Grid
);
363 m_NodesStamp
= m_CellsStamp
;
367 inline void MeshPartition::checkLCells()
372 if (m_CellsStamp
> m_LCellsStamp
) {
373 createCellMapping(m_Cells
, m_LCells
, m_Grid
);
374 m_LCellsStamp
= m_CellsStamp
;
378 inline void MeshPartition::checkLNodes()
381 if (m_NodesStamp
> m_LNodesStamp
) {
382 createNodeMapping(m_Nodes
, m_LNodes
, m_Grid
);
383 m_LNodesStamp
= m_NodesStamp
;
387 inline void MeshPartition::checkN2N()
390 if (m_LNodesStamp
> m_N2NStamp
) {
391 createNodeToNode(m_Cells
, m_Nodes
, m_LNodes
, m_N2N
, m_Grid
);
392 m_N2NStamp
= m_LNodesStamp
;
396 inline void MeshPartition::checkN2C()
399 if (m_LNodesStamp
> m_N2CStamp
) {
400 createNodeToCell(m_Cells
, m_Nodes
, m_LNodes
, m_N2C
, m_Grid
);
401 m_N2CStamp
= m_LNodesStamp
;
405 inline void MeshPartition::checkN2BC()
408 if (m_N2CStamp
> m_N2BCStamp
) {
410 m_N2BCStamp
= m_N2CStamp
;
414 inline void MeshPartition::checkC2C()
417 if (m_CellsStamp
> m_C2CStamp
) {
418 createCellToCell(m_Cells
, m_C2C
, m_Grid
);
419 m_C2CStamp
= m_CellsStamp
;
423 inline const QVector
<vtkIdType
>& MeshPartition::getCells() const
428 inline const QVector
<int>& MeshPartition::getLocalCells()
434 inline const QVector
<vtkIdType
>& MeshPartition::getNodes()
440 inline const QVector
<int>& MeshPartition::getLocalNodes()
446 inline const QVector
<QVector
<int> >& MeshPartition::getN2N()
452 inline const QVector
<QVector
<int> >& MeshPartition::getN2C()
458 inline const QVector
<QVector
<int> >& MeshPartition::getC2C()
464 inline int MeshPartition::n2nLSize(int i_nodes
)
467 return m_N2N
[i_nodes
].size();
470 inline int MeshPartition::n2nLL(int i_nodes
, int j
)
473 return m_N2N
[i_nodes
][j
];
476 inline vtkIdType
MeshPartition::n2nLG(int i_nodes
, int j
)
479 return m_Nodes
[m_N2N
[i_nodes
][j
]];
482 inline int MeshPartition::n2nGSize(vtkIdType id_node
)
485 return m_N2N
[m_LNodes
[id_node
]].size();
488 inline int MeshPartition::n2nGL(vtkIdType id_node
, int j
)
491 return m_N2N
[m_LNodes
[id_node
]][j
];
494 inline vtkIdType
MeshPartition::n2nGG(vtkIdType id_node
, int j
)
497 return m_Nodes
[m_N2N
[m_LNodes
[id_node
]][j
]];
500 inline int MeshPartition::n2cLSize(int i_nodes
)
503 return m_N2C
[i_nodes
].size();
506 inline int MeshPartition::n2cLL(int i_nodes
, int j
)
509 return m_N2C
[i_nodes
][j
];
512 inline vtkIdType
MeshPartition::n2cLG(int i_nodes
, int j
)
515 int i_cell
= m_N2C
[i_nodes
][j
];
516 if(i_cell
<0) return(-1);
517 else return m_Cells
[i_cell
];
520 inline int MeshPartition::n2cGSize(vtkIdType id_node
)
523 return m_N2C
[m_LNodes
[id_node
]].size();
526 inline int MeshPartition::n2cGL(vtkIdType id_node
, int j
)
529 return m_N2C
[m_LNodes
[id_node
]][j
];
532 inline vtkIdType
MeshPartition::n2cGG(vtkIdType id_node
, int j
)
535 int i_cell
= m_N2C
[m_LNodes
[id_node
]][j
];
536 if(i_cell
<0) return(-1);
537 else return m_Cells
[i_cell
];
540 inline int MeshPartition::c2cLSize(int i_cells
)
543 return m_C2C
[i_cells
].size();
546 inline int MeshPartition::c2cLL(int i_cells
, int j
)
549 return m_C2C
[i_cells
][j
];
552 inline vtkIdType
MeshPartition::c2cLG(int i_cells
, int j
)
555 int i_cell
= m_C2C
[i_cells
][j
];
556 if(i_cell
<0) return(-1);
557 else return m_Cells
[i_cell
];
560 inline int MeshPartition::c2cGSize(vtkIdType id_cell
)
564 return m_C2C
[m_LCells
[id_cell
]].size();
567 inline int MeshPartition::c2cGL(vtkIdType id_cell
, int j
)
571 return m_C2C
[m_LCells
[id_cell
]][j
];
574 inline vtkIdType
MeshPartition::c2cGG(vtkIdType id_cell
, int j
)
578 int i_cell
= m_C2C
[m_LCells
[id_cell
]][j
];
579 if(i_cell
<0) return(-1);
580 else return m_Cells
[i_cell
];
583 inline int MeshPartition::getNumberOfCells()
585 return m_Cells
.size();
588 inline int MeshPartition::getNumberOfNodes()
591 return m_Nodes
.size();
594 inline int MeshPartition::localNode(vtkIdType id_node
)
597 return m_LNodes
[id_node
];
600 inline vtkIdType
MeshPartition::globalNode(int i
)
606 inline int MeshPartition::localCell(vtkIdType id_cell
)
609 return m_LCells
[id_cell
];
612 inline vtkIdType
MeshPartition::globalCell(int i
)
615 else return m_Cells
[i
];
618 inline int MeshPartition::n2bcLSize(int i_nodes
)
621 return m_N2BC
[i_nodes
].size();
624 inline int MeshPartition::n2bcL(int i_nodes
, int j
)
627 return m_N2BC
[i_nodes
][j
];
630 inline int MeshPartition::n2bcGSize(vtkIdType id_node
)
633 return m_N2BC
[m_LNodes
[id_node
]].size();
636 inline int MeshPartition::n2bcG(vtkIdType id_node
, int j
)
639 return m_N2BC
[m_LNodes
[id_node
]][j
];
642 template <typename C
>
643 void MeshPartition::getGlobalN2N(vtkIdType id_node
, C
& cont
)
646 for (int i
= 0; i
< n2nGSize(id_node
); ++i
) {
647 cont
<< n2nGG(id_node
, i
);
651 template <typename C
>
652 void MeshPartition::getEdgeFaces(vtkIdType id_node1
, vtkIdType id_node2
, C
&edge_faces
)
655 for (int i
= 0; i
< n2cGSize(id_node1
); ++i
) {
656 vtkIdType id_cell
= n2cGG(id_node1
, i
);
657 if (isSurface(id_cell
, m_Grid
)) {
658 vtkIdType num_pts
, *pts
;
659 m_Grid
->GetCellPoints(id_cell
, num_pts
, pts
);
660 for (int j
= 0; j
< num_pts
; ++j
) {
661 if (pts
[j
] == id_node2
) {
662 edge_faces
<< id_cell
;
670 template <typename C
>
671 void MeshPartition::getCommonNodes(vtkIdType id_cell1
, vtkIdType id_cell2
, C
&common_nodes
)
673 common_nodes
.clear();
674 QSet
<vtkIdType
> nodes1
, nodes2
;
675 vtkIdType num_pts
, *pts
;
676 m_Grid
->GetCellPoints(id_cell1
, num_pts
, pts
);
677 for (int i
= 0; i
< num_pts
; ++i
) {
678 nodes1
.insert(pts
[i
]);
680 m_Grid
->GetCellPoints(id_cell2
, num_pts
, pts
);
681 for (int i
= 0; i
< num_pts
; ++i
) {
682 nodes2
.insert(pts
[i
]);
684 nodes1
.intersect(nodes2
);
685 common_nodes
.resize(nodes1
.size());
686 qCopy(nodes1
.begin(), nodes1
.end(), common_nodes
.begin());
689 #endif // MESHPARTITION_H