Solver convergence checks completed
This commit is contained in:
parent
9955c37a93
commit
938fb28e94
@ -14,16 +14,18 @@
|
||||
#include "tasmet_tracer.h"
|
||||
#include "solver.pb.h"
|
||||
#include <QSharedPointer>
|
||||
#include <QColor>
|
||||
#include "solver_worker.h"
|
||||
#include <algorithm>
|
||||
#include <qcustomplot.h>
|
||||
|
||||
SolverDialog::SolverDialog(QWidget* parent,
|
||||
pb::System& sys):
|
||||
QDialog(parent),
|
||||
_sys(sys),
|
||||
_sparams(sys.solverparams()),
|
||||
_dialog(new Ui::solver_dialog())
|
||||
{
|
||||
|
||||
|
||||
TRACE(15,"SolverDialog");
|
||||
if(_dialog==nullptr) throw TaSMETBadAlloc();
|
||||
|
||||
@ -44,7 +46,32 @@ SolverDialog::SolverDialog(QWidget* parent,
|
||||
_dialog->solvertype->addItem(QString::fromStdString(SolverType_Name((pb::SolverType) solvertype)));
|
||||
}
|
||||
|
||||
// Set the residual plot settings right
|
||||
|
||||
_plot = _dialog->progress_plot;
|
||||
|
||||
_funer = _plot->addGraph();
|
||||
_funer->setName("Residual");
|
||||
QPen funer_pen(Qt::blue);
|
||||
_funer->setPen(QPen(Qt::blue));
|
||||
|
||||
_reler = _plot->addGraph();
|
||||
_reler->setName("Solution error");
|
||||
QPen reler_pen(Qt::red);
|
||||
_reler->setPen(reler_pen);
|
||||
|
||||
_funtol = _plot->addGraph();
|
||||
_funtol->setName("Residual tolerance");
|
||||
QPen funtol_pen(Qt::blue);
|
||||
funtol_pen.setStyle(Qt::DashLine);
|
||||
_funtol->setPen(funtol_pen);
|
||||
|
||||
_reltol = _plot->addGraph();
|
||||
_reltol->setName("Solution tolerance");
|
||||
QPen reltol_pen(Qt::red);
|
||||
reltol_pen.setStyle(Qt::DashLine);
|
||||
_reltol->setPen(reltol_pen);
|
||||
|
||||
_plot->xAxis->setLabel("Iteration [-]");
|
||||
_plot->yAxis->setLabel("Residual [-]");
|
||||
|
||||
@ -52,10 +79,13 @@ SolverDialog::SolverDialog(QWidget* parent,
|
||||
|
||||
QSharedPointer<QCPAxisTicker> ticker(new QCPAxisTickerLog());
|
||||
_plot->yAxis->setTicker(ticker);
|
||||
|
||||
_plot->legend->setVisible(true);
|
||||
|
||||
|
||||
_plot->replot();
|
||||
set(_sys.solverparams());
|
||||
|
||||
_init = false;
|
||||
}
|
||||
SolverDialog::~SolverDialog() {
|
||||
if(_solver_worker)
|
||||
@ -63,13 +93,42 @@ SolverDialog::~SolverDialog() {
|
||||
}
|
||||
void SolverDialog::set(const pb::SolverParams& sol) {
|
||||
TRACE(15,"set");
|
||||
int solvertype= (int) sol.solvertype();
|
||||
_dialog->solvertype->setCurrentIndex(solvertype);
|
||||
|
||||
_dialog->solvertype->setCurrentIndex((int) sol.solvertype());
|
||||
_dialog->funtol->setText(QString::number(sol.funtol()));
|
||||
_dialog->reltol->setText(QString::number(sol.reltol()));
|
||||
d funtol = sol.funtol();
|
||||
_dialog->funtol->setText(QString::number(funtol));
|
||||
|
||||
d reltol = sol.reltol();
|
||||
_dialog->reltol->setText(QString::number(reltol));
|
||||
|
||||
}
|
||||
void SolverDialog::changed() {
|
||||
if(_init) return;
|
||||
_sys.mutable_solverparams()->set_funtol(_dialog->funtol->text().toDouble());
|
||||
_sys.mutable_solverparams()->set_reltol(_dialog->reltol->text().toDouble());
|
||||
_sys.mutable_solverparams()->set_solvertype((pb::SolverType) _dialog->solvertype->currentIndex());
|
||||
}
|
||||
void SolverDialog::solver_progress(const SolverProgress& progress){
|
||||
|
||||
TRACE(15,"SolverDialog::solver_progress()");
|
||||
|
||||
|
||||
// VARTRACE(15,progress.fun_err);
|
||||
// VARTRACE(15,progress.iteration);
|
||||
d funtol = _sys.solverparams().funtol();
|
||||
d reltol = _sys.solverparams().reltol();
|
||||
|
||||
_funer->addData(progress.iteration,progress.fun_err);
|
||||
_reler->addData(progress.iteration,progress.rel_err);
|
||||
|
||||
_funtol->addData(progress.iteration,funtol);
|
||||
_reltol->addData(progress.iteration,reltol);
|
||||
|
||||
_plot->xAxis->setRange(0,progress.iteration);
|
||||
_plot->yAxis->setRange(std::min(funtol,reltol)/10,1e0);
|
||||
|
||||
_plot->replot();
|
||||
|
||||
}
|
||||
void SolverDialog::on_stop_clicked(){
|
||||
@ -78,12 +137,14 @@ void SolverDialog::on_stop_clicked(){
|
||||
}
|
||||
void SolverDialog::on_solve_clicked() {
|
||||
TRACE(15,"on_solve_clicked");
|
||||
_dialog->solve->setEnabled(false);
|
||||
_dialog->singleiteration->setEnabled(false);
|
||||
_dialog->stop->setEnabled(true);
|
||||
|
||||
// Disable buttons
|
||||
setEnabled(false);
|
||||
|
||||
assert(!_solver_worker);
|
||||
|
||||
qRegisterMetaType<SolverProgress>();
|
||||
|
||||
_solver_worker = new SolverWorker(_sys);
|
||||
QThread* thread = new QThread;
|
||||
|
||||
@ -105,29 +166,46 @@ void SolverDialog::on_solve_clicked() {
|
||||
connect(thread, &QThread::finished,
|
||||
_solver_worker, &SolverWorker::deleteLater);
|
||||
|
||||
connect(_solver_worker, &SolverWorker::progress,
|
||||
this, &SolverDialog::solver_progress);
|
||||
|
||||
thread->start();
|
||||
|
||||
|
||||
}
|
||||
void SolverDialog::on_singleiteration_clicked() {
|
||||
_dialog->solve->setEnabled(false);
|
||||
_dialog->singleiteration->setEnabled(false);
|
||||
_dialog->stop->setEnabled(true);
|
||||
|
||||
}
|
||||
void SolverDialog::setEnabled(bool enabled){
|
||||
_dialog->solve->setEnabled(enabled);
|
||||
_dialog->singleiteration->setEnabled(enabled);
|
||||
_dialog->stop->setEnabled(!enabled);
|
||||
|
||||
_dialog->solvertype->setEnabled(enabled);
|
||||
_dialog->reltol->setEnabled(enabled);
|
||||
_dialog->funtol->setEnabled(enabled);
|
||||
|
||||
}
|
||||
|
||||
void SolverDialog::solver_stopped() {
|
||||
_dialog->solve->setEnabled(true);
|
||||
_dialog->singleiteration->setEnabled(true);
|
||||
_dialog->stop->setEnabled(false);
|
||||
|
||||
void SolverDialog::solver_stopped(bool converged) {
|
||||
setEnabled(true);
|
||||
// stop the solver and delete it
|
||||
if(_solver_worker!=nullptr) {
|
||||
_solver_worker->solver_stop();
|
||||
_solver_worker = nullptr;
|
||||
}
|
||||
|
||||
if(converged) {
|
||||
QMessageBox::information(this,
|
||||
"Solution converged",
|
||||
"Solution found within required tolerance");
|
||||
|
||||
}
|
||||
else {
|
||||
QMessageBox::information(this,
|
||||
"Solver failed",
|
||||
"Failed to find solution");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -20,16 +20,21 @@ namespace Ui {
|
||||
class solver_dialog;
|
||||
}
|
||||
class QCustomPlot;
|
||||
class QCPGraph;
|
||||
class SolverWorker;
|
||||
class SolverProgress;
|
||||
|
||||
class SolverDialog: public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
pb::System& _sys; // Reference to system
|
||||
pb::SolverParams _sparams;
|
||||
|
||||
Ui::solver_dialog* _dialog;
|
||||
|
||||
bool _init = true;
|
||||
|
||||
QCustomPlot* _plot;
|
||||
QCPGraph *_funer,*_reler,*_funtol,*_reltol;
|
||||
|
||||
SolverWorker* _solver_worker = nullptr;
|
||||
|
||||
@ -41,12 +46,12 @@ public:
|
||||
~SolverDialog();
|
||||
|
||||
void set(const pb::SolverParams&);
|
||||
|
||||
|
||||
public slots:
|
||||
void solver_progress(const SolverProgress&);
|
||||
private slots:
|
||||
// Connected to the signal from the solver thread. Reactivates the
|
||||
// buttons
|
||||
void solver_stopped();
|
||||
void solver_stopped(bool converged);
|
||||
|
||||
void on_solve_clicked();
|
||||
void on_singleiteration_clicked();
|
||||
@ -58,7 +63,7 @@ private slots:
|
||||
private:
|
||||
// Called whenever the user changes input values
|
||||
void changed();
|
||||
|
||||
void setEnabled(bool);
|
||||
};
|
||||
|
||||
|
||||
|
@ -13,7 +13,9 @@
|
||||
#include <QThread>
|
||||
#include <qcustomplot.h>
|
||||
SolverWorker::SolverWorker(pb::System& sys):
|
||||
_run(false)
|
||||
_run(false),
|
||||
_reltol(sys.solverparams().reltol()),
|
||||
_funtol(sys.solverparams().funtol())
|
||||
{
|
||||
|
||||
}
|
||||
@ -35,55 +37,35 @@ void SolverWorker::solver_start() {
|
||||
|
||||
SolverProgress p;
|
||||
// For testing purposes
|
||||
|
||||
SolverAction action;
|
||||
while(true) {
|
||||
TRACE(15,"Solver start virtual iteration");
|
||||
|
||||
|
||||
SolverAction action = callback(p);
|
||||
if(action == Stop) break;
|
||||
if(action != Continue) break;
|
||||
sleep(1);
|
||||
|
||||
p.fun_err/=10;
|
||||
p.rel_err/=10;
|
||||
p.iteration++;
|
||||
|
||||
}
|
||||
|
||||
emit solver_stopped();
|
||||
emit solver_stopped(_converged);
|
||||
}
|
||||
SolverAction SolverWorker::pg_callback(SolverProgress pg) {
|
||||
TRACE(15,"pg_callback");
|
||||
|
||||
if(!_run) return Stop;
|
||||
|
||||
emit progress(pg);
|
||||
|
||||
// QCPGraph *_funer,*_reler,*_funtol,*_reltol;
|
||||
|
||||
// _funer = _plot->addGraph();
|
||||
// _reler = _plot->addGraph();
|
||||
|
||||
TRACE(15,"SolverWorker::pg_callback()");
|
||||
|
||||
// VARTRACE(15,progress.fun_err);
|
||||
// VARTRACE(15,progress.iteration);
|
||||
// _funer->addData(progress.iteration,progress.fun_err);
|
||||
// _reler->addData(progress.iteration,progress.rel_err);
|
||||
|
||||
// _plot->xAxis->setRange(0,progress.iteration);
|
||||
|
||||
// _plot->replot();
|
||||
|
||||
// if(progress.done) {
|
||||
// // We are done!
|
||||
|
||||
// QString m = "Solver reached a converged solution.";
|
||||
|
||||
// QMessageBox::information(this,
|
||||
// "Solver done",
|
||||
// m);
|
||||
|
||||
|
||||
// }
|
||||
|
||||
if(pg.fun_err <= _funtol && pg.rel_err <= _reltol) {
|
||||
_converged = true;
|
||||
return Stop;
|
||||
}
|
||||
|
||||
return Continue;
|
||||
|
||||
|
@ -25,6 +25,8 @@ class SolverWorker: public QObject {
|
||||
|
||||
std::atomic<bool> _run;
|
||||
Solver<GradientNonlinearSystem,vd>* _solver;
|
||||
bool _converged = false;
|
||||
d _funtol,_reltol;
|
||||
public:
|
||||
|
||||
SolverWorker(pb::System& sys);
|
||||
@ -36,8 +38,8 @@ public slots:
|
||||
signals:
|
||||
|
||||
// This signal is emitted when the solver is stopped
|
||||
void solver_stopped();
|
||||
void progress(SolverProgress);
|
||||
void solver_stopped(bool converged);
|
||||
void progress(const SolverProgress&);
|
||||
private:
|
||||
SolverAction pg_callback(SolverProgress pg);
|
||||
|
||||
|
@ -29,7 +29,7 @@ struct SolverProgress
|
||||
|
||||
enum SolverAction{
|
||||
Continue=0,
|
||||
Stop = 1
|
||||
Stop=1
|
||||
};
|
||||
|
||||
typedef std::function<SolverAction(SolverProgress)> progress_callback;
|
||||
|
@ -82,7 +82,7 @@ namespace constants {
|
||||
const d min_funtol = 1e-16;
|
||||
const d default_funtol = 1e-6;
|
||||
const d max_funtol = 1e-1;
|
||||
const us funtol_decimals = 10;
|
||||
|
||||
|
||||
const us default_maxiter = 1000;
|
||||
const us min_maxiter = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user