Almost finished solver. Plot update needs to run in main thread. Use signaling for progress

This commit is contained in:
Anne de Jong 2017-01-01 20:18:22 +01:00
parent cdc144e7d6
commit 9955c37a93
19 changed files with 556 additions and 354 deletions

View File

@ -7,6 +7,8 @@ add_library(tasmet_gui
add_duct_dialog.cpp
add_ductbc_dialog.cpp
about_dialog.cpp
solver_dialog.cpp
solver_worker.cpp
)
target_link_libraries(tasmet_gui qcustomplot)

View File

@ -7,26 +7,30 @@
//////////////////////////////////////////////////////////////////////
#include "mainwindow.h"
#include "tasmet_config.h"
#include "ui_mainwindow.h"
#include <sstream>
#include <QString>
#include <QSettings>
#include <QWidget>
#include <QDoubleValidator>
#include <QIntValidator>
#include "gas.h"
#include <QFileDialog>
#include <QStandardPaths>
#include "tasmet_config.h"
#include "tasmet_tracer.h"
#include "tasmet_assert.h"
#include "tasmet_exception.h"
#include "add_duct_dialog.h"
#include "add_ductbc_dialog.h"
#include "tasystem.h"
#include "tasmet_exception.h"
#include <QFileDialog>
#include <QStandardPaths>
#include <sstream>
#include "about_dialog.h"
#include <google/protobuf/text_format.h>
#include "about_dialog.h"
#include "solver_dialog.h"
#include <google/protobuf/text_format.h>
using google::protobuf::TextFormat;
const QString default_system_name = QString("Unsaved TaSMET Model") +
@ -426,7 +430,7 @@ void TaSMETMainWindow::on_segmentid_valueChanged(int id) {
_window->removesegment->setEnabled(is_segment);
}
void TaSMETMainWindow::on_name_textEdited() {
void TaSMETMainWindow::on_segmentname_textEdited() {
auto& ductmap = *_system.mutable_ducts();
auto& ductbcmap = *_system.mutable_ductbcs();
@ -444,8 +448,22 @@ void TaSMETMainWindow::on_name_textEdited() {
void TaSMETMainWindow::on_actionSolve_triggered() {
TRACE(15,"actionSolve()");
TaSystem sys(_system);
SolverDialog *d;
try {
d = new SolverDialog(this,_system);
}
catch(TaSMETError &e) {
e.show_user("Solver failed to initialize");
return;
}
d->exec();
// Solution is put in system, system updated from solver
// dialog. Therefore we are now probably dirty
changed();
delete d;
}
bool TaSMETMainWindow::isDirty() const {
TRACE(15,"isDirty()");

View File

@ -54,7 +54,7 @@ private slots:
void on_addsegment_clicked();
void on_removesegment_clicked();
void on_segmentid_valueChanged(int i);
void on_name_textEdited();
void on_segmentname_textEdited();
// Couple slots to functions
void on_actionNew_triggered() { newModel();}

View File

@ -347,6 +347,8 @@
<string>Solver</string>
</property>
<addaction name="actionSolve"/>
<addaction name="actionReinitialize_solver"/>
<addaction name="actionPosprocess_model"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuSolver"/>
@ -419,6 +421,16 @@
<string>Solve...</string>
</property>
</action>
<action name="actionReinitialize_solver">
<property name="text">
<string>Reinitialize solver</string>
</property>
</action>
<action name="actionPosprocess_model">
<property name="text">
<string>Posprocess model...</string>
</property>
</action>
</widget>
<resources>
<include location="tasmet_resources.qrc"/>

View File

@ -1,188 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>730</width>
<height>362</height>
</rect>
</property>
<property name="windowTitle">
<string>TaSMET Solver</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="solversettings">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Solver Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="3" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Maximum iterations:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Solver type</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="solvertype"/>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="reltol">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Solution tolerance:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Residual tolerance:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="funtol">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="maxiter">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="solve_gb">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Solve!</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Solve</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_3">
<property name="text">
<string>Single iteration</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="progress_gb">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Progress</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCustomPlot" name="rel_error" native="true"/>
</item>
<item>
<widget class="QCustomPlot" name="fun_error" native="true"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QCustomPlot</class>
<extends>QWidget</extends>
<header>qcustomplot.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

133
src/gui/solver_dialog.cpp Normal file
View File

@ -0,0 +1,133 @@
// solver_dialog.cpp
//
// last-edit-by: J.A. de Jong
//
// Description:
//
//////////////////////////////////////////////////////////////////////
#include "solver_dialog.h"
#include "ui_solver_dialog.h"
#include "system.pb.h"
#include "tasmet_exception.h"
#include "tasmet_constants.h"
#include "tasmet_tracer.h"
#include "solver.pb.h"
#include <QSharedPointer>
#include "solver_worker.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();
_dialog->setupUi(this);
_dialog->funtol->setValidator(new QDoubleValidator(constants::min_funtol,
constants::max_funtol,
constants::field_decimals));
_dialog->reltol->setValidator(new QDoubleValidator(constants::min_funtol,
constants::max_funtol,
constants::field_decimals));
// _dialog->maxiter->setValidator(new QIntValidator(constants::min_maxiter,
// constants::max_maxiter));
for(int solvertype = pb::SolverType_MIN;solvertype<=pb::SolverType_MAX;solvertype++){
_dialog->solvertype->addItem(QString::fromStdString(SolverType_Name((pb::SolverType) solvertype)));
}
_plot = _dialog->progress_plot;
_plot->xAxis->setLabel("Iteration [-]");
_plot->yAxis->setLabel("Residual [-]");
_plot->yAxis->setScaleType(QCPAxis::stLogarithmic);
QSharedPointer<QCPAxisTicker> ticker(new QCPAxisTickerLog());
_plot->yAxis->setTicker(ticker);
_plot->replot();
set(_sys.solverparams());
}
SolverDialog::~SolverDialog() {
if(_solver_worker)
_solver_worker->solver_stop();
}
void SolverDialog::set(const pb::SolverParams& sol) {
TRACE(15,"set");
_dialog->solvertype->setCurrentIndex((int) sol.solvertype());
_dialog->funtol->setText(QString::number(sol.funtol()));
_dialog->reltol->setText(QString::number(sol.reltol()));
}
void SolverDialog::changed() {
}
void SolverDialog::on_stop_clicked(){
tasmet_assert(_solver_worker!=nullptr,"No _solver_worker");
_solver_worker->solver_stop();
}
void SolverDialog::on_solve_clicked() {
TRACE(15,"on_solve_clicked");
_dialog->solve->setEnabled(false);
_dialog->singleiteration->setEnabled(false);
_dialog->stop->setEnabled(true);
assert(!_solver_worker);
_solver_worker = new SolverWorker(_sys);
QThread* thread = new QThread;
_solver_worker->moveToThread(thread);
connect(thread, &QThread::started,
_solver_worker, &SolverWorker::solver_start);
connect(_solver_worker, &SolverWorker::solver_stopped,
thread, &QThread::quit);
connect(_solver_worker, &SolverWorker::solver_stopped,
this, &SolverDialog::solver_stopped);
connect(thread, &QThread::finished,
thread, &QThread::deleteLater);
connect(thread, &QThread::finished,
_solver_worker, &SolverWorker::deleteLater);
thread->start();
}
void SolverDialog::on_singleiteration_clicked() {
_dialog->solve->setEnabled(false);
_dialog->singleiteration->setEnabled(false);
_dialog->stop->setEnabled(true);
}
void SolverDialog::solver_stopped() {
_dialog->solve->setEnabled(true);
_dialog->singleiteration->setEnabled(true);
_dialog->stop->setEnabled(false);
// stop the solver and delete it
if(_solver_worker!=nullptr) {
_solver_worker->solver_stop();
_solver_worker = nullptr;
}
}
//////////////////////////////////////////////////////////////////////

View File

@ -8,25 +8,59 @@
#pragma once
#ifndef SOLVER_DIALOG_H
#define SOLVER_DIALOG_H
#include <QDialog>
#include <QThread>
#include "solver.pb.h"
// Put here, temporarily
window->funtol->setText(QString::number(constants::default_funtol));
window->funtol->setValidator(new QDoubleValidator(constants::min_funtol,
constants::max_funtol,
constants::field_decimals));
window->reltol->setText(QString::number(constants::default_funtol));
window->reltol->setValidator(new QDoubleValidator(constants::min_funtol,
constants::max_funtol,
constants::field_decimals));
window->maxiter->setText(QString::number(constants::default_maxiter));
window->maxiter->setValidator(new QIntValidator(constants::min_maxiter,
constants::max_maxiter));
for(const SolverType& t: SolverType_vec){
window->solvertype->addItem(SolverTypeToString(t));
namespace pb {
class System;
}
namespace Ui {
class solver_dialog;
}
class QCustomPlot;
class SolverWorker;
class SolverDialog: public QDialog {
Q_OBJECT
pb::System& _sys; // Reference to system
pb::SolverParams _sparams;
Ui::solver_dialog* _dialog;
QCustomPlot* _plot;
SolverWorker* _solver_worker = nullptr;
public:
SolverDialog(QWidget* parent,
pb::System& sys);
~SolverDialog();
void set(const pb::SolverParams&);
private slots:
// Connected to the signal from the solver thread. Reactivates the
// buttons
void solver_stopped();
void on_solve_clicked();
void on_singleiteration_clicked();
void on_stop_clicked();
void on_funtol_textChanged() { changed();}
void on_reltol_textChanged() { changed();}
void on_solvertype_currentIndexChanged(int) { changed();}
private:
// Called whenever the user changes input values
void changed();
};
#endif // SOLVER_DIALOG_H

View File

@ -1,50 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<class>solver_dialog</class>
<widget class="QDialog" name="solver_dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>747</width>
<height>336</height>
<width>730</width>
<height>362</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
<string>TaSMET Solver</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="solversettings">
<property name="geometry">
<rect>
<x>10</x>
<y>40</y>
<width>306</width>
<height>168</height>
</rect>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Solver Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="3" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Maximum iterations:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Solver type</string>
</property>
</widget>
</item>
<item row="4" column="1">
<item row="3" column="1">
<widget class="QComboBox" name="solvertype"/>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="reltol">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
@ -66,13 +67,12 @@
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="funtol">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="maxiter">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
@ -80,7 +80,86 @@
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="solve_gb">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Solve!</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="solve">
<property name="text">
<string>Solve</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="stop">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="singleiteration">
<property name="text">
<string>Single iteration</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="progress_gb">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Progress</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCustomPlot" name="progress_plot" native="true"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QCustomPlot</class>
<extends>QWidget</extends>
<header>qcustomplot.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

95
src/gui/solver_worker.cpp Normal file
View File

@ -0,0 +1,95 @@
// solver_thread.cpp
//
// last-edit-by: J.A. de Jong
//
// Description:
//
//////////////////////////////////////////////////////////////////////
#include "solver_worker.h"
#include <functional>
#include "tasmet_tracer.h"
#include "system.pb.h"
#include <QThread>
#include <qcustomplot.h>
SolverWorker::SolverWorker(pb::System& sys):
_run(false)
{
}
SolverWorker::~SolverWorker(){
TRACE(15,"~SolverWorker");
}
void SolverWorker::solver_stop() {
_run = false;
}
void SolverWorker::solver_start() {
TRACE(15,"SolverWorker::solver_start()");
using namespace std::placeholders; // for _1, _2 etc.
_run = true;
progress_callback callback = std::bind(&SolverWorker::pg_callback,
this,_1);
SolverProgress p;
// For testing purposes
while(true) {
TRACE(15,"Solver start virtual iteration");
SolverAction action = callback(p);
if(action == Stop) break;
sleep(1);
p.fun_err/=10;
p.rel_err/=10;
p.iteration++;
}
emit solver_stopped();
}
SolverAction SolverWorker::pg_callback(SolverProgress pg) {
TRACE(15,"pg_callback");
if(!_run) return Stop;
// 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);
// }
return Continue;
}
//////////////////////////////////////////////////////////////////////

48
src/gui/solver_worker.h Normal file
View File

@ -0,0 +1,48 @@
// solver_worker.h
//
// Author: J.A. de Jong
//
// Description:
// Worker which solves the system, updates the progress graph,
// etc
//////////////////////////////////////////////////////////////////////
#pragma once
#ifndef SOLVER_WORKER_H
#define SOLVER_WORKER_H
#include "tasmet_types.h"
#include "solver.h"
#include "system.h"
#include <atomic>
#include <QObject>
namespace pb{
class System;
}
Q_DECLARE_METATYPE(SolverProgress);
class SolverWorker: public QObject {
Q_OBJECT
std::atomic<bool> _run;
Solver<GradientNonlinearSystem,vd>* _solver;
public:
SolverWorker(pb::System& sys);
~SolverWorker();
void solver_stop();
public slots:
void solver_start();
signals:
// This signal is emitted when the solver is stopped
void solver_stopped();
void progress(SolverProgress);
private:
SolverAction pg_callback(SolverProgress pg);
};
#endif // SOLVER_WORKER_H
//////////////////////////////////////////////////////////////////////

View File

@ -45,22 +45,17 @@ int main(int argc, char *argv[]) {
// Q_INIT_RESOURCE(application);
INITTRACE(15);
std::cout << "hoid" << std::endl;
// Initialize PythonQt
// PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
PythonQt::init();
std::cout << "hoid" << std::endl;
PythonQt* pyqt = PythonQt::self();
PythonQtObjectPtr context = pyqt->getMainModule();
std::cout << "hoid" << std::endl;
QVariant rv = context.evalScript("from math import *\n");
if(pyqt->hadError()) {
return -1;
}
std::cout << "hoid" << std::endl;
// std::cout << rv.typeName() << std::endl;
std::cout << (rv.isNull()?"true": "false") << std::endl;
std::cout << "hoid" << std::endl;
QApplication app(argc, argv);

16
src/protobuf/solver.proto Normal file
View File

@ -0,0 +1,16 @@
syntax = "proto2";
package pb;
enum SolverType {
NewtonRaphson = 0;
}
// Parameters the solver requires to operate
message SolverParams {
optional SolverType solvertype = 1 [default=NewtonRaphson];
optional double reltol = 3 [default = 1e-6];
optional double funtol = 4 [default = 1e-6];
optional double fun_err = 5 [default = 1e0];
optional double rel_err = 2 [default = 1e0];
optional uint32 iteration = 6 [default = 0];
}

View File

@ -4,6 +4,7 @@ package pb;
import "duct.proto";
import "ductbc.proto";
import "gas.proto";
import "solver.proto";
enum SystemType {
TaSystem = 0;
@ -18,4 +19,5 @@ message System {
map<uint32,Duct> ducts = 7;
map<uint32,DuctBc> ductbcs = 8;
repeated double solution = 9;
optional SolverParams solverparams = 10;
}

View File

@ -17,16 +17,15 @@
const d eps = std::numeric_limits<d>::epsilon();
Brent::Brent(const NoGradientNonlinearSystem<d>& sys,us maxiter,d reltol):
Brent::Brent(const NoGradientNonlinearSystem<d>& sys,d reltol):
Solver(sys),
_reltol(reltol),
_maxiter(maxiter)
_reltol(reltol)
{
TRACE(15,"Brent::Brent");
#ifdef TASMET_DEBUG
bool ok=true;
ok&=(maxiter>0);
ok&=(reltol >= eps);
if(!ok){
@ -89,7 +88,7 @@ void Brent::start_implementation(NoGradientNonlinearSystem<d>& system,
bool bisec_flag;
SolverProgress progress;
while(_running && progress.iteration <=_maxiter) {
while(true) {
if((fa!=fc) && (fb!=fc)){
// Inverse quadratic interpolation

View File

@ -12,9 +12,9 @@
class Brent: public Solver<NoGradientNonlinearSystem<d>,d> {
d _reltol;
us _maxiter;
public:
Brent(const NoGradientNonlinearSystem<d>& sys,us maxiter=10000,d reltol=1e-6);
Brent(const NoGradientNonlinearSystem<d>& sys,d reltol=1e-6);
protected:
void start_implementation(NoGradientNonlinearSystem<d>& sys,progress_callback*);
};

View File

@ -26,7 +26,7 @@ void NewtonRaphson::start_implementation(GradientNonlinearSystem& system,
SolverProgress progress;
SolverAction action;
while (_running && progress.iteration<=_maxiter) {
while (true) {
sdmat jac=system.jacobian();

View File

@ -20,70 +20,28 @@ static void SolverThread(Solver<system_T,result_T>* solver,
template<typename system_T,typename result_T>
Solver<system_T,result_T>::Solver(const system_T& sys){
_sys = sys.copy();
if(!_sys)
throw TaSMETBadAlloc();
_running = false;
if(!_sys) throw TaSMETBadAlloc();
}
template<typename system_T,typename result_T>
Solver<system_T,result_T>::~Solver(){
stop();
assert(!_running);
assert(!_solver_thread);
delete _sys;
}
template<typename system_T,typename result_T>
void Solver<system_T,result_T>::start(progress_callback* callback,bool wait){
if(_running){
assert(_solver_thread);
throw TaSMETError("Solver already running");
}
assert(_solver_thread == nullptr);
if(!wait) {
this->_solver_thread = new std::thread(SolverThread<system_T,result_T>,
this,
_sys,
callback);
if(!_solver_thread)
throw TaSMETBadAlloc();
}
else {
void Solver<system_T,result_T>::start(progress_callback* callback){
TRACE(15,"Waiting for solver...");
start_implementation(*_sys,callback);
}
}
template<typename system_T,typename result_T>
void Solver<system_T,result_T>::stop() {
_running = false;
if(_solver_thread){
_solver_thread->join();
delete _solver_thread;
_solver_thread = nullptr;
}
}
template<typename system_T,typename result_T>
result_T Solver<system_T,result_T>::getSolution() {
if(_running){
throw TaSMETError("Solver is running");
}
// Cleanup thread resources
stop();
return _sys->getSolution();
}
template<typename system_T,typename result_T>

View File

@ -21,11 +21,12 @@
struct SolverProgress
{
size_t iteration = 0;
d fun_err;
d rel_err;
d fun_err = 1e0;
d rel_err = 1e0;
bool done = false;
};
enum SolverAction{
Continue=0,
Stop = 1
@ -38,22 +39,17 @@ class Solver {
protected:
system_T* _sys = nullptr;
std::thread* _solver_thread = nullptr;
std::atomic<bool> _running;
public:
Solver(const system_T& sys);
Solver(const Solver&)=delete;
Solver& operator=(const Solver&)=delete;
void start(progress_callback* callback=nullptr,bool wait=true);
void stop(); // Stops the solver
void start(progress_callback* callback);
// Returns the solution of the problem
result_T getSolution();
virtual ~Solver();
template<typename Y,typename rT>
friend void SolverThread(Solver<Y,rT>*,Y*,progress_callback*);
protected:
virtual void start_implementation(system_T& sys,progress_callback*)=0;
};

View File

@ -19,7 +19,10 @@ class NoGradientNonlinearSystem{
public:
virtual T residual() const=0;
virtual T residual(const T& guess) { updateSolution(guess); return residual();}
virtual T residual(const T& guess) {
updateSolution(guess);
return residual();
}
// Obtain an initial guess of the solution
virtual T getSolution() const=0;