fixed density choice: instead of taking first match, the one with smallest length...
[engrid.git] / src / guicreateboundarylayer.cpp
blob8fac54dbe75059176db14910f32ea300ef6cceda
1 //
2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + +
4 // + This file is part of enGrid. +
5 // + +
6 // + Copyright 2008,2009 Oliver Gloth +
7 // + +
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. +
12 // + +
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. +
17 // + +
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/>. +
20 // + +
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);
46 break;
49 populateBoundaryCodes(ui.listWidgetBC);
50 populateVolumes(ui.listWidgetVC);
51 ui.spinBoxIterations->setValue(max_iter);
52 double h;
53 getSet("boundary layer", "relative height of boundary layer", 0.75, h);
54 int hi = 20*h;
55 h = 0.05*hi;
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) {
66 QString msg;
67 msg.setNum(bc);
68 msg = "Boundary code " + msg + " is not part of the volume '" + volume_name +"'.";
69 EG_ERR_RETURN(msg);
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);
85 setAllCells();
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);
100 QSet<int> bcs;
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);
124 GridSmoother smooth;
125 smooth.setGrid(grid);
126 smooth.setBoundaryCodes(m_BoundaryCodes);
127 smooth.prismsOn();
128 //smooth.setNumIterations(5);
130 SeedSimplePrismaticLayer seed_layer;
132 CreateVolumeMesh vol;
133 vol.setGrid(grid);
134 SwapTriangles swap;
135 swap.setGrid(grid);
136 swap.setBoundaryCodes(m_BoundaryCodes);
137 DeleteTetras del;
138 del.setGrid(grid);
140 if (!ui.checkBoxImprove->isChecked()) {
141 cout << "preparing prismatic layer" << endl;
142 seed_layer.setGrid(grid);
143 del();
144 vol();
145 seed_layer.setAllCells();
146 seed_layer.setLayerCells(layer_cells);
147 seed_layer.setBoundaryCodes(m_BoundaryCodes);
148 seed_layer();
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();
157 smooth();
158 del.setAllCells();
159 del();
160 swap();
161 vol.setTraceCells(layer_cells);
162 vol();
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);
182 createIndices(grid);
183 cout << "total mesh error: " << mesh_error << endl;
184 smooth.printMaxErrors();