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 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
21 #include "solvertools.h"
23 #include "guimainwindow.h"
27 #include <QFileDialog>
28 #include <QInputDialog>
35 SolverTools::SolverTools(QObject
*parent
) : QObject(parent
) {
36 m_SolverProcess
= new QProcess(this);
37 m_ToolsProcess
= new QProcess(this);
39 // connect(m_SolverProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(errorHandler(QProcess::ProcessError)));
40 connect(m_SolverProcess
, SIGNAL(finished(int, QProcess::ExitStatus
)), this, SLOT(finishedHandler_Solver(int, QProcess::ExitStatus
)));
41 connect(m_SolverProcess
, SIGNAL(readyReadStandardError()), this, SLOT(readFromStderr_Solver()));
42 connect(m_SolverProcess
, SIGNAL(readyReadStandardOutput()), this, SLOT(readFromStdout_Solver()));
43 // connect(m_SolverProcess, SIGNAL(started()), this, SLOT(startedHandler_Solver()));
44 // connect(m_SolverProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(stateChangedHandler(QProcess::ProcessState)));
46 connect(m_ToolsProcess
, SIGNAL(finished(int, QProcess::ExitStatus
)), this, SLOT(finishedHandler_Tools(int, QProcess::ExitStatus
)));
47 connect(m_ToolsProcess
, SIGNAL(readyReadStandardError()), this, SLOT(readFromStderr_Tools()));
48 connect(m_ToolsProcess
, SIGNAL(readyReadStandardOutput()), this, SLOT(readFromStdout_Tools()));
49 // connect(m_ToolsProcess, SIGNAL(started()), this, SLOT(startedHandler_Tools()));
52 m_WorkingDirectory
= "";
53 m_HostFile
= "hostfile.txt";
57 QSettings
*settings
= GuiMainWindow::pointer()->settings();
58 m_SolverBinPath
= getenv("HOME");
59 m_SolverBinPath
+= "/OpenFOAM/OpenFOAM-1.5";
60 getSet("General", "OpenFOAM path", m_SolverBinPath
, m_SolverBinPath
, 2);
61 m_OpenFoamArch
= "linux64GccDPOpt";
62 getSet("General", "OpenFOAM architecture", m_OpenFoamArch
, m_OpenFoamArch
);
64 m_ParaviewPath
= "paraview";
65 getSet("General", "Paraview path", m_ParaviewPath
, m_ParaviewPath
, 1);
67 m_Program_Solver
= "";
68 m_Arguments_Solver
.clear();
70 m_Arguments_Tools
.clear();
72 m_FullCommand_Tools
= "";
73 m_FullCommand_Solver
= "";
76 SolverTools::~SolverTools() {
77 this->stopSolverProcess();
80 int SolverTools::getArguments()
82 qDebug() << "int OpenFOAMTools::getArguments() called.";
84 // resest command-line
85 m_Program_Solver
= "";
86 m_Arguments_Solver
.clear();
89 int solver_type
= GuiMainWindow::pointer()->getXmlSection("solver/general/solver_type").toInt();
91 QFileInfo solvers_fileinfo
;
92 solvers_fileinfo
.setFile(":/resources/solvers/solvers.txt");
93 QFile
file(solvers_fileinfo
.filePath());
95 qDebug() << "ERROR: " << solvers_fileinfo
.filePath() << " not found.";
99 if (!file
.open(QIODevice::ReadOnly
| QIODevice::Text
)) {
100 qDebug() << "ERROR: Failed to open file " << solvers_fileinfo
.filePath();
104 QTextStream
text_stream(&file
);
105 QString intext
= text_stream
.readAll();
108 QStringList page_list
= intext
.split("=");
109 QString page
= page_list
[solver_type
];
113 QVector
<QString
> files
;
114 QStringList variable_list
= page
.split(";");
115 foreach(QString variable
, variable_list
) {
116 QStringList name_value
= variable
.split(":");
117 if (name_value
[0].trimmed() == "title") title
= name_value
[1].trimmed();
118 if (name_value
[0].trimmed() == "section") section
= name_value
[1].trimmed();
119 if (name_value
[0].trimmed() == "binary") binary
= name_value
[1].trimmed();
120 if (name_value
[0].trimmed() == "files") {
121 QStringList file_list
= name_value
[1].split(",");
122 foreach(QString file
, file_list
) {
123 files
.push_back(file
.trimmed());
128 m_SolverBinary
= m_SolverBinPath
+ "/applications/bin/" + m_OpenFoamArch
+ "/" + binary
;
129 m_StrippedSolverBinary
= binary
;
131 m_WorkingDirectory
= GuiMainWindow::pointer()->getXmlSection("openfoam/CaseDir");
132 if (m_WorkingDirectory
.isEmpty()) {
133 m_WorkingDirectory
= QFileDialog::getExistingDirectory(NULL
, "select case directory", GuiMainWindow::getCwd());
134 if (!m_WorkingDirectory
.isNull()) {
135 GuiMainWindow::setCwd(QFileInfo(m_WorkingDirectory
).absolutePath());
140 setCaseDir(m_WorkingDirectory
);
142 // set working directory of the process
143 m_SolverProcess
->setWorkingDirectory(m_WorkingDirectory
);
144 m_ToolsProcess
->setWorkingDirectory(m_WorkingDirectory
);
146 qDebug() << "getArguments DONE";
151 //=====================================
153 //=====================================
155 void SolverTools::runSolver()
157 if (m_SolverProcess
->state() == QProcess::NotRunning
) {
158 if (getArguments() < 0) {
159 qDebug() << "Failed to run Solver.";
165 QFile
file(m_WorkingDirectory
+ "/system/decomposeParDict");
166 file
.open(QIODevice::ReadOnly
);
167 QTextStream
f(&file
);
169 QString line
= f
.readLine();
170 line
= line
.replace(";","");
171 QStringList words
= line
.split(" ");
172 if (words
.size() >= 2) {
173 if (words
[0].trimmed() == "numberOfSubdomains") {
174 num_cpus
= words
[1].toInt();
175 if (num_cpus
== 0 && num_cpus
> 1000) {
185 m_Program_Solver
= m_SolverBinary
;
186 m_Arguments_Solver
<< "-case" << m_WorkingDirectory
;
189 if (m_SolverProcess
->waitForFinished() && m_SolverProcess
->exitCode() == 0) {
190 QString num_cpus_str
;
191 num_cpus_str
.setNum(num_cpus
);
192 m_Arguments_Solver
.clear();
193 m_Program_Solver
= "mpirun";
194 m_Arguments_Solver
<< "--hostfile" << "machines" << "-np" << num_cpus_str
<< m_SolverBinary
<< "-case" << m_WorkingDirectory
<< "-parallel";
196 qDebug() << "ERROR: decomposePar failed.";
200 m_SolverProcess
->start(m_Program_Solver
, m_Arguments_Solver
);
201 if (m_SolverProcess
->waitForStarted()) {
202 startedHandler_Tools();
205 QMessageBox::information(NULL
, "runSolver error", "Can't run a new solver process, while another is still running.\nCurrent solver process:\n" + m_FullCommand_Solver
);
210 void SolverTools::runTool(QString path
, QString name
, QStringList args
)
212 if (m_ToolsProcess
->state() == QProcess::NotRunning
) {
213 args
<< "-case" << m_WorkingDirectory
;
214 m_Arguments_Tools
= args
;
215 m_Program_Tools
= m_SolverBinPath
+ "/" + path
+ "/" + m_OpenFoamArch
+ "/" + name
;
217 m_ToolsProcess
->start(m_Program_Tools
, m_Arguments_Tools
);
218 if (m_ToolsProcess
->waitForStarted()) {
219 startedHandler_Tools();
220 m_ToolsProcess
->waitForFinished();
222 qDebug() << "failed to start: m_Program_Tools=" << m_Program_Tools
<< " m_Arguments_Tools=" << m_Arguments_Tools
;
223 qDebug() << m_Program_Tools
<< " not found";
226 QMessageBox::information(NULL
, "runTool error", "Can't run a new tool process, while another is still running.\nCurrent tool process:\n" + m_FullCommand_Tools
);
230 void SolverTools::runDecomposePar()
232 if (getArguments() < 0) {
233 qDebug() << "Failed to run DecomposePar.";
236 this->stopSolverProcess();
237 m_Program_Solver
= getBinary("decomposePar");
238 m_Arguments_Solver
<< "-force";
239 m_SolverProcess
->start(m_Program_Solver
, m_Arguments_Solver
);
240 if (m_SolverProcess
->waitForStarted()) {
241 startedHandler_Tools();
243 qDebug() << "decomposePar failed to start.";
247 void SolverTools::runPostProcessingTools()
249 qDebug() << "void OpenFOAMTools::runPostProcessingTools() called";
250 if (getArguments() < 0) {
251 qDebug() << "Failed to run PostProcessingTools";
255 args
<< "-latestTime";
256 qDebug() << "+++++++++++++++++++++++++++++++++++++++";
257 runTool("applications/bin", "reconstructPar", args
);
258 qDebug() << "+++++++++++++++++++++++++++++++++++++++";
259 runTool("applications/bin", "foamToVTK", args
);
260 qDebug() << "+++++++++++++++++++++++++++++++++++++++";
262 qDebug() << "void OpenFOAMTools::runPostProcessingTools() DONE";
265 void SolverTools::runParaview()
268 m_ToolsProcess
->start(m_ParaviewPath
, args
);
270 m_ToolsProcess
->waitForFinished(500);
271 if (m_SolverProcess
->state() == QProcess::NotRunning
) {
272 cout
<< m_ToolsProcess
->readAllStandardOutput().data();
275 QApplication::processEvents();
276 } while (m_ToolsProcess
->state() == QProcess::Running
);
277 if (m_SolverProcess
->state() == QProcess::NotRunning
) {
278 cout
<< m_ToolsProcess
->readAllStandardOutput().data();
283 void SolverTools::stopSolverProcess()
285 if (m_SolverProcess
->state() == QProcess::Running
) {
286 m_SolverProcess
->kill();
290 void SolverTools::runImportFluentCase()
292 QString fluent_file_name
= QFileDialog::getOpenFileName(NULL
, "import FLUENT case", GuiMainWindow::pointer()->getCwd(), "*.msh");
293 if (!fluent_file_name
.isNull()) {
294 QString foam_case_dir
= QFileDialog::getExistingDirectory(NULL
, "select OpenFOAM case directory", GuiMainWindow::getCwd());
295 if (!foam_case_dir
.isNull()) {
296 QString p1
= foam_case_dir
;
297 QString p2
= p1
+ "/system";
302 items
<< tr("millimetres") << tr("centimetres") << tr("metres") << tr("inches");
304 QString scale_txt
= QInputDialog::getItem(NULL
, tr("Select scale"), tr("scale:"), items
, 0, false, &ok
);
305 if (ok
&& !scale_txt
.isEmpty()) {
311 args
<< fluent_file_name
;
313 if (scale_txt
== "millimetres") {
315 } else if (scale_txt
== "centimetres") {
317 } else if (scale_txt
== "metres") {
319 } else if (scale_txt
== "inches") {
324 m_WorkingDirectory
= foam_case_dir
;
325 QFile
file(m_WorkingDirectory
+ "/system/controlDict");
326 if (!file
.open(QIODevice::WriteOnly
| QIODevice::Text
)) {
328 EG_ERR_RETURN("ERROR: Failed to open file " + foam_case_dir
+ "/system/controlDict");
329 } catch (Error err
) {
333 QTextStream
f(&file
);
334 f
<< "/*--------------------------------*- C++ -*----------------------------------*\\\n";
335 f
<< "| ========= | |\n";
336 f
<< "| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |\n";
337 f
<< "| \\ / O peration | Version: 1.5 |\n";
338 f
<< "| \\ / A nd | Web: http://www.OpenFOAM.org |\n";
339 f
<< "| \\/ M anipulation | |\n";
340 f
<< "\\*---------------------------------------------------------------------------*/\n";
343 f
<< " version 2.0;\n";
344 f
<< " format ascii;\n";
345 f
<< " class dictionary;\n";
346 f
<< " object controlDict;\n";
348 f
<< "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n";
350 f
<< "application simpleFoam;\n";
352 f
<< "startFrom startTime;\n";
353 f
<< "startTime 0;\n";
354 f
<< "stopAt endTime;\n";
355 f
<< "endTime 1000;\n";
357 f
<< "writeControl timeStep;\n";
358 f
<< "writeInterval 100;\n";
359 f
<< "purgeWrite 0;\n";
360 f
<< "writeFormat ascii;\n";
361 f
<< "writePrecision 6;\n";
362 f
<< "writeCompression uncompressed;\n";
363 f
<< "timeFormat general;\n";
364 f
<< "timePrecision 6;\n";
365 f
<< "runTimeModifiable yes;\n";
367 runTool("applications/bin", "fluentMeshToFoam", args
);
374 //=====================================
376 //=====================================
378 void SolverTools::finishedHandler_Solver(int exitCode
, QProcess::ExitStatus exitStatus
)
380 qDebug() << "=== solver-process finished with exit-code = " << exitCode
<< " ===";
381 if (exitStatus
== QProcess::NormalExit
) {
382 qDebug() << "QProcess exited normally.";
384 qDebug() << "QProcess crashed.";
388 void SolverTools::readFromStderr_Solver()
390 cout
<< m_SolverProcess
->readAllStandardError().data();
394 void SolverTools::readFromStdout_Solver()
396 cout
<< m_SolverProcess
->readAllStandardOutput().data();
400 void SolverTools::startedHandler_Solver()
402 qDebug() << "=== started solver-process with PID = " << m_SolverProcess
->pid() << "===";
403 m_FullCommand_Solver
= m_Program_Solver
;
404 foreach(QString arg
, m_Arguments_Solver
) {
405 m_FullCommand_Solver
+= " " + arg
;
407 cout
<< "[" << qPrintable(m_WorkingDirectory
) << "]$ " << qPrintable(m_FullCommand_Solver
) << endl
;
410 //=====================================
412 //=====================================
414 void SolverTools::finishedHandler_Tools(int exitCode
, QProcess::ExitStatus exitStatus
)
416 qDebug() << "=== solver-process finished with exit-code = " << exitCode
<< " ===";
417 if (exitStatus
== QProcess::NormalExit
) {
418 qDebug() << "QProcess exited normally.";
420 qDebug() << "QProcess crashed.";
424 void SolverTools::readFromStderr_Tools()
426 cout
<< m_ToolsProcess
->readAllStandardError().data();
430 void SolverTools::readFromStdout_Tools()
432 cout
<< m_ToolsProcess
->readAllStandardOutput().data();
436 void SolverTools::startedHandler_Tools()
438 qDebug() << "=== started tools-process with PID = " << m_ToolsProcess
->pid() << "===";
439 m_FullCommand_Tools
= m_Program_Tools
;
440 foreach(QString arg
, m_Arguments_Tools
) {
441 m_FullCommand_Tools
+= " " + arg
;
443 cout
<< "[" << qPrintable(m_WorkingDirectory
) << "]$ " << qPrintable(m_FullCommand_Tools
) << endl
;
446 void SolverTools::setCaseDirectory()
448 qDebug() << "void OpenFOAMTools::setCaseDirectory()";
449 m_WorkingDirectory
= QFileDialog::getExistingDirectory(NULL
, "select case directory", GuiMainWindow::getCwd());
450 if (!m_WorkingDirectory
.isNull()) {
451 GuiMainWindow::setCwd(QFileInfo(m_WorkingDirectory
).absolutePath());
452 setCaseDir(m_WorkingDirectory
);