added automatix CAD fix
[engrid.git] / src / openfoamcase.cpp
blobab4d83a55364b0530cb6c18e997c385f3f2e1c4d
1 //
2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + +
4 // + This file is part of enGrid. +
5 // + +
6 // + Copyright 2008,2009 Oliver Gloth +
7 // + +
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. +
12 // + +
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. +
17 // + +
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/>. +
20 // + +
21 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
23 #include "openfoamcase.h"
25 #include "filetemplate.h"
26 #include "guimainwindow.h"
28 #include <QtDebug>
30 #include <iostream>
31 using namespace std;
33 OpenFOAMcase::OpenFOAMcase()
37 ///@@@ TODO: Finish this by adding decomposeParDict creation and calling writeMpiParameters from operate
38 void OpenFOAMcase::writeMpiParameters()
40 QString hostfile_text = GuiMainWindow::pointer()->getXmlSection( "solver/general/host_weight_list" );
42 QVector <QString> host;
43 QVector <QString> weight;
45 QStringList host_weight_list = hostfile_text.split(",");
46 foreach(QString host_weight, host_weight_list) {
47 if(!host_weight.isEmpty()){
48 QStringList values = host_weight.split(":");
49 qWarning()<<"values="<<values;
50 host.push_back(values[0].trimmed());
51 weight.push_back(values[1].trimmed());
55 // create the hostfile
56 QFileInfo fileinfo( getFileName() + "/" + "hostfile.txt" );
57 QFile hostfile( fileinfo.filePath() );
58 if (!hostfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
59 try {
60 EG_ERR_RETURN( "ERROR: Failed to open file " + fileinfo.filePath() );
61 } catch ( Error err ) {
62 err.display();
65 QTextStream out( &hostfile );
66 for(int i = 0; i < host.size(); i++) {
67 out << host[i] << endl;
69 hostfile.close();
73 void OpenFOAMcase::writeSolverParameters()
75 int idx = GuiMainWindow::pointer()->getXmlSection( "solver/general/solver_type" ).toInt();
77 QFileInfo solvers_fileinfo;
78 solvers_fileinfo.setFile( ":/resources/solvers/solvers.txt" );
79 QFile file( solvers_fileinfo.filePath() );
80 if ( !file.exists() ) {
81 qDebug() << "ERROR: " << solvers_fileinfo.filePath() << " not found.";
82 EG_BUG;
84 if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
85 qDebug() << "ERROR: Failed to open file " << solvers_fileinfo.filePath();
86 EG_BUG;
88 QTextStream text_stream( &file );
89 QString intext = text_stream.readAll();
90 file.close();
92 QStringList page_list = intext.split( "=" );
93 QString page = page_list[idx];
94 QString title;
95 QString section;
96 QString binary;
97 QVector <QString> files;
98 QStringList variable_list = page.split( ";" );
99 foreach( QString variable, variable_list ) {
100 QStringList name_value = variable.split( ":" );
101 if ( name_value[0].trimmed() == "title" ) title = name_value[1].trimmed();
102 if ( name_value[0].trimmed() == "section" ) section = name_value[1].trimmed();
103 if ( name_value[0].trimmed() == "binary" ) binary = name_value[1].trimmed();
104 if ( name_value[0].trimmed() == "files" ) {
105 QStringList file_list = name_value[1].split( "," );
106 foreach( QString file, file_list ) {
107 files.push_back( file.trimmed() );
112 for ( int i = 0; i < files.size(); i++ ) {
113 FileTemplate file_template( ":/resources/solvers/" + section + "/" + files[i], section );
114 QFileInfo fileinfo_destination( getFileName() + "/" + files[i] );
115 QDir destination_dir = fileinfo_destination.dir();
116 QString destination = destination_dir.absolutePath() + "/" + fileinfo_destination.completeBaseName();
117 if ( !destination_dir.mkpath( destination_dir.absolutePath() ) ) {
118 EG_ERR_RETURN( "ERROR: Could not create directory \n" + destination_dir.absolutePath() );
120 qDebug() << "Writing to " << destination;
121 file_template.exportToOpenFOAM( destination );
125 void OpenFOAMcase::createBoundaryFaces()
127 QVector<int> owner( grid->GetNumberOfCells() );
129 readFile( "constant/polyMesh/owner" );
130 QTextStream f( getBuffer() );
131 int num_faces;
132 f >> num_faces;
133 for ( int i = 0; i < num_faces; ++i ) {
134 int o;
135 f >> o;
136 if ( i >= getFirstBoundaryFace() ) {
137 owner[i - getFirstBoundaryFace()] = o;
141 EG_VTKDCC( vtkIntArray, bc, grid, "cell_code" );
142 m_Faces.resize( grid->GetNumberOfCells() );
143 for ( vtkIdType id_cell = 0; id_cell < grid->GetNumberOfCells(); ++id_cell ) {
144 face_t F;
145 vtkIdType N_pts, *pts;
146 grid->GetCellPoints( id_cell, N_pts, pts );
147 F.node.resize( N_pts );
148 for ( int i = 0; i < N_pts; ++i ) {
149 F.node[i] = surfToVol( pts[i] );
151 F.owner = owner[id_cell];
152 F.bc = bc->GetValue( id_cell );
153 F.neighbour = -1;
154 m_Faces[id_cell] = F;
156 qSort( m_Faces );
159 void OpenFOAMcase::rewriteBoundaryFaces()
161 setCaseDir( getFileName() );
162 buildMaps();
163 QVector<QVector<int> > faces( getFirstBoundaryFace() );
165 readFile( "constant/polyMesh/faces" );
166 QTextStream f( getBuffer() );
167 int num_faces;
168 f >> num_faces;
169 if ( grid->GetNumberOfCells() + getFirstBoundaryFace() != num_faces ) {
170 EG_ERR_RETURN( "Current surface mesh does not match the OpenFOAM case." );
172 for ( int i = 0; i < getFirstBoundaryFace(); ++i ) {
173 int num_nodes;
174 f >> num_nodes;
175 faces[i].resize( num_nodes );
176 for ( int j = 0; j < num_nodes; ++j ) {
177 f >> faces[i][j];
182 QString file_name = getFileName() + "/constant/polyMesh/faces";
183 QFile file( file_name );
184 file.open( QIODevice::WriteOnly );
185 QTextStream f( &file );
186 f << "/*--------------------------------*- C++ -*----------------------------------*\\\n";
187 f << "| ========= | |\n";
188 f << "| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |\n";
189 f << "| \\ / O peration | Version: 1.5 |\n";
190 f << "| \\ / A nd | Web: http://www.OpenFOAM.org |\n";
191 f << "| \\/ M anipulation | |\n";
192 f << "\\*---------------------------------------------------------------------------*/\n\n";
193 f << "FoamFile\n";
194 f << "{\n";
195 f << " version 2.0;\n";
196 f << " format ascii;\n";
197 f << " class faceList;\n";
198 f << " location \"constant/polyMesh\";\n";
199 f << " object faces;\n";
200 f << "}\n\n";
201 f << "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n\n";
202 f << faces.size() + grid->GetNumberOfCells() << "\n(\n";
203 for ( int i = 0; i < faces.size(); ++i ) {
204 f << faces[i].size() << "(";
205 for ( int j = 0; j < faces[i].size(); ++j ) {
206 f << faces[i][j];
207 if ( j == faces[i].size() - 1 ) {
208 f << ")\n";
210 else {
211 f << " ";
215 createBoundaryFaces();
216 foreach( face_t F, m_Faces ) {
217 f << F.node.size() << "(";
218 for ( int i = 0; i < F.node.size(); ++i ) {
219 f << F.node[i];
220 if ( i == F.node.size() - 1 ) {
221 f << ")\n";
223 else {
224 f << " ";
228 f << ")\n\n";
229 f << "// ************************************************************************* //\n\n\n";
232 readFile( "constant/polyMesh/owner" );
233 QTextStream f_in( getBuffer() );
234 QString file_name = getFileName() + "/constant/polyMesh/owner";
235 QFile file( file_name );
236 file.open( QIODevice::WriteOnly );
237 QTextStream f_out( &file );
238 int num_faces;
239 f_in >> num_faces;
240 f_out << "/*--------------------------------*- C++ -*----------------------------------*\\\n";
241 f_out << "| ========= | |\n";
242 f_out << "| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |\n";
243 f_out << "| \\ / O peration | Version: 1.5 |\n";
244 f_out << "| \\ / A nd | Web: http://www.OpenFOAM.org |\n";
245 f_out << "| \\/ M anipulation | |\n";
246 f_out << "\\*---------------------------------------------------------------------------*/\n\n";
247 f_out << "FoamFile\n";
248 f_out << "{\n";
249 f_out << " version 2.0;\n";
250 f_out << " format ascii;\n";
251 f_out << " class labelList;\n";
252 f_out << " location \"constant/polyMesh\";\n";
253 f_out << " object owner;\n";
254 f_out << "}\n\n";
255 f_out << "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n\n";
256 f_out << num_faces << "\n(\n";
257 for ( int i = 0; i < getFirstBoundaryFace(); ++i ) {
258 int owner;
259 f_in >> owner;
260 f_out << owner << "\n";
262 foreach( face_t F, m_Faces ) {
263 f_out << F.owner << "\n";
265 f_out << ")\n\n";
266 f_out << "// ************************************************************************* //\n\n\n";
268 m_Path = getFileName() + "/constant/polyMesh/";
269 writeBoundary( getFirstBoundaryFace() );
272 void OpenFOAMcase::upateVarFile(QString file_name, QString bc_txt)
274 QFile file(getFileName() + "/0/" + file_name);
275 if (file.exists()) {
276 QString buffer;
278 file.open(QIODevice::ReadOnly);
279 QTextStream f(&file);
280 buffer = f.readAll();
281 file.close();
283 buffer = buffer.replace("$$$", bc_txt);
285 file.open(QIODevice::WriteOnly);
286 QTextStream f(&file);
287 f << buffer << "\n";
288 file.close();
293 void OpenFOAMcase::writeBoundaryConditions()
295 QSet<int> bcs;
296 EG_VTKDCC(vtkIntArray, cell_code, grid, "cell_code");
297 GuiMainWindow::pointer()->getAllBoundaryCodes(bcs);
298 QString U_buffer = "";
299 QString p_buffer = "";
300 QString T_buffer = "";
301 QString k_buffer = "";
302 QString epsilon_buffer = "";
303 QString omega_buffer = "";
304 foreach (int bc, bcs) {
305 BoundaryCondition BC = GuiMainWindow::pointer()->getBC(bc);
306 if (!GuiMainWindow::pointer()->physicalTypeDefined(BC.getType())) {
307 QString msg;
308 msg.setNum(bc);
309 msg = "boundary code " + msg + " has not been properly defined";
310 EG_ERR_RETURN(msg);
312 vec3_t n(0,0,0);
313 for (vtkIdType id_cell = 0; id_cell < grid->GetNumberOfCells(); ++id_cell) {
314 if (isSurface(id_cell, grid)) {
315 if (cell_code->GetValue(id_cell) == bc) {
316 n += GeometryTools::cellNormal(grid, id_cell);
320 n.normalise();
321 n *= -1;
322 PhysicalBoundaryCondition PBC = GuiMainWindow::pointer()->getPhysicalBoundaryCondition(BC.getType());
323 U_buffer += " " + BC.getName() + "\n {\n" + PBC.getFoamU(n) + " }\n";
324 p_buffer += " " + BC.getName() + "\n {\n" + PBC.getFoamP() + " }\n";
325 T_buffer += " " + BC.getName() + "\n {\n" + PBC.getFoamT() + " }\n";
326 k_buffer += " " + BC.getName() + "\n {\n" + PBC.getFoamK() + " }\n";
327 epsilon_buffer += " " + BC.getName() + "\n {\n" + PBC.getFoamEpsilon() + " }\n";
328 omega_buffer += " " + BC.getName() + "\n {\n" + PBC.getFoamOmega() + " }\n";
330 upateVarFile("U", U_buffer);
331 upateVarFile("p", p_buffer);
332 upateVarFile("T", T_buffer);
333 upateVarFile("k", k_buffer);
334 upateVarFile("epsilon", epsilon_buffer);
335 upateVarFile("omega", omega_buffer);
338 void OpenFOAMcase::operate()
340 try {
341 if ( getFileName() == "" ) {
342 readOutputDirectory();
344 if (isValid()) {
345 writeSolverParameters();
346 bool has_volume = false;
347 for (vtkIdType id_cell = 0; id_cell < grid->GetNumberOfCells(); ++id_cell) {
348 if (isVolume(id_cell, grid)) {
349 has_volume = true;
352 if (has_volume) {
353 SimpleFoamWriter::operateOnGivenFileName();
354 } else {
355 rewriteBoundaryFaces();
357 writeBoundaryConditions();
360 catch ( Error err ) {
361 err.display();