added sphere tutorial
[engrid.git] / src / openfoamtools.cpp
blob038894491816f9f962d6722e0e440d85573542c1
1 //
2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + +
4 // + This file is part of enGrid. +
5 // + +
6 // + Copyright 2008-2010 enGits GmbH +
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 "openfoamtools.h"
25 #include "guimainwindow.h"
27 #include <QtDebug>
28 #include <QFileInfo>
29 #include <QFileDialog>
30 #include <QInputDialog>
32 #include <iostream>
33 #include <cstdlib>
35 using namespace std;
37 OpenFOAMTools::OpenFOAMTools(QObject *parent) : QObject(parent) {
38 m_SolverProcess = new QProcess(this);
39 m_ToolsProcess = new QProcess(this);
41 // connect(m_SolverProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(errorHandler(QProcess::ProcessError)));
42 connect(m_SolverProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finishedHandler_Solver(int, QProcess::ExitStatus)));
43 connect(m_SolverProcess, SIGNAL(readyReadStandardError()), this, SLOT(readFromStderr_Solver()));
44 connect(m_SolverProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readFromStdout_Solver()));
45 // connect(m_SolverProcess, SIGNAL(started()), this, SLOT(startedHandler_Solver()));
46 // connect(m_SolverProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(stateChangedHandler(QProcess::ProcessState)));
48 connect(m_ToolsProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finishedHandler_Tools(int, QProcess::ExitStatus)));
49 connect(m_ToolsProcess, SIGNAL(readyReadStandardError()), this, SLOT(readFromStderr_Tools()));
50 connect(m_ToolsProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readFromStdout_Tools()));
51 // connect(m_ToolsProcess, SIGNAL(started()), this, SLOT(startedHandler_Tools()));
53 m_SolverBinary = "";
54 m_WorkingDirectory = "";
55 m_HostFile = "hostfile.txt";
56 m_NumProcesses = 1;
57 m_MainHost = "";
59 QSettings *settings = GuiMainWindow::pointer()->settings();
60 m_OpenFoamPath = getenv("HOME");
61 m_OpenFoamPath += "/OpenFOAM/OpenFOAM-1.5";
62 getSet("General", "OpenFOAM path", m_OpenFoamPath, m_OpenFoamPath, 2);
63 m_OpenFoamArch = "linux64GccDPOpt";
64 getSet("General", "OpenFOAM architecture", m_OpenFoamArch, m_OpenFoamArch);
66 m_ParaviewPath = "paraview";
67 getSet("General", "Paraview path", m_ParaviewPath, m_ParaviewPath, 1);
69 m_Program_Solver = "";
70 m_Arguments_Solver.clear();
71 m_Program_Tools = "";
72 m_Arguments_Tools.clear();
74 m_FullCommand_Tools = "";
75 m_FullCommand_Solver = "";
78 OpenFOAMTools::~OpenFOAMTools() {
79 this->stopSolverProcess();
82 void OpenFOAMTools::writeMpiParameters() {
83 QString hostfile_text = GuiMainWindow::pointer()->getXmlSection("solver/general/host_weight_list");
85 QVector <QString> host;
86 QVector <QString> weight;
88 QStringList host_weight_list = hostfile_text.split(",");
89 foreach(QString host_weight, host_weight_list) {
90 if (!host_weight.isEmpty()) {
91 QStringList values = host_weight.split(":");
92 qWarning() << "values=" << values;
93 host.push_back(values[0].trimmed());
94 weight.push_back(values[1].trimmed());
98 if (host.size() >= 1) {
99 // create the hostfile
100 QFileInfo fileinfo(m_WorkingDirectory + "/" + m_HostFile);
101 QFile hostfile(fileinfo.filePath());
102 if (!hostfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
103 try {
104 EG_ERR_RETURN("ERROR: Failed to open file " + fileinfo.filePath());
105 } catch (Error err) {
106 err.display();
109 QTextStream out(&hostfile);
110 for (int i = 0; i < host.size(); i++) {
111 out << host[i] << endl;
113 hostfile.close();
115 // create the decomposeParDict file
116 QFileInfo fileinfo_decomposeParDict(m_WorkingDirectory + "/system/decomposeParDict");
117 QFile decomposeParDict(fileinfo_decomposeParDict.filePath());
118 if (!decomposeParDict.open(QIODevice::WriteOnly | QIODevice::Text)) {
119 try {
120 EG_ERR_RETURN("ERROR: Failed to open file " + fileinfo_decomposeParDict.filePath());
121 } catch (Error err) {
122 err.display();
125 QTextStream out_decomposeParDict(&decomposeParDict);
126 out_decomposeParDict << "/*--------------------------------*- C++ -*----------------------------------*\\" << endl;
127 out_decomposeParDict << "| ========= | |" << endl;
128 out_decomposeParDict << "| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |" << endl;
129 out_decomposeParDict << "| \\ / O peration | Version: 1.5 |" << endl;
130 out_decomposeParDict << "| \\ / A nd | Web: http://www.OpenFOAM.org |" << endl;
131 out_decomposeParDict << "| \\/ M anipulation | |" << endl;
132 out_decomposeParDict << "\\*---------------------------------------------------------------------------*/" << endl;
133 out_decomposeParDict << "FoamFile" << endl;
134 out_decomposeParDict << "{" << endl;
135 out_decomposeParDict << " version 2.0;" << endl;
136 out_decomposeParDict << " format ascii;" << endl;
137 out_decomposeParDict << " class dictionary;" << endl;
138 out_decomposeParDict << " object decomposeParDict;" << endl;
139 out_decomposeParDict << "}" << endl;
140 out_decomposeParDict << "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //" << endl;
141 out_decomposeParDict << "" << endl;
142 out_decomposeParDict << "numberOfSubdomains " << weight.size() << ";" << endl;
143 out_decomposeParDict << "" << endl;
144 out_decomposeParDict << "method metis;" << endl;
145 out_decomposeParDict << "" << endl;
146 out_decomposeParDict << "metisCoeffs" << endl;
147 out_decomposeParDict << "{" << endl;
148 out_decomposeParDict << " processorWeights " << endl;
149 out_decomposeParDict << " (" << endl;
150 for (int i = 0; i < weight.size(); i++) {
151 out_decomposeParDict << " " << weight[i] << "" << endl;
153 out_decomposeParDict << " );" << endl;
154 out_decomposeParDict << "}" << endl;
155 out_decomposeParDict << "" << endl;
156 out_decomposeParDict << "distributed no;" << endl;
157 out_decomposeParDict << "" << endl;
158 out_decomposeParDict << "roots " << endl;
159 out_decomposeParDict << "(" << endl;
160 out_decomposeParDict << ");" << endl;
161 out_decomposeParDict << "" << endl;
162 out_decomposeParDict << "// ************************************************************************* //" << endl;
163 out_decomposeParDict << "" << endl;
164 decomposeParDict.close();
166 m_NumProcesses = weight.size();
167 m_MainHost = host[0];
168 } else {
169 m_NumProcesses = 1;
170 m_MainHost = "";
174 int OpenFOAMTools::getArguments() {
175 qDebug() << "int OpenFOAMTools::getArguments() called.";
177 // resest command-line
178 m_Program_Solver = "";
179 m_Arguments_Solver.clear();
181 // get binary name
182 int solver_type = GuiMainWindow::pointer()->getXmlSection("solver/general/solver_type").toInt();
184 QFileInfo solvers_fileinfo;
185 solvers_fileinfo.setFile(":/resources/solvers/solvers.txt");
186 QFile file(solvers_fileinfo.filePath());
187 if (!file.exists()) {
188 qDebug() << "ERROR: " << solvers_fileinfo.filePath() << " not found.";
189 EG_BUG;
190 return(-1);
192 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
193 qDebug() << "ERROR: Failed to open file " << solvers_fileinfo.filePath();
194 EG_BUG;
195 return(-1);
197 QTextStream text_stream(&file);
198 QString intext = text_stream.readAll();
199 file.close();
201 QStringList page_list = intext.split("=");
202 QString page = page_list[solver_type];
203 QString title;
204 QString section;
205 QString binary;
206 QVector <QString> files;
207 QStringList variable_list = page.split(";");
208 foreach(QString variable, variable_list) {
209 QStringList name_value = variable.split(":");
210 if (name_value[0].trimmed() == "title") title = name_value[1].trimmed();
211 if (name_value[0].trimmed() == "section") section = name_value[1].trimmed();
212 if (name_value[0].trimmed() == "binary") binary = name_value[1].trimmed();
213 if (name_value[0].trimmed() == "files") {
214 QStringList file_list = name_value[1].split(",");
215 foreach(QString file, file_list) {
216 files.push_back(file.trimmed());
221 m_SolverBinary = m_OpenFoamPath + "/applications/bin/" + m_OpenFoamArch + "/" + binary;
222 m_StrippedSolverBinary = binary;
224 m_WorkingDirectory = GuiMainWindow::pointer()->getXmlSection("openfoam/CaseDir");
225 if (m_WorkingDirectory.isEmpty()) {
226 m_WorkingDirectory = QFileDialog::getExistingDirectory(NULL, "select case directory", GuiMainWindow::getCwd());
227 if (!m_WorkingDirectory.isNull()) {
228 GuiMainWindow::setCwd(QFileInfo(m_WorkingDirectory).absolutePath());
229 } else {
230 return(-1);
233 setCaseDir(m_WorkingDirectory);
234 // create hostfile + decomposeParDict + get necessary parameters
235 writeMpiParameters();
237 // set working directory of the process
238 m_SolverProcess->setWorkingDirectory(m_WorkingDirectory);
239 m_ToolsProcess->setWorkingDirectory(m_WorkingDirectory);
241 qDebug() << "getArguments DONE";
243 return(0);
246 //=====================================
247 // Main slots
248 //=====================================
250 void OpenFOAMTools::runFOO(QString path, QString name, QStringList args) {
251 qDebug() << "=== runFOO called ===";
252 if (m_ToolsProcess->state() == QProcess::NotRunning) {
253 args << "-case" << m_WorkingDirectory;
254 m_Arguments_Tools = args;
255 m_Program_Tools = m_OpenFoamPath + "/" + path + "/" + m_OpenFoamArch + "/" + name;
257 // m_ToolsProcess->start( m_Program_Tools, m_Arguments_Tools);
258 QStringList foo;
259 foo << "/foo";
260 // this->stopSolverProcess();
262 m_ToolsProcess->start("ls", foo);
263 if (m_ToolsProcess->waitForStarted()) {
264 startedHandler_Tools();
265 if (m_ToolsProcess->waitForFinished()) {
266 // finishedHandler_Tools();
269 } else {
270 QMessageBox::information(NULL, "runTool error", "Can't run a new tool process, while another is still running.\nCurrent tool process:\n" + m_FullCommand_Tools);
274 void OpenFOAMTools::runSolver() {
275 if (m_SolverProcess->state() == QProcess::NotRunning) {
276 if (getArguments() < 0) {
277 qDebug() << "Failed to run Solver.";
278 return;
280 if (m_NumProcesses <= 1) {
281 if (m_MainHost.isEmpty()) {
282 m_Program_Solver = m_SolverBinary;
283 m_Arguments_Solver << "-case" << m_WorkingDirectory;
284 } else {
285 m_Program_Solver = "ssh";
286 m_Arguments_Solver << m_MainHost << m_SolverBinary << "-case" << m_WorkingDirectory;
288 } else {
289 runDecomposePar();
290 if (m_SolverProcess->waitForFinished() && m_SolverProcess->exitCode() == 0) {
291 QString numprocesses_str;
292 numprocesses_str.setNum(m_NumProcesses);
293 m_Arguments_Solver.clear();
294 //m_Program_Solver = "mpirun";
295 //m_Arguments_Solver << "--hostfile" << m_HostFile << "-np" << numprocesses_str << m_SolverBinary << "-case" << m_WorkingDirectory << "-parallel";
296 m_Program_Solver = "ssh";
297 m_Arguments_Solver << m_MainHost << "mpirun";
298 m_Arguments_Solver << "--hostfile" << m_WorkingDirectory + "/" + m_HostFile;
299 m_Arguments_Solver << "-np" << numprocesses_str << m_SolverBinary << "-case" << m_WorkingDirectory << "-parallel";
300 } else {
301 qDebug() << "ERROR: decomposePar failed.";
302 return;
305 m_SolverProcess->start(m_Program_Solver, m_Arguments_Solver);
306 if (m_SolverProcess->waitForStarted()) {
307 startedHandler_Tools();
309 } else {
310 QMessageBox::information(NULL, "runSolver error", "Can't run a new solver process, while another is still running.\nCurrent solver process:\n" + m_FullCommand_Solver);
315 void OpenFOAMTools::runTool(QString path, QString name, QStringList args) {
316 // qDebug()<<"=== runTool("<<path<<", "<<name<<", "<<args<<") called ===";
317 if (m_ToolsProcess->state() == QProcess::NotRunning) {
318 args << "-case" << m_WorkingDirectory;
319 m_Arguments_Tools = args;
320 m_Program_Tools = m_OpenFoamPath + "/" + path + "/" + m_OpenFoamArch + "/" + name;
322 m_ToolsProcess->start(m_Program_Tools, m_Arguments_Tools);
323 if (m_ToolsProcess->waitForStarted()) {
324 startedHandler_Tools();
325 m_ToolsProcess->waitForFinished();
326 } else {
327 qDebug() << "failed to start: m_Program_Tools=" << m_Program_Tools << " m_Arguments_Tools=" << m_Arguments_Tools;
328 qDebug() << m_Program_Tools << " not found";
330 } else {
331 QMessageBox::information(NULL, "runTool error", "Can't run a new tool process, while another is still running.\nCurrent tool process:\n" + m_FullCommand_Tools);
335 void OpenFOAMTools::runDecomposePar() {
336 if (getArguments() < 0) {
337 qDebug() << "Failed to run DecomposePar.";
338 return;
340 this->stopSolverProcess();
341 m_Program_Solver = getBinary("applications/bin", "decomposePar");
342 m_Arguments_Solver << "-force";
343 m_SolverProcess->start(m_Program_Solver, m_Arguments_Solver);
344 if (m_SolverProcess->waitForStarted()) {
345 startedHandler_Tools();
346 } else {
347 qDebug() << "decomposePar failed to start.";
351 void OpenFOAMTools::runPostProcessingTools() {
352 qDebug() << "void OpenFOAMTools::runPostProcessingTools() called";
353 if (getArguments() < 0) {
354 qDebug() << "Failed to run PostProcessingTools";
355 return;
357 QStringList args;
358 args << "-latestTime";
359 // runFOO("applications/bin", "foo", args);
360 // qDebug()<<"+++ 0 ++++++++++++++++++++++++++++++++++++";
361 // runTool("applications/bin", "foo", args);
362 qDebug() << "+++++++++++++++++++++++++++++++++++++++";
363 runTool("applications/bin", "reconstructPar", args);
364 qDebug() << "+++++++++++++++++++++++++++++++++++++++";
365 runTool("applications/bin", "foamToVTK", args);
366 qDebug() << "+++++++++++++++++++++++++++++++++++++++";
368 qDebug() << "void OpenFOAMTools::runPostProcessingTools() DONE";
371 void OpenFOAMTools::runParaview() {
372 QStringList args;
373 m_ToolsProcess->start(m_ParaviewPath, args);
374 do {
375 m_ToolsProcess->waitForFinished(500);
376 if (m_SolverProcess->state() == QProcess::NotRunning) {
377 cout << m_ToolsProcess->readAllStandardOutput().data();
378 flush(cout);
380 QApplication::processEvents();
381 } while (m_ToolsProcess->state() == QProcess::Running);
382 if (m_SolverProcess->state() == QProcess::NotRunning) {
383 cout << m_ToolsProcess->readAllStandardOutput().data();
384 flush(cout);
388 void OpenFOAMTools::stopSolverProcess() {
389 if (m_SolverProcess->state() == QProcess::Running) {
390 m_SolverProcess->kill();
391 QString cmd = "ssh " + m_MainHost + " killall -9 " + m_StrippedSolverBinary;
392 system(cmd.toAscii().data());
396 void OpenFOAMTools::runImportFluentCase() {
397 QString fluent_file_name = QFileDialog::getOpenFileName(NULL, "import FLUENT case", GuiMainWindow::pointer()->getCwd(), "*.msh");
398 if (!fluent_file_name.isNull()) {
399 QString foam_case_dir = QFileDialog::getExistingDirectory(NULL, "select OpenFOAM case directory", GuiMainWindow::getCwd());
400 if (!foam_case_dir.isNull()) {
401 QString p1 = foam_case_dir;
402 QString p2 = p1 + "/system";
403 QDir d1(p1);
404 QDir d2(p2);
405 if (d1.exists()) {
406 QStringList items;
407 items << tr("millimetres") << tr("centimetres") << tr("metres") << tr("inches");
408 bool ok;
409 QString scale_txt = QInputDialog::getItem(NULL, tr("Select scale"), tr("scale:"), items, 0, false, &ok);
410 if (ok && !scale_txt.isEmpty()) {
411 if (!d2.exists()) {
412 d1.mkdir("system");
413 d2 = QDir(p2);
415 QStringList args;
416 args << fluent_file_name;
417 args << "-scale";
418 if (scale_txt == "millimetres") {
419 args << "0.001";
420 } else if (scale_txt == "centimetres") {
421 args << "0.01";
422 } else if (scale_txt == "metres") {
423 args << "1";
424 } else if (scale_txt == "inches") {
425 args << "0.0254";
426 } else {
427 args << "1";
429 m_WorkingDirectory = foam_case_dir;
430 QFile file(m_WorkingDirectory + "/system/controlDict");
431 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
432 try {
433 EG_ERR_RETURN("ERROR: Failed to open file " + foam_case_dir + "/system/controlDict");
434 } catch (Error err) {
435 err.display();
438 QTextStream f(&file);
439 f << "/*--------------------------------*- C++ -*----------------------------------*\\\n";
440 f << "| ========= | |\n";
441 f << "| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |\n";
442 f << "| \\ / O peration | Version: 1.5 |\n";
443 f << "| \\ / A nd | Web: http://www.OpenFOAM.org |\n";
444 f << "| \\/ M anipulation | |\n";
445 f << "\\*---------------------------------------------------------------------------*/\n";
446 f << "FoamFile\n";
447 f << "{\n";
448 f << " version 2.0;\n";
449 f << " format ascii;\n";
450 f << " class dictionary;\n";
451 f << " object controlDict;\n";
452 f << "}\n";
453 f << "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n";
454 f << "\n";
455 f << "application simpleFoam;\n";
456 f << "\n";
457 f << "startFrom startTime;\n";
458 f << "startTime 0;\n";
459 f << "stopAt endTime;\n";
460 f << "endTime 1000;\n";
461 f << "deltaT 1;\n";
462 f << "writeControl timeStep;\n";
463 f << "writeInterval 100;\n";
464 f << "purgeWrite 0;\n";
465 f << "writeFormat ascii;\n";
466 f << "writePrecision 6;\n";
467 f << "writeCompression uncompressed;\n";
468 f << "timeFormat general;\n";
469 f << "timePrecision 6;\n";
470 f << "runTimeModifiable yes;\n";
471 file.close();
472 runTool("applications/bin", "fluentMeshToFoam", args);
479 //=====================================
480 // Handlers Solver
481 //=====================================
483 void OpenFOAMTools::finishedHandler_Solver(int exitCode, QProcess::ExitStatus exitStatus) {
484 qDebug() << "=== solver-process finished with exit-code = " << exitCode << " ===";
485 if (exitStatus == QProcess::NormalExit) {
486 qDebug() << "QProcess exited normally.";
487 } else {
488 qDebug() << "QProcess crashed.";
492 void OpenFOAMTools::readFromStderr_Solver() {
493 cout << m_SolverProcess->readAllStandardError().data();
494 flush(cout);
497 void OpenFOAMTools::readFromStdout_Solver() {
498 cout << m_SolverProcess->readAllStandardOutput().data();
499 flush(cout);
502 void OpenFOAMTools::startedHandler_Solver() {
503 qDebug() << "=== started solver-process with PID = " << m_SolverProcess->pid() << "===";
504 m_FullCommand_Solver = m_Program_Solver;
505 foreach(QString arg, m_Arguments_Solver) {
506 m_FullCommand_Solver += " " + arg;
508 cout << "[" << qPrintable(m_WorkingDirectory) << "]$ " << qPrintable(m_FullCommand_Solver) << endl;
511 //=====================================
512 // Handlers Tools
513 //=====================================
515 void OpenFOAMTools::finishedHandler_Tools(int exitCode, QProcess::ExitStatus exitStatus) {
516 qDebug() << "=== solver-process finished with exit-code = " << exitCode << " ===";
517 if (exitStatus == QProcess::NormalExit) {
518 qDebug() << "QProcess exited normally.";
519 } else {
520 qDebug() << "QProcess crashed.";
524 void OpenFOAMTools::readFromStderr_Tools() {
525 cout << m_ToolsProcess->readAllStandardError().data();
526 flush(cout);
529 void OpenFOAMTools::readFromStdout_Tools() {
530 cout << m_ToolsProcess->readAllStandardOutput().data();
531 flush(cout);
534 void OpenFOAMTools::startedHandler_Tools() {
535 qDebug() << "=== started tools-process with PID = " << m_ToolsProcess->pid() << "===";
536 m_FullCommand_Tools = m_Program_Tools;
537 foreach(QString arg, m_Arguments_Tools) {
538 m_FullCommand_Tools += " " + arg;
540 cout << "[" << qPrintable(m_WorkingDirectory) << "]$ " << qPrintable(m_FullCommand_Tools) << endl;
543 void OpenFOAMTools::setCaseDirectory() {
544 qDebug() << "void OpenFOAMTools::setCaseDirectory()";
545 m_WorkingDirectory = QFileDialog::getExistingDirectory(NULL, "select case directory", GuiMainWindow::getCwd());
546 if (!m_WorkingDirectory.isNull()) {
547 GuiMainWindow::setCwd(QFileInfo(m_WorkingDirectory).absolutePath());
548 setCaseDir(m_WorkingDirectory);
549 } else {
550 return;