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 "drnumwriter.h"
23 #include "guimainwindow.h"
24 #include "vtkEgNormalExtrusion.h"
25 #include "padsurface.h"
27 DrNumWriter::DrNumWriter()
29 m_BackupGrid
= vtkSmartPointer
<vtkUnstructuredGrid
>::New();
32 QList
<BoundaryCondition
> DrNumWriter::getBcsOfType(QString type
)
34 QList
<BoundaryCondition
> bcs_of_type
;
35 QSet
<int> bcs
= GuiMainWindow::pointer()->getAllBoundaryCodes();
36 foreach (int bc_code
, bcs
) {
37 BoundaryCondition bc
= GuiMainWindow::pointer()->getBC(bc_code
);
38 PhysicalBoundaryCondition pbc
= GuiMainWindow::pointer()->getPhysicalBoundaryCondition(bc
.getType());
39 if (pbc
.getType() == type
) {
47 void DrNumWriter::readSettings()
49 QString buffer
= GuiMainWindow::pointer()->getXmlSection("engrid/surface/settings");
50 if(!buffer
.isEmpty()) {
51 QTextStream
in(&buffer
, QIODevice::ReadOnly
);
52 in
>> m_MaximalEdgeLength
;
53 in
>> m_MinimalEdgeLength
;
58 double DrNumWriter::edgeLength(QString bc_name
)
60 QString rules_txt
= GuiMainWindow::pointer()->getXmlSection("engrid/surface/rules");
61 rules_txt
= rules_txt
.replace("\n", " ");
62 rules_txt
= rules_txt
.trimmed();
63 QStringList rules
= rules_txt
.split(";", QString::SkipEmptyParts
);
64 double h_min
= EG_LARGE_REAL
;
65 foreach (QString rule
, rules
) {
66 QStringList parts
= rule
.split("=");
67 if (parts
.size() > 1) {
68 QString left
= parts
[0].trimmed();
69 double h
= parts
[1].trimmed().toDouble();
70 QStringList or_parts
= left
.split("<OR>");
71 foreach (QString or_part
, or_parts
) {
72 or_part
= or_part
.trimmed();
73 QStringList and_parts
= or_part
.split("<AND>");
74 if (and_parts
.size() == 1) {
75 QString and_part
= and_parts
[0].trimmed();
76 if (and_part
== bc_name
) {
77 h_min
= min(h
, h_min
);
86 void DrNumWriter::prepareLevelSets(QList
<BoundaryCondition
> bcs
, double distance
)
88 bool extrude
= distance
> 1e-3;
89 foreach (BoundaryCondition bc
, bcs
) {
90 BoundaryCondition new_bc
= GuiMainWindow::pointer()->getBC(BoundaryCondition(bc
.getName(), "level-set"));
91 BoundaryCondition tmp_bc
= GuiMainWindow::pointer()->getBC(BoundaryCondition(bc
.getName(), "auxilary"));
92 MeshPartition
part(m_Grid
);
93 part
.setBC(bc
.getCode());
94 if (!part
.isPlanar()) {
95 PhysicalBoundaryCondition pbc
= GuiMainWindow::pointer()->getPhysicalBoundaryCondition(bc
.getType());
96 QString msg
= "only planar surfaces allowed for boundaries of type \"" + pbc
.getType() + "\"";
101 part
.calcPlanarSurfaceMetrics(Dh
, A
, P
, x
, n
);
104 h
<< distance
*Dh
+ 10*m_MaximalEdgeLength
;
106 part
.extrude(n
, h
, bc
, false, false, true, BoundaryCondition(), BoundaryCondition(), tmp_bc
);
107 part
.setBC(tmp_bc
.getCode());
110 part
.resetBC(new_bc
.getName(), new_bc
.getType());
112 //part.setBC(new_bc.getCode());
113 //part.scale((Dh + 10*m_MaximalEdgeLength)/Dh, x);
117 pad
.addBC(new_bc
.getCode());
119 pad
.setDistance(10*m_MaximalEdgeLength
);
120 pad
.setNewBC(new_bc
.getCode());
122 part
.setBC(new_bc
.getCode());
125 part
.translate(-10*m_MaximalEdgeLength
*n
);
127 part
.writeSTL(getFileName() + "/engrid/" + new_bc
.getName() + ".stl");
128 QFile
info_file(getFileName() + "/engrid/" + new_bc
.getName() + ".dnc");
129 info_file
.open(QIODevice::WriteOnly
);
130 QTextStream
info(&info_file
);
131 PhysicalBoundaryCondition pbc
= GuiMainWindow::pointer()->getPhysicalBoundaryCondition(bc
.getType());
133 for (int i
= 0; i
< pbc
.getNumVars(); ++i
) {
134 max_size
= max(max_size
, pbc
.getVarName(i
).size());
136 info
<< "string " + QString("name").leftJustified(max_size
) << " = " << bc
.getName() << ";\n";
137 info
<< "string " + QString("type").leftJustified(max_size
) << " = " << pbc
.getType() << ";\n";
138 info
<< "real " + QString("A").leftJustified(max_size
) << " = " << A
<< ";\n";
139 info
<< "real " + QString("P").leftJustified(max_size
) << " = " << P
<< ";\n";
140 info
<< "real " + QString("Dh").leftJustified(max_size
) << " = " << Dh
<< ";\n";
141 info
<< "vec3_t " + QString("centre").leftJustified(max_size
) << " = (" << x
[0] << ", " << x
[1] << ", " << x
[2] << ");\n";
142 info
<< "vec3_t " + QString("normal").leftJustified(max_size
) << " = (" << n
[0] << ", " << n
[1] << ", " << n
[2] << ");\n";
143 for (int i
= 0; i
< pbc
.getNumVars(); ++i
) {
144 info
<< pbc
.getVarType(i
).leftJustified(7) << pbc
.getVarName(i
).leftJustified(max_size
) << " = " << pbc
.getVarValueAsString(i
) << ";\n";
146 double h
= edgeLength(bc
.getName());
147 if (h
< m_MaximalEdgeLength
) {
148 info
<< "real " + QString("h").leftJustified(max_size
) << " = " << h
<< ";\n";
153 void DrNumWriter::prepareWallLevelSets(QList
<BoundaryCondition
> bcs
)
155 foreach (BoundaryCondition bc
, bcs
) {
156 MeshPartition
part(m_Grid
);
157 part
.setBC(bc
.getCode());
158 part
.writeSTL(getFileName() + "/engrid/" + bc
.getName() + ".stl");
159 QFile
info_file(getFileName() + "/engrid/" + bc
.getName() + ".dnc");
160 info_file
.open(QIODevice::WriteOnly
);
161 QTextStream
info(&info_file
);
162 PhysicalBoundaryCondition pbc
= GuiMainWindow::pointer()->getPhysicalBoundaryCondition(bc
.getType());
164 for (int i
= 0; i
< pbc
.getNumVars(); ++i
) {
165 max_size
= max(max_size
, pbc
.getVarName(i
).size());
167 info
<< "string " + QString("name").leftJustified(max_size
) << " = " << bc
.getName() << ";\n";
168 info
<< "string " + QString("type").leftJustified(max_size
) << " = " << pbc
.getType() << ";\n";
169 for (int i
= 0; i
< pbc
.getNumVars(); ++i
) {
170 info
<< pbc
.getVarType(i
).leftJustified(7) << pbc
.getVarName(i
).leftJustified(max_size
) << " = " << pbc
.getVarValueAsString(i
) << ";\n";
172 double h
= edgeLength(bc
.getName());
173 if (h
< m_MaximalEdgeLength
) {
174 info
<< "real " + QString("h").leftJustified(max_size
) << " = " << h
<< ";\n";
179 void DrNumWriter::computeBBox()
181 m_X1
= vec3_t(EG_LARGE_REAL
, EG_LARGE_REAL
, EG_LARGE_REAL
);
183 for (vtkIdType id_node
= 0; id_node
< m_Grid
->GetNumberOfPoints(); ++id_node
) {
185 m_Grid
->GetPoint(id_node
, x
.data());
186 for (int i
= 0; i
< 3; ++i
) {
187 m_X1
[i
] = min(m_X1
[i
], x
[i
]);
188 m_X2
[i
] = max(m_X2
[i
], x
[i
]);
193 void DrNumWriter::writeGlobals()
195 QFile
info_file(getFileName() + "/engrid/global.dnc");
196 info_file
.open(QIODevice::WriteOnly
);
197 QTextStream
info(&info_file
);
199 info
<< "string name = global;\n";
200 info
<< "real h_max = " << m_MaximalEdgeLength
<< ";\n";
201 info
<< "real gf = " << m_GrowthFactor
<< ";\n";
202 info
<< "vector x1 = (" << m_X1
[0] << ", " << m_X1
[1] << ", " << m_X1
[2] << ");\n";
203 info
<< "vector x2 = (" << m_X2
[0] << ", " << m_X2
[1] << ", " << m_X2
[2] << ");\n";
206 void DrNumWriter::backup()
208 makeCopy(m_Grid
, m_BackupGrid
);
211 void DrNumWriter::restore()
213 makeCopy(m_BackupGrid
, m_Grid
);
214 GuiMainWindow::pointer()->updateBoundaryCodes(true);
215 updateNodeIndex(m_Grid
);
216 updateCellIndex(m_Grid
);
219 void DrNumWriter::operate()
221 readOutputDirectory();
226 QList
<BoundaryCondition
> turb_duct_in_bcs
= getBcsOfType("turbulent-duct-inlet");
227 QList
<BoundaryCondition
> lam_duct_in_bcs
= getBcsOfType("laminar-duct-inlet");
228 QList
<BoundaryCondition
> lam_ext_in_bcs
= getBcsOfType("inflow");
229 QList
<BoundaryCondition
> out_bcs
= getBcsOfType("outflow");
230 QList
<BoundaryCondition
> cyclic_bcs
= getBcsOfType("cyclic");
231 QList
<BoundaryCondition
> sym_bcs
= getBcsOfType("symmetry");
232 QList
<BoundaryCondition
> turb_wall_bcs
= getBcsOfType("DrNUM-turbulent-wall");
233 QList
<BoundaryCondition
> lam_wall_bcs
= getBcsOfType("wall");
234 QList
<BoundaryCondition
> slip_wall_bcs
= getBcsOfType("inviscid-wall");
236 QString root_path
= getFileName();
237 QDir
root_dir(root_path
);
238 QString engrid_path
= "engrid";
239 QDir
engrid_dir(root_path
+ "/" + engrid_path
);
240 if (!engrid_dir
.exists()) {
241 root_dir
.mkdir(engrid_path
);
243 // delete all files in the levelset directory
244 QStringList files
= engrid_dir
.entryList(QDir::Files
);
245 foreach (QString file
, files
) {
246 engrid_dir
.remove(file
);
250 prepareLevelSets(turb_duct_in_bcs
, 3.0);
251 prepareLevelSets(lam_duct_in_bcs
, 0.0);
252 prepareLevelSets(lam_ext_in_bcs
, 0.0);
253 prepareLevelSets(out_bcs
, 0.0);
254 prepareLevelSets(cyclic_bcs
, 0.0);
255 prepareLevelSets(sym_bcs
, 0.0);
257 prepareWallLevelSets(turb_wall_bcs
);
258 prepareWallLevelSets(lam_wall_bcs
);
259 prepareWallLevelSets(slip_wall_bcs
);
263 writeSolverParameters(getFileName());