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 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
21 #include "createhexibmesh.h"
23 #include "guimainwindow.h"
24 #include "updatedesiredmeshdensity.h"
25 #include "deletevolumegrid.h"
27 CreateHexIbMesh::CreateHexIbMesh()
30 m_InsidePosition
= vec3_t(0, 0, 0);
33 double CreateHexIbMesh::meshSize(vtkIdType id_face
)
35 EG_VTKDCN(vtkDoubleArray
, cl
, m_Grid
, "node_meshdensity_desired");
36 EG_GET_CELL(id_face
, m_Grid
);
38 for (int i
= 0; i
< 3; ++i
) {
39 h
= max(h
,cl
->GetValue(pts
[i
]));
44 QString
CreateHexIbMesh::bigIntText(long long int N
)
52 text
= num
+ "," + text
.rightJustified(L
, '0');
59 double CreateHexIbMesh::meshSize(const QList
<vtkIdType
> &faces
)
61 double mesh_size
= m_MaxEdgeLength
;
62 foreach (vtkIdType id_face
, faces
) {
63 mesh_size
= min(meshSize(id_face
), mesh_size
);
68 int CreateHexIbMesh::refine()
71 m_Octree
.resetRefineMarks();
72 int old_num_cells
= m_Octree
.getNumCells();
73 for (int cell
= 0; cell
< m_Octree
.getNumCells(); ++cell
) {
74 if (!m_Octree
.hasChildren(cell
)) {
75 double H
= m_Octree
.getDx(cell
);
76 if (H
> 2*m_MeshSize
[cell
]*m_MinDim
&& H
> 2*m_MinSize
) {
77 m_Octree
.markToRefine(cell
);
83 m_Faces
.insert(old_num_cells
, m_Octree
.getNumCells() - old_num_cells
, QList
<vtkIdType
>());
84 m_MeshSize
.insert(old_num_cells
, m_Octree
.getNumCells() - old_num_cells
, m_MaxEdgeLength
);
85 for (int cell
= old_num_cells
; cell
< m_Octree
.getNumCells(); ++cell
) {
86 foreach (vtkIdType id_face
, m_Faces
[m_Octree
.getParent(cell
)]) {
87 EG_GET_CELL(id_face
, m_Grid
);
91 QVector
<vec3_t
> tri(3);
92 for (int i
= 0; i
< 3; ++i
) {
93 m_Grid
->GetPoint(pts
[i
], tri
[i
].data());
96 // compute scale factor to make sure that we have the required minimal number of layers
97 double H
= max(m_Octree
.getDx(cell
), max(m_Octree
.getDy(cell
), m_Octree
.getDz(cell
)));
98 double h
= meshSize(id_face
)*m_MinNumLayersWithRequiredResolution
;
103 if (m_Octree
.triangleIntersectsCell(cell
, tri
, scale
)) {
104 m_Faces
[cell
].append(id_face
);
107 m_MeshSize
[cell
] = min(meshSize(m_Faces
[cell
]), m_ELSManager
.minEdgeLength(m_Octree
.getCellCentre(cell
)));
109 int num_supercells
= 0;
110 for (int cell
= 0; cell
< m_Octree
.getNumCells(); ++cell
) {
111 if (!m_Octree
.hasChildren(cell
)) {
115 cout
<< qPrintable(bigIntText(num_supercells
)) << " super cells" << endl
;
119 void CreateHexIbMesh::updateMeshSize()
121 // find smallest cell size (on highest level)
123 for (int cell
= 0; cell
< m_Octree
.getNumCells(); ++cell
) {
124 if (!m_Octree
.hasChildren(cell
)) {
125 double l
= m_Octree
.getLevel(cell
);
126 H
= min(H
, m_MeshSize
[cell
]*pow(2.0, l
));
130 // set discrete cell size according to highest level
131 for (int cell
= 0; cell
< m_Octree
.getNumCells(); ++cell
) {
132 if (!m_Octree
.hasChildren(cell
)) {
133 double l
= m_Octree
.getLevel(cell
);
134 m_MeshSize
[cell
] = H
/pow(2.0, l
);
139 void CreateHexIbMesh::findInsideCells(MeshPartition
&part
, QList
<vtkIdType
> &inside_cells
)
141 vtkUnstructuredGrid
*grid
= part
.getGrid();
142 QVector
<bool> is_inside(grid
->GetNumberOfCells(), false);
144 // recompute faces for cells with no children with a minimal scale factor
145 for (int cell
= 0; cell
< m_Octree
.getNumCells(); ++cell
) {
146 if (m_Octree
.getLevel(cell
) > 0 && !m_Octree
.hasChildren(cell
)) {
147 m_Faces
[cell
].clear();
148 foreach (vtkIdType id_face
, m_Faces
[m_Octree
.getParent(cell
)]) {
149 EG_GET_CELL(id_face
, m_Grid
);
150 QVector
<vec3_t
> tri(3);
151 for (int i
= 0; i
< 3; ++i
) {
152 m_Grid
->GetPoint(pts
[i
], tri
[i
].data());
154 if (m_Octree
.triangleIntersectsCell(cell
, tri
, 1.01)) {
155 m_Faces
[cell
].append(id_face
);
161 // find closest cell to m_InsidePosition and mark boundary cells
162 vtkIdType id_start
= -1;
164 double min_dist
= 1e99
;
165 for (vtkIdType id_cell
= 0; id_cell
< grid
->GetNumberOfCells(); ++id_cell
) {
166 vec3_t x
= cellCentre(grid
, id_cell
);
167 double dist
= (m_InsidePosition
- x
).abs();
168 if (dist
< min_dist
) {
172 int cell
= m_Octree
.findCell(x
);
173 if (m_Faces
[cell
].size() > 0) {
174 is_inside
[id_cell
] = true;
178 if (id_start
== -1) {
181 QList
<vtkIdType
> front_cells
;
182 front_cells
<< id_start
;
183 is_inside
[id_start
] = true;
184 while (front_cells
.size() != 0) {
185 QList
<vtkIdType
> new_front_cells
;
186 foreach (vtkIdType id_cell
, front_cells
) {
187 for (int i
= 0; i
< part
.c2cGSize(id_cell
); ++i
) {
188 vtkIdType id_neigh
= part
.c2cGG(id_cell
, i
);
190 if (!is_inside
[id_neigh
]) {
191 is_inside
[id_neigh
] = true;
192 new_front_cells
<< id_neigh
;
197 front_cells
= new_front_cells
;
199 inside_cells
.clear();
200 for (vtkIdType id_cell
= 0; id_cell
< grid
->GetNumberOfCells(); ++id_cell
) {
201 if (is_inside
[id_cell
]) {
202 inside_cells
<< id_cell
;
207 void CreateHexIbMesh::operate()
209 DeleteVolumeGrid del_vol
;
211 m_Part
.setAllCells();
212 cout
<< "refining grid" << endl
;
214 UpdateDesiredMeshDensity update_mesh_density
;
215 update_mesh_density
.readSettings();
216 update_mesh_density
.setRelaxationOff();
217 update_mesh_density();
219 QString buffer
= GuiMainWindow::pointer()->getXmlSection("engrid/surface/settings").replace("\n", " ");
220 if (!buffer
.isEmpty()) {
221 QTextStream
in(&buffer
, QIODevice::ReadOnly
);
222 in
>> m_MaxEdgeLength
;
223 in
>> m_MinEdgeLength
;
224 in
>> m_GrowthFactor
;
226 m_MaxEdgeLength
= 1000.0;
227 m_MinEdgeLength
= 0.0;
228 m_GrowthFactor
= 1.5;
232 m_Octree
.setSmoothTransitionOn();
233 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
234 if (m_Grid
->GetCellType(id_cell
) != VTK_TRIANGLE
) {
240 m_Grid
->GetBounds(bounds
);
241 vec3_t
x1(bounds
[0], bounds
[2], bounds
[4]);
242 vec3_t
x2(bounds
[1], bounds
[3], bounds
[5]);
243 vec3_t xc
= 0.5*(x1
+ x2
);
245 double dx_max
= max(Dx
[0], max(Dx
[1], Dx
[2]));
246 Dx
= vec3_t(dx_max
, dx_max
, dx_max
);
249 m_Octree
.setBounds(x1
, x2
);
253 m_MeshSize
.resize(1);
254 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
255 m_Faces
[0].append(id_cell
);
257 m_MeshSize
[0] = meshSize(m_Faces
[0]);
265 cout
<< "deleting outside super cells" << endl
;
266 EG_VTKSP(vtkUnstructuredGrid
, otgrid
);
267 m_Octree
.toVtkGridPolyhedral(otgrid
, true);
268 MeshPartition
otpart(otgrid
);
269 otpart
.setAllCells();
270 QList
<vtkIdType
> add_cells
;
271 findInsideCells(otpart
, add_cells
);
272 otpart
.setCells(add_cells
);
273 EG_VTKDCC(vtkDoubleArray
, cl
, otgrid
, "cell_subres");
277 foreach (vtkIdType id_cell
, add_cells
) {
278 vec3_t x
= cellCentre(otgrid
, id_cell
);
279 int cell
= m_Octree
.findCell(x
);
280 double h
= m_MeshSize
[cell
];
281 cl
->SetValue(id_cell
, h
);
282 double Ni
= m_Octree
.getDx(cell
)/h
;
283 double Nj
= m_Octree
.getDy(cell
)/h
;
284 double Nk
= m_Octree
.getDx(cell
)/h
;
286 N_min
= min(N_min
, min(int(Ni
), min(int(Nj
), int(Nk
))));
287 N_max
= max(N_max
, max(int(Ni
), max(int(Nj
), int(Nk
))));
289 cout
<< add_cells
.size() << " super cells" << endl
;
290 if (fvcells
> 1e12
) {
291 cout
<< fvcells
<< " finite volume cells!!!!" << endl
;
293 long long int fvcells_li
= fvcells
;
294 cout
<< qPrintable(bigIntText(fvcells_li
)) << " finite volume cells" << endl
;
296 cout
<< "smallest dimension: " << N_min
<< endl
;
297 cout
<< "largest dimension: " << N_max
<< endl
;
298 m_Part
.addPartition(otpart
);
299 m_Part
.setAllCells();