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

View File

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

View File

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

View File

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

View File

@ -29,7 +29,7 @@ struct SolverProgress
enum SolverAction{
Continue=0,
Stop = 1
Stop=1
};
typedef std::function<SolverAction(SolverProgress)> progress_callback;

View File

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