2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 // + This file is part of enGrid. +
6 // + Copyright 2008,2009 Oliver Gloth +
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
)
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)));
50 m_WorkingDirectory
= "";
51 m_HostFile
= "hostfile.txt";
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());
87 // create the hostfile
88 QFileInfo
fileinfo( m_WorkingDirectory
+ "/" + m_HostFile
);
89 QFile
hostfile( fileinfo
.filePath() );
90 if (!hostfile
.open(QIODevice::WriteOnly
| QIODevice::Text
)) {
92 EG_ERR_RETURN( "ERROR: Failed to open file " + fileinfo
.filePath() );
93 } catch ( Error err
) {
97 QTextStream
out( &hostfile
);
98 for(int i
= 0; i
< host
.size(); i
++) {
99 out
<< host
[i
] << endl
;
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
)) {
108 EG_ERR_RETURN( "ERROR: Failed to open file " + fileinfo_decomposeParDict
.filePath() );
109 } catch ( Error err
) {
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];
163 int OpenFOAMTools::getArguments()
165 // resest command-line
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.";
180 if ( !file
.open( QIODevice::ReadOnly
| QIODevice::Text
) ) {
181 qDebug() << "ERROR: Failed to open file " << solvers_fileinfo
.filePath();
185 QTextStream
text_stream( &file
);
186 QString intext
= text_stream
.readAll();
189 QStringList page_list
= intext
.split( "=" );
190 QString page
= page_list
[solver_type
];
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() );
222 // create hostfile + decomposeParDict + get necessary parameters
223 writeMpiParameters();
225 // set working directory of the process
226 m_SolverProcess
->setWorkingDirectory(m_WorkingDirectory
);
231 //=====================================
233 //=====================================
235 void OpenFOAMTools::runSolver()
237 if (m_SolverProcess
->state() == QProcess::NotRunning
) {
238 if (getArguments() < 0) {
241 if (m_NumProcesses
<= 1) {
242 if(m_MainHost
.isEmpty()) {
243 m_Program
= m_SolverBinary
;
244 m_Arguments
<< "-case" << m_WorkingDirectory
;
247 m_Arguments
<< m_MainHost
<< m_SolverBinary
<< "-case" << m_WorkingDirectory
;
251 if(m_SolverProcess
->waitForFinished() && m_SolverProcess
->exitCode() == 0 ) {
252 QString numprocesses_str
;
253 numprocesses_str
.setNum(m_NumProcesses
);
255 //m_Program = "mpirun";
256 //m_Arguments << "--hostfile" << m_HostFile << "-np" << numprocesses_str << m_SolverBinary << "-case" << m_WorkingDirectory << "-parallel";
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";
263 qDebug()<<"ERROR: decomposePar failed.";
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
);
276 m_ToolsProcess
->waitForFinished(500);
277 if (m_SolverProcess
->state() == QProcess::NotRunning
) {
278 cout
<< m_ToolsProcess
->readAllStandardOutput().data();
281 QApplication::processEvents();
282 } while (m_ToolsProcess
->state() == QProcess::Running
);
283 if (m_SolverProcess
->state() == QProcess::NotRunning
) {
284 cout
<< m_ToolsProcess
->readAllStandardOutput().data();
289 void OpenFOAMTools::runDecomposePar()
291 if (getArguments() < 0) {
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()
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";
329 items
<< tr("millimetres") << tr("centimetres") << tr("metres") << tr("inches");
331 QString scale_txt
= QInputDialog::getItem(NULL
, tr("Select scale"), tr("scale:"), items
, 0, false, &ok
);
332 if (ok
&& !scale_txt
.isEmpty()) {
338 args
<< fluent_file_name
;
340 if (scale_txt
== "millimetres") {
342 } else if (scale_txt
== "centimetres") {
344 } else if (scale_txt
== "metres") {
346 } else if (scale_txt
== "inches") {
351 m_WorkingDirectory
= foam_case_dir
;
352 QFile
file(m_WorkingDirectory
+ "/system/controlDict");
353 if (!file
.open(QIODevice::WriteOnly
| QIODevice::Text
)) {
355 EG_ERR_RETURN( "ERROR: Failed to open file " + foam_case_dir
+ "/system/controlDict");
356 } catch (Error err
) {
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";
370 f
<< " version 2.0;\n";
371 f
<< " format ascii;\n";
372 f
<< " class dictionary;\n";
373 f
<< " object controlDict;\n";
375 f
<< "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n";
377 f
<< "application simpleFoam;\n";
379 f
<< "startFrom startTime;\n";
380 f
<< "startTime 0;\n";
381 f
<< "stopAt endTime;\n";
382 f
<< "endTime 1000;\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";
394 runTool("applications/bin", "fluentMeshToFoam", args
);
401 //=====================================
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();
416 void OpenFOAMTools::readFromStdout()
418 cout
<< m_SolverProcess
->readAllStandardOutput().data();
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
) {
429 cout
<< "[" << qPrintable(m_WorkingDirectory
) << "]$ " << qPrintable(cmd
) << endl
;