2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 // + This file is part of enGrid. +
6 // + Copyright 2008,2009 Oliver Gloth +
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 "guidivideboundarylayer.h"
24 #include "math/linsolve.h"
26 void GuiDivideBoundaryLayer::before()
28 populateBoundaryCodes(ui
.listWidget
);
31 void GuiDivideBoundaryLayer::findBoundaryLayer()
34 insert_cell
.fill(true,grid
->GetNumberOfCells());
37 for (int i_cells
= 0; i_cells
< cells
.size(); ++i_cells
) {
38 if (grid
->GetCellType(cells
[i_cells
]) == VTK_WEDGE
) {
40 vtkIdType N_pts
, *pts
;
41 grid
->GetCellPoints(cells
[i_cells
],N_pts
,pts
);
42 for (int j
= 0; j
< 3; ++j
) {
43 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[j
],pts
[j
+3]));
45 for (int j
= 2; j
< 5; ++j
) {
46 if (c2c
[i_cells
][j
] != -1) {
47 vtkIdType type_ncell
= grid
->GetCellType(cells
[c2c
[i_cells
][j
]]);
48 if ((type_ncell
!= VTK_WEDGE
) && (type_ncell
!= VTK_QUAD
)) {
49 EG_ERR_RETURN("unable to identify boundary layer");
53 grid
->GetPoint(pts
[0],x
.data());
58 for (int j
= 0; j
< 2; ++j
) {
59 if (c2c
[i_cells
][j
] != -1) {
60 vtkIdType type_ncell
= grid
->GetCellType(cells
[c2c
[i_cells
][j
]]);
61 if (type_ncell
== VTK_WEDGE
) {
62 EG_ERR_RETURN("the boundary layer seems to have been split already");
69 if (grid
->GetCellType(cells
[i_cells
]) == VTK_QUAD
) {
74 EG_ERR_RETURN("unable to identify boundary layer");
76 is_blayer_node
.clear();
77 is_blayer_node
.fill(false, grid
->GetNumberOfPoints());
79 QPair
<vtkIdType
,vtkIdType
> P
;
81 is_blayer_node
[P
.second
] = true;
85 void GuiDivideBoundaryLayer::findBoundaryLayer1()
90 getSelectedItems(ui
.listWidget
, bcs
);
91 QVector
<vtkIdType
> scells
;
92 getSurfaceCells(bcs
, scells
, grid
);
98 insert_cell
.fill(true,grid
->GetNumberOfCells());
100 foreach (int i_scells
, scells
) {
102 vtkIdType id_scell
= scells
[i_scells
];
103 int i_cells
= findVolumeCell(grid
,id_scell
,_nodes
,cells
,_cells
,n2c
);
104 vtkIdType id_cell
= cells
[i_cells
];
105 vtkIdType type_cell
= grid
->GetCellType(id_cell
);
106 vtkIdType type_scell
= grid
->GetCellType(id_scell
);
108 vtkIdType N_pts
, *pts
;
109 grid
->GetCellPoints(id_cell
,N_pts
,pts
);
111 insert_cell
[id_cell
] = false;
113 if (type_cell
== VTK_WEDGE
) {
118 if (type_scell
!= VTK_QUAD
) {
119 EG_ERR_RETURN("unable to identify boundary layer");
121 if (cells
[c2c
[i_cells
][0]] == id_scell
) {
122 for (int j
= 0; j
< 3; ++j
) {
123 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[j
],pts
[j
+3]));
125 } else if (cells
[c2c
[i_cells
][1]] == id_scell
) {
126 for (int j
= 0; j
< 3; ++j
) {
127 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[j
+3],pts
[j
]));
130 EG_ERR_RETURN("unable to identify boundary layer");
132 for (int j
= 2; j
< 5; ++j
) {
133 if (c2c
[i_cells
][j
] != -1) {
134 vtkIdType id_ncell
= cells
[c2c
[i_cells
][j
]];
135 vtkIdType type_ncell
= grid
->GetCellType(id_ncell
);
136 if ((type_ncell
!= VTK_WEDGE
) && (type_ncell
!= VTK_HEXAHEDRON
) && (type_ncell
!= VTK_QUAD
)) {
137 EG_ERR_RETURN("unable to identify boundary layer");
139 if (type_ncell
== VTK_QUAD
) {
140 insert_cell
[id_ncell
] = false;
146 } else if (type_cell
== VTK_HEXAHEDRON
) {
151 if (type_scell
!= VTK_QUAD
) {
152 EG_ERR_RETURN("unable to identify boundary layer");
154 QVector
<bool> check_neigh(6,true);
155 if (cells
[c2c
[i_cells
][0]] == id_scell
) {
156 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[0],pts
[4]));
157 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[1],pts
[5]));
158 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[2],pts
[6]));
159 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[3],pts
[7]));
160 check_neigh
[0] = false;
161 check_neigh
[1] = false;
162 } else if (cells
[c2c
[i_cells
][1]] == id_scell
) {
163 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[4],pts
[0]));
164 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[5],pts
[1]));
165 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[6],pts
[2]));
166 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[7],pts
[3]));
167 check_neigh
[0] = false;
168 check_neigh
[1] = false;
169 } else if (cells
[c2c
[i_cells
][2]] == id_scell
) {
170 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[0],pts
[3]));
171 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[1],pts
[2]));
172 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[5],pts
[6]));
173 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[4],pts
[7]));
174 check_neigh
[2] = false;
175 check_neigh
[3] = false;
176 } else if (cells
[c2c
[i_cells
][3]] == id_scell
) {
177 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[3],pts
[0]));
178 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[2],pts
[1]));
179 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[6],pts
[5]));
180 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[7],pts
[4]));
181 check_neigh
[2] = false;
182 check_neigh
[3] = false;
183 } else if (cells
[c2c
[i_cells
][4]] == id_scell
) {
184 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[0],pts
[1]));
185 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[4],pts
[5]));
186 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[7],pts
[6]));
187 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[3],pts
[2]));
188 check_neigh
[4] = false;
189 check_neigh
[5] = false;
190 } else if (cells
[c2c
[i_cells
][5]] == id_scell
) {
191 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[1],pts
[0]));
192 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[5],pts
[4]));
193 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[6],pts
[7]));
194 pairs
.insert(QPair
<vtkIdType
,vtkIdType
>(pts
[2],pts
[3]));
195 check_neigh
[4] = false;
196 check_neigh
[5] = false;
198 for (int j
= 0; j
< 6; ++j
) {
199 if (check_neigh
[j
]) {
200 if (c2c
[i_cells
][j
] != -1) {
201 vtkIdType id_ncell
= cells
[c2c
[i_cells
][j
]];
202 vtkIdType type_ncell
= grid
->GetCellType(id_ncell
);
203 if ((type_ncell
!= VTK_WEDGE
) && (type_ncell
!= VTK_HEXAHEDRON
) && (type_ncell
!= VTK_QUAD
)) {
204 EG_ERR_RETURN("unable to identify boundary layer");
206 if (type_ncell
== VTK_QUAD
) {
207 insert_cell
[id_ncell
] = false;
215 } else if (type_cell
== VTK_QUAD
) {
222 EG_ERR_RETURN("unable to identify boundary layer");
230 for (int i_cells = 0; i_cells < cells.size(); ++i_cells) {
231 if (grid->GetCellType(cells[i_cells]) == VTK_WEDGE) {
233 vtkIdType N_pts, *pts;
234 grid->GetCellPoints(cells[i_cells],N_pts,pts);
235 for (int j = 0; j < 3; ++j) {
236 pairs.insert(QPair<vtkIdType,vtkIdType>(pts[j],pts[j+3]));
238 for (int j = 2; j < 5; ++j) {
239 if (c2c[i_cells][j] != -1) {
240 vtkIdType type_ncell = grid->GetCellType(cells[c2c[i_cells][j]]);
241 if ((type_ncell != VTK_WEDGE) && (type_ncell != VTK_QUAD)) {
242 EG_ERR_RETURN("unable to identify boundary layer");
248 for (int j = 0; j < 2; ++j) {
249 if (c2c[i_cells][j] != -1) {
250 vtkIdType type_ncell = grid->GetCellType(cells[c2c[i_cells][j]]);
251 if (type_ncell == VTK_WEDGE) {
252 EG_ERR_RETURN("the boundary layer seems to have been split already");
259 if (grid->GetCellType(cells[i_cells]) == VTK_QUAD) {
265 if (N_prisms
+ N_hexes
== 0) {
266 EG_ERR_RETURN("unable to identify boundary layer");
269 is_blayer_node
.clear();
270 is_blayer_node
.fill(false, grid
->GetNumberOfPoints());
272 QPair
<vtkIdType
,vtkIdType
> P
;
274 is_blayer_node
[P
.second
] = true;
278 void GuiDivideBoundaryLayer::bisectF(double &f1
, double &f2
)
282 if (y
[y
.size()-1] > 1) f2
= f
;
288 //begin GROSSER MURKS
290 void GuiDivideBoundaryLayer::computeF()
293 double f2
= 100;//1.0/h;
295 y
[1] = min(0.33,y
[1]);
297 //cout << f1 << ',' << f2 << endl;
299 //while (fabs(1-y[y.size()-1]) > 1e-6);
300 err
= fabs((y
[y
.size()-1]-1)/(y
[y
.size()-1]-y
[y
.size()-2]));
301 } while (err
> 0.01);
305 void GuiDivideBoundaryLayer::computeY()
308 for (int i
= 2; i
< y
.size(); ++i
) {
309 y
[i
] = y
[i
-1] + C
*(y
[i
-1]-y
[i
-2]);
316 void GuiDivideBoundaryLayer::createEdges(vtkUnstructuredGrid
*new_grid
)
318 edges
.fill(QVector
<vtkIdType
>(N_layers
+1), pairs
.size());
319 old2edge
.fill(-1, grid
->GetNumberOfPoints());
321 vtkIdType id_new_node
= grid
->GetNumberOfPoints();
322 QPair
<vtkIdType
,vtkIdType
> P
;
327 edges
[N
][0] = P
.first
;
328 edges
[N
][N_layers
] = P
.second
;
329 old2edge
[P
.first
] = N
;
330 old2edge
[P
.second
] = N
;
333 grid
->GetPoint(P
.first
, x1
.data());
334 grid
->GetPoint(P
.second
, x2
.data());
336 if (!ui
.checkBoxH
->isChecked() || !y_computed
) {
337 y
.resize(N_layers
+ 1);
339 for (int i
= 0; i
< x
.size(); ++i
) {
340 x
[i
] = i
*1.0/(x
.size() - 1);
343 if (ui
.checkBoxH
->isChecked()) {
354 ymin
= min(ymin
,y
[1]*n
.abs());
355 ymax
= max(ymax
,y
[1]*n
.abs());
356 for (int i
= 1; i
< N_layers
; ++i
) {
357 vec3_t x
= x1
+ y
[i
]*n
;
358 max_step
= max(max_step
,(y
[i
+1]-y
[i
])/(y
[i
]-y
[i
-1]));
359 new_grid
->GetPoints()->SetPoint(id_new_node
, x
.data());
360 edges
[N
][i
] = id_new_node
;
366 cout
<< "maximal increment : " << max_step
<< endl
;
367 cout
<< "min(y) : " << ymin
<< endl
;
368 cout
<< "max(y) : " << ymax
<< endl
;
372 void GuiDivideBoundaryLayer::operate1()
375 N_layers
= ui
.spinBoxLayers
->value();
376 h
= ui
.lineEditH
->text().toDouble();
377 F
= ui
.doubleSpinBoxF
->value();
378 cout
<< "dividing boundary layer into " << N_layers
<< " layers:" << endl
;
379 findBoundaryLayer1();
381 EG_VTKSP(vtkUnstructuredGrid
,new_grid
);
382 int N_new_cells
= grid
->GetNumberOfCells() + (N_prisms
+ N_hexes
+ N_quads
)*(N_layers
-1);
383 int N_new_nodes
= grid
->GetNumberOfPoints() + pairs
.size()*(N_layers
-1);
384 allocateGrid(new_grid
, N_new_cells
, N_new_nodes
);
386 // copy existing mesh without prisms and adjacent cells
387 vtkIdType id_new_node
= 0;
388 for (vtkIdType id_node
= 0; id_node
< grid
->GetNumberOfPoints(); ++id_node
) {
390 grid
->GetPoint(id_node
, x
.data());
391 new_grid
->GetPoints()->SetPoint(id_new_node
, x
.data());
392 copyNodeData(grid
, id_node
, new_grid
, id_new_node
);
395 vtkIdType id_new_cell
;
396 for (vtkIdType id_cell
= 0; id_cell
< grid
->GetNumberOfCells(); ++id_cell
) {
397 vtkIdType N_pts
, *pts
;
398 grid
->GetCellPoints(id_cell
, N_pts
, pts
);
399 //bool insert_cell = true;
400 //if (grid->GetCellType(id_cell) == VTK_WEDGE) insert_cell = false;
401 //if (grid->GetCellType(id_cell) == VTK_QUAD) insert_cell = false;
402 if (insert_cell
[id_cell
]) {
403 id_new_cell
= new_grid
->InsertNextCell(grid
->GetCellType(id_cell
), N_pts
, pts
);
404 copyCellData(grid
, id_cell
, new_grid
, id_new_cell
);
408 // create divided boundary layer
409 createEdges(new_grid
);
411 for (vtkIdType id_cell
= 0; id_cell
< grid
->GetNumberOfCells(); ++id_cell
) {
412 if (!insert_cell
[id_cell
]) {
413 if (grid
->GetCellType(id_cell
) == VTK_WEDGE
) {
414 vtkIdType N_pts
, *pts
;
415 grid
->GetCellPoints(id_cell
, N_pts
, pts
);
416 for (int i
= 0; i
< N_layers
; ++i
) {
418 p
[0] = edges
[old2edge
[pts
[0]]][i
];
419 p
[1] = edges
[old2edge
[pts
[1]]][i
];
420 p
[2] = edges
[old2edge
[pts
[2]]][i
];
421 p
[3] = edges
[old2edge
[pts
[0]]][i
+1];
422 p
[4] = edges
[old2edge
[pts
[1]]][i
+1];
423 p
[5] = edges
[old2edge
[pts
[2]]][i
+1];
424 id_new_cell
= new_grid
->InsertNextCell(VTK_WEDGE
, 6, p
);
425 copyCellData(grid
, id_cell
, new_grid
, id_new_cell
);
428 if (grid
->GetCellType(id_cell
) == VTK_HEXAHEDRON
) {
431 vtkIdType N_pts
, *pts
;
432 grid
->GetCellPoints(id_cell
, N_pts
, pts
);
433 for (int i
= 0; i
< N_layers
; ++i
) {
435 p
[0] = edges
[old2edge
[pts
[0]]][i
];
436 p
[1] = edges
[old2edge
[pts
[1]]][i
];
437 p
[2] = edges
[old2edge
[pts
[2]]][i
];
438 p
[3] = edges
[old2edge
[pts
[0]]][i
+1];
439 p
[4] = edges
[old2edge
[pts
[1]]][i
+1];
440 p
[5] = edges
[old2edge
[pts
[2]]][i
+1];
441 id_new_cell
= new_grid
->InsertNextCell(VTK_WEDGE
, 6, p
);
442 copyCellData(grid
, id_cell
, new_grid
, id_new_cell
);
447 if (grid
->GetCellType(id_cell
) == VTK_QUAD
) {
448 vtkIdType N_pts
, *pts
;
449 grid
->GetCellPoints(id_cell
, N_pts
, pts
);
450 if ((old2edge
[pts
[0]] != -1) && (old2edge
[pts
[1]] != -1) && (old2edge
[pts
[2]] != -1) && (old2edge
[pts
[3]] != -1)) {
451 for (int i
= 0; i
< N_layers
; ++i
) {
453 p
[0] = edges
[old2edge
[pts
[0]]][i
];
454 p
[1] = edges
[old2edge
[pts
[1]]][i
];
455 p
[2] = edges
[old2edge
[pts
[1]]][i
+1];
456 p
[3] = edges
[old2edge
[pts
[0]]][i
+1];
457 id_new_cell
= new_grid
->InsertNextCell(VTK_QUAD
, 4, p
);
458 copyCellData(grid
, id_cell
, new_grid
, id_new_cell
);
465 makeCopy(new_grid
, grid
);
468 void GuiDivideBoundaryLayer::operate()
471 N_layers
= ui
.spinBoxLayers
->value();
472 h
= ui
.lineEditH
->text().toDouble();
473 F
= ui
.doubleSpinBoxF
->value();
474 cout
<< "dividing boundary layer into " << N_layers
<< " layers:" << endl
;
477 EG_VTKSP(vtkUnstructuredGrid
,new_grid
);
478 allocateGrid(new_grid
, grid
->GetNumberOfCells() + (N_prisms
+ N_quads
)*(N_layers
-1), grid
->GetNumberOfPoints() + pairs
.size()*(N_layers
-1));
480 // copy existing mesh without prisms and adjacent cells
481 vtkIdType id_new_node
= 0;
482 for (vtkIdType id_node
= 0; id_node
< grid
->GetNumberOfPoints(); ++id_node
) {
484 grid
->GetPoint(id_node
, x
.data());
485 new_grid
->GetPoints()->SetPoint(id_new_node
, x
.data());
486 copyNodeData(grid
, id_node
, new_grid
, id_new_node
);
489 vtkIdType id_new_cell
;
490 for (vtkIdType id_cell
= 0; id_cell
< grid
->GetNumberOfCells(); ++id_cell
) {
491 vtkIdType N_pts
, *pts
;
492 grid
->GetCellPoints(id_cell
, N_pts
, pts
);
493 bool insert_cell
= true;
494 if (grid
->GetCellType(id_cell
) == VTK_WEDGE
) insert_cell
= false;
495 if (grid
->GetCellType(id_cell
) == VTK_QUAD
) insert_cell
= false;
497 id_new_cell
= new_grid
->InsertNextCell(grid
->GetCellType(id_cell
), N_pts
, pts
);
498 copyCellData(grid
, id_cell
, new_grid
, id_new_cell
);
502 // create divided boundary layer
503 createEdges(new_grid
);
505 for (vtkIdType id_cell
= 0; id_cell
< grid
->GetNumberOfCells(); ++id_cell
) {
506 if (grid
->GetCellType(id_cell
) == VTK_WEDGE
) {
507 vtkIdType N_pts
, *pts
;
508 grid
->GetCellPoints(id_cell
, N_pts
, pts
);
509 for (int i
= 0; i
< N_layers
; ++i
) {
511 p
[0] = edges
[old2edge
[pts
[0]]][i
];
512 p
[1] = edges
[old2edge
[pts
[1]]][i
];
513 p
[2] = edges
[old2edge
[pts
[2]]][i
];
514 p
[3] = edges
[old2edge
[pts
[0]]][i
+1];
515 p
[4] = edges
[old2edge
[pts
[1]]][i
+1];
516 p
[5] = edges
[old2edge
[pts
[2]]][i
+1];
517 id_new_cell
= new_grid
->InsertNextCell(VTK_WEDGE
, 6, p
);
518 copyCellData(grid
, id_cell
, new_grid
, id_new_cell
);
521 if (grid
->GetCellType(id_cell
) == VTK_QUAD
) {
522 vtkIdType N_pts
, *pts
;
523 grid
->GetCellPoints(id_cell
, N_pts
, pts
);
524 if ((old2edge
[pts
[0]] != -1) && (old2edge
[pts
[1]] != -1) && (old2edge
[pts
[2]] != -1) && (old2edge
[pts
[3]] != -1)) {
525 for (int i
= 0; i
< N_layers
; ++i
) {
527 p
[0] = edges
[old2edge
[pts
[0]]][i
];
528 p
[1] = edges
[old2edge
[pts
[1]]][i
];
529 p
[2] = edges
[old2edge
[pts
[1]]][i
+1];
530 p
[3] = edges
[old2edge
[pts
[0]]][i
+1];
531 id_new_cell
= new_grid
->InsertNextCell(VTK_QUAD
, 4, p
);
532 copyCellData(grid
, id_cell
, new_grid
, id_new_cell
);
538 makeCopy(new_grid
, grid
);