Solver convergence checks completed

This commit is contained in:
Anne de Jong 2017-01-02 20:06:41 +01:00
parent 9955c37a93
commit 938fb28e94
6 changed files with 125 additions and 58 deletions

View File

@ -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");
}
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

@ -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);
}; };

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;