1 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + This file is part of enGrid. +
5 // + Copyright 2008-2014 enGits GmbH +
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. +
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. +
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/>. +
20 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22 #include "guicreatehexshell.h"
23 #include "guimainwindow.h"
25 GuiCreateHexShell::GuiCreateHexShell()
27 connect(m_Ui
.spinBoxNx
, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
28 connect(m_Ui
.spinBoxNy
, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
29 connect(m_Ui
.spinBoxNz
, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
30 connect(m_Ui
.spinBoxLx1
, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
31 connect(m_Ui
.spinBoxLx2
, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
32 connect(m_Ui
.spinBoxLy1
, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
33 connect(m_Ui
.spinBoxLy2
, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
34 connect(m_Ui
.spinBoxLz1
, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
35 connect(m_Ui
.spinBoxLz2
, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
38 void GuiCreateHexShell::ijkCell(int idx
, int &i
, int &j
, int &k
)
40 i
= idx
/(m_NumJCells
*m_NumKCells
);
41 int rest
= idx
- i
*(m_NumJCells
*m_NumKCells
);
43 k
= rest
- j
*m_NumKCells
;
46 void GuiCreateHexShell::ijkNode(int idx
, int &i
, int &j
, int &k
)
48 i
= idx
/(m_NumJNodes
*m_NumKNodes
);
49 int rest
= idx
- i
*(m_NumJNodes
*m_NumKNodes
);
51 k
= rest
- j
*m_NumKNodes
;
54 void GuiCreateHexShell::updateNumberOfCells(int)
56 int num_i1
= m_Ui
.spinBoxNx
->value();
57 int num_i2
= num_i1
+ m_Ui
.spinBoxLx1
->value() + m_Ui
.spinBoxLx2
->value();
58 int num_j1
= m_Ui
.spinBoxNy
->value();
59 int num_j2
= num_j1
+ m_Ui
.spinBoxLy1
->value() + m_Ui
.spinBoxLy2
->value();
60 int num_k1
= m_Ui
.spinBoxNz
->value();
61 int num_k2
= num_k1
+ m_Ui
.spinBoxLz1
->value() + m_Ui
.spinBoxLz2
->value();
62 m_TotalNumberOfCells
= num_i2
*num_j2
*num_k2
- num_i1
*num_j1
*num_k1
;
63 int num_cells
= m_TotalNumberOfCells
;
65 while (num_cells
> 0) {
66 numbers
<< num_cells
% 1000;
70 txt
.setNum(numbers
.last());
72 while (numbers
.size() > 0) {
74 num
.setNum(numbers
.last());
75 while (num
.size() < 3) {
81 m_Ui
.labelTotalNumberOfCells
->setText(txt
);
84 void GuiCreateHexShell::before()
86 EG_VTKDCN(vtkDoubleArray
, cl
, m_Grid
, "node_meshdensity_desired");
88 for (vtkIdType id_node
= 0; id_node
< m_Grid
->GetNumberOfPoints(); ++id_node
) {
89 m_H
= min(m_H
, cl
->GetValue(id_node
));
91 vec3_t
x1( 1e99
, 1e99
, 1e99
);
92 vec3_t
x2(-1e99
, -1e99
, -1e99
);
93 for (vtkIdType id_node
= 0; id_node
< m_Grid
->GetNumberOfPoints(); ++id_node
) {
95 m_Grid
->GetPoint(id_node
, x
.data());
96 for (int i
= 0; i
< 3; ++i
) {
97 x1
[i
] = min(x1
[i
], x
[i
]);
98 x2
[i
] = max(x2
[i
], x
[i
]);
101 x1
-= 5*vec3_t(m_H
, m_H
, m_H
);
102 x2
+= 5*vec3_t(m_H
, m_H
, m_H
);
103 m_Ui
.spinBoxNx
->setValue(int((x2
[0] - x1
[0])/m_H
));
104 m_Ui
.spinBoxNy
->setValue(int((x2
[1] - x1
[1])/m_H
));
105 m_Ui
.spinBoxNz
->setValue(int((x2
[2] - x1
[2])/m_H
));
106 setDouble(x1
[0], m_Ui
.lineEditX1
);
107 setDouble(x1
[1], m_Ui
.lineEditY1
);
108 setDouble(x1
[2], m_Ui
.lineEditZ1
);
109 setDouble(x2
[0], m_Ui
.lineEditX2
);
110 setDouble(x2
[1], m_Ui
.lineEditY2
);
111 setDouble(x2
[2], m_Ui
.lineEditZ2
);
112 updateNumberOfCells();
115 void GuiCreateHexShell::createGridWithNodes(vtkUnstructuredGrid
*grid
)
118 m_NodeIDs
.fill(-1, m_NumINodes
*m_NumJNodes
*m_NumKNodes
);
119 vtkIdType id_node
= 0;
120 for (int i
= 0; i
< m_NumINodes
; ++i
) {
121 for (int j
= 0; j
< m_NumJNodes
; ++j
) {
122 for (int k
= 0; k
< m_NumKNodes
; ++k
) {
124 in_core
= in_core
&& i
> m_Ui
.spinBoxLx1
->value();
125 in_core
= in_core
&& i
< m_NumINodes
- m_Ui
.spinBoxLx2
->value() - 1;
126 in_core
= in_core
&& j
> m_Ui
.spinBoxLy1
->value();
127 in_core
= in_core
&& j
< m_NumJNodes
- m_Ui
.spinBoxLy2
->value() - 1;
128 in_core
= in_core
&& k
> m_Ui
.spinBoxLz1
->value();
129 in_core
= in_core
&& k
< m_NumKNodes
- m_Ui
.spinBoxLz2
->value() - 1;
136 allocateGrid(grid
, m_TotalNumberOfCells
, num_nodes
);
137 for (int i
= 0; i
< m_NumINodes
; ++i
) {
138 for (int j
= 0; j
< m_NumJNodes
; ++j
) {
139 for (int k
= 0; k
< m_NumKNodes
; ++k
) {
141 in_core
= in_core
&& i
> m_Ui
.spinBoxLx1
->value();
142 in_core
= in_core
&& i
< m_NumINodes
- m_Ui
.spinBoxLx2
->value() - 1;
143 in_core
= in_core
&& j
> m_Ui
.spinBoxLy1
->value();
144 in_core
= in_core
&& j
< m_NumJNodes
- m_Ui
.spinBoxLy2
->value() - 1;
145 in_core
= in_core
&& k
> m_Ui
.spinBoxLz1
->value();
146 in_core
= in_core
&& k
< m_NumKNodes
- m_Ui
.spinBoxLz2
->value() - 1;
148 m_NodeIDs
[indexNode(i
,j
,k
)] = id_node
;
149 grid
->GetPoints()->SetPoint(id_node
, x(i
), y(j
), z(k
));
157 void GuiCreateHexShell::createHexCells(vtkUnstructuredGrid
*grid
)
159 EG_VTKDCC(vtkIntArray
, cell_code
, grid
, "cell_code");
160 m_CellIDs
.fill(-1, m_NumICells
*m_NumJCells
*m_NumKCells
);
161 for (int i
= 0; i
< m_NumICells
; ++i
) {
162 for (int j
= 0; j
< m_NumJCells
; ++j
) {
163 for (int k
= 0; k
< m_NumKCells
; ++k
) {
165 in_core
= in_core
&& i
>= m_Ui
.spinBoxLx1
->value();
166 in_core
= in_core
&& i
< m_NumICells
- m_Ui
.spinBoxLx2
->value();
167 in_core
= in_core
&& j
>= m_Ui
.spinBoxLy1
->value();
168 in_core
= in_core
&& j
< m_NumJCells
- m_Ui
.spinBoxLy2
->value();
169 in_core
= in_core
&& k
>= m_Ui
.spinBoxLz1
->value();
170 in_core
= in_core
&& k
< m_NumKCells
- m_Ui
.spinBoxLz2
->value();
172 EG_VTKSP(vtkIdList
, pts
);
173 pts
->SetNumberOfIds(8);
174 pts
->SetId(0, m_NodeIDs
[indexNode(i
,j
,k
)]);
175 pts
->SetId(1, m_NodeIDs
[indexNode(i
+1,j
,k
)]);
176 pts
->SetId(2, m_NodeIDs
[indexNode(i
+1,j
+1,k
)]);
177 pts
->SetId(3, m_NodeIDs
[indexNode(i
,j
+1,k
)]);
178 pts
->SetId(4, m_NodeIDs
[indexNode(i
,j
,k
+1)]);
179 pts
->SetId(5, m_NodeIDs
[indexNode(i
+1,j
,k
+1)]);
180 pts
->SetId(6, m_NodeIDs
[indexNode(i
+1,j
+1,k
+1)]);
181 pts
->SetId(7, m_NodeIDs
[indexNode(i
,j
+1,k
+1)]);
182 for (int i_pts
= 0; i_pts
< 8; ++i_pts
) {
183 if (pts
->GetId(i_pts
) == -1) {
187 m_CellIDs
[indexCell(i
,j
,k
)] = grid
->InsertNextCell(VTK_HEXAHEDRON
, pts
);
188 if (m_CellIDs
[indexCell(i
,j
,k
)] >= m_TotalNumberOfCells
) {
191 cell_code
->SetValue(m_CellIDs
[indexCell(i
,j
,k
)], 0);
198 void GuiCreateHexShell::defineBoundaryCodes()
200 QSet
<int> bcs
= mainWindow()->getAllBoundaryCodes();
202 foreach (int bc
, bcs
) {
203 m_InnerBC
= max(bc
, m_InnerBC
);
206 m_OuterBC
= m_InnerBC
+ 1;
207 mainWindow()->addBC(m_InnerBC
, BoundaryCondition("HexShellInside", "patch"));
208 mainWindow()->addBC(m_OuterBC
, BoundaryCondition("HexShellOutside", "patch"));
211 void GuiCreateHexShell::createOuterBoundary(vtkUnstructuredGrid
*grid
)
213 EG_VTKSP(vtkUnstructuredGrid
, new_grid
);
214 allocateGrid(new_grid
, grid
->GetNumberOfCells() + 2*(m_NumICells
*m_NumJCells
+ m_NumICells
*m_NumKCells
+ m_NumJCells
*m_NumKCells
), grid
->GetNumberOfPoints());
215 makeCopyNoAlloc(grid
, new_grid
);
216 EG_VTKDCC(vtkIntArray
, cell_code
, new_grid
, "cell_code");
221 for (int j
= 0; j
< m_NumJCells
; ++j
) {
222 for (int k
= 0; k
< m_NumKCells
; ++k
) {
223 vtkIdType id_cell
= m_CellIDs
[indexCell(i
,j
,k
)];
227 QVector
<vtkIdType
> pts
;
228 getFaceOfCell(new_grid
, id_cell
, 4, pts
);
229 vtkIdType id_new_cell
= new_grid
->InsertNextCell(VTK_QUAD
, 4, pts
.data());
230 cell_code
->SetValue(id_new_cell
, m_OuterBC
);
237 int i
= m_NumICells
- 1;
238 for (int j
= 0; j
< m_NumJCells
; ++j
) {
239 for (int k
= 0; k
< m_NumKCells
; ++k
) {
240 vtkIdType id_cell
= m_CellIDs
[indexCell(i
,j
,k
)];
244 QVector
<vtkIdType
> pts
;
245 getFaceOfCell(new_grid
, id_cell
, 5, pts
);
246 vtkIdType id_new_cell
= new_grid
->InsertNextCell(VTK_QUAD
, 4, pts
.data());
247 cell_code
->SetValue(id_new_cell
, m_OuterBC
);
254 for (int i
= 0; i
< m_NumICells
; ++i
) {
256 for (int k
= 0; k
< m_NumKCells
; ++k
) {
257 vtkIdType id_cell
= m_CellIDs
[indexCell(i
,j
,k
)];
261 QVector
<vtkIdType
> pts
;
262 getFaceOfCell(new_grid
, id_cell
, 2, pts
);
263 vtkIdType id_new_cell
= new_grid
->InsertNextCell(VTK_QUAD
, 4, pts
.data());
264 cell_code
->SetValue(id_new_cell
, m_OuterBC
);
271 for (int i
= 0; i
< m_NumICells
; ++i
) {
272 int j
= m_NumJCells
- 1;
273 for (int k
= 0; k
< m_NumKCells
; ++k
) {
274 vtkIdType id_cell
= m_CellIDs
[indexCell(i
,j
,k
)];
278 QVector
<vtkIdType
> pts
;
279 getFaceOfCell(new_grid
, id_cell
, 3, pts
);
280 vtkIdType id_new_cell
= new_grid
->InsertNextCell(VTK_QUAD
, 4, pts
.data());
281 cell_code
->SetValue(id_new_cell
, m_OuterBC
);
288 for (int i
= 0; i
< m_NumICells
; ++i
) {
289 for (int j
= 0; j
< m_NumJCells
; ++j
) {
291 vtkIdType id_cell
= m_CellIDs
[indexCell(i
,j
,k
)];
295 QVector
<vtkIdType
> pts
;
296 getFaceOfCell(new_grid
, id_cell
, 0, pts
);
297 vtkIdType id_new_cell
= new_grid
->InsertNextCell(VTK_QUAD
, 4, pts
.data());
298 cell_code
->SetValue(id_new_cell
, m_OuterBC
);
305 for (int i
= 0; i
< m_NumICells
; ++i
) {
306 for (int j
= 0; j
< m_NumJCells
; ++j
) {
307 int k
= m_NumKCells
- 1;
308 vtkIdType id_cell
= m_CellIDs
[indexCell(i
,j
,k
)];
312 QVector
<vtkIdType
> pts
;
313 getFaceOfCell(new_grid
, id_cell
, 1, pts
);
314 vtkIdType id_new_cell
= new_grid
->InsertNextCell(VTK_QUAD
, 4, pts
.data());
315 cell_code
->SetValue(id_new_cell
, m_OuterBC
);
320 makeCopy(new_grid
, grid
);
323 void GuiCreateHexShell::createInnerBoundary(vtkUnstructuredGrid
*grid
)
325 int num_new_nodes
= 0;
326 int num_new_faces
= 0;
327 MeshPartition
part(grid
, true);
328 QVector
<bool> copy_cell(grid
->GetNumberOfCells(), true);
329 for (vtkIdType id_cell
= 0; id_cell
< grid
->GetNumberOfCells(); ++id_cell
) {
330 if (isVolume(id_cell
, grid
)) {
331 bool face_found
= false;
332 for (int i
= 0; i
< part
.c2cGSize(id_cell
); ++i
) {
333 vtkIdType id_neigh
= part
.c2cGG(id_cell
, i
);
334 if (id_neigh
== -1) {
341 copy_cell
[id_cell
] = false;
347 EG_VTKSP(vtkUnstructuredGrid
, new_grid
);
348 allocateGrid(new_grid
, grid
->GetNumberOfCells() + num_new_faces
, grid
->GetNumberOfPoints() + num_new_nodes
);
349 for (vtkIdType id_node
= 0; id_node
< grid
->GetNumberOfPoints(); ++id_node
) {
351 grid
->GetPoint(id_node
, x
.data());
352 new_grid
->GetPoints()->SetPoint(id_node
, x
.data());
354 for (vtkIdType id_cell
= 0; id_cell
< grid
->GetNumberOfCells(); ++id_cell
) {
355 if (copy_cell
[id_cell
]) {
356 vtkIdType id_new_cell
= copyCell(grid
, id_cell
, new_grid
);
357 copyCellData(grid
, id_cell
, new_grid
, id_new_cell
);
360 EG_VTKDCC(vtkIntArray
, cell_code
, new_grid
, "cell_code");
361 vtkIdType id_new_node
= grid
->GetNumberOfPoints();
362 for (vtkIdType id_cell
= 0; id_cell
< grid
->GetNumberOfCells(); ++id_cell
) {
363 if (isVolume(id_cell
, grid
)) {
364 int i_replace_face
= -1;
365 QVector
<QVector
<vtkIdType
> > triangles
;
366 for (int i
= 0; i
< part
.c2cGSize(id_cell
); ++i
) {
367 vtkIdType id_neigh
= part
.c2cGG(id_cell
, i
);
368 if (id_neigh
== -1) {
370 QVector
<vtkIdType
> pts
;
371 getFaceOfCell(grid
, id_cell
, i
, pts
);
372 if (pts
.size() != 4) {
376 foreach (vtkIdType id_node
, pts
) {
378 grid
->GetPoint(id_node
, x
.data());
382 new_grid
->GetPoints()->SetPoint(id_new_node
, xc
.data());
383 pts
.append(pts
.first());
384 for (int j
= 0; j
< 4; ++j
) {
385 QVector
<vtkIdType
> triangle(3);
386 triangle
[0] = pts
[j
];
387 triangle
[1] = pts
[j
+1];
388 triangle
[2] = id_new_node
;
389 vtkIdType id_new_face
= new_grid
->InsertNextCell(VTK_TRIANGLE
, 3, triangle
.data());
390 cell_code
->SetValue(id_new_face
, m_InnerBC
);
391 triangles
.push_back(triangle
);
396 if (i_replace_face
!= -1) {
397 EG_VTKSP(vtkIdList
, stream
);
398 stream
->SetNumberOfIds(42);
400 stream
->SetId(id
++, 9);
401 for (int i
= 0; i
< 6; ++i
) {
402 if (i
!= i_replace_face
) {
403 stream
->SetId(id
++, 4);
404 QVector
<vtkIdType
> pts
;
405 getFaceOfCell(grid
, id_cell
, i
, pts
);
406 if (pts
.size() != 4) {
409 foreach (vtkIdType id_node
, pts
) {
410 stream
->SetId(id
++, id_node
);
414 foreach (QVector
<vtkIdType
> triangle
, triangles
) {
415 stream
->SetId(id
++, 3);
416 foreach (vtkIdType id_node
, triangle
) {
417 stream
->SetId(id
++, id_node
);
420 vtkIdType id_new_cell
= new_grid
->InsertNextCell(VTK_POLYHEDRON
, stream
);
421 copyCellData(grid
, id_cell
, new_grid
, id_new_cell
);
425 makeCopy(new_grid
, grid
);
428 void GuiCreateHexShell::createSourceBox()
430 QString xml_text
= mainWindow()->getXmlSection("engrid/sources");
432 QTextStream
s(&xml_text
);
433 s
<< "box: HexShell; " << m_X0
<< "; " << m_Y0
<< "; " << m_Z0
<< "; ";
434 s
<< m_X0
+ m_NumICells
*m_Dx
<< "; ";
435 s
<< m_Y0
+ m_NumJCells
*m_Dy
<< "; ";
436 s
<< m_Z0
+ m_NumKCells
*m_Dz
<< "; ";
437 s
<< 1.5*min(m_Dx
, min(m_Dy
, m_Dz
)) << ";\n";
439 mainWindow()->setXmlSection("engrid/sources", xml_text
);
442 void GuiCreateHexShell::operate()
444 m_NumICells
= m_Ui
.spinBoxNx
->value() + m_Ui
.spinBoxLx1
->value() + m_Ui
.spinBoxLx2
->value();
445 m_NumJCells
= m_Ui
.spinBoxNy
->value() + m_Ui
.spinBoxLy1
->value() + m_Ui
.spinBoxLy2
->value();
446 m_NumKCells
= m_Ui
.spinBoxNz
->value() + m_Ui
.spinBoxLz1
->value() + m_Ui
.spinBoxLz2
->value();
447 m_NumINodes
= m_NumICells
+ 1;
448 m_NumJNodes
= m_NumJCells
+ 1;
449 m_NumKNodes
= m_NumKCells
+ 1;
450 double x1
= m_Ui
.lineEditX1
->text().toDouble();
451 double x2
= m_Ui
.lineEditX2
->text().toDouble();
452 double y1
= m_Ui
.lineEditY1
->text().toDouble();
453 double y2
= m_Ui
.lineEditY2
->text().toDouble();
454 double z1
= m_Ui
.lineEditZ1
->text().toDouble();
455 double z2
= m_Ui
.lineEditZ2
->text().toDouble();
456 m_Dx
= (x2
- x1
)/m_Ui
.spinBoxNx
->value();
457 m_Dy
= (y2
- y1
)/m_Ui
.spinBoxNy
->value();
458 m_Dz
= (z2
- z1
)/m_Ui
.spinBoxNz
->value();
459 m_X0
= x1
- m_Ui
.spinBoxLx1
->value()*m_Dx
;
460 m_Y0
= y1
- m_Ui
.spinBoxLy1
->value()*m_Dy
;
461 m_Z0
= z1
- m_Ui
.spinBoxLz1
->value()*m_Dz
;
462 EG_VTKSP(vtkUnstructuredGrid
, shell_grid
);
463 createGridWithNodes(shell_grid
);
464 createHexCells(shell_grid
);
465 defineBoundaryCodes();
466 createOuterBoundary(shell_grid
);
467 createInnerBoundary(shell_grid
);
468 MeshPartition
shell_part(shell_grid
, true);
469 m_Part
.addPartition(shell_part
);
471 mainWindow()->updateBoundaryCodes(true);