1    | /***************************************
2    |   $Header$
3    | 
4    |   This file contains small utility functions for various aspects of
5    |   visualization and storage.
6    |   ***************************************/
7    | 
8    | 
9    | #include "config.h" /* esp. for inline */
10   | #include "illuminator.h" /* Just to make sure the interface is "right" */
11   | 
12   | /* Build with -DDEBUG for debugging output */
13   | #undef DPRINTF
14   | #ifdef DEBUG
15   | #define DPRINTF(fmt, args...) PetscPrintf (PETSC_COMM_WORLD, "%s: " fmt, __FUNCT__, args)
16   | #else
17   | #define DPRINTF(fmt, args...)
18   | #endif
19   | 
20   | 
21   | #undef __FUNCT__
22   | #define __FUNCT__ "auto_scale"
23   | 
24   | /*++++++++++++++++++++++++++++++++++++++
25   |   Determine a sensible scale for plotting, returned in *scale.  If a scalar
26   |   field, returns the minimum and maximum; if a vector field, returns the
27   |   minimum and maximum magnitudes (in 1-D, just plain minimum and maximum); if a
28   |   ternary, returns the corners of the smallest equilateral triangle in ternary
29   |   space in which all of the data fit.
30   | 
31   |   int auto_scale Returns zero or an error code.
32   | 
33   |   PetscScalar *global_array Array with values to scan for scale.
34   | 
35   |   int points Number of points in array to scan.
36   | 
37   |   int num_fields Number of fields in array.
38   | 
39   |   int display_field This display field (at least the start).
40   | 
41   |   field_plot_type fieldtype Type of field.
42   | 
43   |   int dimensions Number of dimensions.
44   | 
45   |   PetscScalar *scale Array in which to return the minimum/maximum values.
46   |   ++++++++++++++++++++++++++++++++++++++*/
47   | 
48   | int auto_scale
49   | (PetscScalar *global_array, int points, int num_fields, int display_field,
50   |  field_plot_type fieldtype, int dimensions, PetscScalar *scale)
51   | {
52   |   int i;
53   | 
54   |   if (scale == NULL)
55   |     SETERRQ (PETSC_ERR_ARG_BADPTR, "Invalid null pointer");
56   | 
57   |   if ((fieldtype == FIELD_VECTOR || fieldtype == FIELD_VECTOR+1) &&
58   |       dimensions == 1)
59   |     fieldtype = FIELD_SCALAR;
60   | 
61   |   switch (fieldtype)
62   |     {
63   |     case FIELD_SCALAR:
64   |     case FIELD_SCALAR+1:
65   |       {
66   | 	scale [0] = scale [1] = global_array [display_field];
67   | 	for (i=1; i<points; i++)
68   | 	  {
69   | 	    scale [0] = PetscMin
70   | 	      (scale [0], global_array [i*num_fields + display_field]);
71   | 	    scale [1] = PetscMax
72   | 	      (scale [1], global_array [i*num_fields + display_field]);
73   | 	  }
74   | 	return 0;
75   |       }
76   |     case FIELD_TERNARY:
77   |       {
78   | 	/* Find the minimum x and y, and maximum sum, then fill in corners. */
79   | 	PetscScalar maxxpy =
80   | 	  global_array [display_field] + global_array [display_field+1];
81   | 	scale[0] = global_array [display_field];
82   | 	scale[1] = global_array [display_field+1];
83   | 	for (i=1; i<points; i++)
84   | 	  {
85   | 	    scale [0] = PetscMin
86   | 	      (scale[0], global_array [i*num_fields + display_field]);
87   | 	    scale [1] = PetscMin
88   | 	      (scale[1], global_array [i*num_fields + display_field+1]);
89   | 	    maxxpy = PetscMax
90   | 	      (maxxpy, global_array [i*num_fields + display_field] +
91   | 	       global_array [i*num_fields + display_field+1]);
92   | 	  }
93   | 	scale [2] = maxxpy - scale [1];
94   | 	scale [3] = scale [1];
95   | 	scale [4] = scale [0];
96   | 	scale [5] = maxxpy - scale [0];
97   | 	return 0;
98   |       }
99   |     case FIELD_TERNARY_SQUARE:
100  |       {
101  | 	scale [0] = scale [1] = global_array [display_field];
102  | 	scale [2] = scale [3] = global_array [display_field+1];
103  | 	for (i=1; i<points; i++)
104  | 	  {
105  | 	    scale [0] = PetscMin
106  | 	      (scale [0], global_array [i*num_fields + display_field]);
107  | 	    scale [1] = PetscMax
108  | 	      (scale [1], global_array [i*num_fields + display_field]);
109  | 	    scale [2] = PetscMin
110  | 	      (scale [2], global_array [i*num_fields + display_field+1]);
111  | 	    scale [3] = PetscMax
112  | 	      (scale [3], global_array [i*num_fields + display_field+1]);
113  | 	  }
114  | 	return 0;
115  |       }
116  |     case FIELD_VECTOR:
117  |     case FIELD_VECTOR+1:
118  |       scale++;
119  |     case FIELD_TENSOR_SHEAR:
120  |       {
121  | 	/* Find the maximum square magnitude, then sqrt it. */
122  | 	scale[0] =
123  | 	  global_array [display_field] * global_array [display_field] +
124  | 	  global_array [display_field+1] * global_array [display_field+1] +
125  | 	  ((dimensions < 3) ? 0. :
126  | 	   global_array [display_field+2] * global_array [display_field+2]);
127  | 	for (i=1; i<points; i++)
128  | 	  {
129  | 	    scale[0] = PetscMax 
130  | 	      (scale [0], global_array [i*num_fields + display_field] *
131  | 	       global_array [i*num_fields + display_field] +
132  | 	       global_array [i*num_fields + display_field+1] *
133  | 	       global_array [i*num_fields + display_field+1] +
134  | 	       ((dimensions < 3) ? 0. :
135  | 		global_array [i*num_fields + display_field+2] *
136  | 		global_array [i*num_fields + display_field+2]));
137  | 	  }
138  | 	scale [0] = sqrt (scale [0]);
139  | 	return 0;
140  |       }
141  |     }
142  |   SETERRQ (PETSC_ERR_ARG_OUTOFRANGE, "Field type not yet supported");
143  | }
144  | 
145  | 
146  | #undef __FUNCT__
147  | #define __FUNCT__ "field_indices"
148  | 
149  | /*++++++++++++++++++++++++++++++++++++++
150  |   Given an array of
151  |   +latex+{\tt field\_plot\_type} enums, fill (part of) the {\tt indices}
152  |   +html+ <tt>field_plot_type</tt> enums, fill (part of) the <tt>indices</tt>
153  |   array with integers pointing to the true variable starts.  For example, in
154  |   2-D with a vector field (two fields), a scalar field (one field), a symmetric
155  |   tensor field (three fields) and a ternary composition field (two fields) for
156  |   a total of 8 fields, this will fill the indices array with the values 0, 2,
157  |   3, 6 and pad the rest of indices with -1, indicating when those true field
158  |   variables start in the overall set of field variables.
159  | 
160  |   int nfields Total number of fields.
161  | 
162  |   int ds Dimensionality of the space (used to determine the number of fields
163  |   used for a vector or tensor field).
164  | 
165  |   field_plot_type *plottypes Array of
166  |   +latex+{\tt field\_plot\_type} enums with length {\tt nfields}.
167  |   +html+ <tt>field_plot_type</tt> enums with length <tt>nfields</tt>.
168  | 
169  |   int *indices Array to hold the return values.
170  |   ++++++++++++++++++++++++++++++++++++++*/
171  | 
172  | void field_indices (int nfields, int ds, field_plot_type *plottypes,
173  | 		    int *indices)
174  | {
175  |   int i, j;
176  |   for (i=0, j=0; i<nfields; i++, j++)
177  |     {
178  |       indices [j] = i;
179  |       if (plottypes [i] == FIELD_VECTOR ||
180  | 	  plottypes [i] == FIELD_VECTOR+1)
181  | 	i += ds-1;
182  |       else if (plottypes [i] == FIELD_TERNARY ||
183  | 	       plottypes [i] == FIELD_TERNARY_SQUARE)
184  | 	i += 1;
185  |       else if (plottypes [i] == FIELD_TENSOR_FULL)
186  | 	i += ds*ds-1;
187  |       else if (plottypes [i] == FIELD_TENSOR_SYMMETRIC)
188  | 	i += ds*(ds+1)/2 -1;
189  |       else if (plottypes [i] == FIELD_TENSOR_SHEAR)
190  | 	i += ds*(ds+1)/2 -2;
191  |     }
192  |   while (j<i)
193  |     indices [j++] = -1;
194  | }