1 | !M. Indurain & E. Millour |
---|
2 | !March 2015 |
---|
3 | |
---|
4 | PROGRAM spectra_analysis |
---|
5 | |
---|
6 | !Compute energy spectrum of a 2d wind field with spherepack routines. |
---|
7 | !v = sum(n=1..nlat-1) 0.5*b(0,n)*B(0,n)+0.5*c(0,n)*C(0,n) + sum(m=1..mmax-1)sum(n=m..nlat-1) b(m,n)*B(m,n)+c(m,n)*C(m,n) |
---|
8 | !where B(m,n) and C(m,n) are vector spherical harmonics |
---|
9 | !Then energy spectra is defined as: |
---|
10 | !E(n) = 0.5*|b(0,n)|^2 + 0.5*|c(0,n)|^2 + sum(m=1..n) |b(m,n)|^2 + |c(m,n)|^2 |
---|
11 | |
---|
12 | !Wind field read from netcdf file follows lmdz convention: |
---|
13 | ! u(nlong+1,nlat) zonal eastward wind, v(nlong+1,nlat) latitudinal wind |
---|
14 | !Wind field needed for spherepack routines must be like: |
---|
15 | ! u(nlat,nlong) zonal eastward wind, v(nlong,nlat) colatitudinal wind (from North pole) |
---|
16 | |
---|
17 | use netcdf |
---|
18 | |
---|
19 | implicit none |
---|
20 | |
---|
21 | !Physical grid |
---|
22 | integer :: nlat,nlong,nlongp1,nalt,ntime |
---|
23 | double precision, dimension(:,:), allocatable :: merid_wind,zonal_wind !spherepack convention |
---|
24 | double precision, dimension(:,:), allocatable :: merid_wind_lmdz,zonal_wind_lmdz !lmdz convention |
---|
25 | !Spectral grid |
---|
26 | integer :: mmax !spectra truncation mmax=min(nalt,nlong/2) or min(nalt,(nlong+1)/2) |
---|
27 | double precision, dimension (:,:), allocatable :: br,bi,cr,ci !spectra coefficients |
---|
28 | double precision, dimension (:,:), allocatable :: norm,norm_b,norm_c !norm of spectra coefficients |
---|
29 | double precision, dimension (:), allocatable :: spectra,spectra_b,spectra_c |
---|
30 | double precision, dimension (:,:), allocatable :: spectra_config,spectra_b_config,spectra_c_config |
---|
31 | double precision, dimension (:,:), allocatable :: spectra_global,spectra_b_global,spectra_c_global |
---|
32 | !Spherepack declarations |
---|
33 | integer :: ierror,lvhaec,ldwork,lwork,l1,l2,nt=1,ityp=0,idvw,jdvw,mdab,ndab |
---|
34 | double precision, dimension (:), allocatable :: wvhaec,work |
---|
35 | double precision, dimension (:), allocatable :: dwork |
---|
36 | !Netcdf stuff |
---|
37 | integer :: idfile,idmerid_wind,idzonal_wind |
---|
38 | integer :: idlat,idlong,idalt,idtime |
---|
39 | !Input arguments |
---|
40 | character (len=100), dimension(:), allocatable :: arg |
---|
41 | character (len=100) :: file_netcdf,file_spectra |
---|
42 | integer :: n_indt,n_indz,meant,meanz |
---|
43 | integer, dimension(:), allocatable :: tab_indt,tab_indz |
---|
44 | character (len=100) :: name_u,name_v,name_lat,name_long,name_alt,name_time |
---|
45 | character (len=100) :: tab_name_u(4)=(/'u','U','vitu','zonal_wind'/) |
---|
46 | character (len=100) :: tab_name_v(4)=(/'v','V','vitv','merid_wind'/) |
---|
47 | character (len=100) :: tab_name_lat(2)=(/'latitude','lat'/) |
---|
48 | character (len=100) :: tab_name_long(2)=(/'longitude','lon'/) |
---|
49 | character (len=100) :: tab_name_alt(3)=(/'altitude','alt','presnivs'/) |
---|
50 | character (len=100) :: tab_name_time(3)=(/'time','Time','time_counter'/) |
---|
51 | logical :: is_div_rot |
---|
52 | integer :: narg |
---|
53 | !Other |
---|
54 | integer :: i,j,t,z,mt,mz |
---|
55 | integer :: number_config !number of (t,z) configurations wanted by user (from 1 to n_indt*n_indz)) |
---|
56 | integer :: number_local !number of (t,z) sub-configurations to mean (from 1 to (meant+1)*(meanz+1)) |
---|
57 | integer :: number_global !number of total (t,z) configurations to compute (from 1 to n_indt*n_indz*(meant+1)*(meanz+1)) |
---|
58 | logical :: is_file,first_reading=.true. |
---|
59 | integer, dimension(:), allocatable :: tmp_tab_int |
---|
60 | character (len=100) :: tmp_char |
---|
61 | |
---|
62 | !********** |
---|
63 | !Initialisation |
---|
64 | file_netcdf = '??@@??' |
---|
65 | file_spectra = 'spectra' |
---|
66 | n_indt = 0 |
---|
67 | n_indz = 0 |
---|
68 | allocate(tab_indt(20)) |
---|
69 | allocate(tab_indz(20)) |
---|
70 | allocate(tmp_tab_int(20)) |
---|
71 | tab_indt(:) = 1 |
---|
72 | tab_indz(:) = 1 |
---|
73 | meant = 0 |
---|
74 | meanz = 0 |
---|
75 | name_u = '??@@??' |
---|
76 | name_v = '??@@??' |
---|
77 | name_lat = '??@@??' |
---|
78 | name_long = '??@@??' |
---|
79 | name_alt = '??@@??' |
---|
80 | name_time = '??@@??' |
---|
81 | is_div_rot=.false. |
---|
82 | |
---|
83 | !********** |
---|
84 | !Input reading |
---|
85 | narg = command_argument_count() |
---|
86 | allocate(arg(narg)) |
---|
87 | do i = 1, narg |
---|
88 | call get_command_argument(i,arg(i)) |
---|
89 | end do |
---|
90 | i = 1 |
---|
91 | do while (i .le. narg) |
---|
92 | if (arg(i) == '-o' .or. arg(i) == '-t' .or. arg(i) == '-z' .or. arg(i) == '-mt' .or. arg(i) == '-mz'& |
---|
93 | .or. arg(i) == '-u' .or. arg(i) == '-v' .or. arg(i) == '-lat' .or. arg(i) == '-lon' & |
---|
94 | .or. arg(i) == '-alt' .or. arg(i) == '-time') then |
---|
95 | select case(arg(i)) |
---|
96 | case('-t') |
---|
97 | n_indt = n_indt + 1 |
---|
98 | read(arg(i+1),'(i10)' ) tab_indt(n_indt) !temporal indice |
---|
99 | case('-z') |
---|
100 | n_indz = n_indz + 1 |
---|
101 | read(arg(i+1),'(i10)' ) tab_indz(n_indz) !vertical indice |
---|
102 | case('-mt') |
---|
103 | read(arg(i+1),'(i10)' ) meant !extent of temporal mean |
---|
104 | case('-mz') |
---|
105 | read(arg(i+1),'(i10)' ) meanz !extent of vertical mean |
---|
106 | case('-o') |
---|
107 | file_spectra=arg(i+1) !spectra file |
---|
108 | case('-u') |
---|
109 | read(arg(i+1),'(a100)' ) name_u !name of zonal wind |
---|
110 | case('-v') |
---|
111 | read(arg(i+1),'(a100)' ) name_v !name of meridional wind |
---|
112 | case('-lat') |
---|
113 | read(arg(i+1),'(a100)' ) name_lat !name of latitude axis |
---|
114 | case('-lon') |
---|
115 | read(arg(i+1),'(a100)' ) name_long !name of longitude axis |
---|
116 | case('-alt') |
---|
117 | read(arg(i+1),'(a100)' ) name_alt !name of altitude axis |
---|
118 | case('-time') |
---|
119 | read(arg(i+1),'(a100)' ) name_time !name of time axis |
---|
120 | end select |
---|
121 | i = i + 2 |
---|
122 | elseif (arg(i) == '-divrot') then |
---|
123 | is_div_rot = .true. |
---|
124 | i = i + 1 |
---|
125 | elseif (arg(i) == '-h' .or. arg(i) == '--help') then |
---|
126 | print*,'Usage\n spectra netcdfFile [option]\n [-h or --help]\t: brief help' |
---|
127 | print*,'[-t int]\t: temporal indice (default: 1)\n [-z int]\t: vertical indice (default: 1)' |
---|
128 | print*,'[-mt int]\t: extent of temporal mean (default: 0)\n [-mz int]\t: extent of vertical mean (default: 0)' |
---|
129 | print*,'[-o str]\t: output spectra file name (default: spectra)' |
---|
130 | print*,'[-u str]\t: name of zonal wind in netcdf file' |
---|
131 | print*,'[-v str]\t: name of meridional wind in netcdf file' |
---|
132 | print*,'[-lat str]\t: name of latitude field in netcdf file' |
---|
133 | print*,'[-lon str]\t: name of longitude field in netcdf file' |
---|
134 | print*,'[-alt str]\t: name of altitude field in netcdf file. ''none'' if no altitude axis.' |
---|
135 | print*,'[-time str]\t: name of time field in netcdf file. ''none'' if no time axis.' |
---|
136 | print*,'[-divrot]\t: total, divergence and vorticity spectra coefficient in output file' |
---|
137 | stop 'End help' |
---|
138 | else |
---|
139 | file_netcdf = arg(i) |
---|
140 | i = i + 1 |
---|
141 | end if |
---|
142 | end do |
---|
143 | |
---|
144 | !********** |
---|
145 | !Check input/output files |
---|
146 | inquire(file=trim(file_netcdf),exist=is_file) |
---|
147 | if (.not. is_file) then |
---|
148 | print*,"no netcdf file: ",trim(file_netcdf) |
---|
149 | stop "Stopped" |
---|
150 | end if |
---|
151 | call system('rm -f '//trim(file_spectra)) |
---|
152 | |
---|
153 | !********** |
---|
154 | !Netcdf file dimensions |
---|
155 | ierror=nf90_open(trim(file_netcdf),NF90_NOWRITE,idfile) |
---|
156 | |
---|
157 | ierror=-99999 |
---|
158 | i=0 |
---|
159 | ierror=nf90_inq_dimid(idfile,trim(name_lat),idlat) !try user named latitude |
---|
160 | do while (ierror /= 0 .and. i <= size(tab_name_lat)-1)!try automatic named latitude |
---|
161 | i=i+1 |
---|
162 | ierror=nf90_inq_dimid(idfile,trim(tab_name_lat(i)),idlat) |
---|
163 | end do |
---|
164 | if (ierror == 0) then |
---|
165 | ierror=nf90_inquire_dimension(idfile,idlat,tmp_char,nlat) |
---|
166 | else |
---|
167 | print*,'latitude dimension not found!' |
---|
168 | stop ' must have this... use ''-lat latitudefieldname'' option.' |
---|
169 | end if |
---|
170 | |
---|
171 | ierror=-99999 |
---|
172 | i=0 |
---|
173 | ierror=nf90_inq_dimid(idfile,trim(name_long),idlong) !try user named longitude |
---|
174 | do while (ierror /= 0 .and. i <= size(tab_name_long)-1) !try automatic named longitude |
---|
175 | i=i+1 |
---|
176 | ierror=nf90_inq_dimid(idfile,trim(tab_name_long(i)),idlong) |
---|
177 | end do |
---|
178 | if (ierror == 0) then |
---|
179 | ierror=nf90_inquire_dimension(idfile,idlong,tmp_char,nlongp1) |
---|
180 | else |
---|
181 | print*,'longitude dimension not found!' |
---|
182 | stop ' must have this... use ''-lon longitudefieldname'' option.' |
---|
183 | end if |
---|
184 | |
---|
185 | ierror=-99999 |
---|
186 | i=0 |
---|
187 | ierror=nf90_inq_dimid(idfile,trim(name_alt),idalt) !try user named altitude |
---|
188 | do while (ierror /= 0 .and. i <= size(tab_name_alt)-1)!try automatic named altitude |
---|
189 | i=i+1 |
---|
190 | ierror=nf90_inq_dimid(idfile,trim(tab_name_alt(i)),idalt) |
---|
191 | end do |
---|
192 | if (ierror == 0) then |
---|
193 | ierror=nf90_inquire_dimension(idfile,idalt,tmp_char,nalt) |
---|
194 | else |
---|
195 | if (name_alt == 'none') then |
---|
196 | print*,'netcdf file without altitude axis: all the same.' |
---|
197 | else |
---|
198 | print*,'altitude dimension not found!' |
---|
199 | stop ' if no altitude axis, use ''-alt none'' option...' |
---|
200 | end if |
---|
201 | end if |
---|
202 | |
---|
203 | ierror=-99999 |
---|
204 | i=0 |
---|
205 | ierror=nf90_inq_dimid(idfile,trim(name_time),idtime) !try user named time |
---|
206 | do while (ierror /= 0 .and. i <= size(tab_name_time)-1) !try automatic named time |
---|
207 | i=i+1 |
---|
208 | ierror=nf90_inq_dimid(idfile,trim(tab_name_time(i)),idtime) |
---|
209 | end do |
---|
210 | if (ierror == 0) then |
---|
211 | ierror=nf90_inquire_dimension(idfile,idtime,tmp_char,ntime) |
---|
212 | else |
---|
213 | if (name_time == 'none') then |
---|
214 | print*,'netcdf file without time axis: all the same.' |
---|
215 | else |
---|
216 | print*,'time dimension not found!' |
---|
217 | stop ' if no time axis, use ''-time none'' option...' |
---|
218 | end if |
---|
219 | end if |
---|
220 | |
---|
221 | !********** |
---|
222 | !Check input indices and add average indices |
---|
223 | if (n_indt == 0) n_indt = 1 |
---|
224 | tmp_tab_int(:) = tab_indt(:) |
---|
225 | deallocate(tab_indt) |
---|
226 | allocate(tab_indt(n_indt*(meant+1))) |
---|
227 | do t = 1,n_indt |
---|
228 | do mt = 0,meant |
---|
229 | tab_indt((t-1)*(meant+1)+1+mt) = tmp_tab_int(t)+mt |
---|
230 | end do |
---|
231 | end do |
---|
232 | do t = 1,n_indt*(meant+1) |
---|
233 | if (tab_indt(t) > ntime .or. tab_indt(t) < 1) tab_indt(t) = 1 |
---|
234 | end do |
---|
235 | |
---|
236 | if (n_indz == 0) n_indz = 1 |
---|
237 | tmp_tab_int(:) = tab_indz(:) |
---|
238 | deallocate(tab_indz) |
---|
239 | allocate(tab_indz(n_indz*(meanz+1))) |
---|
240 | do z = 1,n_indz |
---|
241 | do mz = 0,meanz |
---|
242 | tab_indz((z-1)*(meanz+1)+1+mz) = tmp_tab_int(z)+mz |
---|
243 | end do |
---|
244 | end do |
---|
245 | do z = 1,n_indz*(meanz+1) |
---|
246 | if (tab_indz(z) > nalt .or. tab_indz(z) < 1) tab_indz(z) = 1 |
---|
247 | end do |
---|
248 | |
---|
249 | !********** |
---|
250 | !Loop over time and altitude indices |
---|
251 | allocate(spectra_config(nlat,n_indt*n_indz)) |
---|
252 | allocate(spectra_b_config(nlat,n_indt*n_indz)) |
---|
253 | allocate(spectra_c_config(nlat,n_indt*n_indz)) |
---|
254 | allocate(spectra_global(nlat,n_indt*(meant+1)*n_indz*(meanz+1))) |
---|
255 | allocate(spectra_b_global(nlat,n_indt*(meant+1)*n_indz*(meanz+1))) |
---|
256 | allocate(spectra_c_global(nlat,n_indt*(meant+1)*n_indz*(meanz+1))) |
---|
257 | do t = 1,n_indt |
---|
258 | do z = 1,n_indz |
---|
259 | number_config = (t-1)*n_indz+z |
---|
260 | do mt = 0,meant |
---|
261 | do mz = 0,meanz |
---|
262 | number_local = mt*(meanz+1)+mz+1 |
---|
263 | number_global = (number_config-1)*(meant+1)*(meanz+1) + number_local |
---|
264 | if (first_reading) then |
---|
265 | print*,'First netcdf file reading...' |
---|
266 | first_reading = .false. |
---|
267 | end if |
---|
268 | |
---|
269 | !********** |
---|
270 | !Netcdf file reading |
---|
271 | ierror=-99999 |
---|
272 | i=0 |
---|
273 | ierror=nf90_inq_varid(idfile,trim(name_u),idzonal_wind) !try user named zonal wind |
---|
274 | do while (ierror /= 0 .and. i <= size(tab_name_u)-1) !try automatic named zonal wind |
---|
275 | i=i+1 |
---|
276 | ierror=nf90_inq_varid(idfile,trim(tab_name_u(i)),idzonal_wind) |
---|
277 | end do |
---|
278 | if (ierror == 0) then |
---|
279 | allocate(zonal_wind_lmdz(nlongp1,nlat)) |
---|
280 | if (name_alt == 'none') then |
---|
281 | if(name_time == 'none') then |
---|
282 | ierror=nf90_get_var(idfile,idzonal_wind,zonal_wind_lmdz,(/1,1/),(/nlongp1,nlat/)) |
---|
283 | else |
---|
284 | ierror=nf90_get_var(idfile,idzonal_wind,zonal_wind_lmdz,(/1,1,tab_indt((t-1)*(meant+1)+mt+1)/),(/nlongp1,nlat,1/)) |
---|
285 | end if |
---|
286 | end if |
---|
287 | if (name_alt /= 'none') then |
---|
288 | if(name_time == 'none') then |
---|
289 | ierror=nf90_get_var(idfile,idzonal_wind,zonal_wind_lmdz,(/1,1,tab_indz((z-1)*(meanz+1)+1)/),(/nlongp1,nlat,1/)) |
---|
290 | else |
---|
291 | ierror=nf90_get_var(idfile,idzonal_wind,zonal_wind_lmdz,& |
---|
292 | (/1,1,tab_indz((z-1)*(meanz+1)+1),tab_indt((t-1)*(meant+1)+mt+1)/),(/nlongp1,nlat,1,1/)) |
---|
293 | end if |
---|
294 | end if |
---|
295 | else |
---|
296 | print*,'zonal wind variable not found!' |
---|
297 | stop ' must have this... use ''-u zonalwindfieldname'' option.' |
---|
298 | end if |
---|
299 | |
---|
300 | ierror=-99999 |
---|
301 | i=0 |
---|
302 | ierror=nf90_inq_varid(idfile,trim(name_v),idmerid_wind) !try user named meridional wind |
---|
303 | do while (ierror /= 0 .and. i <= size(tab_name_v)-1) !try automatic named meridional wind |
---|
304 | i=i+1 |
---|
305 | ierror=nf90_inq_varid(idfile,trim(tab_name_v(i)),idmerid_wind) |
---|
306 | end do |
---|
307 | if (ierror == 0) then |
---|
308 | allocate(merid_wind_lmdz(nlongp1,nlat)) |
---|
309 | if (name_alt == 'none') then |
---|
310 | if(name_time == 'none') then |
---|
311 | ierror=nf90_get_var(idfile,idmerid_wind,merid_wind_lmdz,(/1,1/),(/nlongp1,nlat/)) |
---|
312 | else |
---|
313 | ierror=nf90_get_var(idfile,idmerid_wind,merid_wind_lmdz,(/1,1,tab_indt((t-1)*(meant+1)+mt+1)/),(/nlongp1,nlat,1/)) |
---|
314 | end if |
---|
315 | end if |
---|
316 | if (name_alt /= 'none') then |
---|
317 | if(name_time == 'none') then |
---|
318 | ierror=nf90_get_var(idfile,idmerid_wind,merid_wind_lmdz,(/1,1,tab_indz((z-1)*(meanz+1)+1)/),(/nlongp1,nlat,1/)) |
---|
319 | else |
---|
320 | ierror=nf90_get_var(idfile,idmerid_wind,merid_wind_lmdz,& |
---|
321 | (/1,1,tab_indz((z-1)*(meanz+1)+1),tab_indt((t-1)*(meant+1)+mt+1)/),(/nlongp1,nlat,1,1/)) |
---|
322 | end if |
---|
323 | end if |
---|
324 | else |
---|
325 | print*,'meridional wind variable not found!' |
---|
326 | stop ' must have this... use ''-v meridionalwindfieldname'' option.' |
---|
327 | end if |
---|
328 | |
---|
329 | !**********From lmdz to spherepack convention |
---|
330 | nlong=nlongp1-1 |
---|
331 | allocate(zonal_wind(nlat,nlong)) |
---|
332 | allocate(merid_wind(nlat,nlong)) |
---|
333 | zonal_wind(:,:)=transpose(zonal_wind_lmdz(1:nlong,:)) |
---|
334 | merid_wind(:,:)=transpose(merid_wind_lmdz(1:nlong,:)) |
---|
335 | !if (mod(nlat,2) == 0) then |
---|
336 | ! merid_wind(1:nlat/2,:)=-merid_wind(1:nlat/2,:) |
---|
337 | !else |
---|
338 | ! merid_wind(1:(nlat+1)/2,:)=-merid_wind(1:(nlat+1)/2,:) |
---|
339 | !end if |
---|
340 | |
---|
341 | !##### |
---|
342 | !Spectra computation |
---|
343 | !##### |
---|
344 | !**********Maximum value for m |
---|
345 | if (mod(nlong,2) == 0) then |
---|
346 | mmax = min(nlat,nlong/2) |
---|
347 | else |
---|
348 | mmax = min(nlat,(nlong+1)/2) |
---|
349 | end if |
---|
350 | |
---|
351 | !**********Vhaeci function (initialisations for Vhaec function) |
---|
352 | if (mod(nlong,2) == 0) then |
---|
353 | l1 = min(nlat,nlong/2) |
---|
354 | else |
---|
355 | l1 = min(nlat,(nlong+1)/2) |
---|
356 | end if |
---|
357 | if (mod(nlat,2) == 0) then |
---|
358 | l2 = nlat/2 |
---|
359 | else |
---|
360 | l2 = (nlat+1)/2 |
---|
361 | end if |
---|
362 | lvhaec=4*nlat*l2+3*max(l1-2,0)*(nlat+nlat-l1-1)+nlong+15 |
---|
363 | allocate(wvhaec(lvhaec)) |
---|
364 | wvhaec(:) = 0. |
---|
365 | ldwork=2*(nlat+2) |
---|
366 | allocate(dwork(ldwork)) |
---|
367 | dwork(:) = 0. |
---|
368 | ierror=3 |
---|
369 | call vhaeci(nlat,nlong,wvhaec,lvhaec,dwork,ldwork,ierror) |
---|
370 | |
---|
371 | !**********Vhaeci function result |
---|
372 | select case (ierror) |
---|
373 | case(1) |
---|
374 | print*,'Vhaeci: ERROR on nlat' |
---|
375 | case(2) |
---|
376 | print*,'Vhaeci: ERROR on nlong' |
---|
377 | case(3) |
---|
378 | print*,'Vhaeci: ERROR on lvhaec' |
---|
379 | case(4) |
---|
380 | print*,'Vhaeci: ERROR on ldwork' |
---|
381 | end select |
---|
382 | |
---|
383 | !**********Vhaec function (computes spectra coefficients) |
---|
384 | idvw=nlat |
---|
385 | jdvw=nlong |
---|
386 | mdab=mmax |
---|
387 | ndab=nlat |
---|
388 | allocate(br(mdab,ndab)) |
---|
389 | allocate(bi(mdab,ndab)) |
---|
390 | allocate(cr(mdab,ndab)) |
---|
391 | allocate(ci(mdab,ndab)) |
---|
392 | br(:,:) = 0. |
---|
393 | bi(:,:) = 0. |
---|
394 | cr(:,:) = 0. |
---|
395 | ci(:,:) = 0. |
---|
396 | if (mod(nlong,2) == 0) then |
---|
397 | l1 = min(nlat,nlong/2) |
---|
398 | else |
---|
399 | l1 = min(nlat,(nlong+1)/2) |
---|
400 | end if |
---|
401 | if (mod(nlat,2) == 0) then |
---|
402 | l2 = nlat/2 |
---|
403 | else |
---|
404 | l2 = (nlat+1)/2 |
---|
405 | end if |
---|
406 | lvhaec=4*nlat*l2+3*max(l1-2,0)*(nlat+nlat-l1-1)+nlong+15 |
---|
407 | if (ityp .le. 2) then |
---|
408 | lwork=nlat*(2*nt*nlong+max(6*l2,nlong)) |
---|
409 | else |
---|
410 | lwork=l2*(2*nt*nlong+max(6*nlat,nlong)) |
---|
411 | end if |
---|
412 | allocate(work(lwork)) |
---|
413 | work(:) = 0. |
---|
414 | ierror=3 |
---|
415 | call vhaec(nlat,nlong,ityp,nt,merid_wind,zonal_wind,idvw,jdvw,br,bi,cr,ci,mdab,ndab,wvhaec,lvhaec,work,lwork,ierror) |
---|
416 | |
---|
417 | !**********Vhaec function result |
---|
418 | select case (ierror) |
---|
419 | case(1) |
---|
420 | print*,'Vhaec: ERROR on nlat' |
---|
421 | case(2) |
---|
422 | print*,'Vhaec: ERROR on nlong' |
---|
423 | case(3) |
---|
424 | print*,'Vhaec: ERROR on ityp' |
---|
425 | case(4) |
---|
426 | print*,'Vhaec: ERROR on nt' |
---|
427 | case(5) |
---|
428 | print*,'Vhaec: ERROR on idvw' |
---|
429 | case(6) |
---|
430 | print*,'Vhaec: ERROR on jdvw' |
---|
431 | case(7) |
---|
432 | print*,'Vhaec: ERROR on mdab' |
---|
433 | case(8) |
---|
434 | print*,'Vhaec: ERROR on ndab' |
---|
435 | case(9) |
---|
436 | print*,'Vhaec: ERROR on lvhaec' |
---|
437 | case(10) |
---|
438 | print*,'Vhaec: ERROR on lwork' |
---|
439 | end select |
---|
440 | |
---|
441 | !**********Energy spectra |
---|
442 | allocate(norm(mMax,nLat)) |
---|
443 | allocate(norm_b(mMax,nLat)) |
---|
444 | allocate(norm_c(mMax,nLat)) |
---|
445 | do i = 1,mMax |
---|
446 | do j = 1,nLat |
---|
447 | norm(i,j)=(br(i,j)*br(i,j)+bi(i,j)*bi(i,j)+cr(i,j)*cr(i,j)+ci(i,j)*ci(i,j)) |
---|
448 | norm_b(i,j)=(br(i,j)*br(i,j)+bi(i,j)*bi(i,j)) |
---|
449 | norm_c(i,j)=(cr(i,j)*cr(i,j)+ci(i,j)*ci(i,j)) |
---|
450 | end do |
---|
451 | end do |
---|
452 | allocate(spectra(nLat)) |
---|
453 | allocate(spectra_b(nLat)) |
---|
454 | allocate(spectra_c(nLat)) |
---|
455 | do j = 1,nLat |
---|
456 | spectra(j) = 0.5*norm(1,j) |
---|
457 | spectra_b(j) = 0.5*norm_b(1,j) |
---|
458 | spectra_c(j) = 0.5*norm_c(1,j) |
---|
459 | do i = 2,mMax |
---|
460 | spectra(j) = spectra(j) + norm(i,j) |
---|
461 | spectra_b(j) = spectra_b(j) + norm_b(i,j) |
---|
462 | spectra_c(j) = spectra_c(j) + norm_c(i,j) |
---|
463 | end do |
---|
464 | end do |
---|
465 | !do j = 2,nLat |
---|
466 | ! spectra(j) = spectra(j)/((j-1)*j) |
---|
467 | ! spectra_b(j) = spectra_b(j)/((j-1)*j) |
---|
468 | ! spectra_c(j) = spectra_c(j)/((j-1)*j) |
---|
469 | !end do |
---|
470 | write(*,'(a16,i5,a3,i5,a1)') 'done spectra (t=',tab_indt((t-1)*(meant+1)+mt+1),',z=',tab_indz((z-1)*(meanz+1)+mz+1),')' |
---|
471 | |
---|
472 | !**********Storage of all spectra |
---|
473 | spectra_global(:,number_global) = spectra(:) |
---|
474 | spectra_b_global(:,number_global) = spectra_b(:) |
---|
475 | spectra_c_global(:,number_global) = spectra_c(:) |
---|
476 | |
---|
477 | !********** |
---|
478 | !End of loop over time and altitude indices |
---|
479 | end do |
---|
480 | end do |
---|
481 | write(*,'(a24,i5,a3,i5,a8)') 'spectra computed for (t=',tab_indt((t-1)*(meant+1)+1),',z=',tab_indz((z-1)*(meanz+1)+1),') config' |
---|
482 | write(*,*) '**********' |
---|
483 | end do |
---|
484 | end do |
---|
485 | |
---|
486 | !********** |
---|
487 | !Spectra mean |
---|
488 | do t = 1,n_indt |
---|
489 | do z = 1,n_indz |
---|
490 | number_config = (t-1)*n_indz+z |
---|
491 | spectra_config(:,number_config) = 0. |
---|
492 | do mt = 0,meant |
---|
493 | do mz = 0,meanz |
---|
494 | number_local = mt*(meanz+1)+mz+1 |
---|
495 | number_global = (number_config-1)*(meant+1)*(meanz+1) + number_local |
---|
496 | spectra_config(:,number_config) = spectra_config(:,number_config) + & |
---|
497 | spectra_global(:,number_global) |
---|
498 | spectra_b_config(:,number_config) = spectra_b_config(:,number_config) + & |
---|
499 | spectra_b_global(:,number_global) |
---|
500 | spectra_c_config(:,number_config) = spectra_c_config(:,number_config) + & |
---|
501 | spectra_c_global(:,number_global) |
---|
502 | end do |
---|
503 | end do |
---|
504 | spectra_config(:,number_config) = spectra_config(:,number_config)/(meanz+1)/(meant+1) |
---|
505 | spectra_b_config(:,number_config) = spectra_b_config(:,number_config)/(meanz+1)/(meant+1) |
---|
506 | spectra_c_config(:,number_config) = spectra_c_config(:,number_config)/(meanz+1)/(meant+1) |
---|
507 | end do |
---|
508 | end do |
---|
509 | |
---|
510 | !**********Writing header of file_spectra |
---|
511 | open(unit=10,file=file_spectra,action="write",position="rewind") |
---|
512 | write(10,'(a10,a2)',advance='no') '#Spherical',' ' |
---|
513 | do t = 1,n_indt |
---|
514 | do z = 1,n_indz |
---|
515 | write(10,'(a50)',advance='no') file_netcdf |
---|
516 | end do |
---|
517 | end do |
---|
518 | write(10,*) '' |
---|
519 | write(10,'(a11,a1)',advance='no') '#wavenumber',' ' |
---|
520 | do t = 1,n_indt |
---|
521 | do z = 1,n_indz |
---|
522 | write(10,'(a2,i5,a3,i5,a35)',advance='no') 't=',tab_indt((t-1)*(meant+1)+1),' z=',tab_indz((z-1)*(meanz+1)+1),' ' |
---|
523 | end do |
---|
524 | end do |
---|
525 | write(10,*) '' |
---|
526 | write(10,'(a1,a11)',advance='no') '#',' ' |
---|
527 | do t = 1,n_indt |
---|
528 | do z = 1,n_indz |
---|
529 | if (is_div_rot) then |
---|
530 | write(10,'(a8,a8,a8,a8,a8,a10)',advance='no') 'spec_tot',' ','spec_div',' ','spec_rot',' ' |
---|
531 | else |
---|
532 | write(10,'(a8,a42)',advance='no') 'spec_tot',' ' |
---|
533 | end if |
---|
534 | end do |
---|
535 | end do |
---|
536 | write(10,*)'' |
---|
537 | !**********Writing file_spectra |
---|
538 | do j=1,nLat |
---|
539 | write(10,'(i5,a7)',advance='no') j-1,' ' |
---|
540 | do t = 1,n_indt |
---|
541 | do z = 1,n_indz |
---|
542 | number_config = (t-1)*n_indz+z |
---|
543 | if (is_div_rot) then |
---|
544 | write(10,'(e13.6E2,a4,e13.6E2,a4,e13.6E2,a6)',advance='no') spectra_config(j,number_config),' ',& |
---|
545 | spectra_b_config(j,number_config),' ',spectra_c_config(j,number_config),' ' |
---|
546 | else |
---|
547 | write(10,'(e13.6E2,a38)',advance='no') spectra_config(j,number_config),' ' |
---|
548 | end if |
---|
549 | end do |
---|
550 | end do |
---|
551 | if (j /= nlat) write(10,*)'' |
---|
552 | end do |
---|
553 | close(10) |
---|
554 | |
---|
555 | print *, "***SUCCESS writing ",trim(file_spectra) |
---|
556 | deallocate(br) |
---|
557 | deallocate(bi) |
---|
558 | deallocate(cr) |
---|
559 | deallocate(ci) |
---|
560 | deallocate(wvhaec) |
---|
561 | deallocate(dwork) |
---|
562 | deallocate(work) |
---|
563 | |
---|
564 | contains |
---|
565 | subroutine check(status) |
---|
566 | integer, intent (in) :: status |
---|
567 | |
---|
568 | if(status /= nf90_noerr) then |
---|
569 | print *, trim(nf90_strerror(status)) |
---|
570 | stop "Stopped" |
---|
571 | end if |
---|
572 | end subroutine check |
---|
573 | |
---|
574 | END PROGRAM spectra_analysis |
---|