Almost finished solver. Plot update needs to run in main thread. Use signaling for progress
This commit is contained in:
parent
cdc144e7d6
commit
9955c37a93
@ -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)
|
||||
|
@ -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()");
|
||||
|
@ -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();}
|
||||
|
@ -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"/>
|
||||
|
@ -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
133
src/gui/solver_dialog.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
@ -8,25 +8,59 @@
|
||||
#pragma once
|
||||
#ifndef SOLVER_DIALOG_H
|
||||
#define SOLVER_DIALOG_H
|
||||
#include <QDialog>
|
||||
#include <QThread>
|
||||
|
||||
#include "solver.pb.h"
|
||||
|
||||
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&);
|
||||
|
||||
|
||||
// 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));
|
||||
private slots:
|
||||
// Connected to the signal from the solver thread. Reactivates the
|
||||
// buttons
|
||||
void solver_stopped();
|
||||
|
||||
window->maxiter->setText(QString::number(constants::default_maxiter));
|
||||
window->maxiter->setValidator(new QIntValidator(constants::min_maxiter,
|
||||
constants::max_maxiter));
|
||||
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();
|
||||
|
||||
};
|
||||
|
||||
for(const SolverType& t: SolverType_vec){
|
||||
window->solvertype->addItem(SolverTypeToString(t));
|
||||
}
|
||||
|
||||
|
||||
#endif // SOLVER_DIALOG_H
|
||||
|
@ -1,86 +1,165 @@
|
||||
<?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>
|
||||
<widget class="QGroupBox" name="solversettings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>40</y>
|
||||
<width>306</width>
|
||||
<height>168</height>
|
||||
</rect>
|
||||
</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="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="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</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>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<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_13">
|
||||
<property name="text">
|
||||
<string>Solver type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<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>
|
||||
</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>
|
||||
</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
95
src/gui/solver_worker.cpp
Normal 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
48
src/gui/solver_worker.h
Normal 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
|
||||
//////////////////////////////////////////////////////////////////////
|
@ -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
16
src/protobuf/solver.proto
Normal 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];
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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*);
|
||||
};
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user