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