From 119214800de390d231aa6067567b49360d003905 Mon Sep 17 00:00:00 2001 From: "J.A. de Jong @ vulgaris" Date: Mon, 2 Jan 2017 22:46:22 +0100 Subject: [PATCH] Now working on solving models --- CMakeLists.txt | 3 +- src/CMakeLists.txt | 2 + src/duct/duct.cpp | 2 +- src/gui/mainwindow.cpp | 126 ++++++++++------------------------ src/gui/mainwindow.h | 4 +- src/gui/solver_dialog.cpp | 21 +++++- src/protobuf/system_tools.cpp | 76 ++++++++++++++++++++ src/protobuf/system_tools.h | 27 ++++++++ src/tasmet_solvemodel.cpp | 70 +++++++++++++++++++ 9 files changed, 233 insertions(+), 98 deletions(-) create mode 100644 src/protobuf/system_tools.cpp create mode 100644 src/protobuf/system_tools.h create mode 100644 src/tasmet_solvemodel.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f3f595a..2ade057 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,5 +131,6 @@ add_subdirectory(src) add_subdirectory(testing) add_executable(tasmet src/main.cpp src/gui/tasmet_resources.qrc) +add_executable(tasmet_solvemodel src/tasmet_solvemodel.cpp) target_link_libraries(tasmet tasmet_gui tasmet_src messages PythonQt Qt5::Widgets openblas) - +target_link_libraries(tasmet_solvemodel tasmet_src messages PythonQt openblas) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3a3de20..2bcd0c8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,6 +32,8 @@ add_library(tasmet_src tasmet_assert.cpp tasmet_pyeval.cpp + protobuf/system_tools.cpp + duct/grid.cpp duct/geom.cpp duct/duct.cpp diff --git a/src/duct/duct.cpp b/src/duct/duct.cpp index faa89ee..2fbae1e 100644 --- a/src/duct/duct.cpp +++ b/src/duct/duct.cpp @@ -14,7 +14,7 @@ Duct::Duct(const us id,const pb::Duct& duct): Segment(id,duct.name()), Geom(duct) { - + TRACE(15,"Duct::Duct()"); const char* invTsfun = "Invalid solid-temperature prescribing function"; EvaluateFun Tsfun(duct.stempfunc(),invTsfun); Tsfun.addGlobalDef("L",duct.length()); diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 4a16bde..38c8384 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -29,9 +29,7 @@ #include "about_dialog.h" #include "solver_dialog.h" - -#include -using google::protobuf::TextFormat; +#include "system_tools.h" const QString default_system_name = QString("Unsaved TaSMET Model") + constants::system_fileext; @@ -41,41 +39,6 @@ const QString start_file_location = QStandardPaths:: const QString filetype = QString("TaSMET Model files (*") + constants::system_fileext + ")"; const QString window_title_part = "TaSMET Model Builder - "; namespace { - pb::System loadSystem(const string& filepath) { - - TRACE(15,"loadSystem()"); - VARTRACE(15,filepath); - std::ifstream myfile(filepath); - - if(!myfile.good()) { - string error = "Read error on "; - error += filepath; - throw TaSMETError(error); - - } - - pb::System sys; - - std::stringstream strStream; - strStream << myfile.rdbuf(); //read the file - string data = strStream.str();//str holds the content of the file - VARTRACE(15,data); - - if(!TextFormat::ParseFromString(data,&sys)) { - string error = "Invalid TaSMET Model file: "; - error += filepath; - throw TaSMETError(error); - } - - return sys; - - - } - - // // Returns true when the two systems are equal - bool compareSys(const pb::System& s1,const pb::System& s2) { - return (s1.SerializeAsString()==s2.SerializeAsString()); - } int saveFileFirstQuestion(QWidget* parent) { @@ -127,7 +90,7 @@ TaSMETMainWindow::TaSMETMainWindow(): _window->p0->setValidator(new QDoubleValidator(constants::min_p0, constants::max_p0, constants::field_decimals)); - _window->segmentname->setText(default_system_name); + _window->segmentname->setText(default_segment_name); _window->segmentid->setMaximum(constants::max_segs); @@ -160,9 +123,9 @@ void TaSMETMainWindow::loadModel() { QString title = tr("Open existing TaSMET model file"); QString filepath = QFileDialog::getOpenFileName(this, - title, - start_file_location, - filetype); + title, + start_file_location, + filetype); string filepath_s = filepath.toStdString(); if(filepath.size()!=0) { try { @@ -190,35 +153,16 @@ void TaSMETMainWindow::saveModel(string* filepath) { else if(filepath == nullptr) { filepath = &_filepath; } - - std::ofstream sfile(*filepath); - if(!sfile.good()){ - - QMessageBox::warning(this, - "File error", - "Could not open file for saving"); - return; - } - string data; - if(TextFormat::PrintToString(_system,&data)) { - // Can maybe assign to itself. Which is no problem - // according to C++ docs - TRACE(15,"Saving file succeeded"); - VARTRACE(15,data); - sfile << data; - // Close file here, such that in can be opened to compare - // whether the file is still dirty - sfile.close(); + try { + saveSystem(*filepath,_system); _filepath = *filepath; changed(); } - else { - QMessageBox::warning(this, - "File error", - "Could not save model to file"); + catch(TaSMETError &e) { + + e.show_user("Saving file failed"); } - } } @@ -276,8 +220,27 @@ void TaSMETMainWindow::changed() { _window->segoverview->setPlainText(QString::fromStdString(_system.DebugString())); // Update stuff based on the segments - int value = _window->segmentid->value(); - on_segmentid_valueChanged(value); + int segid = _window->segmentid->value(); + + bool is_segment = false; + + auto& ductmap = *_system.mutable_ducts(); + auto& ductbcmap = *_system.mutable_ductbcs(); + + if(ductmap.find(segid) != ductmap.end()) { + _window->segmentname->setText(QString::fromStdString(ductmap[segid].name())); + _window->segmenttype->setCurrentIndex((int) Duct); + is_segment = true; + } + if(ductbcmap.find(segid) != ductbcmap.end()) { + _window->segmentname->setText(QString::fromStdString(ductbcmap[segid].name())); + _window->segmenttype->setCurrentIndex((int) DuctBc); + is_segment = true; + } + + _window->removesegment->setEnabled(is_segment); + _window->segmenttype->setEnabled(!is_segment); + } void TaSMETMainWindow::set(const pb::System& sys) { @@ -388,11 +351,11 @@ void TaSMETMainWindow::on_addsegment_clicked() { } if(exitcode == QDialog::Accepted) { - _window->segmentid->setValue(id+1); changed(); } } + void TaSMETMainWindow::on_removesegment_clicked() { TRACE(15,"on_remove"); QString question = "Are you you wish to delete segment "; @@ -411,27 +374,8 @@ void TaSMETMainWindow::on_removesegment_clicked() { } } -void TaSMETMainWindow::on_segmentid_valueChanged(int id) { - - auto& ductmap = *_system.mutable_ducts(); - auto& ductbcmap = *_system.mutable_ductbcs(); - - bool is_segment = false; - - if(ductmap.find(id) != ductmap.end()) { - _window->segmentname->setText(QString::fromStdString(ductmap[id].name())); - is_segment = true; - } - if(ductbcmap.find(id) != ductbcmap.end()) { - _window->segmentname->setText(QString::fromStdString(ductbcmap[id].name())); - is_segment = true; - } - - _window->removesegment->setEnabled(is_segment); - -} -void TaSMETMainWindow::on_segmentname_textEdited() { - +void TaSMETMainWindow::on_segmentname_textChanged() { + if(_init) return; auto& ductmap = *_system.mutable_ducts(); auto& ductbcmap = *_system.mutable_ductbcs(); @@ -443,7 +387,7 @@ void TaSMETMainWindow::on_segmentname_textEdited() { if(ductbcmap.find(id) != ductbcmap.end()) { ductbcmap[id].set_name(_window->segmentname->text().toStdString()); } - + changed(); } void TaSMETMainWindow::on_actionSolve_triggered() { diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index 54c89b0..7779b69 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -53,8 +53,8 @@ private slots: void closeEvent(QCloseEvent *event); void on_addsegment_clicked(); void on_removesegment_clicked(); - void on_segmentid_valueChanged(int i); - void on_segmentname_textEdited(); + void on_segmentid_valueChanged(int i) {changed();} + void on_segmentname_textChanged(); // Couple slots to functions void on_actionNew_triggered() { newModel();} diff --git a/src/gui/solver_dialog.cpp b/src/gui/solver_dialog.cpp index 05224e3..68dc031 100644 --- a/src/gui/solver_dialog.cpp +++ b/src/gui/solver_dialog.cpp @@ -80,16 +80,23 @@ SolverDialog::SolverDialog(QWidget* parent, QSharedPointer ticker(new QCPAxisTickerLog()); _plot->yAxis->setTicker(ticker); + + // Toggle legend _plot->legend->setVisible(true); - _plot->replot(); set(_sys.solverparams()); + + setEnabled(true); + _init = false; + } SolverDialog::~SolverDialog() { - if(_solver_worker) + if(_solver_worker) { + // deleteLater is called on this one, so no delete here _solver_worker->solver_stop(); + } } void SolverDialog::set(const pb::SolverParams& sol) { TRACE(15,"set"); @@ -104,6 +111,7 @@ void SolverDialog::set(const pb::SolverParams& sol) { } void SolverDialog::changed() { + TRACE(15,"changed"); if(_init) return; _sys.mutable_solverparams()->set_funtol(_dialog->funtol->text().toDouble()); _sys.mutable_solverparams()->set_reltol(_dialog->reltol->text().toDouble()); @@ -113,7 +121,6 @@ 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(); @@ -141,6 +148,14 @@ void SolverDialog::on_solve_clicked() { // Disable buttons setEnabled(false); + // Clear figure data + QVector empty; + _funer->setData(empty,empty); + _reler->setData(empty,empty); + _funtol->setData(empty,empty); + _reltol->setData(empty,empty); + + assert(!_solver_worker); qRegisterMetaType(); diff --git a/src/protobuf/system_tools.cpp b/src/protobuf/system_tools.cpp new file mode 100644 index 0000000..424995b --- /dev/null +++ b/src/protobuf/system_tools.cpp @@ -0,0 +1,76 @@ +// system_tools.cpp +// +// last-edit-by: J.A. de Jong +// +// Description: +// +////////////////////////////////////////////////////////////////////// +#include "system_tools.h" +#include +#include +#include "tasmet_types.h" +#include "tasmet_io.h" +#include "tasmet_exception.h" + +#include + +using google::protobuf::TextFormat; + +pb::System loadSystem(const string& filepath) { + + TRACE(15,"loadSystem()"); + VARTRACE(15,filepath); + std::ifstream myfile(filepath,ios::binary); + + if(!myfile.good()) { + string error = "Read error on "; + error += filepath; + throw TaSMETError(error); + + } + + pb::System sys; + + std::stringstream strStream; + strStream << myfile.rdbuf(); //read the file + string data = strStream.str();//str holds the content of the file + + if(!TextFormat::ParseFromString(data,&sys)) { + string error = "Invalid TaSMET Model file: "; + error += filepath; + throw TaSMETError(error); + } + + return sys; + + +} +void saveSystem(const string& filepath,const pb::System& sys) { + + std::ofstream sfile(filepath,ios::binary); + if(!sfile.good()){ + throw TaSMETError("Could not write to file"); + } + string data; + if(TextFormat::PrintToString(sys,&data)) { + // Can maybe assign to itself. Which is no problem + // according to C++ docs + TRACE(15,"Saving file succeeded"); + sfile << data << std::flush; + + // Close file here, such that in can be opened to compare + // whether the file is still dirty + sfile.close(); + } + else { + throw TaSMETError("Could not save model to file"); + + } +} +// // Returns true when the two systems are equal +bool compareSys(const pb::System& s1,const pb::System& s2) { + return (s1.SerializeAsString()==s2.SerializeAsString()); +} + +////////////////////////////////////////////////////////////////////// + diff --git a/src/protobuf/system_tools.h b/src/protobuf/system_tools.h new file mode 100644 index 0000000..745010b --- /dev/null +++ b/src/protobuf/system_tools.h @@ -0,0 +1,27 @@ +// system_tools.h +// +// Author: J.A. de Jong +// +// Description: +// +////////////////////////////////////////////////////////////////////// +#pragma once +#ifndef SYSTEM_TOOLS_H +#define SYSTEM_TOOLS_H +#include "system.pb.h" +#include "tasmet_tracer.h" +#include "tasmet_types.h" + +// Load a system from a filepath +pb::System loadSystem(const string& filepath); + +// Save a system to a filepath +void saveSystem(const string& filepath,const pb::System& sys); + +// Returns true when the two systems are equal +bool compareSys(const pb::System& s1,const pb::System& s2); + + + +#endif // SYSTEM_TOOLS_H +////////////////////////////////////////////////////////////////////// diff --git a/src/tasmet_solvemodel.cpp b/src/tasmet_solvemodel.cpp new file mode 100644 index 0000000..723e0d6 --- /dev/null +++ b/src/tasmet_solvemodel.cpp @@ -0,0 +1,70 @@ +// tasmet_solvemodel.cpp +// +// last-edit-by: J.A. de Jong +// +// Description: +// Program which can be used to solve a TaSMET Model from the CLI +////////////////////////////////////////////////////////////////////// +#include "protobuf/system_tools.h" // loadSystem, saveSystem +#include "tasmet_io.h" +#include "tasmet_exception.h" +#include "sys/tasystem.h" + +// For using python from within Qt +#include + +void usage(const char* fn) { + cout << "Usage: " << endl; + cout << fn << " [Input file] " << endl; +} + +int main(int argc, char *argv[]) { + + INITTRACE(10); + + // Initialize PythonQt + // PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut); + PythonQt::init(); + + PythonQt* pyqt = PythonQt::self(); + PythonQtObjectPtr context = pyqt->getMainModule(); + + QVariant rv = context.evalScript("from math import *\n"); + if(pyqt->hadError()) { + return -1; + } + + if(argc != 2) { + usage(argv[0]); + return -1; + } + + pb::System sys; + + string filename = argv[1]; + try { + sys = loadSystem(filename); + } + catch(TaSMETError &e) { + cerr << e.what() << endl; + return -1; + } + + cout << "Loaded model: " << endl; + cout << sys.DebugString(); + + TaSystem* system; + + try { + system = new TaSystem(sys); + } + catch(TaSMETError &e) { + cerr << "Model initialization error: " << endl; + cerr << e.what() << endl; + return -1; + } + +} + + +//////////////////////////////////////////////////////////////////////