2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 // + This file is part of enGrid. +
6 // + Copyright 2008-2013 enGits GmbH +
8 // + enGrid is free software: you can redistribute it and/or modify +
9 // + it under the terms of the GNU General Public License as published by +
10 // + the Free Software Foundation, either version 3 of the License, or +
11 // + (at your option) any later version. +
13 // + enGrid is distributed in the hope that it will be useful, +
14 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
15 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
16 // + GNU General Public License for more details. +
18 // + You should have received a copy of the GNU General Public License +
19 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
21 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
23 #include "seedsimpleprismaticlayer.h"
24 #include <vtkIdList.h>
26 SeedSimplePrismaticLayer::SeedSimplePrismaticLayer()
32 void SeedSimplePrismaticLayer::setLayerCells(const QVector
<vtkIdType
> &cells
)
34 layer_cells
.resize(cells
.size());
35 qCopy(cells
.begin(), cells
.end(), layer_cells
.begin());
38 void SeedSimplePrismaticLayer::getLayerCells(QVector
<vtkIdType
> &cells
)
40 cells
.resize(layer_cells
.size());
41 qCopy(layer_cells
.begin(), layer_cells
.end(), cells
.begin());
44 void SeedSimplePrismaticLayer::prepareLayer()
47 EG_VTKSP(vtkIdList
, nds
);
48 EG_VTKSP(vtkIdList
, cls
);
49 EG_VTKDCN(vtkIntArray
, node_layer
, m_Grid
, "node_layer");
50 vol_cells
.fill(-1, layer_cells
.size());
51 faces
.resize(layer_cells
.size());
53 QSet
<vtkIdType
> new_points
;
54 for (int i_layer_cell
= 0; i_layer_cell
< layer_cells
.size(); ++i_layer_cell
) {
55 vtkIdType id_cell
= layer_cells
[i_layer_cell
];
56 vtkIdType type_cell
= m_Grid
->GetCellType(id_cell
);
59 m_Grid
->GetCellPoints(id_cell
, Npts
, pts
);
60 if (type_cell
== VTK_TRIANGLE
) {
62 faces
[i_layer_cell
].resize(Npts
);
63 for (int i_pts
= 0; i_pts
< Npts
; ++i_pts
) {
64 faces
[i_layer_cell
][Npts
- 1 - i_pts
] = pts
[i_pts
];
65 nds
->InsertNextId(pts
[i_pts
]);
66 new_points
.insert(pts
[i_pts
]);
68 m_Grid
->GetCellNeighbors(id_cell
, nds
, cls
);
69 for (int i_cls
= 0; i_cls
< cls
->GetNumberOfIds(); ++i_cls
) {
70 if (isVolume(cls
->GetId(i_cls
), m_Grid
)) {
71 if (cls
->GetId(i_cls
) != id_cell
) {
72 vol_cells
[i_layer_cell
] = cls
->GetId(i_cls
);
77 } else if (type_cell
== VTK_WEDGE
) {
79 faces
[i_layer_cell
].resize(3);
80 for (int i_pts
= 0; i_pts
< 3; ++i_pts
) {
81 faces
[i_layer_cell
][2 - i_pts
] = pts
[i_pts
+3];
82 //faces[i_layer_cell][i_pts] = pts[i_pts+3];
83 nds
->InsertNextId(pts
[i_pts
+3]);
84 new_points
.insert(pts
[i_pts
+3]);
86 m_Grid
->GetCellNeighbors(id_cell
, nds
, cls
);
87 for (int i_cls
= 0; i_cls
< cls
->GetNumberOfIds(); ++i_cls
) {
88 if (isVolume(cls
->GetId(i_cls
), m_Grid
)) {
89 if (cls
->GetId(i_cls
) != id_cell
) {
90 vol_cells
[i_layer_cell
] = cls
->GetId(i_cls
);
99 if (faces
.size() > 0) {
100 old_layer
= node_layer
->GetValue(faces
[0][0]);
101 new_layer
= old_layer
+ 1;
103 N_new_cells
+= countBoundaryElements();
104 N_new_points
= new_points
.size();
107 int SeedSimplePrismaticLayer::countBoundaryElements()
110 QVector
<QSet
<int> > n2f(m_Grid
->GetNumberOfPoints());
111 for (int i_faces
= 0; i_faces
< faces
.size(); ++i_faces
) {
112 for (int j_faces
= 0; j_faces
< faces
[i_faces
].size(); ++j_faces
) {
113 n2f
[faces
[i_faces
][j_faces
]].insert(i_faces
);
116 EG_VTKDCN(vtkIntArray
, node_layer
, m_Grid
, "node_layer");
117 EG_VTKDCN(vtkIntArray
, node_status
, m_Grid
, "node_status");
118 for (int i_faces
= 0; i_faces
< faces
.size(); ++i_faces
) {
119 for (int j_faces
= 0; j_faces
< faces
[i_faces
].size(); ++j_faces
) {
120 vtkIdType p1
= faces
[i_faces
][j_faces
];
121 vtkIdType p2
= faces
[i_faces
][0];
122 if (j_faces
< faces
[i_faces
].size() - 1) {
123 p2
= faces
[i_faces
][j_faces
+1];
125 bool consider_edge
= false;
126 if ((node_status
->GetValue(p1
) & 2) && (node_status
->GetValue(p2
) & 2)) {
127 consider_edge
= true;
129 if ((node_layer
->GetValue(p1
) == 0) && (node_layer
->GetValue(p2
) == 0)) {
130 consider_edge
= true;
133 QSet
<int> faces_on_edge
;
134 qcontIntersection(n2f
[p1
], n2f
[p2
], faces_on_edge
);
135 if (faces_on_edge
.size() == 0) {
137 } else if (faces_on_edge
.size() == 1) {
139 } else if (faces_on_edge
.size() > 2) {
148 void SeedSimplePrismaticLayer::createBoundaryElements(vtkUnstructuredGrid
*new_grid
)
150 QVector
<QSet
<int> > n2f(m_Grid
->GetNumberOfPoints());
151 for (int i_faces
= 0; i_faces
< faces
.size(); ++i_faces
) {
152 for (int j_faces
= 0; j_faces
< faces
[i_faces
].size(); ++j_faces
) {
153 n2f
[faces
[i_faces
][j_faces
]].insert(i_faces
);
156 QVector
<vtkIdType
> bcells
;
157 QVector
<vtkIdType
> bnodes
;
158 QVector
<int> _bnodes
;
159 QVector
<QSet
<int> > bn2bc
;
160 getAllSurfaceCells(bcells
, new_grid
);
161 getNodesFromCells(bcells
, bnodes
, new_grid
);
162 createNodeMapping(bnodes
, _bnodes
, new_grid
);
163 createNodeToCell(bcells
, bnodes
, _bnodes
, bn2bc
, new_grid
);
164 EG_VTKDCC(vtkIntArray
, cell_code
, new_grid
, "cell_code");
165 EG_VTKDCN(vtkIntArray
, node_layer
, new_grid
, "node_layer");
166 EG_VTKDCN(vtkIntArray
, node_status
, new_grid
, "node_status");
167 EG_VTKDCC(vtkIntArray
, cell_orgdir
, new_grid
, "cell_orgdir");
168 EG_VTKDCC(vtkIntArray
, cell_voldir
, new_grid
, "cell_voldir");
169 EG_VTKDCC(vtkIntArray
, cell_curdir
, new_grid
, "cell_curdir");
170 for (int i_faces
= 0; i_faces
< faces
.size(); ++i_faces
) {
171 for (int j_faces
= 0; j_faces
< faces
[i_faces
].size(); ++j_faces
) {
172 vtkIdType p1
= faces
[i_faces
][j_faces
];
173 vtkIdType p2
= faces
[i_faces
][0];
174 if (j_faces
< faces
[i_faces
].size() - 1) {
175 p2
= faces
[i_faces
][j_faces
+1];
177 bool consider_edge
= false;
178 if ((node_status
->GetValue(p1
) & 2) && (node_status
->GetValue(p2
) & 2)) {
179 consider_edge
= true;
181 if ((node_layer
->GetValue(p1
) == 0) && (node_layer
->GetValue(p2
) == 0)) {
182 consider_edge
= true;
185 QSet
<int> faces_on_edge
;
186 qcontIntersection(n2f
[p1
], n2f
[p2
], faces_on_edge
);
187 if (faces_on_edge
.size() == 0) {
189 } else if (faces_on_edge
.size() == 1) {
190 vtkIdType pts
[4] = { p1
, p2
, old2new
[p2
], old2new
[p1
] };
191 vtkIdType id_new_bcell
= new_grid
->InsertNextCell(VTK_QUAD
,4, pts
);
193 QSet
<int> bc1
, bc2
, bc3
;
197 if (_bnodes
[old2new
[p1
]] != -1) {
198 foreach (int i_bcells
, bn2bc
[_bnodes
[old2new
[p1
]]]) {
199 if (org_dir
== -99) {
200 org_dir
= cell_orgdir
->GetValue(bcells
[i_bcells
]);
201 } else if (cell_orgdir
->GetValue(bcells
[i_bcells
]) != org_dir
) {
204 if (cur_dir
== -99) {
205 cur_dir
= cell_curdir
->GetValue(bcells
[i_bcells
]);
206 } else if (cell_curdir
->GetValue(bcells
[i_bcells
]) != cur_dir
) {
209 if (vol_dir
== -99) {
210 vol_dir
= cell_voldir
->GetValue(bcells
[i_bcells
]);
211 } else if (cell_voldir
->GetValue(bcells
[i_bcells
]) != vol_dir
) {
214 if (!m_BoundaryCodes
.contains(cell_code
->GetValue(bcells
[i_bcells
]))) {
215 bc1
.insert(cell_code
->GetValue(bcells
[i_bcells
]));
219 if (_bnodes
[old2new
[p2
]] != -1) {
220 foreach (int i_bcells
, bn2bc
[_bnodes
[old2new
[p2
]]]) {
221 if (org_dir
== -99) {
222 org_dir
= cell_orgdir
->GetValue(bcells
[i_bcells
]);
223 } else if (cell_orgdir
->GetValue(bcells
[i_bcells
]) != org_dir
) {
226 if (cur_dir
== -99) {
227 cur_dir
= cell_curdir
->GetValue(bcells
[i_bcells
]);
228 } else if (cell_curdir
->GetValue(bcells
[i_bcells
]) != cur_dir
) {
231 if (vol_dir
== -99) {
232 vol_dir
= cell_voldir
->GetValue(bcells
[i_bcells
]);
233 } else if (cell_voldir
->GetValue(bcells
[i_bcells
]) != vol_dir
) {
236 /* if (!boundary_codes.contains(cell_code->GetValue(bcells[i_bcells]))) {
237 bc1.insert(cell_code->GetValue(bcells[i_bcells]));
239 if (!m_BoundaryCodes
.contains(cell_code
->GetValue(bcells
[i_bcells
]))) {
240 bc2
.insert(cell_code
->GetValue(bcells
[i_bcells
]));
244 qcontIntersection(bc1
, bc2
, bc3
);
245 if (bc3
.size() == 1) {
251 cell_code
->SetValue(id_new_bcell
, bc
);
252 cell_orgdir
->SetValue(id_new_bcell
, org_dir
);
253 cell_voldir
->SetValue(id_new_bcell
, vol_dir
);
254 cell_curdir
->SetValue(id_new_bcell
, cur_dir
);
255 node_status
->SetValue(p1
, node_status
->GetValue(p1
) | 2);
256 node_status
->SetValue(old2new
[p1
], node_status
->GetValue(p1
) | 2);
257 node_status
->SetValue(p2
, node_status
->GetValue(p2
) | 2);
258 node_status
->SetValue(old2new
[p2
], node_status
->GetValue(p2
) | 2);
259 } else if (faces_on_edge
.size() > 2) {
267 void SeedSimplePrismaticLayer::operate()
269 cout
<< "seeding prismatic layer" << endl
;
271 EG_VTKSP(vtkUnstructuredGrid
, new_grid
);
272 allocateGrid(new_grid
, m_Grid
->GetNumberOfCells() + N_new_cells
, m_Grid
->GetNumberOfPoints() + N_new_points
);
273 vtkIdType id_new_node
= 0;
274 EG_VTKDCN(vtkIntArray
, node_status_old
, m_Grid
, "node_status");
275 EG_VTKDCN(vtkIntArray
, node_status_new
, new_grid
, "node_status");
276 EG_VTKDCN(vtkIntArray
, node_layer_old
, m_Grid
, "node_layer");
277 EG_VTKDCN(vtkIntArray
, node_layer_new
, new_grid
, "node_layer");
278 EG_VTKDCC(vtkIntArray
, bc
, m_Grid
, "cell_code");
279 EG_VTKDCN(vtkDoubleArray
, cl_old
, m_Grid
, "node_meshdensity_desired");
280 EG_VTKDCN(vtkDoubleArray
, cl_new
, new_grid
, "node_meshdensity_desired");
282 l2l_t n2c
= getPartN2C();
283 g2l_t _nodes
= getPartLocalNodes();
285 QVector
<QSet
<int> > n2f(m_Grid
->GetNumberOfPoints());
286 for (int i_faces
= 0; i_faces
< faces
.size(); ++i_faces
) {
287 for (int j_faces
= 0; j_faces
< faces
[i_faces
].size(); ++j_faces
) {
288 n2f
[faces
[i_faces
][j_faces
]].insert(i_faces
);
292 // copy old grid nodes to the new grid
293 old2new
.resize(m_Grid
->GetNumberOfPoints());
294 for (vtkIdType id_node
= 0; id_node
< m_Grid
->GetNumberOfPoints(); ++id_node
) {
296 m_Grid
->GetPoints()->GetPoint(id_node
, x
.data());
297 new_grid
->GetPoints()->SetPoint(id_new_node
, x
.data());
298 copyNodeData(m_Grid
, id_node
, new_grid
, id_new_node
);
299 old2new
[id_node
] = id_new_node
;
303 QSet
<vtkIdType
> split_nodes
;
304 for (int i_faces
= 0; i_faces
< faces
.size(); ++i_faces
) {
305 for (int j_faces
= 0; j_faces
< faces
[i_faces
].size(); ++j_faces
) {
306 split_nodes
.insert(faces
[i_faces
][j_faces
]);
309 qDebug() << split_nodes
.size();
310 QVector
<bool> is_split_node(m_Grid
->GetNumberOfPoints(), false);
311 foreach (vtkIdType id_node
, split_nodes
) {
313 m_Grid
->GetPoints()->GetPoint(id_node
, x
.data());
314 double h
= cl_old
->GetValue(id_node
);
316 if (n2f
[id_node
].size() > 0) {
319 foreach (int i_faces
, n2f
[id_node
]) {
321 if (faces
[i_faces
][0] == id_node
) {
322 m_Grid
->GetPoint(faces
[i_faces
][1],a
.data());
323 m_Grid
->GetPoint(faces
[i_faces
][2],b
.data());
325 if (faces
[i_faces
][1] == id_node
) {
326 m_Grid
->GetPoint(faces
[i_faces
][2],a
.data());
327 m_Grid
->GetPoint(faces
[i_faces
][0],b
.data());
329 if (faces
[i_faces
][2] == id_node
) {
330 m_Grid
->GetPoint(faces
[i_faces
][0],a
.data());
331 m_Grid
->GetPoint(faces
[i_faces
][1],b
.data());
339 vec3_t nf
= a
.cross(b
);
341 double alpha
= acos(a
*b
);
344 for (int i_boundary_correction
= 0; i_boundary_correction
< 20; ++i_boundary_correction
) {
345 foreach (vtkIdType id_cell
, n2c
[_nodes
[id_node
]]) {
346 if (isSurface(id_cell
, m_Grid
)) {
347 if (!m_BoundaryCodes
.contains(bc
->GetValue(id_cell
))) {
348 double A
= GeometryTools::cellVA(m_Grid
, id_cell
);
350 vec3_t nf
= GeometryTools::cellNormal(m_Grid
, id_cell
);
364 new_grid
->GetPoints()->SetPoint(id_new_node
, x
.data());
365 cl_new
->SetValue(id_new_node
, h
);
366 old2new
[id_node
] = id_new_node
;
367 node_status_new
->SetValue(id_new_node
, node_status_old
->GetValue(id_node
));
368 node_layer_new
->SetValue(id_new_node
, node_layer_old
->GetValue(id_node
) + 1);
370 is_split_node
[id_node
] = true;
372 QVector
<bool> needs_correction(m_Grid
->GetNumberOfCells(), false);
373 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
374 vtkIdType type_cell
= m_Grid
->GetCellType(id_cell
);
375 if ((type_cell
== VTK_TRIANGLE
) || (type_cell
== VTK_TETRA
)) {
376 vtkIdType
*pts
, N_pts
;
377 m_Grid
->GetCellPoints(id_cell
, N_pts
, pts
);
379 for (int i_pts
= 0; i_pts
< N_pts
; ++i_pts
) {
380 if (is_split_node
[pts
[i_pts
]]) {
382 if (node_layer_old
->GetValue(pts
[i_pts
]) != old_layer
) {
388 if (type_cell
== VTK_TETRA
) {
389 needs_correction
[id_cell
] = true;
393 for (int i_pts
= 0; i_pts
< N_pts
; ++i_pts
) {
394 if (node_layer_old
->GetValue(pts
[i_pts
]) == old_layer
- 1) {
400 needs_correction
[id_cell
] = true;
402 cout
<< "dodgy face: " << id_cell
<< " ";
403 for (int i_pts
= 0; i_pts
< N_pts
; ++i_pts
) {
404 cout
<< "(" << pts
[i_pts
] << "," << node_layer_old
->GetValue(pts
[i_pts
]) << ") ";
407 for (int i_pts
= 0; i_pts
< N_pts
; ++i_pts
) {
408 if (is_split_node
[pts
[i_pts
]]) {
410 m_Grid
->GetPoint(pts
[i_pts
], x
.data());
411 cout
<< "split node: " << pts
[i_pts
] << " " << x
<< endl
;
419 foreach (vtkIdType id_cell
, layer_cells
) {
420 needs_correction
[id_cell
] = false;
423 QVector
<bool> is_in_vol_cells(m_Grid
->GetNumberOfCells(), false);
424 for (int i_faces
= 0; i_faces
< faces
.size(); ++i_faces
) {
425 vtkIdType id_vol_cell
= vol_cells
[i_faces
];
426 if (id_vol_cell
>= 0) {
427 is_in_vol_cells
[id_vol_cell
] = true;
428 vtkIdType type_vol_cell
= m_Grid
->GetCellType(id_vol_cell
);
429 if (type_vol_cell
== VTK_TETRA
) {
430 vtkIdType
*pts
, N_pts
, p
[6];
431 m_Grid
->GetCellPoints(id_vol_cell
, N_pts
, pts
);
432 p
[0] = faces
[i_faces
][0];
433 p
[1] = faces
[i_faces
][1];
434 p
[2] = faces
[i_faces
][2];
435 p
[3] = old2new
[p
[0]];
436 p
[4] = old2new
[p
[1]];
437 p
[5] = old2new
[p
[2]];
439 vtkIdType pts
[6] = { p
[2], p
[1], p
[0], p
[5], p
[4], p
[3] };
440 layer_cells
[i_faces
] = new_grid
->InsertNextCell(VTK_WEDGE
, 6, pts
);
443 qDebug() << type_vol_cell
;
449 // writeGrid(new_grid, "pre-cellcopy");
451 // copy old cells to the new grid
452 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
453 vtkIdType
*pts
, N_pts
;
454 m_Grid
->GetCellPoints(id_cell
, N_pts
, pts
);
455 vtkIdType type_cell
= m_Grid
->GetCellType(id_cell
);
456 if (needs_correction
[id_cell
]) {
457 for (int i_pts
= 0; i_pts
< N_pts
; ++i_pts
) {
458 pts
[i_pts
] = old2new
[pts
[i_pts
]];
461 vtkIdType id_new_cell
= new_grid
->InsertNextCell(type_cell
, N_pts
, pts
);
462 copyCellData(m_Grid
, id_cell
, new_grid
, id_new_cell
);
465 // writeGrid(new_grid, "pre-createBoundaryElements");
467 createBoundaryElements(new_grid
);
468 UpdateCellIndex(new_grid
);
469 m_Grid
->DeepCopy(new_grid
);
470 cout
<< "done." << endl
;