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 "guicreateboundarylayer.h"
24 #include "guimainwindow.h"
25 #include "seedsimpleprismaticlayer.h"
26 #include "gridsmoother.h"
27 #include "createvolumemesh.h"
28 #include "swaptriangles.h"
29 #include "deletetetras.h"
30 #include "deletecells.h"
31 #include "meshpartition.h"
33 GuiCreateBoundaryLayer::GuiCreateBoundaryLayer()
35 getSet("boundary layer", "maximal relative error", 0.01, err_max
);
36 getSet("boundary layer", "maximal number of smoothing iterations", 5, max_iter
);
39 void GuiCreateBoundaryLayer::before()
41 ui
.checkBoxImprove
->setChecked(false);
42 l2g_t cells
= m_Part
.getCells();
43 foreach (vtkIdType id_cell
, cells
) {
44 if (grid
->GetCellType(id_cell
) == VTK_WEDGE
) {
45 ui
.checkBoxImprove
->setChecked(true);
49 populateBoundaryCodes(ui
.listWidgetBC
);
50 populateVolumes(ui
.listWidgetVC
);
51 ui
.spinBoxIterations
->setValue(max_iter
);
53 getSet("boundary layer", "relative height of boundary layer", 0.75, h
);
56 ui
.doubleSpinBoxHeight
->setValue(h
);
59 void GuiCreateBoundaryLayer::operate()
61 getSelectedItems(ui
.listWidgetBC
, m_BoundaryCodes
);
62 QString volume_name
= getSelectedVolume(ui
.listWidgetVC
);
63 VolumeDefinition V
= GuiMainWindow::pointer()->getVol(volume_name
);
64 foreach (int bc
, m_BoundaryCodes
) {
65 if (V
.getSign(bc
) == 0) {
68 msg
= "Boundary code " + msg
+ " is not part of the volume '" + volume_name
+"'.";
73 EG_VTKSP(vtkUnstructuredGrid
, rest_grid
);
75 EG_VTKSP(vtkUnstructuredGrid
, vol_grid
);
76 MeshPartition
volume(volume_name
);
77 MeshPartition
rest(grid
);
78 rest
.setRemainder(volume
);
79 volume
.setVolumeOrientation();
80 volume
.extractToVtkGrid(vol_grid
);
81 rest
.extractToVtkGrid(rest_grid
);
82 makeCopy(vol_grid
, grid
);
86 l2g_t nodes
= getPartNodes();
87 l2g_t cells
= getPartCells();
88 g2l_t _nodes
= getPartLocalNodes();
89 l2l_t n2c
= getPartN2C();
90 getSurfaceCells(m_BoundaryCodes
, layer_cells
, grid
);
92 cout
<< "\n\ncreating boundary layer mesh)" << endl
;
94 if (!ui
.checkBoxImprove
->isChecked()) {
95 EG_VTKDCN(vtkIntArray
, node_status
, grid
, "node_status");
96 EG_VTKDCN(vtkIntArray
, node_layer
, grid
, "node_layer");
97 EG_VTKDCC(vtkIntArray
, bc
, grid
, "cell_code");
98 foreach(vtkIdType id_node
, nodes
) {
99 node_status
->SetValue(id_node
, 0);
101 foreach (int i_neigh_cells
, n2c
[_nodes
[id_node
]]) {
102 vtkIdType id_neigh_cell
= cells
[i_neigh_cells
];
103 if (isSurface(id_neigh_cell
, grid
)) {
104 if (m_BoundaryCodes
.contains(bc
->GetValue(id_neigh_cell
))) {
105 bcs
.insert(bc
->GetValue(id_neigh_cell
));
109 if (bcs
.size() >= 2) {
110 node_status
->SetValue(id_node
, 1);
112 node_layer
->SetValue(id_node
, -1);
114 foreach (vtkIdType id_cell
, layer_cells
) {
115 vtkIdType N_pts
, *pts
;
116 grid
->GetCellPoints(id_cell
, N_pts
, pts
);
117 for (int i_pts
= 0; i_pts
< N_pts
; ++i_pts
) {
118 node_layer
->SetValue(pts
[i_pts
], 0);
125 smooth
.setGrid(grid
);
126 smooth
.setBoundaryCodes(m_BoundaryCodes
);
128 //smooth.setNumIterations(5);
130 SeedSimplePrismaticLayer seed_layer
;
132 CreateVolumeMesh vol
;
136 swap
.setBoundaryCodes(m_BoundaryCodes
);
140 if (!ui
.checkBoxImprove
->isChecked()) {
141 cout
<< "preparing prismatic layer" << endl
;
142 seed_layer
.setGrid(grid
);
145 seed_layer
.setAllCells();
146 seed_layer
.setLayerCells(layer_cells
);
147 seed_layer
.setBoundaryCodes(m_BoundaryCodes
);
149 seed_layer
.getLayerCells(layer_cells
);
152 double h
= ui
.doubleSpinBoxHeight
->value();
153 smooth
.setRelativeHeight(h
);
154 for (int j
= 0; j
< ui
.spinBoxIterations
->value(); ++j
) {
155 cout
<< "improving prismatic layer -> iteration " << j
+1 << "/" << ui
.spinBoxIterations
->value() << endl
;
156 smooth
.setAllCells();
161 vol
.setTraceCells(layer_cells
);
163 vol
.getTraceCells(layer_cells
);
165 double mesh_error
= smooth
.lastTotalError();
168 EG_VTKDCC(vtkIntArray
, cell_code
, grid
, "cell_code");
169 for (vtkIdType id_cell
= 0; id_cell
< grid
->GetNumberOfCells(); ++id_cell
) {
170 if (isVolume(id_cell
, grid
)) {
171 cell_code
->SetValue(id_cell
, V
.getVC());
177 MeshPartition
volume(grid
, true);
178 MeshPartition
rest(rest_grid
, true);
179 volume
.addPartition(rest
);
181 resetOrientation(grid
);
183 cout
<< "total mesh error: " << mesh_error
<< endl
;
184 smooth
.printMaxErrors();