Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
output.h
Go to the documentation of this file.
1/** @file output.h
2 */
3/**
4# Output functions
5
6## *output_field()*: Multiple fields interpolated on a regular grid (text format)
7
8This function interpolates a *list* of fields on a *n+1 x n+1* regular
9grid. The resulting data are written in text format in the file
10pointed to by *fp*. The correspondance between column numbers and
11variables is summarised in the first line of the file. The data are
12written row-by-row and each row is separated from the next by a blank
13line. This format is compatible with the *splot* command of *gnuplot*
14i.e. one could use something like
15
16~~~bash
17gnuplot> set pm3d map
18gnuplot> splot 'fields' u 1:2:4
19~~~
20
21The arguments and their default values are:
22
23*list*
24: list of fields to output. Default is *all*.
25
26*fp*
27: file pointer. Default is *stdout*.
28
29*n*
30: number of points along each dimension. Default is *N*.
31
32*linear*
33: use first-order (default) or bilinear interpolation.
34
35*box*
36: the lower-left and upper-right coordinates of the domain to consider.
37 Default is the entire domain. */
38
41 FILE * fp = stdout,
42 int n = N,
43 bool linear = false,
44 coord box[2] = {{X0, Y0}, {X0 + L0, Y0 + L0*Dimensions.y/Dimensions.x}})
45{
46 n++;
47 int len = list_len (list);
48 double Delta = 0.999999*(box[1].x - box[0].x)/(n - 1);
49 int ny = (box[1].y - box[0].y)/Delta + 1;
50 double ** field = (double **) matrix_new (n, ny, len*sizeof(double)), * v = field[0];
51 for (int i = 0; i < n*ny*len; i++, v++)
52 *v = nodata;
53 coord box1[2] = {{box[0].x - Delta/2., box[0].y - Delta/2.},
54 {box[0].x + (n - 0.5)*Delta, box[0].y + (ny - 0.5)*Delta}};
55 coord cn = {n, ny}, p;
56#if _MPI
57 v = field[0];
59#else
61#endif
62 {
63 double ** alias = field; // so that qcc considers 'field' a local variable
64 int i = (p.x - box1[0].x)/(box1[1].x - box1[0].x)*cn.x;
65 int j = (p.y - box1[0].y)/(box1[1].y - box1[0].y)*cn.y;
66 int k = 0;
67 for (int _s = 0; _s < 1; _s++) /* scalar in list */
68 alias[i][len*j + k++] = linear ? interpolate_linear (point, s, p.x, p.y, p.z) : s[];
69 }
70
71 if (pid() == 0) {
72 fprintf (fp, "# 1:x 2:y");
73 int i = 3;
74 for (int _s = 0; _s < 1; _s++) /* scalar in list */
75 fprintf (fp, " %d:%s", i++, s.name);
76 fputc('\n', fp);
77 for (int i = 0; i < n; i++) {
78 double x = Delta*i + box[0].x;
79 for (int j = 0; j < ny; j++) {
80 double y = Delta*j + box[0].y;
81 // map (x, y);
82 fprintf (fp, "%g %g", x, y);
83 int k = 0;
84 for (int _s = 0; _s < 1; _s++) /* scalar in list */
85 fprintf (fp, " %g", field[i][len*j + k++]);
86 fputc ('\n', fp);
87 }
88 fputc ('\n', fp);
89 }
90 fflush (fp);
91 }
92
94}
95
96/**
97## *output_matrix()*: Single field interpolated on a regular grid (binary format)
98
99This function writes a binary representation of a single field
100interpolated on a regular *n x n* grid. The format is compatible with
101the binary matrix format of gnuplot i.e. one could use
102
103~~~bash
104gnuplot> set pm3d map
105gnuplot> splot 'matrix' binary u 2:1:3
106~~~
107
108The arguments and their default values are:
109
110*f*
111: a scalar field (compulsory).
112
113*fp*
114: file pointer. Default is *stdout*.
115
116*n*
117: number of points along each dimension. Default is *N*.
118
119*linear*
120: use first-order (default) or bilinear interpolation.
121
122*box*
123: the lower-left and upper-right coordinates of the domain to consider.
124 Default is the entire domain.
125*/
126
127trace
129 FILE * fp = stdout,
130 int n = N,
131 bool linear = false,
132 const char * file = NULL,
133 coord box[2] = {{X0, Y0}, {X0 + L0, Y0 + L0*Dimensions.y/Dimensions.x}})
134{
135 coord cn = {n}, p;
136 double delta = (box[1].x - box[0].x)/n;
137 cn.y = (int)((box[1].y - box[0].y)/delta);
138
139 double ** ppm = (double **) matrix_new (cn.x, cn.y, sizeof(double));
140 double * ppm0 = &ppm[0][0];
141 unsigned int len = cn.x*cn.y;
142 for (int i = 0; i < len; i++)
143 ppm0[i] = - HUGE;
144
145#if _MPI
147#else
149#endif
150 {
151 int i = (p.x - box[0].x)/(box[1].x - box[0].x)*cn.x;
152 int j = (p.y - box[0].y)/(box[1].y - box[0].y)*cn.y;
153 double ** alias = ppm; // so that qcc considers ppm a local variable
154 alias[i][j] = linear ? interpolate_linear (point, f, p.x, p.y, p.z) : f[];
155 }
156
157 if (pid() == 0) {
158 if (file) {
159 fp = fopen (file, "wb");
160 if (!fp) {
161 perror (file);
162 exit (1);
163 }
164 }
165 float fn = cn.y;
166 fwrite (&fn, sizeof(float), 1, fp);
167 coord delta = {(box[1].x - box[0].x)/cn.x, (box[1].y - box[0].y)/cn.y};
168 for (int j = 0; j < cn.y; j++) {
169 float yp = box[0].y + delta.y*(j + 0.5);
170 fwrite (&yp, sizeof(float), 1, fp);
171 }
172 for (int i = 0; i < cn.x; i++) {
173 float xp = box[0].x + delta.x*(i + 0.5);
174 fwrite (&xp, sizeof(float), 1, fp);
175 for (int j = 0; j < cn.y; j++) {
176 float z = ppm[i][j];
177 fwrite (&z, sizeof(float), 1, fp);
178 }
179 }
180 if (file)
181 fclose (fp);
182 else
183 fflush (fp);
184 }
185
187}
188
189/**
190## Colormaps
191
192Colormaps are arrays of (127) red, green, blue triplets. */
193
194#define NCMAP 127
195
196typedef void (* Colormap) (double cmap[NCMAP][3]);
197
198void jet (double cmap[NCMAP][3])
199{
200 for (int i = 0; i < NCMAP; i++) {
201 cmap[i][0] =
202 i <= 46 ? 0. :
203 i >= 111 ? -0.03125*(i - 111) + 1. :
204 i >= 78 ? 1. :
205 0.03125*(i - 46);
206 cmap[i][1] =
207 i <= 14 || i >= 111 ? 0. :
208 i >= 79 ? -0.03125*(i - 111) :
209 i <= 46 ? 0.03125*(i - 14) :
210 1.;
211 cmap[i][2] =
212 i >= 79 ? 0. :
213 i >= 47 ? -0.03125*(i - 79) :
214 i <= 14 ? 0.03125*(i - 14) + 1.:
215 1.;
216 }
217}
218
219void cool_warm (double cmap[NCMAP][3])
220{
221 /* diverging cool-warm from:
222 * http://www.sandia.gov/~kmorel/documents/ColorMaps/CoolWarmFloat33.csv
223 * see also:
224 * Diverging Color Maps for Scientific Visualization (Expanded)
225 * Kenneth Moreland
226 */
227 static double basemap[33][3] = {
228 {0.2298057, 0.298717966, 0.753683153},
229 {0.26623388, 0.353094838, 0.801466763},
230 {0.30386891, 0.406535296, 0.84495867},
231 {0.342804478, 0.458757618, 0.883725899},
232 {0.38301334, 0.50941904, 0.917387822},
233 {0.424369608, 0.558148092, 0.945619588},
234 {0.46666708, 0.604562568, 0.968154911},
235 {0.509635204, 0.648280772, 0.98478814},
236 {0.552953156, 0.688929332, 0.995375608},
237 {0.596262162, 0.726149107, 0.999836203},
238 {0.639176211, 0.759599947, 0.998151185},
239 {0.681291281, 0.788964712, 0.990363227},
240 {0.722193294, 0.813952739, 0.976574709},
241 {0.761464949, 0.834302879, 0.956945269},
242 {0.798691636, 0.849786142, 0.931688648},
243 {0.833466556, 0.860207984, 0.901068838},
244 {0.865395197, 0.86541021, 0.865395561},
245 {0.897787179, 0.848937047, 0.820880546},
246 {0.924127593, 0.827384882, 0.774508472},
247 {0.944468518, 0.800927443, 0.726736146},
248 {0.958852946, 0.769767752, 0.678007945},
249 {0.96732803, 0.734132809, 0.628751763},
250 {0.969954137, 0.694266682, 0.579375448},
251 {0.966811177, 0.650421156, 0.530263762},
252 {0.958003065, 0.602842431, 0.481775914},
253 {0.943660866, 0.551750968, 0.434243684},
254 {0.923944917, 0.49730856, 0.387970225},
255 {0.89904617, 0.439559467, 0.343229596},
256 {0.869186849, 0.378313092, 0.300267182},
257 {0.834620542, 0.312874446, 0.259301199},
258 {0.795631745, 0.24128379, 0.220525627},
259 {0.752534934, 0.157246067, 0.184115123},
260 {0.705673158, 0.01555616, 0.150232812}
261 };
262
263 for (int i = 0; i < NCMAP; i++) {
264 double x = i*(32 - 1e-10)/(NCMAP - 1);
265 int j = x; x -= j;
266 for (int k = 0; k < 3; k++)
267 cmap[i][k] = (1. - x)*basemap[j][k] + x*basemap[j+1][k];
268 }
269}
270
271void gray (double cmap[NCMAP][3])
272{
273 for (int i = 0; i < NCMAP; i++)
274 for (int k = 0; k < 3; k++)
275 cmap[i][k] = i/(NCMAP - 1.);
276}
277
278void randomap (double cmap[NCMAP][3])
279{
280 srand(0);
281 for (int i = 0; i < NCMAP; i++)
282 for (int k = 0; k < 3; k++)
283 cmap[i][k] = (noise() + 1.)/2.;
284}
285
286void blue_white_red (double cmap[NCMAP][3])
287{
288 for (int i = 0; i < (NCMAP + 1)/2; i++) {
289 cmap[i][0] = i/((NCMAP - 1)/2.);
290 cmap[i][1] = i/((NCMAP - 1)/2.);
291 cmap[i][2] = 1.;
292 }
293 for (int i = 0; i < (NCMAP - 1)/2; i++) {
294 cmap[i + (NCMAP + 1)/2][0] = 1.;
295 cmap[i + (NCMAP + 1)/2][1] = cmap[(NCMAP - 3)/2 - i][1];
296 cmap[i + (NCMAP + 1)/2][2] = cmap[(NCMAP - 3)/2 - i][1];
297 }
298}
299
300/**
301Given a colormap and a minimum and maximum value, this function
302returns the red/green/blue triplet corresponding to *val*. */
303
304typedef struct {
305 unsigned char r, g, b;
306} Color;
307
309 double val, double min, double max)
310{
311 Color c;
312 if (val == nodata) {
313 c.r = c.g = c.b = 0; // nodata is black
314 return c;
315 }
316 int i;
317 double coef;
318 if (max != min)
319 val = (val - min)/(max - min);
320 else
321 val = 0.;
322 if (val <= 0.) i = 0, coef = 0.;
323 else if (val >= 1.) i = NCMAP - 2, coef = 1.;
324 else {
325 i = val*(NCMAP - 1);
326 coef = val*(NCMAP - 1) - i;
327 }
328 if (i < 0 || i >= NCMAP - 1)
329 return (Color){99,55,43}; // brown is an error
330 unsigned char * c1 = (unsigned char *) &c;
331 for (int j = 0; j < 3; j++)
332 c1[j] = 255*(cmap[i][j]*(1. - coef) + cmap[i + 1][j]*coef);
333 return c;
334}
335
336/**
337## Image/animation conversion
338
339The open_image()/close_image() functions use pipes to convert PPM
340images to other formats, including `.mp4`, `.ogv` and `.gif`
341animations.
342
343The functions check whether the 'ffmpeg' or 'convert' executables are
344accessible, if they are not the conversion is disabled and the raw PPM
345images are saved. An extra ".ppm" extension is added to the file name
346to indicate that this happened. */
347
348static const char * extension (const char * file, const char * ext) {
349 int len = strlen(file);
350 return len > 4 && !strcmp (file + len - 4, ext) ? file + len - 4 : NULL;
351}
352
353static const char * is_animation (const char * file) {
354 const char * ext;
355 if ((ext = extension (file, ".mp4")) ||
356 (ext = extension (file, ".ogv")) ||
357 (ext = extension (file, ".gif")))
358 return ext;
359 return NULL;
360}
361
362static struct {
364 char ** names;
365 int n;
367
369{
370 for (int i = 0; i < open_image_data.n; i++) {
372 free (open_image_data.names[i]);
373 }
375 free (open_image_data.names);
377 open_image_data.names = NULL;
378 open_image_data.n = 0;
379}
380
381static FILE * open_image_lookup (const char * file)
382{
383 for (int i = 0; i < open_image_data.n; i++)
384 if (!strcmp (file, open_image_data.names[i]))
385 return open_image_data.fp[i];
386 return NULL;
387}
388
389static bool which (const char * command)
390{
391 char * s = getenv ("PATH");
392 if (!s)
393 return false;
394 char path[strlen(s) + 1];
395 strcpy (path, s);
396 s = strtok (path, ":");
397 while (s) {
398 char f[strlen(s) + strlen(command) + 2];
399 strcpy (f, s);
400 strcat (f, "/");
401 strcat (f, command);
402 FILE * fp = fopen (f, "r");
403 if (fp) {
404 fclose (fp);
405 return true;
406 }
407 s = strtok (NULL, ":");
408 }
409 return false;
410}
411
412static FILE * ppm_fallback (const char * file, const char * mode)
413{
414 char filename[strlen(file) + 5];
416 strcat (filename, ".ppm");
417 FILE * fp = fopen (filename, mode);
418 if (!fp) {
419 perror (file);
420#if _MPI
422#endif
423 exit (1);
424 }
425 return fp;
426}
427
428FILE * open_image (const char * file, const char * options)
429{
431 return ppm_fallback (file, "w");
432@else // !__EMSCRIPTEN__
433 assert (pid() == 0);
434 const char * ext;
435 if ((ext = is_animation (file))) {
437 if (fp)
438 return fp;
439
440 int len = strlen ("ppm2??? ") + strlen (file) +
441 (options ? strlen (options) : 0);
442 char command[len + 1];
443 strcpy (command, "ppm2"); strcat (command, ext + 1);
444
445 static int has_ffmpeg = -1;
446 if (has_ffmpeg < 0) {
447 if (which (command) && (which ("ffmpeg") || which ("avconv")))
448 has_ffmpeg = true;
449 else {
450 fprintf (ferr,
451 "src/output.h:%d: warning: cannot find '%s' or 'ffmpeg'/'avconv'\n"
452 "src/output.h:%d: warning: falling back to raw PPM outputs\n",
454 has_ffmpeg = false;
455 }
456 }
457 if (!has_ffmpeg)
458 return ppm_fallback (file, "a");
459
460 static bool added = false;
461 if (!added) {
463 added = true;
464 }
465 open_image_data.n++;
466 qrealloc (open_image_data.names, open_image_data.n, char *);
468
469 if (options) {
470 strcat (command, " ");
472 }
473 strcat (command, !strcmp (ext, ".mp4") ? " " : " > ");
476 return open_image_data.fp[open_image_data.n - 1] = popen (command, "w");
477 }
478 else { // !animation
479 static int has_convert = -1;
480 if (has_convert < 0) {
481 if (which ("convert"))
482 has_convert = true;
483 else {
484 fprintf (ferr,
485 "src/output.h:%d: warning: cannot find 'convert'\n"
486 "src/output.h:%d: warning: falling back to raw PPM outputs\n",
487 LINENO, LINENO);
488 has_convert = false;
489 }
490 }
491 if (!has_convert)
492 return ppm_fallback (file, "w");
493
494 int len = strlen ("convert ppm:- ") + strlen (file) +
495 (options ? strlen (options) : 0);
496 char command[len];
497 strcpy (command, "convert ppm:- ");
498 if (options) {
500 strcat (command, " ");
501 }
503 return popen (command, "w");
504 }
505@endif // !__EMSCRIPTEN__
506}
507
508void close_image (const char * file, FILE * fp)
509{
510 assert (pid() == 0);
511 if (is_animation (file)) {
512 if (!open_image_lookup (file))
513 fclose (fp);
514 }
516 else if (which ("convert"))
517 pclose (fp);
518@endif // !__EMSCRIPTEN__
519 else
520 fclose (fp);
521}
522
523/**
524## *output_ppm()*: Portable PixMap (PPM) image output
525
526Given a field, this function outputs a colormaped representation as a
527[Portable PixMap](http://en.wikipedia.org/wiki/Netpbm_format) image.
528
529If [ImageMagick](http://www.imagemagick.org/) is installed on the
530system, this image can optionally be converted to any image format
531supported by ImageMagick.
532
533The arguments and their default values are:
534
535*f*
536: a scalar field (compulsory).
537
538*fp*
539: a file pointer. Default is stdout.
540
541*n*
542: number of pixels. Default is *N*.
543
544*file*
545: sets the name of the file used as output for
546ImageMagick. This allows outputs in all formats supported by
547ImageMagick. For example, one could use
548
549~~~c
550output_ppm (f, file = "f.png");
551~~~
552
553to get a [PNG](http://en.wikipedia.org/wiki/Portable_Network_Graphics)
554image.
555
556*min, max*
557: minimum and maximum values used to define the
558colorscale. By default these are set automatically using the *spread*
559parameter.
560
561*spread*
562: if not specified explicitly, *min* and *max* are set to the average
563of the field minus (resp. plus) *spread* times the standard deviation.
564By default *spread* is five. If negative, the minimum and maximum
565values of the field are used.
566
567*z*
568: the z-coordinate (in 3D) of the plane being represented.
569
570*linear*
571: whether to use bilinear or first-order interpolation. Default is
572first-order.
573
574*box*
575: the lower-left and upper-right coordinates of the domain to consider.
576 Default is the entire domain.
577
578*mask*
579: if set, this field will be used to mask out (in black), the regions
580of the domain for which *mask* is negative.
581
582*map*
583: the colormap: *jet*, *cool_warm* or *gray*. Default is *jet*.
584
585*opt*
586: options to pass to 'convert' or to the 'ppm2???' scripts (used
587with *file*).
588
589*fps*
590: used only for [online output](grid/gpu/output.h) on GPUs.
591
592*checksum*
593: write a checksum of the generated image in the file pointed.
594*/
595
596trace
598 FILE * fp = stdout,
599 int n = N,
600 char * file = NULL,
601 double min = 0, double max = 0, double spread = 5,
602 double z = 0,
603 bool linear = false,
604 coord box[2] = {{X0, Y0}, {X0 + L0, Y0 + L0*Dimensions.y/Dimensions.x}},
605 scalar mask = {-1},
606 Colormap map = jet,
607 char * opt = NULL,
608 int fps = 0,
609 FILE * checksum = NULL)
610{
611 // default values
612 if (!min && !max) {
613 stats s = statsf (f);
614 if (spread < 0.)
615 min = s.min, max = s.max;
616 else {
617 double avg = s.sum/s.volume;
618 min = avg - spread*s.stddev; max = avg + spread*s.stddev;
619 }
620 }
621 box[0].z = z, box[1].z = z;
622
623 coord cn = {n}, p;
624 double delta = (box[1].x - box[0].x)/n;
625 cn.y = (int)((box[1].y - box[0].y)/delta);
626 if (((int)cn.y) % 2) cn.y++;
627
628 Color ** ppm = (Color **) matrix_new (cn.y, cn.x, sizeof(Color));
629 unsigned char * ppm0 = &ppm[0][0].r;
630 int len = 3*cn.x*cn.y;
631 memset (ppm0, 0, len*sizeof (unsigned char));
632 double cmap[NCMAP][3];
633 (* map) (cmap);
634
635#if _MPI
637#else
639#endif
640 {
641 double v;
642 if (mask.i >= 0) { // masking
643 if (linear) {
644 double m = interpolate_linear (point, mask, p.x, p.y, p.z);
645 if (m < 0.)
646 v = nodata;
647 else
648 v = interpolate_linear (point, f, p.x, p.y, p.z);
649 }
650 else {
651 if (mask[] < 0.)
652 v = nodata;
653 else
654 v = f[];
655 }
656 }
657 else if (linear)
658 v = interpolate_linear (point, f, p.x, p.y, p.z);
659 else
660 v = f[];
661 int i = (p.x - box[0].x)/(box[1].x - box[0].x)*cn.x;
662 int j = (p.y - box[0].y)/(box[1].y - box[0].y)*cn.y;
663 Color ** alias = ppm; // so that qcc considers ppm a local variable
664 alias[(int)cn.y - 1 - j][i] = colormap_color (cmap, v, min, max);
665 }
666
667 if (pid() == 0) {
668 if (file)
669 fp = open_image (file, opt);
670
671 fprintf (fp, "P6\n%g %g 255\n", cn.x, cn.y);
672 fwrite (ppm0, sizeof(unsigned char), 3*cn.x*cn.y, fp);
673
674 if (file)
676 else
677 fflush (fp);
678
679 if (checksum) {
682 a32_hash_add (&hash, ppm0, sizeof(unsigned char)*3*cn.x*cn.y);
683 fputs ("# ", checksum);
684 if (file)
685 fprintf (checksum, "%s: ", file);
686 fprintf (checksum, "checksum: %08lx\n", (unsigned long) a32_hash (&hash));
687 }
688 }
689
691}
692
693/**
694## *output_grd()*: ESRI ASCII Grid format
695
696The [ESRI GRD format](http://en.wikipedia.org/wiki/Esri_grid) is a
697standard format for importing raster data into [GIS
698systems](http://en.wikipedia.org/wiki/Geographic_information_system).
699
700The arguments and their default values are:
701
702*f*
703: a scalar field (compulsory).
704
705*fp*
706: a file pointer. Default is stdout.
707
708\f$\Delta\f$
709: size of a grid element. Default is L0/N.
710
711*linear*
712: whether to use bilinear or first-order interpolation. Default is
713first-order.
714
715*box*
716: the lower-left and upper-right coordinates of the domain to consider.
717 Default is the entire domain.
718
719*mask*
720: if set, this field will be used to mask out, the regions
721of the domain for which *mask* is negative. */
722
723trace
725 FILE * fp = stdout,
726 double Delta = L0/N,
727 bool linear = false,
728 coord box[2] = {{X0, Y0}, {X0 + L0, Y0 + L0*Dimensions.y/Dimensions.x}},
729 scalar mask = {-1})
730{
731 int nx = (box[1].x - box[0].x)/Delta;
732 int ny = (box[1].y - box[0].y)/Delta;
733
734 // header
735 fprintf (fp, "ncols %d\n", nx);
736 fprintf (fp, "nrows %d\n", ny);
737 fprintf (fp, "xllcorner %g\n", box[0].x);
738 fprintf (fp, "yllcorner %g\n", box[0].y);
739 fprintf (fp, "cellsize %g\n", Delta);
740 fprintf (fp, "nodata_value -9999\n");
741
742 // data
743 for (int j = ny-1; j >= 0; j--) {
744 double yp = Delta*j + box[0].y + Delta/2.;
745 for (int i = 0; i < nx; i++) {
746 double xp = Delta*i + box[0].x + Delta/2., v;
747 if (mask.i >= 0) { // masking
748 double m = interpolate (mask, xp, yp, linear = linear);
749 if (m < 0.)
750 v = nodata;
751 else
752 v = interpolate (f, xp, yp, linear = linear);
753 }
754 else
755 v = interpolate (f, xp, yp, linear = linear);
756 if (v == nodata)
757 fprintf (fp, "-9999 ");
758 else
759 fprintf (fp, "%f ", v);
760 }
761 fprintf (fp, "\n");
762 }
763
764 fflush (fp);
765}
766
767#if MULTIGRID
768
769/**
770## *output_gfs()*: Gerris simulation format
771
772The function writes simulation data in the format used in
773[Gerris](https://gerris.dalembert.upmc.fr) simulation files. These
774files can be read with GfsView.
775
776The arguments and their default values are:
777
778*fp*
779: a file pointer. Default is stdout or *file*.
780
781*list*
782: a list of scalar fields to write. Default is *all*.
783
784*file*
785: the name of the file to write to (mutually exclusive with *fp*).
786
787*translate*
788: whether to replace "well-known" Basilisk variables with their Gerris
789equivalents.
790*/
791
792static char * replace (const char * input, int target, int with,
793 bool translate)
794{
795 if (translate) {
796 if (!strcmp (input, "u.x"))
797 return strdup ("U");
798 if (!strcmp (input, "u.y"))
799 return strdup ("V");
800 if (!strcmp (input, "u.z"))
801 return strdup ("W");
802 }
803 char * name = strdup (input), * i = name;
804 while (*i != '\0') {
805 if (*i == target)
806 *i = with;
807 i++;
808 }
809 return name;
810}
811
812trace
813void output_gfs (FILE * fp = NULL,
814 scalar * list = NULL,
815 char * file = NULL,
816 bool translate = false)
817{
818 char * fname = file;
819
820#if _MPI
821#if MULTIGRID_MPI
823#endif // !MULTIGRID_MPI
824 FILE * sfp = fp;
825 if (file == NULL) {
826 long pid = getpid();
827 MPI_Bcast (&pid, 1, MPI_LONG, 0, MPI_COMM_WORLD);
828 fname = qmalloc (80, char);
829 snprintf (fname, 80, ".output-%ld", pid);
830 fp = NULL;
831 }
832#endif // _MPI
833
834 bool opened = false;
835 if (fp == NULL) {
836 if (fname == NULL)
837 fp = stdout;
838 else if (!(fp = fopen (fname, "w"))) {
839 perror (fname);
840 exit (1);
841 }
842 else
843 opened = true;
844 }
845
846 scalar * slist = list ? list : list_copy (all);
847
849 fprintf (fp,
850 "1 0 GfsSimulation GfsBox GfsGEdge { binary = 1"
851 " x = %g y = %g ",
852 0.5 + X0/L0, 0.5 + Y0/L0);
853#if dimension == 3
854 fprintf (fp, "z = %g ", 0.5 + Z0/L0);
855#endif
856
857 if (slist != NULL && slist[0].i != -1) {
858 scalar s = slist[0];
859 char * name = replace (s.name, '.', '_', translate);
860 fprintf (fp, "variables = %s", name);
861 free (name);
862 for (int i = 1; i < list_len(slist); i++) {
863 scalar s = slist[i];
864 if (s.name) {
865 char * name = replace (s.name, '.', '_', translate);
866 fprintf (fp, ",%s", name);
867 free (name);
868 }
869 }
870 fprintf (fp, " ");
871 }
872 fprintf (fp, "} {\n");
873 fprintf (fp, " Time { t = %g }\n", t);
874 if (L0 != 1.)
875 fprintf (fp, " PhysicalParams { L = %g }\n", L0);
876 fprintf (fp, " VariableTracerVOF f\n");
877 fprintf (fp, "}\nGfsBox { x = 0 y = 0 z = 0 } {\n");
878
879#if _MPI
880 long header;
881 if ((header = ftell (fp)) < 0) {
882 perror ("output_gfs(): error in header");
883 exit (1);
884 }
885 int cell_size = sizeof(unsigned) + sizeof(double);
886 for (int _s = 0; _s < 1; _s++) /* scalar in slist */
887 if (s.name)
888 cell_size += sizeof(double);
889 scalar index = {0} /* new scalar */;
890 size_t total_size = header + (z_indexing (index, false) + 1)*cell_size;
891#endif
892
893 // see gerris/ftt.c:ftt_cell_write()
894 // gerris/domain.c:gfs_cell_write()
895 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
896#if _MPI // fixme: this won't work when combining MPI and mask()
897 if (is_local(cell))
898#endif
899 {
900#if _MPI
901 if (fseek (fp, header + index[]*cell_size, SEEK_SET) < 0) {
902 perror ("output_gfs(): error while seeking");
903 exit (1);
904 }
905#endif
906 unsigned flags =
907 level == 0 ? 0 :
908#if dimension == 1
909 child.x == 1;
910#elif dimension == 2
911 child.x == -1 && child.y == -1 ? 0 :
912 child.x == -1 && child.y == 1 ? 1 :
913 child.x == 1 && child.y == -1 ? 2 :
914 3;
915#else // dimension == 3
916 child.x == -1 && child.y == -1 && child.z == -1 ? 0 :
917 child.x == -1 && child.y == -1 && child.z == 1 ? 1 :
918 child.x == -1 && child.y == 1 && child.z == -1 ? 2 :
919 child.x == -1 && child.y == 1 && child.z == 1 ? 3 :
920 child.x == 1 && child.y == -1 && child.z == -1 ? 4 :
921 child.x == 1 && child.y == -1 && child.z == 1 ? 5 :
922 child.x == 1 && child.y == 1 && child.z == -1 ? 6 :
923 7;
924#endif
925 if (is_leaf(cell))
926 flags |= (1 << 4);
927 fwrite (&flags, sizeof (unsigned), 1, fp);
928 double a = -1;
929 fwrite (&a, sizeof (double), 1, fp);
930 for (int _s = 0; _s < 1; _s++) /* scalar in slist */
931 if (s.name) {
932 if (s.v.x.i >= 0) {
933 // this is a vector component, we need to rotate from
934 // N-ordering (Basilisk) to Z-ordering (Gerris)
935 // fixme: this does not work for tensors
936#if dimension >= 2
937 if (s.v.x.i == s.i) {
938 s = s.v.y;
939 a = is_local(cell) && s[] != nodata ? s[] : (double) DBL_MAX;
940 }
941 else if (s.v.y.i == s.i) {
942 s = s.v.x;
943 a = is_local(cell) && s[] != nodata ? - s[] : (double) DBL_MAX;
944 }
945#endif
946#if dimension >= 3
947 else
948 a = is_local(cell) && s[] != nodata ? s[] : (double) DBL_MAX;
949#endif
950 }
951 else
952 a = is_local(cell) && s[] != nodata ? s[] : (double) DBL_MAX;
953 fwrite (&a, sizeof (double), 1, fp);
954 }
955 }
956 if (is_leaf(cell))
957 continue;
958 }
959
960#if _MPI
961 delete ({index});
962 if (!pid() && fseek (fp, total_size, SEEK_SET) < 0) {
963 perror ("output_gfs(): error while finishing");
964 exit (1);
965 }
966 if (!pid())
967#endif
968 fputs ("}\n", fp);
969 fflush (fp);
970
971 if (!list)
972 free (slist);
973 if (opened)
974 fclose (fp);
975
976#if _MPI
977 if (file == NULL) {
979 if (pid() == 0) {
980 if (sfp == NULL)
981 sfp = stdout;
982 fp = fopen (fname, "r");
983 size_t l;
984 unsigned char buffer[8192];
985 while ((l = fread (buffer, 1, 8192, fp)) > 0)
986 fwrite (buffer, 1, l, sfp);
987 fflush (sfp);
988 remove (fname);
989 }
990 free (fname);
991 }
992#endif // _MPI
993}
994
995/**
996## *dump()*: Basilisk snapshots
997
998This function (together with *restore()*) can be used to dump/restore
999entire simulations.
1000
1001The arguments and their default values are:
1002
1003*file*
1004: the name of the file to write to (mutually exclusive with *fp*). The
1005default is "dump".
1006
1007*list*
1008: a list of scalar fields to write. Default is *all*.
1009
1010*fp*
1011: a file pointer. Default is stdout.
1012
1013*unbuffered*
1014: whether to use a file buffer. Default is false.
1015
1016*zero*
1017: whether to dump fields which are zero. Default is true.
1018*/
1019
1020struct DumpHeader {
1021 double t;
1022 long len;
1023 int i, depth, npe, version;
1024 coord n;
1025};
1026
1027static const int dump_version =
1028 // 161020
1029 170901;
1030
1031static scalar * dump_list (scalar * lista, bool zero)
1032{
1034 // fixme: on GPUs statsf() can change the `all` list, because it
1035 // allocates new fields to store reductions, which causes a nasty
1036 // crash...
1037#if 1
1039#endif
1040 for (int _s = 0; _s < 1; _s++) /* scalar in listb */
1041 if (!s.face && !s.nodump && s.i != cm.i) {
1042 if (zero)
1043 list = list_add (list, s);
1044 else {
1045 stats ss = statsf (s);
1046 if (ss.min != 0. || ss.max != 0.)
1047 list = list_add (list, s);
1048 }
1049 }
1050 free (listb);
1051 return list;
1052}
1053
1054static void dump_header (FILE * fp, struct DumpHeader * header, scalar * list)
1055{
1056 if (fwrite (header, sizeof(struct DumpHeader), 1, fp) < 1) {
1057 perror ("dump(): error while writing header");
1058 exit (1);
1059 }
1060 for (int _s = 0; _s < 1; _s++) /* scalar in list */ {
1061 unsigned len = strlen(s.name);
1062 if (fwrite (&len, sizeof(unsigned), 1, fp) < 1) {
1063 perror ("dump(): error while writing len");
1064 exit (1);
1065 }
1066 if (fwrite (s.name, sizeof(char), len, fp) < len) {
1067 perror ("dump(): error while writing s.name");
1068 exit (1);
1069 }
1070 }
1071 double o[4] = {X0,Y0,Z0,L0};
1072 if (fwrite (o, sizeof(double), 4, fp) < 4) {
1073 perror ("dump(): error while writing coordinates");
1074 exit (1);
1075 }
1076}
1077
1078#if !_MPI
1079trace
1080void dump (const char * file = "dump",
1081 scalar * list = all,
1082 FILE * fp = NULL,
1083 bool unbuffered = false,
1084 bool zero = true)
1085{
1086 char * name = NULL;
1087 if (!fp) {
1088 name = (char *) malloc (strlen(file) + 2);
1089 strcpy (name, file);
1090 if (!unbuffered)
1091 strcat (name, "~");
1092 if ((fp = fopen (name, "w")) == NULL) {
1093 perror (name);
1094 exit (1);
1095 }
1096 }
1097 assert (fp);
1098
1100 scalar size[];
1102 struct DumpHeader header = { t, list_len(slist), iter, depth(), npe(),
1103 dump_version };
1104 int npe = 1;
1105 for (int _d = 0; _d < dimension; _d++) {
1106 header.n.x = Dimensions.x;
1107 npe *= header.n.x;
1108 }
1109 header.npe = npe;
1111
1112 subtree_size (size, false);
1113#if _GPU
1114 for (int _s = 0; _s < 1; _s++) /* scalar in slist */
1115 s.stencil.io |= s_input;
1117#endif // _GPU
1118 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
1119 unsigned flags = is_leaf(cell) ? leaf : 0;
1120 if (fwrite (&flags, sizeof(unsigned), 1, fp) < 1) {
1121 perror ("dump(): error while writing flags");
1122 exit (1);
1123 }
1124 for (int _s = 0; _s < 1; _s++) /* scalar in slist */ {
1125 double val = s[];
1126 if (fwrite (&val, sizeof(double), 1, fp) < 1) {
1127 perror ("dump(): error while writing scalars");
1128 exit (1);
1129 }
1130 }
1131 if (is_leaf(cell))
1132 continue;
1133 }
1134
1135 free (slist);
1136 if (file) {
1137 fclose (fp);
1138 if (!unbuffered)
1139 rename (name, file);
1140 free (name);
1141 }
1142}
1143#else // _MPI
1144trace
1145void dump (const char * file = "dump",
1146 scalar * list = all,
1147 FILE * fp = NULL,
1148 bool unbuffered = false,
1149 bool zero = true)
1150{
1151 if (fp != NULL || file == NULL) {
1152 fprintf (ferr, "dump(): must specify a file name when using MPI\n");
1153 exit(1);
1154 }
1155
1156 char name[strlen(file) + 2];
1157 strcpy (name, file);
1158 if (!unbuffered)
1159 strcat (name, "~");
1160 FILE * fh = NULL;
1161 if (pid() == 0) {
1162 fh = fopen (name, "w");
1163 if (fh == NULL) {
1164 perror (name);
1165 exit (1);
1166 }
1167 }
1168
1170 scalar size[];
1172 struct DumpHeader header = { t, list_len(slist), iter, depth(), npe(),
1173 dump_version };
1174 for (int _d = 0; _d < dimension; _d++)
1175 header.n.x = Dimensions.x;
1176
1177#if MULTIGRID_MPI
1179#endif
1180
1181 if (pid() == 0) {
1183 fflush (fh);
1184 }
1185
1187
1188 if (pid() != 0) {
1189 fh = fopen (name, "r+");
1190 if (fh == NULL) {
1191 perror (name);
1192 exit (1);
1193 }
1194 }
1195
1196 scalar index = {-1};
1197
1198 index = {0} /* new scalar */;
1199 z_indexing (index, false);
1200 long cell_size = sizeof(unsigned) + header.len*sizeof(double);
1201 long sizeofheader = sizeof(header) + 4*sizeof(double);
1202 for (int _s = 0; _s < 1; _s++) /* scalar in slist */
1203 sizeofheader += sizeof(unsigned) + sizeof(char)*strlen(s.name);
1204 long pos = pid() ? 0 : sizeofheader;
1205
1206 subtree_size (size, false);
1207
1208 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
1209 // fixme: this won't work when combining MPI and mask()
1210 if (is_local(cell)) {
1211 long offset = sizeofheader + index[]*cell_size;
1212 if (pos != offset) {
1213 fseek (fh, offset, SEEK_SET);
1214 pos = offset;
1215 }
1216 unsigned flags = is_leaf(cell) ? leaf : 0;
1217 fwrite (&flags, 1, sizeof(unsigned), fh);
1218 for (int _s = 0; _s < 1; _s++) /* scalar in slist */ {
1219 double val = s[];
1220 fwrite (&val, 1, sizeof(double), fh);
1221 }
1222 pos += cell_size;
1223 }
1224 if (is_leaf(cell))
1225 continue;
1226 }
1227
1228 delete ({index});
1229
1230 free (slist);
1231 fclose (fh);
1232 if (!unbuffered && pid() == 0)
1233 rename (name, file);
1234}
1235#endif // _MPI
1236
1237trace
1238bool restore (const char * file = "dump",
1239 scalar * list = NULL,
1240 FILE * fp = NULL)
1241{
1242 if (!fp && (fp = fopen (file, "r")) == NULL)
1243 return false;
1244 assert (fp);
1245
1246 struct DumpHeader header = {0};
1247 if (fread (&header, sizeof(header), 1, fp) < 1) {
1248 fprintf (ferr, "restore(): error: expecting header\n");
1249 exit (1);
1250 }
1251
1252#if TREE
1253 init_grid (1);
1254 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
1255 cell.pid = pid();
1256 cell.flags |= active;
1257 }
1258 tree->dirty = true;
1259#else // multigrid
1260#if MULTIGRID_MPI
1261 if (header.npe != npe()) {
1262 fprintf (ferr,
1263 "restore(): error: the number of processes don't match:"
1264 " %d != %d\n",
1265 header.npe, npe());
1266 exit (1);
1267 }
1268#endif // MULTIGRID_MPI
1269 dimensions (header.n.x, header.n.y, header.n.z);
1270 double n = header.n.x;
1271 int depth = header.depth;
1272 while (n > 1)
1273 depth++, n /= 2;
1274 init_grid (1 << depth);
1275#endif // multigrid
1276
1277 bool restore_all = (list == all);
1278 scalar * slist = dump_list (list ? list : all, true);
1279 if (header.version == 161020) {
1280 if (header.len - 1 != list_len (slist)) {
1281 fprintf (ferr,
1282 "restore(): error: the list lengths don't match: "
1283 "%ld (file) != %d (code)\n",
1284 header.len - 1, list_len (slist));
1285 exit (1);
1286 }
1287 }
1288 else { // header.version != 161020
1289 if (header.version != dump_version) {
1290 fprintf (ferr,
1291 "restore(): error: file version mismatch: "
1292 "%d (file) != %d (code)\n",
1293 header.version, dump_version);
1294 exit (1);
1295 }
1296
1297 scalar * input = NULL;
1298 for (int i = 0; i < header.len; i++) {
1299 unsigned len;
1300 if (fread (&len, sizeof(unsigned), 1, fp) < 1) {
1301 fprintf (ferr, "restore(): error: expecting len\n");
1302 exit (1);
1303 }
1304 char name[len + 1];
1305 if (fread (name, sizeof(char), len, fp) < 1) {
1306 fprintf (ferr, "restore(): error: expecting s.name\n");
1307 exit (1);
1308 }
1309 name[len] = '\0';
1310
1311 if (i > 0) { // skip subtree size
1312 bool found = false;
1313 for (int _s = 0; _s < 1; _s++) /* scalar in slist */
1314 if (!strcmp (s.name, name)) {
1315 input = list_append (input, s);
1316 found = true; break;
1317 }
1318 if (!found) {
1319 if (restore_all) {
1320 scalar s = {0} /* new scalar */;
1321 free (s.name);
1322 s.name = strdup (name);
1323 input = list_append (input, s);
1324 }
1325 else
1327 }
1328 }
1329 }
1330 free (slist);
1331 slist = input;
1332
1333 double o[4];
1334 if (fread (o, sizeof(double), 4, fp) < 4) {
1335 fprintf (ferr, "restore(): error: expecting coordinates\n");
1336 exit (1);
1337 }
1338 origin (o[0], o[1], o[2]);
1339 size (o[3]);
1340 }
1341
1342#if MULTIGRID_MPI
1343 long cell_size = sizeof(unsigned) + header.len*sizeof(double);
1344 long offset = pid()*((1L << dimension*(header.depth + 1)) - 1)/
1345 ((1L << dimension) - 1)*cell_size;
1346 if (fseek (fp, offset, SEEK_CUR) < 0) {
1347 perror ("restore(): error while seeking");
1348 exit (1);
1349 }
1350#endif // MULTIGRID_MPI
1351
1352 scalar * listm = is_constant(cm) ? NULL : (scalar *){fm};
1353#if TREE && _MPI
1354 restore_mpi (fp, slist);
1355#else // ! (TREE && _MPI)
1356#if !_MPI
1357 int rootlevel = 0;
1358#endif
1359#if TREE
1360 for (int _d = 0; _d < dimension; _d++)
1361 while ((1 << rootlevel) < header.n.x)
1362 rootlevel++;
1363 if (rootlevel > 0)
1364 init_grid (1 << rootlevel);
1365#endif // TREE
1366#if _MPI
1367 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
1368#else
1370#endif
1371 unsigned flags;
1372 if (fread (&flags, sizeof(unsigned), 1, fp) != 1) {
1373 fprintf (ferr, "restore(): error: expecting 'flags'\n");
1374 exit (1);
1375 }
1376 // skip subtree size
1377 fseek (fp, sizeof(double), SEEK_CUR);
1378 for (int _s = 0; _s < 1; _s++) /* scalar in slist */ {
1379 double val;
1380 if (fread (&val, sizeof(double), 1, fp) != 1) {
1381 fprintf (ferr, "restore(): error: expecting a scalar\n");
1382 exit (1);
1383 }
1384 if (s.i != INT_MAX)
1385 s[] = isfinite(val) ? val : nodata;
1386 }
1387 if (!(flags & leaf) && is_leaf(cell))
1388 refine_cell (point, listm, 0, NULL);
1389 if (is_leaf(cell))
1390 continue;
1391 }
1392#if _GPU
1393 for (int _s = 0; _s < 1; _s++) /* scalar in slist */
1394 if (s.i != INT_MAX)
1395 s.gpu.stored = 1; // stored on CPU
1396#endif // _GPU
1397 for (int _s = 0; _s < 1; _s++) /* scalar in all */
1399#endif // ! (TREE && _MPI)
1400
1401 scalar * other = NULL;
1402 for (int _s = 0; _s < 1; _s++) /* scalar in all */
1403 if (!list_lookup (slist, s) && !list_lookup (listm, s))
1404 other = list_append (other, s);
1405 reset (other, 0.);
1406 free (other);
1407
1408 free (slist);
1409 if (file)
1410 fclose (fp);
1411
1412 // the events are advanced to catch up with the time
1413 while (iter < header.i && events (false))
1414 iter = inext;
1415 events (false);
1416 while (t < header.t && events (false))
1417 t = tnext;
1418 t = header.t;
1419 events (false);
1420
1421 return true;
1422}
1423
1424#endif // MULTIGRID
1425
1426#if _GPU
1427# include "grid/gpu/output.h"
1428#endif
vector g[]
We store the combined pressure gradient and acceleration field in g*.
Definition all-mach.h:65
const vector a
Definition all-mach.h:59
int npe
Definition balance.h:195
if TRASH define &&NewPid *& val(newpid, 0, 0, 0)) -> pid > 0) @else @ define is_newpid()(((NewPid *)&val(newpid, 0, 0, 0)) ->pid > 0) @endif Array *linear_tree(size_t size, scalar newpid)
Definition balance.h:13
int min
Definition balance.h:192
#define dimension
Definition bitree.h:3
trace double interpolate(scalar v, double xp=0., double yp=0., double zp=0., bool linear=true)
define k
define double double char flags
static double interpolate_linear(Point point, scalar v, double xp=0., double yp=0., double zp=0.)
define l
define m((k)==0 &&(l)==0 &&(m)==0) macro2 foreach_point(double _x=0.
free(list1)
define VT _attribute[s.i] v y scalar * list
Definition cartesian.h:276
void spread
Definition centered.h:199
int y
Definition common.h:76
int x
Definition common.h:76
double zero(double s0, double s1, double s2)
Definition common.h:116
int z
Definition common.h:76
void free_solver_func_add(free_solver_func func)
Definition common.h:512
scalar * all
Definition common.h:342
const scalar cm[]
Definition common.h:397
double Z0
Definition common.h:34
#define nodata
Definition common.h:7
scalar * list_concat(scalar *l1, scalar *l2)
Definition common.h:234
scalar * list_add(scalar *list, scalar s)
Definition common.h:208
#define HUGE
Definition common.h:6
int list_lookup(scalar *l, scalar s)
Definition common.h:216
ivec Dimensions
Definition common.h:173
double L0
Definition common.h:36
int N
Definition common.h:39
static uint32_t a32_hash(const Adler32Hash *hash)
Definition common.h:608
void origin(double x=0., double y=0., double z=0.)
Definition common.h:108
scalar * list_copy(scalar *l)
Definition common.h:225
void matrix_free(void *m)
Definition common.h:500
int list_len(scalar *list)
Definition common.h:180
void * matrix_new(int n, int=(type *) realloc(p,(size) *sizeof(type)) p=(type *) realloc(p,(size) *sizeof(type)), size_t size)
Definition common.h:486
static void a32_hash_add(Adler32Hash *hash, const void *data, size_t size)
Definition common.h:600
double X0
Definition common.h:34
scalar * list_append(scalar *list, scalar s)
Definition common.h:188
double Y0
Definition common.h:34
static void a32_hash_init(Adler32Hash *hash)
Definition common.h:594
static double noise()
Definition common.h:23
const vector fm[]
Definition common.h:396
scalar f[]
The primary fields are:
Definition two-phase.h:56
#define p
Definition tree.h:320
#define popen
Definition config.h:666
#define qmalloc(size, type)
#define pclose
Definition config.h:667
define sysmalloc malloc define syscalloc calloc define sysrealloc realloc define sysfree free define systrdup strdup define file
Definition config.h:120
#define assert(a)
Definition config.h:107
#define LINENO
Definition config.h:105
define sysmalloc malloc define syscalloc calloc define sysrealloc realloc define sysfree free define systrdup strdup define line line line line strdup(s) @ define tracing(...) @ define end_tracing(...) @define tid() 0 @define pid() 0 @define npe() 1 @define mpi_all_reduce(v
Point point
Definition conserving.h:86
double pos
Definition curvature.h:674
coord o
Definition curvature.h:672
else return n
Definition curvature.h:101
macro translate(float x=0, float y=0., float z=0.)
Definition draw.h:216
trace bool box(bool notics=false, float lc[3]={0}, float lw=1.)
Definition draw.h:1397
else
Definition embed-tree.h:79
scalar s
Definition embed-tree.h:56
*cs[i, 0, 0] a *[i -1, 0, 0] j
Definition embed.h:88
double v[2]
Definition embed.h:383
scalar scalar coord coord double double * coef
For non-degenerate cases, the gradient is obtained using either second- or third-order estimates.
Definition embed.h:380
scalar int i
Definition embed.h:74
static char * fname
Definition errors.c:753
double t
Definition events.h:24
int inext
Definition events.h:23
int iter
Definition events.h:23
double tnext
Definition events.h:24
macro2 foreach_cell_restore(ivec d=Dimensions, int rootlevel=0)
#define GL_MAP_READ_BIT
Definition glad.h:1211
#define depth()
Definition cartesian.h:14
#define output_ppm(...)
Definition output.h:270
#define reset(...)
Definition grid.h:1388
static void gpu_cpu_sync(scalar *list, GLenum mode, const char *fname, int line)
Definition grid.h:1330
#define init_grid(n)
Definition grid.h:1402
static int input(void)
Definition include.c:2085
static int
Definition include.c:978
static int target
Definition include.c:949
size_t max
Definition mtrace.h:8
FILE * fp
Definition mtrace.h:7
void(* restriction)(Point, scalar)
void subtree_size(scalar size, bool leaves)
size_t size
int int int level
trace double z_indexing(scalar index, bool leaves)
define is_active() cell(true) @define is_leaf(cell)(point.level
trace void output_grd(scalar f, FILE *fp=stdout, double Delta=L0/N, bool linear=false, coord box[2]={{X0, Y0}, {X0+L0, Y0+L0 *Dimensions.y/Dimensions.x}}, scalar mask={-1})
Definition output.h:724
FILE * open_image(const char *file, const char *options)
Definition output.h:428
char ** names
Definition output.h:364
#define NCMAP
Definition output.h:194
static void open_image_cleanup()
Definition output.h:368
void gray(double cmap[127][3])
Definition output.h:271
void(* Colormap)(double cmap[127][3])
Definition output.h:196
Color colormap_color(double cmap[127][3], double val, double min, double max)
Definition output.h:308
trace void output_field(scalar *list=all, FILE *fp=stdout, int n=N, bool linear=false, coord box[2]={{X0, Y0}, {X0+L0, Y0+L0 *Dimensions.y/Dimensions.x}})
Definition output.h:40
static bool which(const char *command)
Definition output.h:389
static const char * is_animation(const char *file)
Definition output.h:353
void jet(double cmap[127][3])
Definition output.h:198
trace void output_matrix(scalar f, FILE *fp=stdout, int n=N, bool linear=false, const char *file=NULL, coord box[2]={{X0, Y0}, {X0+L0, Y0+L0 *Dimensions.y/Dimensions.x}})
Definition output.h:128
void randomap(double cmap[127][3])
Definition output.h:278
static FILE * ppm_fallback(const char *file, const char *mode)
Definition output.h:412
static const char * extension(const char *file, const char *ext)
Definition output.h:348
void cool_warm(double cmap[127][3])
Definition output.h:219
void blue_white_red(double cmap[127][3])
Definition output.h:286
void close_image(const char *file, FILE *fp)
Definition output.h:508
static FILE * open_image_lookup(const char *file)
Definition output.h:381
static struct @15 open_image_data
int cpu
Definition qcc.c:61
int events
Definition qcc.c:60
static FILE * dimensions
Definition qcc.c:62
def _i
Definition stencils.h:405
def false def true def S_LINENO def true
Definition stencils.h:414
static void set_dirty_stencil(scalar s)
Definition stencils.h:34
@ s_input
Definition stencils.h:23
Given a colormap and a minimum and maximum value, this function returns the red/green/blue triplet co...
Definition output.h:304
unsigned char b
Definition output.h:305
unsigned char r
Definition output.h:305
Definition common.h:78
double x
Definition common.h:79
double y
Definition common.h:79
int y
Definition common.h:142
int x
Definition common.h:140
int i
Definition common.h:44
The statsf() function returns the minimum, maximum, volume sum, standard deviation and volume for fie...
Definition utils.h:166
int refine_cell(Point point, scalar *list, int flag, Cache *refined)
Definition tree-common.h:23
void restore_mpi(FILE *fp, scalar *list1)
Definition tree-mpi.h:1297
#define tree
Definition tree.h:184
@ active
Definition tree.h:59
@ leaf
Definition tree.h:60
macro mask(double func)
Definition tree.h:1432
stats statsf(scalar f)
Definition utils.h:170
Array * index
scalar c
Definition vof.h:57
src vof fflush(ferr)