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 "updatedesiredmeshdensity.h"
24 #include "guimainwindow.h"
26 #include <vtkCharArray.h>
28 UpdateDesiredMeshDensity::UpdateDesiredMeshDensity() : SurfaceOperation()
31 m_MaxEdgeLength
= 1e99
;
32 m_NodesPerQuarterCircle
= 0;
36 void UpdateDesiredMeshDensity::computeExistingLengths()
39 GuiMainWindow::pointer()->getAllBoundaryCodes(all_bcs
);
40 QSet
<int> fixed_bcs
= all_bcs
- m_BoundaryCodes
;
41 QVector
<double> edge_length(m_Grid
->GetNumberOfPoints(), 1e99
);
42 QVector
<int> edge_count(m_Grid
->GetNumberOfPoints(), 0);
43 m_Fixed
.fill(false, m_Grid
->GetNumberOfPoints());
44 EG_VTKDCC(vtkIntArray
, cell_code
, m_Grid
, "cell_code");
45 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
46 if (isSurface(id_cell
, m_Grid
)) {
47 if (fixed_bcs
.contains(cell_code
->GetValue(id_cell
))) {
48 vtkIdType N_pts
, *pts
;
49 m_Grid
->GetCellPoints(id_cell
, N_pts
, pts
);
51 for (int i
= 0; i
< N_pts
; ++i
) {
52 m_Grid
->GetPoint(pts
[i
], x
[i
].data());
53 m_Fixed
[pts
[i
]] = true;
55 for (int i
= 0; i
< N_pts
; ++i
) {
60 double L
= (x
[i
] - x
[j
]).abs();
61 edge_length
[pts
[i
]] = min(edge_length
[pts
[i
]], L
);
62 edge_length
[pts
[j
]] = min(edge_length
[pts
[j
]], L
);
69 EG_VTKDCN(vtkDoubleArray
, characteristic_length_desired
, m_Grid
, "node_meshdensity_desired");
70 for (vtkIdType id_node
= 0; id_node
< m_Grid
->GetNumberOfPoints(); ++id_node
) {
71 if (edge_count
[id_node
] > 0) {
72 if (edge_length
[id_node
] > 1e98
) {
75 characteristic_length_desired
->SetValue(id_node
, edge_length
[id_node
]);
80 void UpdateDesiredMeshDensity::operate()
83 EG_VTKDCC(vtkIntArray
, cell_code
, m_Grid
, "cell_code");
86 l2g_t nodes
= getPartNodes();
87 g2l_t _nodes
= getPartLocalNodes();
88 l2g_t cells
= getPartCells();
89 l2l_t n2n
= getPartN2N();
90 l2l_t c2c
= getPartC2C();
92 EG_VTKDCN(vtkDoubleArray
, characteristic_length_desired
, m_Grid
, "node_meshdensity_desired");
93 EG_VTKDCN(vtkIntArray
, characteristic_length_specified
, m_Grid
, "node_specified_density");
95 QVector
<vec3_t
> normals(cells
.size(), vec3_t(0,0,0));
96 QVector
<vec3_t
> centres(cells
.size(), vec3_t(0,0,0));
97 QVector
<double> cl_radius(nodes
.size(), 1e99
);
99 computeExistingLengths();
100 if (m_BoundaryCodes
.size() == 0) {
104 if (m_NodesPerQuarterCircle
> 1e-3) {
106 // compute node normals
107 for (int i_cells
= 0; i_cells
< cells
.size(); ++i_cells
) {
108 normals
[i_cells
] = GeometryTools::cellNormal(m_Grid
, cells
[i_cells
]);
109 normals
[i_cells
].normalise();
110 centres
[i_cells
] = cellCentre(m_Grid
, cells
[i_cells
]);
113 // compute characteristic length according to nodes per quarter circle
114 for (int i_cells
= 0; i_cells
< cells
.size(); ++i_cells
) {
115 vec3_t xi
= centres
[i_cells
];
116 vtkIdType N_pts
, *pts
;
117 m_Grid
->GetCellPoints(cells
[i_cells
], N_pts
, pts
);
118 for (int j
= 0; j
< c2c
[i_cells
].size(); ++j
) {
119 int j_cells
= c2c
[i_cells
][j
];
120 if (cell_code
->GetValue(cells
[i_cells
]) == cell_code
->GetValue(cells
[j_cells
])) {
121 vec3_t xj
= centres
[j_cells
];
122 double cosa
= normals
[i_cells
]*normals
[j_cells
];
123 double alpha
= acos(cosa
);
124 if (alpha
> 0.01*M_PI
) {
126 vec3_t n1
= normals
[i_cells
] + normals
[j_cells
];
127 vec3_t n2
= GeometryTools::orthogonalVector(n1
);
131 double R
= 0.5*a
/sin(alpha
);
132 double cl
= 0.5*R
*M_PI
/m_NodesPerQuarterCircle
;
133 for (int k
= 0; k
< N_pts
; ++k
) {
134 cl_radius
[_nodes
[pts
[k
]]] = min(cl_radius
[_nodes
[pts
[k
]]], cl
);
142 // set everything to desired mesh density and find maximal mesh-density
143 double cl_min
= 1e99
;
144 int i_nodes_min
= -1;
145 for (int i_nodes
= 0; i_nodes
< nodes
.size(); ++i_nodes
) {
146 vtkIdType id_node
= nodes
[i_nodes
];
148 if (m_BoundaryCodes
.size() > 0) {
149 int idx
= characteristic_length_specified
->GetValue(id_node
);
151 if (idx
>= m_VMDvector
.size()) {
152 qWarning()<<"idx="<<idx
;
153 qWarning()<<"m_VMDvector.size()="<<m_VMDvector
.size();
156 cl
= m_VMDvector
[idx
].density
;
159 if (m_Fixed
[id_node
]) {
160 cl
= characteristic_length_desired
->GetValue(id_node
);
162 cl
= min(cl_radius
[i_nodes
], cl
);
164 m_Grid
->GetPoint(id_node
, x
.data());
165 double cl_src
= m_ELSManager
.minEdgeLength(x
);
167 cl
= min(cl
, cl_src
);
171 characteristic_length_desired
->SetValue(id_node
, cl
);
175 i_nodes_min
= i_nodes
;
178 if (i_nodes_min
== -1) {
182 // start from smallest characteristic length and loop as long as nodes are updated
187 for (int i_nodes
= 0; i_nodes
< nodes
.size(); ++i_nodes
) {
188 double cli
= characteristic_length_desired
->GetValue(nodes
[i_nodes
]);
191 m_Grid
->GetPoint(nodes
[i_nodes
], xi
.data());
192 for (int j
= 0; j
< n2n
[i_nodes
].size(); ++j
) {
193 int j_nodes
= n2n
[i_nodes
][j
];
194 double clj
= characteristic_length_desired
->GetValue(nodes
[j_nodes
]);
195 if (clj
> cli
&& clj
> cl_min
) {
197 m_Grid
->GetPoint(nodes
[j_nodes
], xj
.data());
199 double L_new
= min(m_MaxEdgeLength
, cli
* m_GrowthFactor
);
200 if (!m_Fixed
[nodes
[j_nodes
]]) {
202 double cl_min
= min(characteristic_length_desired
->GetValue(nodes
[j_nodes
]), L_new
);
204 qWarning()<<"m_MaxEdgeLength="<<m_MaxEdgeLength
;
205 qWarning()<<"cli="<<cli
;
206 qWarning()<<"m_GrowthFactor="<<m_GrowthFactor
;
207 qWarning()<<"characteristic_length_desired->GetValue(nodes[j_nodes])="<<characteristic_length_desired
->GetValue(nodes
[j_nodes
]);
208 qWarning()<<"L_new="<<L_new
;
211 characteristic_length_desired
->SetValue(nodes
[j_nodes
], cl_min
);
218 cl_min
*= m_GrowthFactor
;
219 } while (num_updated
> 0);
221 // do a simple averaging step
223 QVector<double> cl_save(m_Grid->GetNumberOfPoints(), 0.0);
224 for (vtkIdType id_node = 0; id_node < m_Grid->GetNumberOfPoints(); ++id_node) {
225 cl_save[id_node] = characteristic_length_desired->GetValue(id_node);
227 for (vtkIdType id_node = 0; id_node < m_Grid->GetNumberOfPoints(); ++id_node) {
229 for (int i = 0; i < m_Part.n2nGSize(id_node); ++i) {
230 cl_new += cl_save[m_Part.n2nGG(id_node, i)];
232 if (m_Part.n2nGSize(id_node) > 0) {
233 characteristic_length_desired->SetValue(id_node, cl_new/m_Part.n2nGSize(id_node));