de-activated insert-points for now
[engrid.git] / src / openfoamtools.cpp
blob15d065ee5ef0718d994d60c186e7019dce4dd33d
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 "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 )
39 m_SolverProcess = new QProcess(this);
40 m_ToolsProcess = new QProcess(this);
42 // connect(m_SolverProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(errorHandler(QProcess::ProcessError)));
43 connect(m_SolverProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finishedHandler(int, QProcess::ExitStatus)));
44 connect(m_SolverProcess, SIGNAL(readyReadStandardError()), this, SLOT(readFromStderr()));
45 connect(m_SolverProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readFromStdout()));
46 connect(m_SolverProcess, SIGNAL(started()), this, SLOT(startedHandler()));
47 // connect(m_SolverProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(stateChangedHandler(QProcess::ProcessState)));
49 m_SolverBinary = "";
50 m_WorkingDirectory = "";
51 m_HostFile = "hostfile.txt";
52 m_NumProcesses = 1;
53 m_MainHost = "";
55 QSettings *settings = GuiMainWindow::pointer()->settings();
56 if (settings->contains("openfoam_directory")) {
57 m_OpenFoamPath = settings->value("openfoam_directory").toString();
58 } else {
59 m_OpenFoamPath = getenv("HOME");
60 m_OpenFoamPath += "/OpenFOAM/OpenFOAM-1.5";
61 settings->setValue("openfoam_directory", m_OpenFoamPath);
63 if (settings->contains("openfoam_architecture")) {
64 m_OpenFoamArch = settings->value("openfoam_architecture").toString();
65 } else {
66 m_OpenFoamArch = "linux64GccDPOpt";
67 settings->setValue("openfoam_architecture", m_OpenFoamArch);
72 OpenFOAMTools::~OpenFOAMTools()
74 this->stopSolverProcess();
77 void OpenFOAMTools::writeMpiParameters()
79 QString hostfile_text = GuiMainWindow::pointer()->getXmlSection( "solver/general/host_weight_list" );
81 QVector <QString> host;
82 QVector <QString> weight;
84 QStringList host_weight_list = hostfile_text.split(",");
85 foreach(QString host_weight, host_weight_list) {
86 if(!host_weight.isEmpty()){
87 QStringList values = host_weight.split(":");
88 qWarning()<<"values="<<values;
89 host.push_back(values[0].trimmed());
90 weight.push_back(values[1].trimmed());
94 if(host.size()>=1) {
95 // create the hostfile
96 QFileInfo fileinfo( m_WorkingDirectory + "/" + m_HostFile );
97 QFile hostfile( fileinfo.filePath() );
98 if (!hostfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
99 try {
100 EG_ERR_RETURN( "ERROR: Failed to open file " + fileinfo.filePath() );
101 } catch ( Error err ) {
102 err.display();
105 QTextStream out( &hostfile );
106 for(int i = 0; i < host.size(); i++) {
107 out << host[i] << endl;
109 hostfile.close();
111 // create the decomposeParDict file
112 QFileInfo fileinfo_decomposeParDict( m_WorkingDirectory + "/system/decomposeParDict" );
113 QFile decomposeParDict( fileinfo_decomposeParDict.filePath() );
114 if (!decomposeParDict.open(QIODevice::WriteOnly | QIODevice::Text)) {
115 try {
116 EG_ERR_RETURN( "ERROR: Failed to open file " + fileinfo_decomposeParDict.filePath() );
117 } catch ( Error err ) {
118 err.display();
121 QTextStream out_decomposeParDict( &decomposeParDict );
122 out_decomposeParDict << "/*--------------------------------*- C++ -*----------------------------------*\\" << endl;
123 out_decomposeParDict << "| ========= | |" << endl;
124 out_decomposeParDict << "| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |" << endl;
125 out_decomposeParDict << "| \\ / O peration | Version: 1.5 |" << endl;
126 out_decomposeParDict << "| \\ / A nd | Web: http://www.OpenFOAM.org |" << endl;
127 out_decomposeParDict << "| \\/ M anipulation | |" << endl;
128 out_decomposeParDict << "\\*---------------------------------------------------------------------------*/" << endl;
129 out_decomposeParDict << "FoamFile" << endl;
130 out_decomposeParDict << "{" << endl;
131 out_decomposeParDict << " version 2.0;" << endl;
132 out_decomposeParDict << " format ascii;" << endl;
133 out_decomposeParDict << " class dictionary;" << endl;
134 out_decomposeParDict << " object decomposeParDict;" << endl;
135 out_decomposeParDict << "}" << endl;
136 out_decomposeParDict << "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //" << endl;
137 out_decomposeParDict << "" << endl;
138 out_decomposeParDict << "numberOfSubdomains "<<weight.size()<<";" << endl;
139 out_decomposeParDict << "" << endl;
140 out_decomposeParDict << "method metis;" << endl;
141 out_decomposeParDict << "" << endl;
142 out_decomposeParDict << "metisCoeffs" << endl;
143 out_decomposeParDict << "{" << endl;
144 out_decomposeParDict << " processorWeights " << endl;
145 out_decomposeParDict << " (" << endl;
146 for(int i = 0; i < weight.size(); i++) {
147 out_decomposeParDict << " "<<weight[i]<<"" << endl;
149 out_decomposeParDict << " );" << endl;
150 out_decomposeParDict << "}" << endl;
151 out_decomposeParDict << "" << endl;
152 out_decomposeParDict << "distributed no;" << endl;
153 out_decomposeParDict << "" << endl;
154 out_decomposeParDict << "roots " << endl;
155 out_decomposeParDict << "(" << endl;
156 out_decomposeParDict << ");" << endl;
157 out_decomposeParDict << "" << endl;
158 out_decomposeParDict << "// ************************************************************************* //" << endl;
159 out_decomposeParDict << "" << endl;
160 decomposeParDict.close();
162 m_NumProcesses = weight.size();
163 m_MainHost = host[0];
165 else {
166 m_NumProcesses = 1;
167 m_MainHost = "";
171 int OpenFOAMTools::getArguments()
173 // resest command-line
174 m_Program = "";
175 m_Arguments.clear();
177 // get binary name
178 int solver_type = GuiMainWindow::pointer()->getXmlSection("solver/general/solver_type").toInt();
180 QFileInfo solvers_fileinfo;
181 solvers_fileinfo.setFile(":/resources/solvers/solvers.txt");
182 QFile file( solvers_fileinfo.filePath() );
183 if ( !file.exists() ) {
184 qDebug() << "ERROR: " << solvers_fileinfo.filePath() << " not found.";
185 EG_BUG;
186 return( -1 );
188 if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
189 qDebug() << "ERROR: Failed to open file " << solvers_fileinfo.filePath();
190 EG_BUG;
191 return( -1 );
193 QTextStream text_stream( &file );
194 QString intext = text_stream.readAll();
195 file.close();
197 QStringList page_list = intext.split( "=" );
198 QString page = page_list[solver_type];
199 QString title;
200 QString section;
201 QString binary;
202 QVector <QString> files;
203 QStringList variable_list = page.split( ";" );
204 foreach( QString variable, variable_list ) {
205 QStringList name_value = variable.split( ":" );
206 if ( name_value[0].trimmed() == "title" ) title = name_value[1].trimmed();
207 if ( name_value[0].trimmed() == "section" ) section = name_value[1].trimmed();
208 if ( name_value[0].trimmed() == "binary" ) binary = name_value[1].trimmed();
209 if ( name_value[0].trimmed() == "files" ) {
210 QStringList file_list = name_value[1].split( "," );
211 foreach( QString file, file_list ) {
212 files.push_back( file.trimmed() );
217 m_SolverBinary = m_OpenFoamPath + "/applications/bin/" + m_OpenFoamArch + "/" + binary;
218 m_StrippedSolverBinary = binary;
220 m_WorkingDirectory = GuiMainWindow::pointer()->getXmlSection("openfoam/CaseDir");
221 if ( m_WorkingDirectory.isEmpty() ) {
222 m_WorkingDirectory = QFileDialog::getExistingDirectory( NULL, "select case directory", GuiMainWindow::getCwd() );
223 if ( !m_WorkingDirectory.isNull() ) {
224 GuiMainWindow::setCwd( QFileInfo( m_WorkingDirectory ).absolutePath() );
225 } else {
226 return(-1);
230 // create hostfile + decomposeParDict + get necessary parameters
231 writeMpiParameters();
233 // set working directory of the process
234 m_SolverProcess->setWorkingDirectory(m_WorkingDirectory);
236 return(0);
239 //=====================================
240 // Main slots
241 //=====================================
243 void OpenFOAMTools::runSolver()
245 if (m_SolverProcess->state() == QProcess::NotRunning) {
246 if (getArguments() < 0) {
247 return;
249 if (m_NumProcesses <= 1) {
250 if(m_MainHost.isEmpty()) {
251 m_Program = m_SolverBinary;
252 m_Arguments << "-case" << m_WorkingDirectory;
253 } else {
254 m_Program = "ssh";
255 m_Arguments << m_MainHost << m_SolverBinary << "-case" << m_WorkingDirectory;
257 } else {
258 runDecomposePar();
259 if(m_SolverProcess->waitForFinished() && m_SolverProcess->exitCode() == 0 ) {
260 QString numprocesses_str;
261 numprocesses_str.setNum(m_NumProcesses);
262 m_Arguments.clear();
263 //m_Program = "mpirun";
264 //m_Arguments << "--hostfile" << m_HostFile << "-np" << numprocesses_str << m_SolverBinary << "-case" << m_WorkingDirectory << "-parallel";
265 m_Program = "ssh";
266 m_Arguments << m_MainHost << "mpirun";
267 m_Arguments << "--hostfile" << m_WorkingDirectory + "/" + m_HostFile;
268 m_Arguments << "-np" << numprocesses_str << m_SolverBinary << "-case" << m_WorkingDirectory << "-parallel";
270 else {
271 qDebug()<<"ERROR: decomposePar failed.";
272 return;
275 m_SolverProcess->start(m_Program, m_Arguments);
279 void OpenFOAMTools::runTool(QString path, QString name, QStringList args)
281 args << "-case" << m_WorkingDirectory;
282 m_ToolsProcess->start(m_OpenFoamPath + "/" + path + "/" + m_OpenFoamArch + "/" + name, args);
283 do {
284 m_ToolsProcess->waitForFinished(500);
285 if (m_SolverProcess->state() == QProcess::NotRunning) {
286 cout << m_ToolsProcess->readAllStandardOutput().data();
287 flush(cout);
289 QApplication::processEvents();
290 } while (m_ToolsProcess->state() == QProcess::Running);
291 if (m_SolverProcess->state() == QProcess::NotRunning) {
292 cout << m_ToolsProcess->readAllStandardOutput().data();
293 flush(cout);
297 void OpenFOAMTools::runDecomposePar()
299 if (getArguments() < 0) {
300 return;
302 this->stopSolverProcess();
303 m_Program = getBinary("applications/bin", "decomposePar");
304 m_Arguments << "-force";
305 m_SolverProcess->start(m_Program, m_Arguments);
308 void OpenFOAMTools::runPostProcessingTools()
310 QStringList args;
311 args << "-latestTime";
312 runTool("applications/bin", "reconstructPar", args);
313 runTool("applications/bin", "foamToVTK", args);
316 void OpenFOAMTools::stopSolverProcess()
318 if (m_SolverProcess->state() == QProcess::Running) {
319 m_SolverProcess->kill();
320 QString cmd = "ssh " + m_MainHost + " killall -9 " + m_StrippedSolverBinary;
321 system(cmd.toAscii().data());
325 void OpenFOAMTools::runImportFluentCase()
327 QString fluent_file_name = QFileDialog::getOpenFileName(NULL, "import FLUENT case",GuiMainWindow::pointer()->getCwd(), "*.msh");
328 if (!fluent_file_name.isNull()) {
329 QString foam_case_dir = QFileDialog::getExistingDirectory(NULL, "select OpenFOAM case directory", GuiMainWindow::getCwd());
330 if (!foam_case_dir.isNull()) {
331 QString p1 = foam_case_dir;
332 QString p2 = p1 + "/system";
333 QDir d1(p1);
334 QDir d2(p2);
335 if (d1.exists()) {
336 QStringList items;
337 items << tr("millimetres") << tr("centimetres") << tr("metres") << tr("inches");
338 bool ok;
339 QString scale_txt = QInputDialog::getItem(NULL, tr("Select scale"), tr("scale:"), items, 0, false, &ok);
340 if (ok && !scale_txt.isEmpty()) {
341 if (!d2.exists()) {
342 d1.mkdir("system");
343 d2 = QDir(p2);
345 QStringList args;
346 args << fluent_file_name;
347 args << "-scale";
348 if (scale_txt == "millimetres") {
349 args << "0.001";
350 } else if (scale_txt == "centimetres") {
351 args << "0.01";
352 } else if (scale_txt == "metres") {
353 args << "1";
354 } else if (scale_txt == "inches") {
355 args << "0.0254";
356 } else {
357 args << "1";
359 m_WorkingDirectory = foam_case_dir;
360 QFile file(m_WorkingDirectory + "/system/controlDict");
361 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
362 try {
363 EG_ERR_RETURN( "ERROR: Failed to open file " + foam_case_dir + "/system/controlDict");
364 } catch (Error err) {
365 err.display();
368 QTextStream f(&file);
369 f << "/*--------------------------------*- C++ -*----------------------------------*\\\n";
370 f << "| ========= | |\n";
371 f << "| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |\n";
372 f << "| \\ / O peration | Version: 1.5 |\n";
373 f << "| \\ / A nd | Web: http://www.OpenFOAM.org |\n";
374 f << "| \\/ M anipulation | |\n";
375 f << "\\*---------------------------------------------------------------------------*/\n";
376 f << "FoamFile\n";
377 f << "{\n";
378 f << " version 2.0;\n";
379 f << " format ascii;\n";
380 f << " class dictionary;\n";
381 f << " object controlDict;\n";
382 f << "}\n";
383 f << "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n";
384 f << "\n";
385 f << "application simpleFoam;\n";
386 f << "\n";
387 f << "startFrom startTime;\n";
388 f << "startTime 0;\n";
389 f << "stopAt endTime;\n";
390 f << "endTime 1000;\n";
391 f << "deltaT 1;\n";
392 f << "writeControl timeStep;\n";
393 f << "writeInterval 100;\n";
394 f << "purgeWrite 0;\n";
395 f << "writeFormat ascii;\n";
396 f << "writePrecision 6;\n";
397 f << "writeCompression uncompressed;\n";
398 f << "timeFormat general;\n";
399 f << "timePrecision 6;\n";
400 f << "runTimeModifiable yes;\n";
401 file.close();
402 runTool("applications/bin", "fluentMeshToFoam", args);
409 //=====================================
410 // Handlers
411 //=====================================
413 void OpenFOAMTools::finishedHandler(int exitCode, QProcess::ExitStatus exitStatus)
415 qDebug() << "=== solver-process finished with exit-code = " << exitCode << " ===";
418 void OpenFOAMTools::readFromStderr()
420 cout << m_SolverProcess->readAllStandardError().data();
421 flush(cout);
424 void OpenFOAMTools::readFromStdout()
426 cout << m_SolverProcess->readAllStandardOutput().data();
427 flush(cout);
430 void OpenFOAMTools::startedHandler()
432 qDebug() << "=== started solver-process with PID = " << m_SolverProcess->pid() << "===";
433 QString cmd = m_Program;
434 foreach(QString arg, m_Arguments) {
435 cmd += " " + arg;
437 cout << "[" << qPrintable(m_WorkingDirectory) << "]$ " << qPrintable(cmd) << endl;