LAMPCAE/src/SolverControl/SolverControlerBase.cpp

338 lines
9.8 KiB
C++

/**
* @file SolverControlerBase.cpp
* @brief 求解器控制基类源文件
* @author LAMPCAE研发小组(LAMPCAE@diso.cn)
* @version 2.5.0
* @date 2022-03-12 15:34
* @copyright Copyright (c) Since 2020 青岛数智船海科技有限公司 All rights reserved.
*
* ============================================================================
* Program: LAMPCAE
*
* Copyright (c) Since 2020 青岛数智船海科技有限公司 All rights reserved.
* See License or http://www.LAMPCAE.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 <QMessageBox>
#include <QCoreApplication>
#include <QFileInfo>
#include <QDir>
#include <QDebug>
#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<ModelData::ModelDataBaseExtend*>(_model);
if(extend != nullptr && !_solveOnly) {
QList<ConfigOption::PostCurve*> 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<ModelData::ModelDataBaseExtend*>(_model);
if(extend != nullptr && !_solveOnly) {
QList<ConfigOption::PostCurve*> 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