added foam path/arch to config
[engrid.git] / src / openfoamtools.cpp
blob739b76c578f4b370b2dd3e6309bbfc6ab5ec2281
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 m_OpenFoamPath = getenv("HOME");
57 m_OpenFoamPath += "/OpenFOAM/OpenFOAM-1.5";
58 getSet("General", "OpenFOAM path", m_OpenFoamPath, m_OpenFoamPath);
59 m_OpenFoamArch = "linux64GccDPOpt";
60 getSet("General", "OpenFOAM architecture", m_OpenFoamArch, m_OpenFoamArch);
64 OpenFOAMTools::~OpenFOAMTools()
66 this->stopSolverProcess();
69 void OpenFOAMTools::writeMpiParameters()
71 QString hostfile_text = GuiMainWindow::pointer()->getXmlSection( "solver/general/host_weight_list" );
73 QVector <QString> host;
74 QVector <QString> weight;
76 QStringList host_weight_list = hostfile_text.split(",");
77 foreach(QString host_weight, host_weight_list) {
78 if(!host_weight.isEmpty()){
79 QStringList values = host_weight.split(":");
80 qWarning()<<"values="<<values;
81 host.push_back(values[0].trimmed());
82 weight.push_back(values[1].trimmed());
86 if(host.size()>=1) {
87 // create the hostfile
88 QFileInfo fileinfo( m_WorkingDirectory + "/" + m_HostFile );
89 QFile hostfile( fileinfo.filePath() );
90 if (!hostfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
91 try {
92 EG_ERR_RETURN( "ERROR: Failed to open file " + fileinfo.filePath() );
93 } catch ( Error err ) {
94 err.display();
97 QTextStream out( &hostfile );
98 for(int i = 0; i < host.size(); i++) {
99 out << host[i] << endl;
101 hostfile.close();
103 // create the decomposeParDict file
104 QFileInfo fileinfo_decomposeParDict( m_WorkingDirectory + "/system/decomposeParDict" );
105 QFile decomposeParDict( fileinfo_decomposeParDict.filePath() );
106 if (!decomposeParDict.open(QIODevice::WriteOnly | QIODevice::Text)) {
107 try {
108 EG_ERR_RETURN( "ERROR: Failed to open file " + fileinfo_decomposeParDict.filePath() );
109 } catch ( Error err ) {
110 err.display();
113 QTextStream out_decomposeParDict( &decomposeParDict );
114 out_decomposeParDict << "/*--------------------------------*- C++ -*----------------------------------*\\" << endl;
115 out_decomposeParDict << "| ========= | |" << endl;
116 out_decomposeParDict << "| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |" << endl;
117 out_decomposeParDict << "| \\ / O peration | Version: 1.5 |" << endl;
118 out_decomposeParDict << "| \\ / A nd | Web: http://www.OpenFOAM.org |" << endl;
119 out_decomposeParDict << "| \\/ M anipulation | |" << endl;
120 out_decomposeParDict << "\\*---------------------------------------------------------------------------*/" << endl;
121 out_decomposeParDict << "FoamFile" << endl;
122 out_decomposeParDict << "{" << endl;
123 out_decomposeParDict << " version 2.0;" << endl;
124 out_decomposeParDict << " format ascii;" << endl;
125 out_decomposeParDict << " class dictionary;" << endl;
126 out_decomposeParDict << " object decomposeParDict;" << endl;
127 out_decomposeParDict << "}" << endl;
128 out_decomposeParDict << "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //" << endl;
129 out_decomposeParDict << "" << endl;
130 out_decomposeParDict << "numberOfSubdomains "<<weight.size()<<";" << endl;
131 out_decomposeParDict << "" << endl;
132 out_decomposeParDict << "method metis;" << endl;
133 out_decomposeParDict << "" << endl;
134 out_decomposeParDict << "metisCoeffs" << endl;
135 out_decomposeParDict << "{" << endl;
136 out_decomposeParDict << " processorWeights " << endl;
137 out_decomposeParDict << " (" << endl;
138 for(int i = 0; i < weight.size(); i++) {
139 out_decomposeParDict << " "<<weight[i]<<"" << endl;
141 out_decomposeParDict << " );" << endl;
142 out_decomposeParDict << "}" << endl;
143 out_decomposeParDict << "" << endl;
144 out_decomposeParDict << "distributed no;" << endl;
145 out_decomposeParDict << "" << endl;
146 out_decomposeParDict << "roots " << endl;
147 out_decomposeParDict << "(" << endl;
148 out_decomposeParDict << ");" << endl;
149 out_decomposeParDict << "" << endl;
150 out_decomposeParDict << "// ************************************************************************* //" << endl;
151 out_decomposeParDict << "" << endl;
152 decomposeParDict.close();
154 m_NumProcesses = weight.size();
155 m_MainHost = host[0];
157 else {
158 m_NumProcesses = 1;
159 m_MainHost = "";
163 int OpenFOAMTools::getArguments()
165 // resest command-line
166 m_Program = "";
167 m_Arguments.clear();
169 // get binary name
170 int solver_type = GuiMainWindow::pointer()->getXmlSection("solver/general/solver_type").toInt();
172 QFileInfo solvers_fileinfo;
173 solvers_fileinfo.setFile(":/resources/solvers/solvers.txt");
174 QFile file( solvers_fileinfo.filePath() );
175 if ( !file.exists() ) {
176 qDebug() << "ERROR: " << solvers_fileinfo.filePath() << " not found.";
177 EG_BUG;
178 return( -1 );
180 if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
181 qDebug() << "ERROR: Failed to open file " << solvers_fileinfo.filePath();
182 EG_BUG;
183 return( -1 );
185 QTextStream text_stream( &file );
186 QString intext = text_stream.readAll();
187 file.close();
189 QStringList page_list = intext.split( "=" );
190 QString page = page_list[solver_type];
191 QString title;
192 QString section;
193 QString binary;
194 QVector <QString> files;
195 QStringList variable_list = page.split( ";" );
196 foreach( QString variable, variable_list ) {
197 QStringList name_value = variable.split( ":" );
198 if ( name_value[0].trimmed() == "title" ) title = name_value[1].trimmed();
199 if ( name_value[0].trimmed() == "section" ) section = name_value[1].trimmed();
200 if ( name_value[0].trimmed() == "binary" ) binary = name_value[1].trimmed();
201 if ( name_value[0].trimmed() == "files" ) {
202 QStringList file_list = name_value[1].split( "," );
203 foreach( QString file, file_list ) {
204 files.push_back( file.trimmed() );
209 m_SolverBinary = m_OpenFoamPath + "/applications/bin/" + m_OpenFoamArch + "/" + binary;
210 m_StrippedSolverBinary = binary;
212 m_WorkingDirectory = GuiMainWindow::pointer()->getXmlSection("openfoam/CaseDir");
213 if ( m_WorkingDirectory.isEmpty() ) {
214 m_WorkingDirectory = QFileDialog::getExistingDirectory( NULL, "select case directory", GuiMainWindow::getCwd() );
215 if ( !m_WorkingDirectory.isNull() ) {
216 GuiMainWindow::setCwd( QFileInfo( m_WorkingDirectory ).absolutePath() );
217 } else {
218 return(-1);
222 // create hostfile + decomposeParDict + get necessary parameters
223 writeMpiParameters();
225 // set working directory of the process
226 m_SolverProcess->setWorkingDirectory(m_WorkingDirectory);
228 return(0);
231 //=====================================
232 // Main slots
233 //=====================================
235 void OpenFOAMTools::runSolver()
237 if (m_SolverProcess->state() == QProcess::NotRunning) {
238 if (getArguments() < 0) {
239 return;
241 if (m_NumProcesses <= 1) {
242 if(m_MainHost.isEmpty()) {
243 m_Program = m_SolverBinary;
244 m_Arguments << "-case" << m_WorkingDirectory;
245 } else {
246 m_Program = "ssh";
247 m_Arguments << m_MainHost << m_SolverBinary << "-case" << m_WorkingDirectory;
249 } else {
250 runDecomposePar();
251 if(m_SolverProcess->waitForFinished() && m_SolverProcess->exitCode() == 0 ) {
252 QString numprocesses_str;
253 numprocesses_str.setNum(m_NumProcesses);
254 m_Arguments.clear();
255 //m_Program = "mpirun";
256 //m_Arguments << "--hostfile" << m_HostFile << "-np" << numprocesses_str << m_SolverBinary << "-case" << m_WorkingDirectory << "-parallel";
257 m_Program = "ssh";
258 m_Arguments << m_MainHost << "mpirun";
259 m_Arguments << "--hostfile" << m_WorkingDirectory + "/" + m_HostFile;
260 m_Arguments << "-np" << numprocesses_str << m_SolverBinary << "-case" << m_WorkingDirectory << "-parallel";
262 else {
263 qDebug()<<"ERROR: decomposePar failed.";
264 return;
267 m_SolverProcess->start(m_Program, m_Arguments);
271 void OpenFOAMTools::runTool(QString path, QString name, QStringList args)
273 args << "-case" << m_WorkingDirectory;
274 m_ToolsProcess->start(m_OpenFoamPath + "/" + path + "/" + m_OpenFoamArch + "/" + name, args);
275 do {
276 m_ToolsProcess->waitForFinished(500);
277 if (m_SolverProcess->state() == QProcess::NotRunning) {
278 cout << m_ToolsProcess->readAllStandardOutput().data();
279 flush(cout);
281 QApplication::processEvents();
282 } while (m_ToolsProcess->state() == QProcess::Running);
283 if (m_SolverProcess->state() == QProcess::NotRunning) {
284 cout << m_ToolsProcess->readAllStandardOutput().data();
285 flush(cout);
289 void OpenFOAMTools::runDecomposePar()
291 if (getArguments() < 0) {
292 return;
294 this->stopSolverProcess();
295 m_Program = getBinary("applications/bin", "decomposePar");
296 m_Arguments << "-force";
297 m_SolverProcess->start(m_Program, m_Arguments);
300 void OpenFOAMTools::runPostProcessingTools()
302 QStringList args;
303 args << "-latestTime";
304 runTool("applications/bin", "reconstructPar", args);
305 runTool("applications/bin", "foamToVTK", args);
308 void OpenFOAMTools::stopSolverProcess()
310 if (m_SolverProcess->state() == QProcess::Running) {
311 m_SolverProcess->kill();
312 QString cmd = "ssh " + m_MainHost + " killall -9 " + m_StrippedSolverBinary;
313 system(cmd.toAscii().data());
317 void OpenFOAMTools::runImportFluentCase()
319 QString fluent_file_name = QFileDialog::getOpenFileName(NULL, "import FLUENT case",GuiMainWindow::pointer()->getCwd(), "*.msh");
320 if (!fluent_file_name.isNull()) {
321 QString foam_case_dir = QFileDialog::getExistingDirectory(NULL, "select OpenFOAM case directory", GuiMainWindow::getCwd());
322 if (!foam_case_dir.isNull()) {
323 QString p1 = foam_case_dir;
324 QString p2 = p1 + "/system";
325 QDir d1(p1);
326 QDir d2(p2);
327 if (d1.exists()) {
328 QStringList items;
329 items << tr("millimetres") << tr("centimetres") << tr("metres") << tr("inches");
330 bool ok;
331 QString scale_txt = QInputDialog::getItem(NULL, tr("Select scale"), tr("scale:"), items, 0, false, &ok);
332 if (ok && !scale_txt.isEmpty()) {
333 if (!d2.exists()) {
334 d1.mkdir("system");
335 d2 = QDir(p2);
337 QStringList args;
338 args << fluent_file_name;
339 args << "-scale";
340 if (scale_txt == "millimetres") {
341 args << "0.001";
342 } else if (scale_txt == "centimetres") {
343 args << "0.01";
344 } else if (scale_txt == "metres") {
345 args << "1";
346 } else if (scale_txt == "inches") {
347 args << "0.0254";
348 } else {
349 args << "1";
351 m_WorkingDirectory = foam_case_dir;
352 QFile file(m_WorkingDirectory + "/system/controlDict");
353 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
354 try {
355 EG_ERR_RETURN( "ERROR: Failed to open file " + foam_case_dir + "/system/controlDict");
356 } catch (Error err) {
357 err.display();
360 QTextStream f(&file);
361 f << "/*--------------------------------*- C++ -*----------------------------------*\\\n";
362 f << "| ========= | |\n";
363 f << "| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |\n";
364 f << "| \\ / O peration | Version: 1.5 |\n";
365 f << "| \\ / A nd | Web: http://www.OpenFOAM.org |\n";
366 f << "| \\/ M anipulation | |\n";
367 f << "\\*---------------------------------------------------------------------------*/\n";
368 f << "FoamFile\n";
369 f << "{\n";
370 f << " version 2.0;\n";
371 f << " format ascii;\n";
372 f << " class dictionary;\n";
373 f << " object controlDict;\n";
374 f << "}\n";
375 f << "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n";
376 f << "\n";
377 f << "application simpleFoam;\n";
378 f << "\n";
379 f << "startFrom startTime;\n";
380 f << "startTime 0;\n";
381 f << "stopAt endTime;\n";
382 f << "endTime 1000;\n";
383 f << "deltaT 1;\n";
384 f << "writeControl timeStep;\n";
385 f << "writeInterval 100;\n";
386 f << "purgeWrite 0;\n";
387 f << "writeFormat ascii;\n";
388 f << "writePrecision 6;\n";
389 f << "writeCompression uncompressed;\n";
390 f << "timeFormat general;\n";
391 f << "timePrecision 6;\n";
392 f << "runTimeModifiable yes;\n";
393 file.close();
394 runTool("applications/bin", "fluentMeshToFoam", args);
401 //=====================================
402 // Handlers
403 //=====================================
405 void OpenFOAMTools::finishedHandler(int exitCode, QProcess::ExitStatus exitStatus)
407 qDebug() << "=== solver-process finished with exit-code = " << exitCode << " ===";
410 void OpenFOAMTools::readFromStderr()
412 cout << m_SolverProcess->readAllStandardError().data();
413 flush(cout);
416 void OpenFOAMTools::readFromStdout()
418 cout << m_SolverProcess->readAllStandardOutput().data();
419 flush(cout);
422 void OpenFOAMTools::startedHandler()
424 qDebug() << "=== started solver-process with PID = " << m_SolverProcess->pid() << "===";
425 QString cmd = m_Program;
426 foreach(QString arg, m_Arguments) {
427 cmd += " " + arg;
429 cout << "[" << qPrintable(m_WorkingDirectory) << "]$ " << qPrintable(cmd) << endl;