1 | /*************************************** 2 | $Header: /cvsroot/petscgraphics/utility.c,v 1.1 2004/08/17 15:05:42 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 | 13 | #undef __FUNCT__ 14 | #define __FUNCT__ "minmax_scale" 15 | 16 | /*++++++++++++++++++++++++++++++++++++++ 17 | Determine a sensible scale for plotting, returned in *minmax. If a scalar 18 | field, returns the minimum and maximum; if a vector field, returns the 19 | minimum and maximum magnitudes (in 1-D, just plain minimum and maximum); if a 20 | ternary, returns the corners of the smallest equilateral triangle in ternary 21 | space in which all of the data fit. 22 | 23 | int minmax_scale Returns zero or an error code. 24 | 25 | PetscScalar *global_array Array with values to scan for scale. 26 | 27 | int points Number of points in array to scan. 28 | 29 | int num_fields Number of fields in array. 30 | 31 | int display_field This display field (at least the start). 32 | 33 | field_plot_type fieldtype Type of field. 34 | 35 | int dimensions Number of dimensions. 36 | 37 | PetscScalar *minmax Array in which to return the minimum/maximum values. 38 | ++++++++++++++++++++++++++++++++++++++*/ 39 | 40 | int minmax_scale 41 | (PetscScalar *global_array, int points, int num_fields, int display_field, 42 | field_plot_type fieldtype, int dimensions, PetscScalar *minmax) 43 | { 44 | int i; 45 | 46 | if (minmax == NULL) 47 | SETERRQ (PETSC_ERR_ARG_BADPTR, "Invalid null pointer"); 48 | 49 | if ((fieldtype == FIELD_VECTOR || fieldtype == FIELD_VECTOR+1) && 50 | dimensions == 1) 51 | fieldtype = FIELD_SCALAR; 52 | 53 | switch (fieldtype) 54 | { 55 | case FIELD_SCALAR: 56 | case FIELD_SCALAR+1: 57 | { 58 | minmax [0] = minmax [1] = global_array [display_field]; 59 | for (i=1; i<points; i++) 60 | { 61 | minmax [0] = PetscMin 62 | (minmax [0], global_array [i*num_fields + display_field]); 63 | minmax [1] = PetscMax 64 | (minmax [1], global_array [i*num_fields + display_field]); 65 | } 66 | return 0; 67 | } 68 | case FIELD_VECTOR: 69 | case FIELD_VECTOR+1: 70 | { 71 | /* Find the minimum and maximum square magnitudes, then sqrt them. */ 72 | minmax[0] = minmax[1] = 73 | global_array [display_field] * global_array [display_field] + 74 | global_array [display_field+1] * global_array [display_field+1] + 75 | ((dimensions < 3) ? 0. : 76 | global_array [display_field+2] * global_array [display_field+2]); 77 | for (i=1; i<points; i++) 78 | { 79 | PetscScalar localmag = 80 | global_array [i*num_fields + display_field] * 81 | global_array [i*num_fields + display_field] + 82 | global_array [i*num_fields + display_field+1] * 83 | global_array [i*num_fields + display_field+1] + 84 | ((dimensions < 3) ? 0. : 85 | global_array [i*num_fields + display_field+2] * 86 | global_array [i*num_fields + display_field+2]); 87 | minmax[0] = PetscMin (minmax [0], localmag); 88 | minmax[1] = PetscMax (minmax [1], localmag); 89 | } 90 | minmax [0] = sqrt (minmax [0]); 91 | minmax [1] = sqrt (minmax [1]); 92 | return 0; 93 | } 94 | case FIELD_TERNARY: 95 | { 96 | /* Find the minimum x and y, and maximum sum, then fill in corners. */ 97 | PetscScalar maxxpy = 98 | global_array [display_field] + global_array [display_field+1]; 99 | minmax[0] = global_array [display_field]; 100 | minmax[1] = global_array [display_field+1]; 101 | for (i=1; i<points; i++) 102 | { 103 | minmax [0] = PetscMin (minmax[0], global_array [display_field]); 104 | minmax [1] = PetscMin (minmax[1], global_array [display_field+1]); 105 | maxxpy = PetscMax (maxxpy, global_array [display_field] + 106 | global_array [display_field+1]); 107 | } 108 | minmax [2] = minmax [0]; 109 | minmax [3] = maxxpy - minmax [0]; 110 | minmax [4] = maxxpy - minmax [1]; 111 | minmax [5] = minmax [1]; 112 | return 0; 113 | } 114 | default: 115 | SETERRQ (PETSC_ERR_ARG_OUTOFRANGE, "Field type not yet supported"); 116 | } 117 | } 118 | 119 | 120 | #undef __FUNCT__ 121 | #define __FUNCT__ "field_indices" 122 | 123 | /*++++++++++++++++++++++++++++++++++++++ 124 | Given an array of 125 | +latex+{\tt field\_plot\_type} enums, fill (part of) the {\tt indices} 126 | +html+ <tt>field_plot_type</tt> enums, fill (part of) the <tt>indices</tt> 127 | array with integers pointing to the true variable starts. For example, in 128 | 2-D with a vector field (two fields), a scalar field (one field), a symmetric 129 | tensor field (three fields) and a ternary composition field (two fields) for 130 | a total of 8 fields, this will fill the indices array with the values 0, 2, 131 | 3, 6 and pad the rest of indices with -1, indicating when those true field 132 | variables start in the overall set of field variables. 133 | 134 | int nfields Total number of fields. 135 | 136 | int ds Dimensionality of the space (used to determine the number of fields 137 | used for a vector or tensor field). 138 | 139 | field_plot_type *plottypes Array of 140 | +latex+{\tt field\_plot\_type} enums with length {\tt nfields}. 141 | +html+ <tt>field_plot_type</tt> enums with length <tt>nfields</tt>. 142 | 143 | int *indices Array to hold the return values. 144 | ++++++++++++++++++++++++++++++++++++++*/ 145 | 146 | void field_indices (int nfields, int ds, field_plot_type *plottypes, 147 | int *indices) 148 | { 149 | int i, j; 150 | for (i=0, j=0; i<nfields; i++, j++) 151 | { 152 | indices [j] = i; 153 | if (plottypes [i] == FIELD_VECTOR || 154 | plottypes [i] == FIELD_VECTOR+1) 155 | i += ds-1; 156 | else if (plottypes [i] == FIELD_TERNARY) 157 | i += 1; 158 | else if (plottypes [i] == FIELD_TENSOR_FULL) 159 | i += ds*ds-1; 160 | else if (plottypes [i] == FIELD_TENSOR_SYMMETRIC) 161 | i += ds*(ds+1)/2 -1; 162 | else if (plottypes [i] == FIELD_TENSOR_SYMMETRIC_ZERODIAG) 163 | i += ds*(ds+1)/2 -2; 164 | } 165 | while (j<i) 166 | indices [j++] = -1; 167 | }