2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 // + This file is part of enGrid. +
6 // + Copyright 2008-2013 enGits GmbH +
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 "openfoamtools.h"
25 #include "guimainwindow.h"
29 #include <QFileDialog>
30 #include <QInputDialog>
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()));
54 m_WorkingDirectory
= "";
55 m_HostFile
= "hostfile.txt";
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();
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
)) {
104 EG_ERR_RETURN("ERROR: Failed to open file " + fileinfo
.filePath());
105 } catch (Error err
) {
109 QTextStream
out(&hostfile
);
110 for (int i
= 0; i
< host
.size(); i
++) {
111 out
<< host
[i
] << endl
;
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
)) {
120 EG_ERR_RETURN("ERROR: Failed to open file " + fileinfo_decomposeParDict
.filePath());
121 } catch (Error err
) {
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];
174 int OpenFOAMTools::getArguments() {
175 qDebug() << "int OpenFOAMTools::getArguments() called.";
177 // resest command-line
178 m_Program_Solver
= "";
179 m_Arguments_Solver
.clear();
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.";
192 if (!file
.open(QIODevice::ReadOnly
| QIODevice::Text
)) {
193 qDebug() << "ERROR: Failed to open file " << solvers_fileinfo
.filePath();
197 QTextStream
text_stream(&file
);
198 QString intext
= text_stream
.readAll();
201 QStringList page_list
= intext
.split("=");
202 QString page
= page_list
[solver_type
];
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());
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";
246 //=====================================
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);
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();
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.";
280 if (m_NumProcesses
<= 1) {
281 if (m_MainHost
.isEmpty()) {
282 m_Program_Solver
= m_SolverBinary
;
283 m_Arguments_Solver
<< "-case" << m_WorkingDirectory
;
285 m_Program_Solver
= "ssh";
286 m_Arguments_Solver
<< m_MainHost
<< m_SolverBinary
<< "-case" << m_WorkingDirectory
;
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";
301 qDebug() << "ERROR: decomposePar failed.";
305 m_SolverProcess
->start(m_Program_Solver
, m_Arguments_Solver
);
306 if (m_SolverProcess
->waitForStarted()) {
307 startedHandler_Tools();
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();
327 qDebug() << "failed to start: m_Program_Tools=" << m_Program_Tools
<< " m_Arguments_Tools=" << m_Arguments_Tools
;
328 qDebug() << m_Program_Tools
<< " not found";
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.";
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();
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";
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() {
373 m_ToolsProcess
->start(m_ParaviewPath
, args
);
375 m_ToolsProcess
->waitForFinished(500);
376 if (m_SolverProcess
->state() == QProcess::NotRunning
) {
377 cout
<< m_ToolsProcess
->readAllStandardOutput().data();
380 QApplication::processEvents();
381 } while (m_ToolsProcess
->state() == QProcess::Running
);
382 if (m_SolverProcess
->state() == QProcess::NotRunning
) {
383 cout
<< m_ToolsProcess
->readAllStandardOutput().data();
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";
407 items
<< tr("millimetres") << tr("centimetres") << tr("metres") << tr("inches");
409 QString scale_txt
= QInputDialog::getItem(NULL
, tr("Select scale"), tr("scale:"), items
, 0, false, &ok
);
410 if (ok
&& !scale_txt
.isEmpty()) {
416 args
<< fluent_file_name
;
418 if (scale_txt
== "millimetres") {
420 } else if (scale_txt
== "centimetres") {
422 } else if (scale_txt
== "metres") {
424 } else if (scale_txt
== "inches") {
429 m_WorkingDirectory
= foam_case_dir
;
430 QFile
file(m_WorkingDirectory
+ "/system/controlDict");
431 if (!file
.open(QIODevice::WriteOnly
| QIODevice::Text
)) {
433 EG_ERR_RETURN("ERROR: Failed to open file " + foam_case_dir
+ "/system/controlDict");
434 } catch (Error err
) {
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";
448 f
<< " version 2.0;\n";
449 f
<< " format ascii;\n";
450 f
<< " class dictionary;\n";
451 f
<< " object controlDict;\n";
453 f
<< "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n";
455 f
<< "application simpleFoam;\n";
457 f
<< "startFrom startTime;\n";
458 f
<< "startTime 0;\n";
459 f
<< "stopAt endTime;\n";
460 f
<< "endTime 1000;\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";
472 runTool("applications/bin", "fluentMeshToFoam", args
);
479 //=====================================
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.";
488 qDebug() << "QProcess crashed.";
492 void OpenFOAMTools::readFromStderr_Solver() {
493 cout
<< m_SolverProcess
->readAllStandardError().data();
497 void OpenFOAMTools::readFromStdout_Solver() {
498 cout
<< m_SolverProcess
->readAllStandardOutput().data();
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 //=====================================
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.";
520 qDebug() << "QProcess crashed.";
524 void OpenFOAMTools::readFromStderr_Tools() {
525 cout
<< m_ToolsProcess
->readAllStandardError().data();
529 void OpenFOAMTools::readFromStdout_Tools() {
530 cout
<< m_ToolsProcess
->readAllStandardOutput().data();
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
);