compiles on openSUSE 15.4 part 2
[engrid-github.git] / src / libengrid / solvertools.cpp
blob5cda434105b6c9c6d486591f42f6197de26b8b72
1 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 // + +
3 // + This file is part of enGrid. +
4 // + +
5 // + Copyright 2008-2014 enGits GmbH +
6 // + +
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. +
11 // + +
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. +
16 // + +
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/>. +
19 // + +
20 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
21 #include "solvertools.h"
23 #include "guimainwindow.h"
25 #include <QtDebug>
26 #include <QFileInfo>
27 #include <QFileDialog>
28 #include <QInputDialog>
30 #include <iostream>
31 #include <cstdlib>
33 using namespace std;
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()));
51 m_SolverBinary = "";
52 m_WorkingDirectory = "";
53 m_HostFile = "hostfile.txt";
54 m_NumProcesses = 1;
55 m_MainHost = "";
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();
69 m_Program_Tools = "";
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();
88 // get binary name
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());
94 if (!file.exists()) {
95 qDebug() << "ERROR: " << solvers_fileinfo.filePath() << " not found.";
96 EG_BUG;
97 return(-1);
99 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
100 qDebug() << "ERROR: Failed to open file " << solvers_fileinfo.filePath();
101 EG_BUG;
102 return(-1);
104 QTextStream text_stream(&file);
105 QString intext = text_stream.readAll();
106 file.close();
108 QStringList page_list = intext.split("=");
109 QString page = page_list[solver_type];
110 QString title;
111 QString section;
112 QString binary;
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());
136 } else {
137 return(-1);
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";
148 return(0);
151 //=====================================
152 // Main slots
153 //=====================================
155 void SolverTools::runSolver()
157 if (m_SolverProcess->state() == QProcess::NotRunning) {
158 if (getArguments() < 0) {
159 qDebug() << "Failed to run Solver.";
160 return;
163 int num_cpus = 1;
165 QFile file(m_WorkingDirectory + "/system/decomposeParDict");
166 file.open(QIODevice::ReadOnly);
167 QTextStream f(&file);
168 while (!f.atEnd()) {
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) {
176 num_cpus = 1;
184 if (num_cpus <= 1) {
185 m_Program_Solver = m_SolverBinary;
186 m_Arguments_Solver << "-case" << m_WorkingDirectory;
187 } else {
188 runDecomposePar();
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";
195 } else {
196 qDebug() << "ERROR: decomposePar failed.";
197 return;
200 m_SolverProcess->start(m_Program_Solver, m_Arguments_Solver);
201 if (m_SolverProcess->waitForStarted()) {
202 startedHandler_Tools();
204 } else {
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();
221 } else {
222 qDebug() << "failed to start: m_Program_Tools=" << m_Program_Tools << " m_Arguments_Tools=" << m_Arguments_Tools;
223 qDebug() << m_Program_Tools << " not found";
225 } else {
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.";
234 return;
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();
242 } else {
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";
252 return;
254 QStringList args;
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()
267 QStringList args;
268 m_ToolsProcess->start(m_ParaviewPath, args);
269 do {
270 m_ToolsProcess->waitForFinished(500);
271 if (m_SolverProcess->state() == QProcess::NotRunning) {
272 cout << m_ToolsProcess->readAllStandardOutput().data();
273 flush(cout);
275 QApplication::processEvents();
276 } while (m_ToolsProcess->state() == QProcess::Running);
277 if (m_SolverProcess->state() == QProcess::NotRunning) {
278 cout << m_ToolsProcess->readAllStandardOutput().data();
279 flush(cout);
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";
298 QDir d1(p1);
299 QDir d2(p2);
300 if (d1.exists()) {
301 QStringList items;
302 items << tr("millimetres") << tr("centimetres") << tr("metres") << tr("inches");
303 bool ok;
304 QString scale_txt = QInputDialog::getItem(NULL, tr("Select scale"), tr("scale:"), items, 0, false, &ok);
305 if (ok && !scale_txt.isEmpty()) {
306 if (!d2.exists()) {
307 d1.mkdir("system");
308 d2 = QDir(p2);
310 QStringList args;
311 args << fluent_file_name;
312 args << "-scale";
313 if (scale_txt == "millimetres") {
314 args << "0.001";
315 } else if (scale_txt == "centimetres") {
316 args << "0.01";
317 } else if (scale_txt == "metres") {
318 args << "1";
319 } else if (scale_txt == "inches") {
320 args << "0.0254";
321 } else {
322 args << "1";
324 m_WorkingDirectory = foam_case_dir;
325 QFile file(m_WorkingDirectory + "/system/controlDict");
326 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
327 try {
328 EG_ERR_RETURN("ERROR: Failed to open file " + foam_case_dir + "/system/controlDict");
329 } catch (Error err) {
330 err.display();
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";
341 f << "FoamFile\n";
342 f << "{\n";
343 f << " version 2.0;\n";
344 f << " format ascii;\n";
345 f << " class dictionary;\n";
346 f << " object controlDict;\n";
347 f << "}\n";
348 f << "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n";
349 f << "\n";
350 f << "application simpleFoam;\n";
351 f << "\n";
352 f << "startFrom startTime;\n";
353 f << "startTime 0;\n";
354 f << "stopAt endTime;\n";
355 f << "endTime 1000;\n";
356 f << "deltaT 1;\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";
366 file.close();
367 runTool("applications/bin", "fluentMeshToFoam", args);
374 //=====================================
375 // Handlers Solver
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.";
383 } else {
384 qDebug() << "QProcess crashed.";
388 void SolverTools::readFromStderr_Solver()
390 cout << m_SolverProcess->readAllStandardError().data();
391 flush(cout);
394 void SolverTools::readFromStdout_Solver()
396 cout << m_SolverProcess->readAllStandardOutput().data();
397 flush(cout);
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 //=====================================
411 // Handlers Tools
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.";
419 } else {
420 qDebug() << "QProcess crashed.";
424 void SolverTools::readFromStderr_Tools()
426 cout << m_ToolsProcess->readAllStandardError().data();
427 flush(cout);
430 void SolverTools::readFromStdout_Tools()
432 cout << m_ToolsProcess->readAllStandardOutput().data();
433 flush(cout);
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);
453 } else {
454 return;