Path: blob/devel/ElmerGUI/Application/src/convergenceview.cpp
3203 views
/*****************************************************************************1* *2* Elmer, A Finite Element Software for Multiphysical Problems *3* *4* Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland *5* *6* This program is free software; you can redistribute it and/or *7* modify it under the terms of the GNU General Public License *8* as published by the Free Software Foundation; either version 2 *9* of the License, or (at your option) any later version. *10* *11* This program is distributed in the hope that it will be useful, *12* but WITHOUT ANY WARRANTY; without even the implied warranty of *13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *14* GNU General Public License for more details. *15* *16* You should have received a copy of the GNU General Public License *17* along with this program (in file fem/GPL-2); if not, write to the *18* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *19* Boston, MA 02110-1301, USA. *20* *21*****************************************************************************/2223/*****************************************************************************24* *25* ElmerGUI convergenceview *26* *27*****************************************************************************28* *29* Authors: Mikko Lyly, Juha Ruokolainen and Peter R�back *30* Email: [email protected] *31* Web: http://www.csc.fi/elmer *32* Address: CSC - IT Center for Science Ltd. *33* Keilaranta 14 *34* 02101 Espoo, Finland *35* *36* Original Date: 15 Mar 2008 *37* *38*****************************************************************************/3940#include <QtGui>41#include <iostream>42#include "convergenceview.h"43#include "mainwindow.h"4445#if defined(__cplusplus) && __cplusplus >= 201703L46# define REGISTER47#else48# define REGISTER register49#endif5051using namespace std;5253//-----------------------------------------------------------------------------54CurveData::CurveData()55: d_count(0)56{57}5859void CurveData::append(double *x, double *y, int count)60{61int newSize = ((d_count + count) / 1000 + 1) * 1000;62if(newSize > size()) {63d_x.resize(newSize);64d_y.resize(newSize);65}6667for(REGISTER int i = 0; i < count; i++) {68d_x[d_count + i] = x[i];69d_y[d_count + i] = y[i];70}7172d_count += count;73}7475int CurveData::count() const76{77return d_count;78}7980int CurveData::size() const81{82return d_x.size();83}8485const double *CurveData::x() const86{87return d_x.data();88}8990const double *CurveData::y() const91{92return d_y.data();93}9495//-----------------------------------------------------------------------------96ConvergenceView::ConvergenceView(Limit *limit, QWidget *parent)97: QMainWindow(parent)98{99iconChecked = QIcon::fromTheme("dialog-accept");100101plot = new QwtPlot(this);102plot->resize(200, 200);103104plot->setAutoReplot(true);105plot->setCanvasBackground(QColor(Qt::white));106title = "Nonlinear system convergence";107plot->setTitle(title);108109// legend110legend = new QwtLegend;111legend->setFrameStyle(QFrame::Box|QFrame::Sunken);112plot->insertLegend(legend, QwtPlot::RightLegend);113114// grid115grid = new QwtPlotGrid;116grid->enableXMin(true);117#if QWT_VERSION >= 0x060100118grid->setMajorPen(QPen(Qt::black, 0, Qt::DotLine));119grid->setMinorPen(QPen(Qt::gray, 0 , Qt::DotLine));120#else121grid->setMajPen(QPen(Qt::black, 0, Qt::DotLine));122grid->setMinPen(QPen(Qt::gray, 0 , Qt::DotLine));123#endif124grid->attach(plot);125126// axis127plot->setAxisTitle(QwtPlot::xBottom, "Iteration step");128plot->setAxisTitle(QwtPlot::yLeft, "Relative change");129plot->setAxisMaxMajor(QwtPlot::xBottom, 20);130plot->setAxisMaxMinor(QwtPlot::xBottom, 1);131plot->setAxisMaxMajor(QwtPlot::yLeft, 10);132plot->setAxisMaxMinor(QwtPlot::yLeft, 10);133134// scale engine135scaleEngine = new QwtLog10ScaleEngine;136plot->setAxisScaleEngine(QwtPlot::yLeft, scaleEngine);137138// default pen139pen = new QPen[MAX_NOF_PENS];140for(int i = 0; i < MAX_NOF_PENS; i++)141pen[i] = QPen(Qt::black);142143// available colors144pen[0] = QPen(Qt::red);145pen[1] = QPen(Qt::green);146pen[2] = QPen(Qt::blue);147pen[3] = QPen(Qt::black);148pen[4] = QPen(Qt::cyan);149pen[5] = QPen(Qt::yellow);150151createActions();152createMenus();153createToolBars();154createStatusBar();155156setCentralWidget(plot);157setWindowTitle("Convergence monitor");158159showLegend = true;160showGrid = true;161showNSHistory = true;162showSSHistory = false;163164setWindowIcon(QIcon(":/icons/Mesh3D.png"));165}166167ConvergenceView::~ConvergenceView()168{169#if 0170curveList.clear();171delete plot;172#endif173}174175176void ConvergenceView::appendData(double y, QString name)177{178appendData(&y, 1, name);179}180181void ConvergenceView::appendData(double *y, int size, QString name)182{183QStringList nameSplitted = name.trimmed().split("/");184185bool NS = false;186if(nameSplitted.at(0) == "NS")187NS = true;188189bool SS = false;190if(nameSplitted.at(0) == "SS")191SS = true;192193Curve *curve = curveList.value(name, NULL);194195if(curve == NULL) {196curve = new Curve;197curve->d_data = new CurveData;198curve->d_curve = new QwtPlotCurve(name);199// curve->d_curve->setRenderHint(QwtPlotItem::RenderAntialiased);200QPen currentPen = pen[curveList.count()];201currentPen.setWidth(2);202curve->d_curve->setPen(currentPen);203204if(NS && showNSHistory)205curve->d_curve->attach(plot);206207if(SS && showSSHistory)208curve->d_curve->attach(plot);209210curveList.insert(name, curve);211}212213double x = (double)(curve->d_data->count());214curve->d_data->append(&x, y, size);215/*curve->d_curve->setRawData(curve->d_data->x(),216curve->d_data->y(),217curve->d_data->count());*/218curve->d_curve->setRawSamples(curve->d_data->x(),219curve->d_data->y(),220curve->d_data->count());221plot->setTitle(title);222}223224void ConvergenceView::removeData()225{226for( int i = 0; i < curveList.count(); i++) {227Curve *curve = curveList.values().at(i);228delete curve->d_data;229curve->d_data = NULL;230curve->d_curve->detach();231delete curve->d_curve;232curve->d_curve = NULL;233}234curveList.clear();235title = "Convergence history";236/* plot->clear(); */237plot->detachItems();238plot->replot();239}240241QSize ConvergenceView::minimumSizeHint() const242{243return QSize(64, 64);244}245246247QSize ConvergenceView::sizeHint() const248{249return QSize(480, 640);250}251252void ConvergenceView::createActions()253{254savePictureAct = new QAction(QIcon(""), tr("&Save picture as..."), this);255savePictureAct->setStatusTip("Save picture in jpg-format");256connect(savePictureAct, SIGNAL(triggered()), this, SLOT(savePictureSlot()));257258exitAct = new QAction(QIcon::fromTheme("application-exit"), tr("&Quit"), this);259exitAct->setShortcut(tr("Ctrl+Q"));260exitAct->setStatusTip("Quit convergence monitor");261connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));262263showGridAct = new QAction(QIcon(iconChecked), tr("&Grid"), this);264showGridAct->setStatusTip("Show grid");265connect(showGridAct, SIGNAL(triggered()), this, SLOT(showGridSlot()));266267showLegendAct = new QAction(QIcon(iconChecked), tr("&Legend"), this);268showLegendAct->setStatusTip("Show legend");269connect(showLegendAct, SIGNAL(triggered()), this, SLOT(showLegendSlot()));270271showNSHistoryAct = new QAction(QIcon(iconChecked),272tr("&Nonlinear system"), this);273showNSHistoryAct->setStatusTip("Show nonlinear system convergence history");274connect(showNSHistoryAct, SIGNAL(triggered()), this, SLOT(showNSHistorySlot()));275276showSSHistoryAct = new QAction(QIcon(""), tr("&Steady state"), this);277showSSHistoryAct->setStatusTip("Show steady state convergence history");278connect(showSSHistoryAct, SIGNAL(triggered()), this, SLOT(showSSHistorySlot()));279280clearHistoryAct = new QAction(QIcon(""), tr("&Clear history"), this);281clearHistoryAct->setStatusTip("Clear current convergence history");282connect(clearHistoryAct, SIGNAL(triggered()), this, SLOT(clearHistorySlot()));283}284285void ConvergenceView::createMenus()286{287fileMenu = menuBar()->addMenu(tr("&File"));288fileMenu->addAction(savePictureAct);289fileMenu->addSeparator();290fileMenu->addAction(exitAct);291292viewMenu = menuBar()->addMenu(tr("&View"));293viewMenu->addAction(showGridAct);294viewMenu->addAction(showLegendAct);295viewMenu->addSeparator();296viewMenu->addAction(showNSHistoryAct);297viewMenu->addAction(showSSHistoryAct);298viewMenu->addSeparator();299viewMenu->addAction(clearHistoryAct);300}301302void ConvergenceView::createToolBars()303{304#if 0305viewToolBar = addToolBar(tr("&View"));306viewToolBar->addAction(showGridAct);307viewToolBar->addAction(showLegendAct);308#endif309}310311void ConvergenceView::createStatusBar()312{313statusBar()->showMessage("Ready");314}315316void ConvergenceView::savePictureSlot()317{318#if WITH_QT5 || WITH_QT6319QPixmap pixmap = grab();320#else321QPixmap pixmap = QPixmap::grabWidget(plot);322#endif323324QString fileName = QFileDialog::getSaveFileName(this,325tr("Save picture"), "", tr("Picture files (*.bmp *.jpg *.png *.pbm *.pgm *.ppm)"));326327if(fileName == "")328return;329330QFileInfo fi(fileName);331QString suffix = fi.suffix();332suffix = suffix.toUpper();333334#if WITH_QT5 || WITH_QT6335bool ok = pixmap.save(fileName, suffix.toLatin1(), 95); // fixed quality336#else337bool ok = pixmap.save(fileName, suffix.toAscii(), 95); // fixed quality338#endif339340if(!ok) {341cout << "Failed writing picture" << endl;342cout.flush();343}344}345346void ConvergenceView::showGridSlot()347{348showGrid = !showGrid;349350if(showGrid) {351grid->attach(plot);352showGridAct->setIcon(QIcon(iconChecked));353} else {354grid->detach();355showGridAct->setIcon(QIcon(""));356}357358plot->replot();359}360361void ConvergenceView::showLegendSlot()362{363showLegend = !showLegend;364365if(showLegend) {366legend = new QwtLegend;367legend->setFrameStyle(QFrame::Box|QFrame::Sunken);368plot->insertLegend(legend, QwtPlot::RightLegend);369showLegendAct->setIcon(QIcon(iconChecked));370} else {371delete legend;372showLegendAct->setIcon(QIcon(""));373}374375plot->replot();376}377378void ConvergenceView::showNSHistorySlot()379{380showNSHistory = !showNSHistory;381382if(showNSHistory) {383showNSHistoryAct->setIcon(QIcon(iconChecked));384} else {385showNSHistoryAct->setIcon(QIcon(""));386}387388// attach/detach curves:389for(int i = 0; i < curveList.count(); i++) {390QString key = curveList.keys().at(i);391Curve *curve = curveList.values().at(i);392QStringList keySplitted = key.trimmed().split("/");393if(keySplitted.at(0) == "NS") {394if(showNSHistory)395curve->d_curve->attach(plot);396else397curve->d_curve->detach();398}399}400401plot->replot();402}403404void ConvergenceView::showSSHistorySlot()405{406showSSHistory = !showSSHistory;407408if(showSSHistory) {409showSSHistoryAct->setIcon(QIcon(iconChecked));410} else {411showSSHistoryAct->setIcon(QIcon(""));412}413414// attach/detach curves:415for(int i = 0; i < curveList.count(); i++) {416QString key = curveList.keys().at(i);417Curve *curve = curveList.values().at(i);418QStringList keySplitted = key.trimmed().split("/");419if(keySplitted.at(0) == "SS") {420if(showSSHistory)421curve->d_curve->attach(plot);422else423curve->d_curve->detach();424}425}426427plot->replot();428}429430void ConvergenceView::clearHistorySlot()431{432removeData();433}434435