2
/// This file is part of Rheolef.
4
/// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
6
/// Rheolef is free software; you can redistribute it and/or modify
7
/// it under the terms of the GNU General Public License as published by
8
/// the Free Software Foundation; either version 2 of the License, or
9
/// (at your option) any later version.
11
/// Rheolef 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.
16
/// You should have received a copy of the GNU General Public License
17
/// along with Rheolef; if not, write to the Free Software
18
/// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
/// =========================================================================
22
// gnuplot geo visualisation
24
// author: Pierre.Saramito@imag.fr
28
# include "rheolef/field.h"
29
# include "rheolef/field_indirect.h"
30
# include "rheolef/field_expr.h"
31
# include "rheolef/field_expr_ops.h"
32
# include "rheolef/field_evaluate.h"
33
# include "rheolef/piola.h"
34
# include "rheolef/rounder.h"
35
# include "rheolef/rheostream.h"
40
odiststream& visu_gnuplot (odiststream& ops, const geo_basic<T,sequential>& omega);
42
// ----------------------------------------------------------------------------
43
// bounds: for curved geometries, need to commpute it on the fly
44
// ----------------------------------------------------------------------------
48
point_basic<T> xmin, xmax;
51
void update (const point_basic<T>& x, const T& u) {
52
for (size_t i = 0; i < 3; i++) {
53
xmin[i] = std::min(xmin[i], x[i]);
54
xmax[i] = std::max(xmax[i], x[i]);
56
umin = std::min(umin, u);
57
umax = std::max(umax, u);
60
// ----------------------------------------------------------------------------
61
// puts for one element
62
// ----------------------------------------------------------------------------
66
put_edge (std::ostream& gdat, const geo_element& E, const geo_basic<T,sequential>& omega,
67
const field_basic<T,sequential>& uh,
68
const basis_on_nodal_basis& geo_on_pointset,
69
const basis_on_nodal_basis& field_on_pointset,
73
typedef typename geo_basic<T,sequential>::size_type size_type;
74
typedef point_basic<size_type> ilat;
75
size_type dim = omega.dimension();
76
size_type my_order = geo_on_pointset.pointset_order();
77
std::vector<size_type> dis_idof1;
78
uh.get_space().dis_idof (E, dis_idof1);
79
std::vector<size_type> dis_inod;
80
omega.dis_inod (E, dis_inod);
81
std::vector<point_basic<T> > hat_xi;
82
uh.get_space().get_numbering().get_basis().hat_node (E.variant(), hat_xi);
83
for (size_type i = 0; i <= my_order; i++) {
84
size_type iloc = reference_element_e::ilat2loc_inod (my_order, ilat(i));
85
point_basic<T> xi = piola_transformation (omega, geo_on_pointset, E.variant(), dis_inod, iloc);
86
T ui = field_evaluate (uh, field_on_pointset, E.variant(), dis_idof1, iloc);
87
xi.put (gdat, dim); gdat << " " << ui << endl;
95
put_triangle (std::ostream& gdat, const geo_element& F, const geo_basic<T,sequential>& omega,
96
const field_basic<T,sequential>& uh,
97
const basis_on_nodal_basis& geo_on_pointset,
98
const basis_on_nodal_basis& field_on_pointset,
102
typedef typename geo_basic<T,sequential>::size_type size_type;
103
typedef point_basic<size_type> ilat;
104
size_type dim = omega.dimension();
105
std::vector<size_type> dis_idof1;
106
std::vector<size_type> dis_inod;
107
omega.dis_inod (F, dis_inod);
108
uh.get_space().dis_idof (F, dis_idof1);
109
size_type nloc = geo_on_pointset.size(F);
110
std::vector<point_basic<T> > xdof (nloc);
111
std::vector<T> udof (nloc);
112
for (size_type iloc = 0; iloc < nloc; iloc++) {
113
xdof[iloc] = piola_transformation (omega, geo_on_pointset, F.variant(), dis_inod, iloc);
114
udof[iloc] = field_evaluate (uh, field_on_pointset, F.variant(), dis_idof1, iloc);
115
bbox.update (xdof[iloc], udof[iloc]);
117
size_type my_order = geo_on_pointset.pointset_order();
118
for (size_type j = 0; j <= my_order; j++) {
119
for (size_type i1 = 0; i1 <= my_order; i1++) {
120
size_type i = std::min(i1, my_order-j);
121
size_type iloc = reference_element_t::ilat2loc_inod (my_order, ilat(i, j));
122
xdof [iloc].put (gdat, dim); gdat << " " << udof[iloc] << endl;
126
gdat << endl << endl;
131
put_quadrangle (std::ostream& gdat, const geo_element& F, const geo_basic<T,sequential>& omega,
132
const field_basic<T,sequential>& uh, const basis_on_nodal_basis& b)
135
typedef typename geo_basic<T,sequential>::size_type size_type;
136
typedef point_basic<size_type> ilat;
137
size_type dim = omega.dimension();
138
size_type degree = uh.get_space().get_numbering().get_basis().degree();
139
std::vector<size_type> dis_idof1;
140
uh.get_space().dis_idof (F, dis_idof1);
141
std::vector<size_type> dis_inod;
142
omega.dis_inod (F, dis_inod);
143
std::vector<point_basic<T> > xdof (dis_idof1.size());
144
for (size_type loc_idof = 0, loc_ndof = xdof.size(); loc_idof < loc_ndof; loc_idof++) {
145
xdof[loc_idof] = piola_transformation (omega, b, F.variant(), dis_inod, loc_idof);
147
for (size_type j = 0; j < degree+1; j++) {
148
for (size_type i = 0; i < degree+1; i++) {
149
size_type loc_idof00 = reference_element_q::ilat2loc_inod (degree, ilat(i, j));
150
xdof [loc_idof00].put (gdat, dim); gdat << " " << uh.dof(dis_idof1[loc_idof00]) << endl;
154
gdat << endl << endl;
159
put (std::ostream& gdat, const geo_element& K, const geo_basic<T,sequential>& omega,
160
const field_basic<T,sequential>& uh,
161
const basis_on_nodal_basis& geo_on_pointset,
162
const basis_on_nodal_basis& field_on_pointset,
165
switch (K.variant()) {
166
case reference_element::e: put_edge (gdat, K, omega, uh, geo_on_pointset, field_on_pointset, bbox); break;
167
case reference_element::t: put_triangle (gdat, K, omega, uh, geo_on_pointset, field_on_pointset, bbox); break;
168
case reference_element::q: put_quadrangle (gdat, K, omega, uh, geo_on_pointset); break;
169
default: error_macro ("unsupported element variant `"<<K.variant()<<"'");
172
// ----------------------------------------------------------------------------
174
// ----------------------------------------------------------------------------
177
visu_gnuplot_scalar (odiststream& ods, const field_basic<T,sequential>& uh)
180
typedef typename field_basic<T,sequential>::float_type float_type;
181
typedef typename geo_basic<float_type,sequential>::size_type size_type;
182
typedef point_basic<size_type> ilat;
183
ostream& os = ods.os();
184
bool verbose = iorheo::getverbose(os);
185
bool clean = iorheo::getclean(os);
186
bool execute = iorheo::getexecute(os);
187
bool fill = iorheo::getfill(os); // show grid or fill elements
188
bool elevation = iorheo::getelevation(os);
189
bool color = iorheo::getcolor(os);
190
bool gray = iorheo::getgray(os);
191
bool black_and_white = iorheo::getblack_and_white(os);
192
bool reader_on_stdin = iorheo::getreader_on_stdin(os);
193
string format = iorheo::getimage_format(os);
194
string basename = iorheo::getbasename(os);
195
size_type subdivide = iorheo::getsubdivide(os);
196
size_type n_isovalue = iorheo::getn_isovalue(os);
197
size_type n_isovalue_negative = iorheo::getn_isovalue_negative(os);
198
string outfile_fmt = "";
199
string tmp = get_tmpdir() + "/";
200
if (!clean) tmp = "";
202
const geo_basic<float_type,sequential>& omega = uh.get_geo();
203
size_type dim = omega.dimension();
204
size_type map_dim = omega.map_dimension();
205
size_type nv = omega.sizes().ownership_by_dimension[0].size();
206
size_type nedg = omega.sizes().ownership_by_dimension[1].size();
207
size_type nfac = omega.sizes().ownership_by_dimension[2].size();
208
size_type nvol = omega.sizes().ownership_by_dimension[3].size();
209
size_type ne = omega.sizes().ownership_by_dimension[map_dim].size();
211
const numbering<float_type,sequential>& fem = uh.get_space().get_numbering();
212
if (subdivide == 0) { // subdivide is unset: use default
213
subdivide = std::max(omega.order(), subdivide);
214
subdivide = std::max(fem.degree (), subdivide);
216
basis subdivide_pointset ("P"+itos(subdivide));
217
basis_on_nodal_basis geo_on_pointset (subdivide_pointset, omega.get_piola_basis());
218
basis_on_nodal_basis field_on_pointset (subdivide_pointset, fem.get_basis());
221
bbox.xmin = omega.xmin();
222
bbox.xmax = omega.xmax();
223
bbox.umin = uh.min();
224
bbox.umax = uh.max();
226
std::vector<T> values;
227
if (n_isovalue_negative != 0) {
228
for (size_t i = 0; i <= n_isovalue_negative; i++) {
229
values.push_back (bbox.umin*(n_isovalue_negative - i)/n_isovalue_negative);
231
for (size_t i = 1; i <= n_isovalue - n_isovalue_negative; i++) {
232
values.push_back (bbox.umax*i/(n_isovalue - n_isovalue_negative));
239
string filename = tmp+basename + ".gdat";
240
string gdatname = filename;
241
filelist = filelist + " " + filename;
242
ofstream gdat (filename.c_str());
243
if (verbose) clog << "! file \"" << filename << "\" created.\n";
244
gdat << setprecision(numeric_limits<float_type>::digits10);
245
size_type used_dim = (fill ? map_dim : 1);
246
for (size_type ie = 0, ne = omega.size(used_dim); ie < ne; ie++) {
247
const geo_element& K = omega.get_geo_element(used_dim,ie);
248
put (gdat, K, omega, uh, geo_on_pointset, field_on_pointset, bbox);
255
bbox.umin = floorer(eps) (bbox.umin);
256
bbox.umax = ceiler(eps) (bbox.umax);
260
filename = tmp+basename + ".plot";
261
filelist = filelist + " " + filename;
262
ofstream plot (filename.c_str());
263
if (verbose) clog << "! file \"" << filename << "\" created.\n";
265
plot << "#!gnuplot" << endl
266
<< setprecision(numeric_limits<float_type>::digits10);
268
outfile_fmt = basename + "." + format;
269
string terminal = format;
270
if (terminal == "ps") {
271
terminal = "postscript eps";
272
if (color) terminal += " color";
274
if (terminal == "jpg") terminal = "jpeg";
275
if (terminal == "jpeg" || terminal == "png" || terminal == "gif") {
278
plot << "set terminal " << terminal << endl
279
<< "set output \"" << outfile_fmt << "\"" << endl;
281
if (!black_and_white) {
282
plot << "set noborder" << endl;
285
plot << "umin = " << bbox.umin << endl
286
<< "umax = " << bbox.umax << endl;
287
if (bbox.xmin[0] >= bbox.xmax[0]) plot << "#";
288
plot << "set xrange [" << bbox.xmin[0] << ":" << bbox.xmax[0] << "]" << endl;
289
if (bbox.xmin[1] >= bbox.xmax[1]) plot << "#";
290
plot << "set yrange [" << bbox.xmin[1] << ":" << bbox.xmax[1] << "]" << endl;
291
if (bbox.umin >= bbox.umax) plot << "#";
292
plot << "set zrange [umin:umax]" << endl;
293
if (bbox.xmin[0] >= bbox.xmax[0] || bbox.xmin[1] >= bbox.xmax[1]) {
294
plot << "set size square" << endl;
296
plot << "set size ratio -1 # equal scales" << endl
297
<< "set noxtics" << endl
298
<< "set noytics" << endl;
301
plot << "set xyplane at umin-0.1*(umax-umin)" << endl;
303
plot << "set view map" << endl;
306
plot << "set pm3d interpolate 10,10 corners2color mean" << endl;
308
plot << "set palette gray" << endl;
310
plot << "set palette rgbformulae 33,13,-4" << endl;
312
} else { // black-and-white
313
if (values.size() != 0) {
314
plot << "set cntrparam levels discrete ";
315
for (size_t i = 0, n = values.size(); i < n; i++) {
317
if (i != n-1) plot << ", ";
321
plot << "set cntrparam levels incremental umin,(umax-umin)/10.0,umax"<< endl;
323
plot << "unset surface" << endl
324
<< "set contour base" << endl
325
<< "set nokey" << endl
326
<< "set palette rgbformulae 0,0,0" << endl
327
<< "unset colorbox" << endl;
331
plot << "plot \"" << gdatname << "\" notitle with lines";
332
if (black_and_white) {
333
plot << " lc 0" << endl;
337
if (!fill && dim == 2) {
342
plot << " \"" << gdatname << "\" notitle";
344
if (!black_and_white && fill) {
345
plot << " with pm3d" << endl;
347
plot << " with lines palette" << endl;
349
} else { // a 2d line
350
plot << " with lines palette lw 2" << endl;
356
if (format == "" && !reader_on_stdin) {
357
plot << "pause -1 \"<return>\"\n";
366
command = "gnuplot ";
367
if (reader_on_stdin) command += "-persist ";
368
command += tmp + basename + ".plot";
369
if (verbose) clog << "! " << command << endl;
371
status = system (command.c_str());
373
check_macro (file_exists (outfile_fmt), "! file \"" << outfile_fmt << "\" creation failed");
374
if (verbose) clog << "! file \"" << outfile_fmt << "\" created" << endl;
378
// clear gnuplot data
381
command = "/bin/rm -f " + filelist;
382
if (verbose) clog << "! " << command << endl;
383
status = system (command.c_str());
387
// ----------------------------------------------------------------------------
389
// ----------------------------------------------------------------------------
392
visu_gnuplot_vector (odiststream& ods, const field_basic<T,sequential>& uh)
394
typedef typename geo_basic<T,sequential>::size_type size_type;
395
const geo_basic<T,sequential>& omega = uh.get_geo();
396
check_macro (omega.get_piola_basis().name() == uh.get_space().get_numbering().name(),
397
"gnuplot vector: unsupported non-isoparametric approx " << uh.get_space().get_numbering().name());
398
size_type n_elt = omega.size();
399
size_type d = omega.dimension();
400
Float diam_omega = norm (omega.xmax() - omega.xmin()); // characteristic length in omega
401
Float h_moy = diam_omega/pow(n_elt,1./d);
402
field_basic<T,sequential> norm_uh = norm(uh);
403
Float norm_max_uh = norm_uh.max_abs(); // get max vector length
404
if (norm_max_uh + 1 == 1) norm_max_uh = 1;
405
Float scale = h_moy/norm_max_uh;
406
size_type n_comp = uh.size();
407
std::vector<field_component_const<T,sequential> > uh_comp (n_comp);
408
for (size_type i_comp = 0; i_comp < n_comp; i_comp++) {
409
uh_comp[i_comp] = uh[i_comp];
411
array<point_basic<T>, sequential> x = omega.get_nodes();
412
for (size_type inod = 0, nnod = x.size(); inod < nnod; inod++) {
414
for (size_type i_comp = 0; i_comp < n_comp; i_comp++) {
415
vi[i_comp] = uh[i_comp].dof(inod); // TODO: non-isoparam => interpolate
419
geo_basic<T,sequential> deformed_omega = omega;
420
deformed_omega.set_nodes(x);
421
space_basic<T,sequential> deformed_Vh (deformed_omega, norm_uh.get_space().get_numbering().name());
422
field_basic<T,sequential> deformed_norm_uh (deformed_Vh);
423
std::copy (norm_uh.begin_dof(), norm_uh.end_dof(), deformed_norm_uh.begin_dof());
424
visu_gnuplot (ods, deformed_norm_uh);
427
// ----------------------------------------------------------------------------
429
// ----------------------------------------------------------------------------
432
visu_gnuplot (odiststream& ods, const field_basic<T,sequential>& uh)
434
switch (uh.get_space().valued_tag()) {
435
case space_constant::scalar: visu_gnuplot_scalar (ods, uh); break;
436
case space_constant::vector: visu_gnuplot_vector (ods, uh); break;
437
default: error_macro ("do not known how to print " << uh.valued() << "-valued field");
441
// ----------------------------------------------------------------------------
442
// instanciation in library
443
// ----------------------------------------------------------------------------
444
template odiststream& visu_gnuplot<Float> (odiststream&, const field_basic<Float,sequential>&);
446
} // rheolef namespace