/** * @file SolverControlerBase.cpp * @brief 求解器控制基类源文件 * @author FastCAE研发小组(fastcae@diso.cn) * @version 2.5.0 * @date 2022-03-12 15:34 * @copyright Copyright (c) Since 2020 青岛数智船海科技有限公司 All rights reserved. * * ============================================================================ * Program: FastCAE * * Copyright (c) Since 2020 青岛数智船海科技有限公司 All rights reserved. * See License or http://www.fastcae.com/ for details. * * BSD 3-Clause License * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. * ================================================================================== */ #include "SolverControlerBase.h" #include "MainWindow/MainWindow.h" #include "ModuleBase/processBar.h" #include "PostWidgets/RealTimeWindowBase.h" #include "ModelData/modelDataSingleton.h" #include "ModelData/modelDataBaseExtend.h" #include "ConfigOptions/ConfigOptions.h" #include "ConfigOptions/SolverConfig.h" #include "ConfigOptions/SolverInfo.h" #include "IO/SolverIO.h" #include #include #include #include #include #include "PythonModule/PyAgent.h" namespace SolverControl { SolverControlBase::SolverControlBase(GUI::MainWindow* mainwindow, ConfigOption::SolverInfo* solver, ModelData::ModelDataBase* m, bool sonly) : _mainWindow(mainwindow) , _solver(solver) , _model(m) , _solveOnly(sonly) { connect(&_process, SIGNAL(readyReadStandardOutput()), this, SLOT(readSolverOutput())); connect(this, SIGNAL(sendMessage(QString)), _mainWindow, SIGNAL(printMessageToMessageWindow(QString))); connect(this, SIGNAL(solverStarted(QWidget*)), _mainWindow, SIGNAL(addProcessBarSig(QWidget*))); connect(_mainWindow, SIGNAL(stopSolve(QWidget*)), this, SLOT(stopSolver(QWidget*))); connect(&_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus))); connect(this, SIGNAL(processFinish(int)), _mainWindow, SIGNAL(processFinished(int))); connect(this, SIGNAL(openRealTime(Post::RealTimeWindowBase*, int)), _mainWindow, SIGNAL(openRealTimeWindowSig(Post::RealTimeWindowBase*, int))); } SolverControlBase::~SolverControlBase() { if(_processBar != nullptr) delete _processBar; } void SolverControlBase::setSolverDescription(QString des) { _description = des; } void SolverControlBase::startSolver() { QString solverPath = _solver->getExePath(); qDebug() << solverPath; QFileInfo info(solverPath); int id = _model->getID(); if((!info.exists()) || (!info.isFile())) { QMessageBox::warning(nullptr, tr("Warning"), tr("Solver Path Error! Solve Path : %1").arg(solverPath)); emit processFinish(id); return; } bool ok = preProcess(); if(!ok) { QMessageBox::warning(nullptr, tr("Warning"), tr("Input file write failed !")); emit processFinish(id); return; } QString oldDir = ""; QString startPath = _model->getPath(); if(_solver->getType() == ConfigOption::SelfDevelop) { QDir dir(startPath); if(dir.exists() && (!startPath.isEmpty())) { oldDir = QDir::currentPath(); QDir::setCurrent(startPath); } } _processBar = new ModuleBase::ProcessBar(_mainWindow, _description, false); QString args = _solver->getParameter(); args.replace("%modelpath%", startPath, Qt::CaseInsensitive); /*QRegExp regExp("%.*%"); regExp.setMinimal(true); // int pos = regExp.indexIn(args); QStringList variables = regExp.capturedTexts(); for(int i = 0; i < variables.size(); ++i) { QString variable = variables.at(i); QString va = variable.remove("%"); if(va.toLower() == "modelpath") args.replace(variables.at(i), startPath); }*/ // QString startProcess = solverPath + " " + args; // if (solverPath.contains(" ")) // startProcess = QString("\"%1\"").arg(startProcess); // qDebug() << startProcess; // if (!_args.isEmpty()) // startProcess = startProcess + " " + _args; // qDebug() << startProcess; _process.start(solverPath, args.split(" ", QString::SkipEmptyParts)); emit solverStarted(_processBar); ModelData::ModelDataBaseExtend* extend = dynamic_cast(_model); if(extend != nullptr && !_solveOnly) { QList curves = extend->getMonitorCurves(); if(curves.size() > 0) { int id = _model->getID(); Post::RealTimeWindowBase* w = new Post::RealTimeWindowBase(_mainWindow, id); emit openRealTime(w, id); } } if(_solver->getType() == ConfigOption::SelfDevelop) { if(!oldDir.isEmpty()) QDir::setCurrent(oldDir); } } void SolverControlBase::readSolverOutput() { _outputBuffer = QString::fromLocal8Bit(_process.readAll()); QString process = _solver->getProcessKeyWord() + "(\\d+)(?:\\s*)"; // qDebug() << process; QRegExp rx(process); int pos = _outputBuffer.indexOf(rx); if(pos > -1 && _processBar != nullptr) { QString s = rx.cap(1); _processBar->setProcess(s.toInt()); } emit sendMessage(_outputBuffer); } void SolverControlBase::stopSolver(QWidget* w) { if(w != _processBar) return; int id = -1; if(_model != nullptr) id = _model->getID(); emit removeSolver(id); if(!_processFinished) { _process.kill(); } _processBar = nullptr; // this->deleteLater(); } void SolverControlBase::stopSolver() { if(!_processFinished) { _process.kill(); } } void SolverControlBase::startMPI(int nprocess) { QString solverPath = _solver->getExePath(); QFileInfo info(solverPath); if((!info.exists()) || (!info.isFile())) { QMessageBox::warning(nullptr, tr("Warning"), tr("Solver Path Error! Solve Path : %1").arg(solverPath)); return; } bool ok = preProcess(); if(!ok) { QMessageBox::warning(nullptr, tr("Warning"), tr("Input file write failed !")); return; } QString oldDir = ""; QString startPath = _model->getPath(); if(_solver->getType() == ConfigOption::SelfDevelop) { QDir dir(startPath); if(dir.exists() && (!startPath.isEmpty())) { oldDir = QDir::currentPath(); QDir::setCurrent(startPath); } } _processBar = new ModuleBase::ProcessBar(_mainWindow, _description, false); QString args = _solver->getParameter(); QRegExp regExp("%.*%"); regExp.setMinimal(true); // int pos = regExp.indexIn(args); QStringList variables = regExp.capturedTexts(); for(int i = 0; i < variables.size(); ++i) { QString variable = variables.at(i); QString va = variable.remove("%"); if(va.toLower() == "modelpath") args.replace(variables.at(i), startPath); // qDebug() << args; } // QString startProcess = solverPath + " " + args; // if (solverPath.contains(" ")) // startProcess = QString("\"%1\"").arg(startProcess); // qDebug() << startProcess; // if (!_args.isEmpty()) // startProcess = startProcess + " " + _args; // qDebug() << startProcess; QString c = QString("mpiexec -n %1 %2").arg(nprocess).arg(solverPath); _process.start(c); emit solverStarted(_processBar); ModelData::ModelDataBaseExtend* extend = dynamic_cast(_model); if(extend != nullptr && !_solveOnly) { QList curves = extend->getMonitorCurves(); if(curves.size() > 0) { int id = _model->getID(); Post::RealTimeWindowBase* w = new Post::RealTimeWindowBase(_mainWindow, id); emit openRealTime(w, id); } } if(_solver->getType() == ConfigOption::SelfDevelop) { if(!oldDir.isEmpty()) QDir::setCurrent(oldDir); } } void SolverControlBase::setSolveArgs(QString arg) { _args = arg; } void SolverControlBase::startSolverClear() { _solveOnly = true; _processBar = new ModuleBase::ProcessBar(_mainWindow, _description, false); QString solverPath = _solver->getExePath(); _process.start(solverPath, QStringList(_args)); emit solverStarted(_processBar); } void SolverControlBase::processFinished(int exitCode, QProcess::ExitStatus exitStatus) { Q_UNUSED(exitCode); _processFinished = true; int id = -1; if(_model != nullptr) id = _model->getID(); emit processFinish(id); switch(exitStatus) { case QProcess::NormalExit: emit sendMessage("************************************"); emit sendMessage("***** Solving process finished *****"); emit sendMessage("************************************"); break; case QProcess::CrashExit: emit sendMessage("************************************"); emit sendMessage("***** Solving process Crashed ******"); emit sendMessage("************************************"); break; default: emit sendMessage("***********************************"); emit sendMessage("***** Solving process Stopped *****"); emit sendMessage("***********************************"); break; } if(_processBar != nullptr) { if(_processBar->isBusy()) _processBar->setProcessRange(0, 100); _processBar->setProcess(100); } postPorocess(); Py::PythonAgent::getInstance()->unLock(); } bool SolverControlBase::preProcess() { if(_solveOnly) return true; bool istemp = _solver->isWriteTemplate(); if(istemp) { QString te = _solver->getTemplate(); QString path = _model->getPath(); return IO::SolverIO::replaceTemplate(te, path, _model); } else { QString format = _solver->getInputFormat(); return IO::SolverIO::writeInpFile(format, _model); } return false; } bool SolverControlBase::postPorocess() { if(_solveOnly) return true; QString trans = _solver->getTransfer(); QString path = _model->getPath(); return IO::SolverIO::transformFile(trans, path); } } // namespace SolverControl