compiles on openSUSE 15.4 part 2
[engrid-github.git] / src / libengrid / guicreateboundarylayer.cpp
blobe22dd7b8863fe6d714577fab620a7d1374b7d077
1 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 // + +
3 // + This file is part of enGrid. +
4 // + +
5 // + Copyright 2008-2014 enGits GmbH +
6 // + +
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. +
11 // + +
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. +
16 // + +
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/>. +
19 // + +
20 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
21 #include "guicreateboundarylayer.h"
22 #include "guimainwindow.h"
23 #include "seedsimpleprismaticlayer.h"
24 #include "gridsmoother.h"
25 #include "createvolumemesh.h"
26 #include "swaptriangles.h"
27 #include "deletetetras.h"
28 #include "deletecells.h"
29 #include "meshpartition.h"
30 #include "laplacesmoother.h"
31 #include "updatedesiredmeshdensity.h"
32 #include "insertpoints.h"
34 GuiCreateBoundaryLayer::GuiCreateBoundaryLayer()
36 getSet("boundary layer", "number of smoothing iterations", 10, m_NumIterations);
37 getSet("boundary layer", "remove points", true, m_RemovePoints);
39 connect(m_Ui.pushButton_SelectAll_BC, SIGNAL(clicked()), this, SLOT(SelectAll_BC()));
40 connect(m_Ui.pushButton_ClearAll_BC, SIGNAL(clicked()), this, SLOT(ClearAll_BC()));
43 void GuiCreateBoundaryLayer::before()
45 m_Ui.checkBoxImprove->setChecked(false);
46 l2g_t cells = m_Part.getCells();
47 foreach (vtkIdType id_cell, cells) {
48 if (m_Grid->GetCellType(id_cell) == VTK_WEDGE) {
49 m_Ui.checkBoxImprove->setChecked(true);
50 break;
53 m_Ui.checkBoxRemovePoints->setChecked(m_RemovePoints);
54 m_Ui.checkBoxSafeMode->setChecked(false);
55 populateBoundaryCodes(m_Ui.listWidgetBC);
56 populateVolumes(m_Ui.listWidgetVC);
57 m_Ui.spinBoxIterations->setValue(m_NumIterations);
58 double hr, ha, b, ds = 1.5, fr = 0.8;
59 int num_layers = 0;
60 int num_hr, num_nr;
61 getSet("boundary layer", "relative height of boundary layer", 0.01, hr);
62 getSet("boundary layer", "absolute height of boundary layer", 1.0, ha);
63 getSet("boundary layer", "blending between absolute and relative", 0.0, b);
64 getSet("boundary layer", "number of layer height relax iterations", 5, num_hr);
65 getSet("boundary layer", "number of normal vector relax iterations", 20, num_nr);
67 QString blayer_txt = GuiMainWindow::pointer()->getXmlSection("blayer/global");
68 QTextStream s(&blayer_txt);
69 if (!s.atEnd()) s >> ha;
70 if (!s.atEnd()) s >> hr;
71 if (!s.atEnd()) s >> b;
72 if (!s.atEnd()) s >> ds;
73 if (!s.atEnd()) s >> fr;
74 if (!s.atEnd()) s >> num_layers;
75 if (!s.atEnd()) s >> num_hr;
76 if (!s.atEnd()) s >> num_nr;
79 int hi = 2000*hr;
80 hr = 0.0005*hi;
81 m_Ui.doubleSpinBoxHeight->setValue(hr);
84 QString num;
85 num.setNum(ha);
86 m_Ui.lineEditAbsolute->setText(num);
89 if (b > 0.5) {
90 m_Ui.checkBoxAbsolute->setChecked(true);
91 } else {
92 m_Ui.checkBoxAbsolute->setChecked(false);
96 m_Ui.doubleSpinBoxStretching->setValue(ds);
97 m_Ui.doubleSpinBoxFarRatio->setValue(fr);
99 m_Ui.spinBoxHeightIterations->setValue(num_hr);
100 m_Ui.spinBoxNormalIterations->setValue(num_nr);
101 if (num_layers > 0) {
102 QString num;
103 num.setNum(num_layers);
104 m_Ui.lineEditNumLayers->setText(num);
105 } else {
106 m_Ui.lineEditNumLayers->setText("not yet available");
110 void GuiCreateBoundaryLayer::reduceSurface()
112 RemovePoints remove_points;
113 MeshPartition part;
114 part.setGrid(m_Grid);
115 part.setAllCells();
116 remove_points.setMeshPartition(part);
117 remove_points.setBoundaryCodes(m_LayerAdjacentBoundaryCodes);
118 remove_points.setUpdatePSPOn();
119 remove_points.setThreshold(3);
120 QVector<bool> fix(m_Grid->GetNumberOfPoints(), true);
122 for (vtkIdType id_node = 0; id_node < m_Grid->GetNumberOfPoints(); ++id_node) {
123 for (int i = 0; i < part.n2cGSize(id_node); ++i) {
124 if (m_Grid->GetCellType(part.n2cGG(id_node, i)) == VTK_WEDGE) {
125 fix[id_node] = false;
129 for (int layer = 0; layer < 3; ++layer) {
130 QVector<bool> tmp = fix;
131 for (vtkIdType id_node = 0; id_node < m_Grid->GetNumberOfPoints(); ++id_node) {
132 if (!tmp[id_node]) {
133 for (int i = 0; i < part.n2nGSize(id_node); ++i) {
134 fix[part.n2nGG(id_node, i)] = false;
139 for (vtkIdType id_node = 0; id_node < m_Grid->GetNumberOfPoints(); ++id_node) {
140 for (int i = 0; i < part.n2cGSize(id_node); ++i) {
141 if (m_Grid->GetCellType(part.n2cGG(id_node, i)) == VTK_WEDGE) {
142 fix[id_node] = true;
147 remove_points.fixNodes(fix);
148 remove_points();
151 void GuiCreateBoundaryLayer::updateSurface()
153 QString buffer = GuiMainWindow::pointer()->getXmlSection("engrid/surface/table").replace("\n", " ");
154 int row_count = 0;
155 int column_count = 0;
156 QVector <VertexMeshDensity> vmd;
157 if(!buffer.isEmpty()) {
158 QTextStream in(&buffer, QIODevice::ReadOnly);
159 in >> row_count >> column_count;
160 QVector<int> tmp_bcs;
161 GuiMainWindow::pointer()->getAllBoundaryCodes(tmp_bcs);
162 if (column_count == tmp_bcs.size() + 3) {
163 vmd.fill(VertexMeshDensity(), row_count);
164 for (int i = 0; i < row_count; ++i) {
165 int row, column;
166 QString formula;
167 foreach (int bc, tmp_bcs) {
168 in >> row >> column >> formula;
169 vmd[row].BCmap[bc] = formula.toInt();
171 in >> row >> column >> formula;
172 vmd[row].type = Str2VertexType(formula);
173 in >> row >> column >> formula;
174 if (formula == "{{{empty}}}") {
175 formula = "";
177 vmd[i].setNodes(formula);
178 in >> row >> column >> formula;
179 vmd[i].density = formula.toDouble();
181 } else {
182 EG_ERR_RETURN(QObject::tr("Mismatch of number of boundary codes!"));
185 UpdateDesiredMeshDensity update;
186 MeshPartition part;
187 part.setGrid(m_Grid);
188 part.setAllCells();
189 update.setMeshPartition(part);
190 update.setVertexMeshDensityVector(vmd);
191 update.setBoundaryCodes(m_LayerAdjacentBoundaryCodes);
192 update();
195 void GuiCreateBoundaryLayer::insertPoints()
197 InsertPoints insert_points;
198 MeshPartition part;
199 part.setGrid(m_Grid);
200 part.setAllCells();
201 insert_points.setMeshPartition(part);
202 insert_points.setBoundaryCodes(m_LayerAdjacentBoundaryCodes);
203 insert_points();
206 void GuiCreateBoundaryLayer::smoothSurface()
208 LaplaceSmoother smooth;
209 MeshPartition part;
210 part.setGrid(m_Grid);
211 part.setAllCells();
212 smooth.setMeshPartition(part);
213 smooth.setNumberOfIterations(5);
214 smooth.setBoundaryCodes(m_LayerAdjacentBoundaryCodes);
216 QVector<bool> fix(m_Grid->GetNumberOfPoints(), true);
217 for (vtkIdType id_node = 0; id_node < m_Grid->GetNumberOfPoints(); ++id_node) {
218 for (int i = 0; i < part.n2cGSize(id_node); ++i) {
219 if (m_Grid->GetCellType(part.n2cGG(id_node, i)) == VTK_WEDGE) {
220 fix[id_node] = false;
224 for (int layer = 0; layer < 3; ++layer) {
225 QVector<bool> tmp = fix;
226 for (vtkIdType id_node = 0; id_node < m_Grid->GetNumberOfPoints(); ++id_node) {
227 if (!tmp[id_node]) {
228 for (int i = 0; i < part.n2nGSize(id_node); ++i) {
229 fix[part.n2nGG(id_node, i)] = false;
235 smooth.fixNodes(fix);
236 smooth();
239 void GuiCreateBoundaryLayer::operate()
241 if (!GuiMainWindow::pointer()->checkCadInterfaces()) {
242 GuiMainWindow::pointer()->storeCadInterfaces();
244 ///////////////////////////////////////////////////////////////
245 // set m_Grid to selected volume
246 getSelectedItems(m_Ui.listWidgetBC, m_BoundaryCodes); // fill m_BoundaryCodes with values from listWidgetBC
247 QString volume_name = getSelectedVolume(m_Ui.listWidgetVC);
248 VolumeDefinition V = GuiMainWindow::pointer()->getVol(volume_name);
249 foreach (int bc, m_BoundaryCodes) {
250 qDebug()<<"V.getSign("<<bc<<")="<<V.getSign(bc);
251 if (V.getSign(bc) == 0) {
252 QString msg;
253 msg.setNum(bc);
254 msg = "Boundary code " + msg + " is not part of the volume '" + volume_name +"'.";
255 EG_ERR_RETURN(msg);
259 EG_VTKSP(vtkUnstructuredGrid, rest_grid);
261 EG_VTKSP(vtkUnstructuredGrid, vol_grid);
262 MeshPartition volume(volume_name);
263 MeshPartition rest(m_Grid);
264 rest.setRemainder(volume);
265 volume.setVolumeOrientation();
266 volume.extractToVtkGrid(vol_grid);
267 rest.extractToVtkGrid(rest_grid);
268 makeCopy(vol_grid, m_Grid);
270 setAllCells();
272 l2g_t nodes = getPartNodes();
273 g2l_t _nodes = getPartLocalNodes();
274 l2g_t cells = getPartCells();
275 g2l_t _cells = getPartLocalCells();
276 l2l_t n2c = getPartN2C();
277 l2l_t c2c = getPartC2C();
278 getSurfaceCells(m_BoundaryCodes, layer_cells, m_Grid);
280 bool delete_nodes = m_Ui.checkBoxRemovePoints->isChecked();
282 // fill m_LayerAdjacentBoundaryCodes
283 EG_VTKDCC(vtkIntArray, cell_code, m_Grid, "cell_code");
284 foreach(vtkIdType id_cell, layer_cells) {
285 foreach(int i_cell_neighbour, c2c[_cells[id_cell]]) {
286 m_LayerAdjacentBoundaryCodes.insert(cell_code->GetValue(cells[i_cell_neighbour]));
289 m_LayerAdjacentBoundaryCodes = m_LayerAdjacentBoundaryCodes - m_BoundaryCodes;
291 cout << "\n\ncreating boundary layer mesh)" << endl;
293 if (!m_Ui.checkBoxImprove->isChecked()) {
294 EG_VTKDCN(vtkIntArray, node_status, m_Grid, "node_status");
295 EG_VTKDCN(vtkIntArray, node_layer, m_Grid, "node_layer");
296 EG_VTKDCC(vtkIntArray, bc, m_Grid, "cell_code");
297 foreach(vtkIdType id_node, nodes) {
298 node_status->SetValue(id_node, 0);
299 QSet<int> bcs;
300 foreach (int i_neigh_cells, n2c[_nodes[id_node]]) {
301 vtkIdType id_neigh_cell = cells[i_neigh_cells];
302 if (isSurface(id_neigh_cell, m_Grid)) {
303 if (m_BoundaryCodes.contains(bc->GetValue(id_neigh_cell))) {
304 bcs.insert(bc->GetValue(id_neigh_cell));
308 if (bcs.size() >= 2) {
309 node_status->SetValue(id_node, 1);
311 node_layer->SetValue(id_node, -1);
313 foreach (vtkIdType id_cell, layer_cells) {
314 EG_GET_CELL(id_cell, m_Grid);
315 for (int i_pts = 0; i_pts < num_pts; ++i_pts) {
316 node_layer->SetValue(pts[i_pts], 0);
322 GridSmoother smooth;
323 smooth.setGrid(m_Grid);
324 smooth.setBoundaryCodes(m_BoundaryCodes);
325 smooth.setLayerAdjacentBoundaryCodes(m_LayerAdjacentBoundaryCodes);
327 SeedSimplePrismaticLayer seed_layer;
329 CreateVolumeMesh vol;
330 vol.setGrid(m_Grid);
331 SwapTriangles swap;
332 swap.setGrid(m_Grid);
333 QSet<int> swap_codes = getAllBoundaryCodes(m_Grid);
334 swap_codes -= m_LayerAdjacentBoundaryCodes;
335 swap.setBoundaryCodes(swap_codes);
336 swap.setVerboseOff();
338 DeleteTetras del;
339 del.setGrid(m_Grid);
341 if (!m_Ui.checkBoxImprove->isChecked()) {
342 cout << "preparing prismatic layer" << endl;
343 seed_layer.setGrid(m_Grid);
344 del();
345 vol();
346 seed_layer.setAllCells();
347 seed_layer.setLayerCells(layer_cells);
348 seed_layer.setBoundaryCodes(m_BoundaryCodes);
349 seed_layer();
350 seed_layer.getLayerCells(layer_cells);
353 double Hr = m_Ui.doubleSpinBoxHeight->value();
354 double Ha = m_Ui.lineEditAbsolute->text().toDouble();
355 double bl = 0.0;
356 if (m_Ui.checkBoxAbsolute->isChecked()) {
357 bl = 1.0;
359 smooth.setRelativeHeight(Hr);
360 smooth.setAbsoluteHeight(Ha);
361 smooth.setBlending(bl);
362 smooth.setDesiredStretching(m_Ui.doubleSpinBoxStretching->value());
363 smooth.setFarRatio(m_Ui.doubleSpinBoxFarRatio->value());
364 smooth.setNumHeightRelaxations(m_Ui.spinBoxHeightIterations->value());
365 smooth.setNumNormalRelaxations(m_Ui.spinBoxNormalIterations->value());
368 QString blayer_txt = "";
369 QTextStream s(&blayer_txt);
370 s << Ha << " ";
371 s << Hr << " ";
372 s << bl << " ";
373 s << m_Ui.doubleSpinBoxStretching->value() << " ";
374 s << m_Ui.doubleSpinBoxFarRatio->value() << " ";
375 s << 0 << " ";
376 s << m_Ui.spinBoxHeightIterations->value() << " ";
377 s << m_Ui.spinBoxNormalIterations->value() << " ";
378 GuiMainWindow::pointer()->setXmlSection("blayer/global", blayer_txt);
382 for (int j = 0; j < m_Ui.spinBoxIterations->value(); ++j) {
383 cout << "improving prismatic layer -> iteration " << j+1 << "/" << m_Ui.spinBoxIterations->value() << endl;
384 if (!m_Ui.checkBoxSafeMode->isChecked()) {
385 del.setAllCells();
386 del();
388 if (delete_nodes || m_Ui.checkBoxSafeMode->isChecked()) {
389 smooth.forceNormalCalculation();
391 smooth.setAllCells();
392 smooth();
393 if (delete_nodes) {
394 //updateSurface();
395 reduceSurface();
396 //insertPoints();
398 swap();
399 smoothSurface();
400 swap();
401 //vol.setTraceCells(layer_cells);
402 if (m_Ui.checkBoxSafeMode->isChecked()) {
403 vol();
405 //vol.getTraceCells(layer_cells);
409 EG_VTKDCC(vtkIntArray, cell_code, m_Grid, "cell_code");
410 for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
411 if (isVolume(id_cell, m_Grid)) {
412 cell_code->SetValue(id_cell, V.getVC());
417 ///////////////////////////////////////////////////////////////
418 // set m_Grid to modified selected volume + unselected volumes
420 MeshPartition volume(m_Grid, true);
421 MeshPartition rest(rest_grid, true);
422 volume.addPartition(rest);
424 resetOrientation(m_Grid);
425 createIndices(m_Grid);
426 ///////////////////////////////////////////////////////////////
429 void GuiCreateBoundaryLayer::SelectAll_BC()
431 for (int i = 0; i < m_Ui.listWidgetBC->count(); ++i) {
432 m_Ui.listWidgetBC->item(i)->setCheckState(Qt::Checked);
436 void GuiCreateBoundaryLayer::ClearAll_BC()
438 for (int i = 0; i < m_Ui.listWidgetBC->count(); ++i) {
439 m_Ui.listWidgetBC->item(i)->setCheckState(Qt::Unchecked);