source: TOOLS/CMIP6_FORCING/AER_TROP_EMISSIONS/REGRID/struct_dims.pro @ 3391

Last change on this file since 3391 was 3391, checked in by oboucher, 4 years ago

Current version of regrid scripts for creating aerosol emissions files for CMIP6

File size: 6.8 KB
Line 
1; 1.1 01/10/07
2
3; Work out the "dimensions" to a structure for writing
4; to netcdf file, based on some simplistic rules which
5; fail if more than one dimension has the same length
6;
7; Where by these rules it is not obvious which should be
8; dimensions and which variables relate to which dimension
9; there are two options - either a quick and dirty fix, or
10; tediously indicating and linking dimensions by hand:
11;
12;   DIM_ALL - just flags all vectors as dimensions in the
13;       netcdf file. The NetCDF linkage between dimensions
14;       and variables will be broken and should be ignored.
15;       This is fine if you're planning on no more than
16;       reading the data into an IDL structure again, but
17;       will produce confusing results with ncdump
18;
19;   DIMENSIONS - A structure indicating dimensions and
20;       the dimensions applying to variables, up to
21;       a maximum of five. E.g. when there are four
22;       elements in the IDL structure (the netcdf_write.pro
23;       example):
24;
25;       dimensions = {isdim:intarr(4), links:intarr(5,4)}
26;       dimensions.isdim =  [1,1,1,0]  ; (1=dimension, 0=variable)
27;       dimensions.links = [[-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1],$
28;          [-1,-1,-1,-1,-1],[0,1,2,-1,-1]]
29;
30; Run through all data "tags" to identify "dimensions" and
31; "variables". For this to work, the data structure must always
32; have dimensions before normal variables 
33;
34; AJG 31/7/06 extracted from netcdf_write.pro
35;
36pro struct_dims, field, dimension_sizes, is_string_max, var_type, $
37  nDimensions, dim_num, iDimLink, dim_all=dim_all, dimensions=dimensions
38
39; Output codes from the IDL SIZE routine - numerical types
40; that we may convert to float in our simplistic universe
41; though there may be some truncation of information
42; (e.g. 64bit int reduced to float). Simplistic universe now
43; includes treatment of doubles, though (essential for Julian time)
44valid_float = [1,2,3,4,5,12,13,14,15]
45
46; We can make a special (and difficult) exception for string data,
47; too, but only string vectors at the moment. See NetCDF user's
48; guide, "reading and writing character string values". Also
49; IDL online help "String data in NetCDF files"
50valid_string = [7]
51
52; Find tag names and number
53tag_names = tag_names(field)
54nTags = N_TAGS(field)
55
56; Output data: information on what we think are dimensions and
57; variables
58dimension_sizes = lonarr(nTags) ; Made long not int for big files!
59is_string_max = intarr(nTags) ; 0=not a string; >0=max string length
60var_type = intarr(nTags) ; Variable type based on the output of SIZE
61nDimensions = 0
62dim_num = intarr(nTags)
63iDimlink = intarr(nTags,5) ; up to 5D currently
64
65; First pass - identify dimensions. All dimensions must
66; be vectors. Also identifies variables, and flags string data
67for iTag=0, nTags-1 do begin
68   
69  tag_size = size(field.(iTag))
70  var_type[iTag] = size(field.(iTag),/type)
71           
72  if tag_size[0] le 1 then begin
73
74    ; We have found a vector (tag_size[0]=1) or a scalar (=0)
75    ; which we will treat as a 1D 1 element vector. The
76    ; following rules apply: If it's a numerical vector, it
77    ; is a dimension only if it's the first of that size.
78    ; Following vectors of the same size will be treated as
79    ; variables. (unless keyword DIM_ALL is set)
80
81    ; If scalar pretend it's a 1D 1 element vector
82    if tag_size[0] eq 0 then begin
83      tag_size[0] = 1
84      tag_size[1] = 1
85    endif
86
87    iTemp = where( var_type[iTag] eq valid_float, count)
88    if count gt 0 then begin
89     
90      ; We have a numerical value that will be treated as FLOAT or DOUBLE
91     
92      ; Is this a dimension?
93      bDim = 0
94
95      ; (a) If it's the first vector of this length found
96      iTemp = where( tag_size[1] eq dimension_sizes, count)
97      if count eq 0 then bDim = 1
98
99      ; (b) If the DIM_ALL keyword is set (all vectors treated as dimensions)
100      if keyword_set(DIM_ALL) then bDim = 1
101
102      ; (c) If indicated by the DIMENSIONS structure
103      if keyword_set(DIMENSIONS) then begin
104        if dimensions.isdim[iTag] then bDim = 1
105      endif
106
107      if bDim then begin
108
109        ; We have found a new dimension
110        dimension_sizes[iTag] = tag_size[1]
111        dim_num[iTag] = 0 ; indicates this IS a dimension
112        nDimensions = nDimensions + 1
113
114      endif else begin
115           
116        ; This is a variable
117        dim_num[iTag] = tag_size[0] ; number of dimensions linked           
118
119      endelse
120
121    endif else begin
122         
123      iTemp = where( tag_size[2] eq valid_string, count)
124      if count eq 1 then begin
125           
126        ; This is a variable, but it's a string array
127        ; which needs special treatment
128        dim_num[iTag] = tag_size[0] ; number of dimensions linked*
129        is_string_max[iTag] = max(strlen(field.(iTag))) 
130
131        ; * Note that a string variable will gain an extra, hidden
132        ; dimension when we write it to file because of NetCDF
133        ; limitations.
134
135        ; NB also that a string array cannot be a dimension.
136                 
137      endif else begin
138        message, "Data type not supported for "+tag_names[iTag]
139      endelse
140    endelse
141
142  endif else begin
143
144    ; This is a 2D or more variable
145    dim_num[iTag] = tag_size[0] ; number of dimensions applicable
146         
147  endelse
148endfor   
149   
150; Second pass - link variables to dimensions
151for iTag=0, nTags-1 do begin
152   
153  tag_size = size(field.(iTag))
154     
155  ; Is it a variable?     
156  if dim_num[iTag] ne 0 then begin
157
158    ; If scalar pretend it's a 1D 1 element vector
159    if tag_size[0] eq 0 then begin
160      tag_size[0] = 1
161      tag_size[1] = 1
162    endif
163         
164    ; find which dimensions apply to this variable by finding
165    ; vectors of the same length as the array dimensions
166    for iDim = 0, tag_size[0]-1 do begin
167
168      if keyword_set(DIMENSIONS) then begin
169
170        ; Caller has explicitly specified the dimensions and links
171        iDimlink[iTag,iDim] = dimensions.links[iDim,iTag]
172
173      endif else begin
174
175        ; Assign dimensions on a first come first served basis.
176        ; by matching sizes. This works fine until you have two
177        ; dimensions the same size. Use DIM_ALL or DIMENSIONS in that case
178        iDimSizeEqual = where(dimension_sizes eq tag_size[iDim+1], count)
179        if count ne 0 then begin
180          if count eq 1 then begin
181            iDimlink[iTag,iDim] = iDimSizeEqual[0]
182          endif else begin
183            ; Work out which dimension applies if more than one is of
184            ; identical length: do this by order.
185            iTagSizeEqual = where(tag_size eq tag_size[iDim+1], tag_ct)
186            if tag_ct eq 1 then begin
187              iDimlink[iTag,iDim] = iDimSizeEqual[0]
188            endif else begin
189              tag_order = where(iTagSizeEqual eq iDim+1)
190              iDimlink[iTag,iDim] = iDimSizeEqual[tag_order]
191            endelse
192          endelse
193        endif else begin
194          message, "Matching dimension not found for "+tag_names[iTag]
195        endelse   
196     
197      endelse
198
199    endfor
200
201  endif       
202   
203endfor
204
205end
206
Note: See TracBrowser for help on using the repository browser.