1    | /***************************************
2    |   $Header: /cvsroot/petscgraphics/utility.c,v 1.5 2004/11/04 22:47:45 hazelsct Exp $
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_VECTOR:
100  |     case FIELD_VECTOR+1:
101  |       scale++;
102  |     case FIELD_TENSOR_SHEAR:
103  |       {
104  | 	/* Find the maximum square magnitude, then sqrt it. */
105  | 	scale[0] =
106  | 	  global_array [display_field] * global_array [display_field] +
107  | 	  global_array [display_field+1] * global_array [display_field+1] +
108  | 	  ((dimensions < 3) ? 0. :
109  | 	   global_array [display_field+2] * global_array [display_field+2]);
110  | 	for (i=1; i<points; i++)
111  | 	  {
112  | 	    scale[0] = PetscMax 
113  | 	      (scale [0], global_array [i*num_fields + display_field] *
114  | 	       global_array [i*num_fields + display_field] +
115  | 	       global_array [i*num_fields + display_field+1] *
116  | 	       global_array [i*num_fields + display_field+1] +
117  | 	       ((dimensions < 3) ? 0. :
118  | 		global_array [i*num_fields + display_field+2] *
119  | 		global_array [i*num_fields + display_field+2]));
120  | 	  }
121  | 	scale [0] = sqrt (scale [0]);
122  | 	return 0;
123  |       }
124  |     }
125  |   SETERRQ (PETSC_ERR_ARG_OUTOFRANGE, "Field type not yet supported");
126  | }
127  | 
128  | 
129  | #undef __FUNCT__
130  | #define __FUNCT__ "field_indices"
131  | 
132  | /*++++++++++++++++++++++++++++++++++++++
133  |   Given an array of
134  |   +latex+{\tt field\_plot\_type} enums, fill (part of) the {\tt indices}
135  |   +html+ <tt>field_plot_type</tt> enums, fill (part of) the <tt>indices</tt>
136  |   array with integers pointing to the true variable starts.  For example, in
137  |   2-D with a vector field (two fields), a scalar field (one field), a symmetric
138  |   tensor field (three fields) and a ternary composition field (two fields) for
139  |   a total of 8 fields, this will fill the indices array with the values 0, 2,
140  |   3, 6 and pad the rest of indices with -1, indicating when those true field
141  |   variables start in the overall set of field variables.
142  | 
143  |   int nfields Total number of fields.
144  | 
145  |   int ds Dimensionality of the space (used to determine the number of fields
146  |   used for a vector or tensor field).
147  | 
148  |   field_plot_type *plottypes Array of
149  |   +latex+{\tt field\_plot\_type} enums with length {\tt nfields}.
150  |   +html+ <tt>field_plot_type</tt> enums with length <tt>nfields</tt>.
151  | 
152  |   int *indices Array to hold the return values.
153  |   ++++++++++++++++++++++++++++++++++++++*/
154  | 
155  | void field_indices (int nfields, int ds, field_plot_type *plottypes,
156  | 		    int *indices)
157  | {
158  |   int i, j;
159  |   for (i=0, j=0; i<nfields; i++, j++)
160  |     {
161  |       indices [j] = i;
162  |       if (plottypes [i] == FIELD_VECTOR ||
163  | 	  plottypes [i] == FIELD_VECTOR+1)
164  | 	i += ds-1;
165  |       else if (plottypes [i] == FIELD_TERNARY)
166  | 	i += 1;
167  |       else if (plottypes [i] == FIELD_TENSOR_FULL)
168  | 	i += ds*ds-1;
169  |       else if (plottypes [i] == FIELD_TENSOR_SYMMETRIC)
170  | 	i += ds*(ds+1)/2 -1;
171  |       else if (plottypes [i] == FIELD_TENSOR_SHEAR)
172  | 	i += ds*(ds+1)/2 -2;
173  |     }
174  |   while (j<i)
175  |     indices [j++] = -1;
176  | }