Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/Application/src/convergenceview.cpp
3203 views
1
/*****************************************************************************
2
* *
3
* Elmer, A Finite Element Software for Multiphysical Problems *
4
* *
5
* Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland *
6
* *
7
* This program is free software; you can redistribute it and/or *
8
* modify it under the terms of the GNU General Public License *
9
* as published by the Free Software Foundation; either version 2 *
10
* of the License, or (at your option) any later version. *
11
* *
12
* This program is distributed in the hope that it will be useful, *
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15
* GNU General Public License for more details. *
16
* *
17
* You should have received a copy of the GNU General Public License *
18
* along with this program (in file fem/GPL-2); if not, write to the *
19
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
20
* Boston, MA 02110-1301, USA. *
21
* *
22
*****************************************************************************/
23
24
/*****************************************************************************
25
* *
26
* ElmerGUI convergenceview *
27
* *
28
*****************************************************************************
29
* *
30
* Authors: Mikko Lyly, Juha Ruokolainen and Peter R�back *
31
* Email: [email protected] *
32
* Web: http://www.csc.fi/elmer *
33
* Address: CSC - IT Center for Science Ltd. *
34
* Keilaranta 14 *
35
* 02101 Espoo, Finland *
36
* *
37
* Original Date: 15 Mar 2008 *
38
* *
39
*****************************************************************************/
40
41
#include <QtGui>
42
#include <iostream>
43
#include "convergenceview.h"
44
#include "mainwindow.h"
45
46
#if defined(__cplusplus) && __cplusplus >= 201703L
47
# define REGISTER
48
#else
49
# define REGISTER register
50
#endif
51
52
using namespace std;
53
54
//-----------------------------------------------------------------------------
55
CurveData::CurveData()
56
: d_count(0)
57
{
58
}
59
60
void CurveData::append(double *x, double *y, int count)
61
{
62
int newSize = ((d_count + count) / 1000 + 1) * 1000;
63
if(newSize > size()) {
64
d_x.resize(newSize);
65
d_y.resize(newSize);
66
}
67
68
for(REGISTER int i = 0; i < count; i++) {
69
d_x[d_count + i] = x[i];
70
d_y[d_count + i] = y[i];
71
}
72
73
d_count += count;
74
}
75
76
int CurveData::count() const
77
{
78
return d_count;
79
}
80
81
int CurveData::size() const
82
{
83
return d_x.size();
84
}
85
86
const double *CurveData::x() const
87
{
88
return d_x.data();
89
}
90
91
const double *CurveData::y() const
92
{
93
return d_y.data();
94
}
95
96
//-----------------------------------------------------------------------------
97
ConvergenceView::ConvergenceView(Limit *limit, QWidget *parent)
98
: QMainWindow(parent)
99
{
100
iconChecked = QIcon::fromTheme("dialog-accept");
101
102
plot = new QwtPlot(this);
103
plot->resize(200, 200);
104
105
plot->setAutoReplot(true);
106
plot->setCanvasBackground(QColor(Qt::white));
107
title = "Nonlinear system convergence";
108
plot->setTitle(title);
109
110
// legend
111
legend = new QwtLegend;
112
legend->setFrameStyle(QFrame::Box|QFrame::Sunken);
113
plot->insertLegend(legend, QwtPlot::RightLegend);
114
115
// grid
116
grid = new QwtPlotGrid;
117
grid->enableXMin(true);
118
#if QWT_VERSION >= 0x060100
119
grid->setMajorPen(QPen(Qt::black, 0, Qt::DotLine));
120
grid->setMinorPen(QPen(Qt::gray, 0 , Qt::DotLine));
121
#else
122
grid->setMajPen(QPen(Qt::black, 0, Qt::DotLine));
123
grid->setMinPen(QPen(Qt::gray, 0 , Qt::DotLine));
124
#endif
125
grid->attach(plot);
126
127
// axis
128
plot->setAxisTitle(QwtPlot::xBottom, "Iteration step");
129
plot->setAxisTitle(QwtPlot::yLeft, "Relative change");
130
plot->setAxisMaxMajor(QwtPlot::xBottom, 20);
131
plot->setAxisMaxMinor(QwtPlot::xBottom, 1);
132
plot->setAxisMaxMajor(QwtPlot::yLeft, 10);
133
plot->setAxisMaxMinor(QwtPlot::yLeft, 10);
134
135
// scale engine
136
scaleEngine = new QwtLog10ScaleEngine;
137
plot->setAxisScaleEngine(QwtPlot::yLeft, scaleEngine);
138
139
// default pen
140
pen = new QPen[MAX_NOF_PENS];
141
for(int i = 0; i < MAX_NOF_PENS; i++)
142
pen[i] = QPen(Qt::black);
143
144
// available colors
145
pen[0] = QPen(Qt::red);
146
pen[1] = QPen(Qt::green);
147
pen[2] = QPen(Qt::blue);
148
pen[3] = QPen(Qt::black);
149
pen[4] = QPen(Qt::cyan);
150
pen[5] = QPen(Qt::yellow);
151
152
createActions();
153
createMenus();
154
createToolBars();
155
createStatusBar();
156
157
setCentralWidget(plot);
158
setWindowTitle("Convergence monitor");
159
160
showLegend = true;
161
showGrid = true;
162
showNSHistory = true;
163
showSSHistory = false;
164
165
setWindowIcon(QIcon(":/icons/Mesh3D.png"));
166
}
167
168
ConvergenceView::~ConvergenceView()
169
{
170
#if 0
171
curveList.clear();
172
delete plot;
173
#endif
174
}
175
176
177
void ConvergenceView::appendData(double y, QString name)
178
{
179
appendData(&y, 1, name);
180
}
181
182
void ConvergenceView::appendData(double *y, int size, QString name)
183
{
184
QStringList nameSplitted = name.trimmed().split("/");
185
186
bool NS = false;
187
if(nameSplitted.at(0) == "NS")
188
NS = true;
189
190
bool SS = false;
191
if(nameSplitted.at(0) == "SS")
192
SS = true;
193
194
Curve *curve = curveList.value(name, NULL);
195
196
if(curve == NULL) {
197
curve = new Curve;
198
curve->d_data = new CurveData;
199
curve->d_curve = new QwtPlotCurve(name);
200
// curve->d_curve->setRenderHint(QwtPlotItem::RenderAntialiased);
201
QPen currentPen = pen[curveList.count()];
202
currentPen.setWidth(2);
203
curve->d_curve->setPen(currentPen);
204
205
if(NS && showNSHistory)
206
curve->d_curve->attach(plot);
207
208
if(SS && showSSHistory)
209
curve->d_curve->attach(plot);
210
211
curveList.insert(name, curve);
212
}
213
214
double x = (double)(curve->d_data->count());
215
curve->d_data->append(&x, y, size);
216
/*curve->d_curve->setRawData(curve->d_data->x(),
217
curve->d_data->y(),
218
curve->d_data->count());*/
219
curve->d_curve->setRawSamples(curve->d_data->x(),
220
curve->d_data->y(),
221
curve->d_data->count());
222
plot->setTitle(title);
223
}
224
225
void ConvergenceView::removeData()
226
{
227
for( int i = 0; i < curveList.count(); i++) {
228
Curve *curve = curveList.values().at(i);
229
delete curve->d_data;
230
curve->d_data = NULL;
231
curve->d_curve->detach();
232
delete curve->d_curve;
233
curve->d_curve = NULL;
234
}
235
curveList.clear();
236
title = "Convergence history";
237
/* plot->clear(); */
238
plot->detachItems();
239
plot->replot();
240
}
241
242
QSize ConvergenceView::minimumSizeHint() const
243
{
244
return QSize(64, 64);
245
}
246
247
248
QSize ConvergenceView::sizeHint() const
249
{
250
return QSize(480, 640);
251
}
252
253
void ConvergenceView::createActions()
254
{
255
savePictureAct = new QAction(QIcon(""), tr("&Save picture as..."), this);
256
savePictureAct->setStatusTip("Save picture in jpg-format");
257
connect(savePictureAct, SIGNAL(triggered()), this, SLOT(savePictureSlot()));
258
259
exitAct = new QAction(QIcon::fromTheme("application-exit"), tr("&Quit"), this);
260
exitAct->setShortcut(tr("Ctrl+Q"));
261
exitAct->setStatusTip("Quit convergence monitor");
262
connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
263
264
showGridAct = new QAction(QIcon(iconChecked), tr("&Grid"), this);
265
showGridAct->setStatusTip("Show grid");
266
connect(showGridAct, SIGNAL(triggered()), this, SLOT(showGridSlot()));
267
268
showLegendAct = new QAction(QIcon(iconChecked), tr("&Legend"), this);
269
showLegendAct->setStatusTip("Show legend");
270
connect(showLegendAct, SIGNAL(triggered()), this, SLOT(showLegendSlot()));
271
272
showNSHistoryAct = new QAction(QIcon(iconChecked),
273
tr("&Nonlinear system"), this);
274
showNSHistoryAct->setStatusTip("Show nonlinear system convergence history");
275
connect(showNSHistoryAct, SIGNAL(triggered()), this, SLOT(showNSHistorySlot()));
276
277
showSSHistoryAct = new QAction(QIcon(""), tr("&Steady state"), this);
278
showSSHistoryAct->setStatusTip("Show steady state convergence history");
279
connect(showSSHistoryAct, SIGNAL(triggered()), this, SLOT(showSSHistorySlot()));
280
281
clearHistoryAct = new QAction(QIcon(""), tr("&Clear history"), this);
282
clearHistoryAct->setStatusTip("Clear current convergence history");
283
connect(clearHistoryAct, SIGNAL(triggered()), this, SLOT(clearHistorySlot()));
284
}
285
286
void ConvergenceView::createMenus()
287
{
288
fileMenu = menuBar()->addMenu(tr("&File"));
289
fileMenu->addAction(savePictureAct);
290
fileMenu->addSeparator();
291
fileMenu->addAction(exitAct);
292
293
viewMenu = menuBar()->addMenu(tr("&View"));
294
viewMenu->addAction(showGridAct);
295
viewMenu->addAction(showLegendAct);
296
viewMenu->addSeparator();
297
viewMenu->addAction(showNSHistoryAct);
298
viewMenu->addAction(showSSHistoryAct);
299
viewMenu->addSeparator();
300
viewMenu->addAction(clearHistoryAct);
301
}
302
303
void ConvergenceView::createToolBars()
304
{
305
#if 0
306
viewToolBar = addToolBar(tr("&View"));
307
viewToolBar->addAction(showGridAct);
308
viewToolBar->addAction(showLegendAct);
309
#endif
310
}
311
312
void ConvergenceView::createStatusBar()
313
{
314
statusBar()->showMessage("Ready");
315
}
316
317
void ConvergenceView::savePictureSlot()
318
{
319
#if WITH_QT5 || WITH_QT6
320
QPixmap pixmap = grab();
321
#else
322
QPixmap pixmap = QPixmap::grabWidget(plot);
323
#endif
324
325
QString fileName = QFileDialog::getSaveFileName(this,
326
tr("Save picture"), "", tr("Picture files (*.bmp *.jpg *.png *.pbm *.pgm *.ppm)"));
327
328
if(fileName == "")
329
return;
330
331
QFileInfo fi(fileName);
332
QString suffix = fi.suffix();
333
suffix = suffix.toUpper();
334
335
#if WITH_QT5 || WITH_QT6
336
bool ok = pixmap.save(fileName, suffix.toLatin1(), 95); // fixed quality
337
#else
338
bool ok = pixmap.save(fileName, suffix.toAscii(), 95); // fixed quality
339
#endif
340
341
if(!ok) {
342
cout << "Failed writing picture" << endl;
343
cout.flush();
344
}
345
}
346
347
void ConvergenceView::showGridSlot()
348
{
349
showGrid = !showGrid;
350
351
if(showGrid) {
352
grid->attach(plot);
353
showGridAct->setIcon(QIcon(iconChecked));
354
} else {
355
grid->detach();
356
showGridAct->setIcon(QIcon(""));
357
}
358
359
plot->replot();
360
}
361
362
void ConvergenceView::showLegendSlot()
363
{
364
showLegend = !showLegend;
365
366
if(showLegend) {
367
legend = new QwtLegend;
368
legend->setFrameStyle(QFrame::Box|QFrame::Sunken);
369
plot->insertLegend(legend, QwtPlot::RightLegend);
370
showLegendAct->setIcon(QIcon(iconChecked));
371
} else {
372
delete legend;
373
showLegendAct->setIcon(QIcon(""));
374
}
375
376
plot->replot();
377
}
378
379
void ConvergenceView::showNSHistorySlot()
380
{
381
showNSHistory = !showNSHistory;
382
383
if(showNSHistory) {
384
showNSHistoryAct->setIcon(QIcon(iconChecked));
385
} else {
386
showNSHistoryAct->setIcon(QIcon(""));
387
}
388
389
// attach/detach curves:
390
for(int i = 0; i < curveList.count(); i++) {
391
QString key = curveList.keys().at(i);
392
Curve *curve = curveList.values().at(i);
393
QStringList keySplitted = key.trimmed().split("/");
394
if(keySplitted.at(0) == "NS") {
395
if(showNSHistory)
396
curve->d_curve->attach(plot);
397
else
398
curve->d_curve->detach();
399
}
400
}
401
402
plot->replot();
403
}
404
405
void ConvergenceView::showSSHistorySlot()
406
{
407
showSSHistory = !showSSHistory;
408
409
if(showSSHistory) {
410
showSSHistoryAct->setIcon(QIcon(iconChecked));
411
} else {
412
showSSHistoryAct->setIcon(QIcon(""));
413
}
414
415
// attach/detach curves:
416
for(int i = 0; i < curveList.count(); i++) {
417
QString key = curveList.keys().at(i);
418
Curve *curve = curveList.values().at(i);
419
QStringList keySplitted = key.trimmed().split("/");
420
if(keySplitted.at(0) == "SS") {
421
if(showSSHistory)
422
curve->d_curve->attach(plot);
423
else
424
curve->d_curve->detach();
425
}
426
}
427
428
plot->replot();
429
}
430
431
void ConvergenceView::clearHistorySlot()
432
{
433
removeData();
434
}
435