source: trunk/LMDZ.VENUS/Tools/psi.F90 @ 1696

Last change on this file since 1696 was 1458, checked in by slebonnois, 9 years ago

SL: one additional bug in my previous commit for Venus tools.....

File size: 11.2 KB
Line 
1program streamfunction
2
3! SL 12/2009:
4! This program reads 4D (lon-lat-alt-time) fields directly from LMD outputs
5! without regrid : histmth OR from files recast in log P coordinates (_P)
6!
7! it computes:
8! dmass -- 4D -- mass of each cell
9! psi   -- 3D -- Stream function
10!
11! Minimal requirements and dependencies:
12! The dataset must include the following data:
13! - surface pressure and surface geopotential
14! - meridional winds
15
16implicit none
17
18include "netcdf.inc" ! NetCDF definitions
19
20character (len=128) :: infile ! input file name (name_P.nc)
21character (len=128) :: outfile ! output file name
22
23character (len=64) :: text ! to store some text
24integer infid ! NetCDF input file ID
25integer outfid ! NetCDF output file ID
26integer lon_dimid,lat_dimid,alt_dimid,time_dimid ! NetCDF dimension IDs
27integer lon_varid,lat_varid,alt_varid,time_varid
28integer              :: datashape1d ! shape of 1D datasets
29integer,dimension(2) :: datashape2d ! shape of 2D datasets
30integer,dimension(3) :: datashape3d ! shape of 3D datasets
31integer,dimension(4) :: datashape4d ! shape of 4D datasets
32
33real :: miss_val ! special "missing value" to specify missing data
34real,parameter :: miss_val_def=-9.99e+33 ! default value for "missing value"
35real :: pi
36real,dimension(:),allocatable :: lon ! longitude
37integer lonlength ! # of grid points along longitude
38real,dimension(:),allocatable :: lat ! latitude
39real,dimension(:),allocatable :: coslat ! cos of latitude
40integer latlength ! # of grid points along latitude
41real,dimension(:),allocatable :: plev ! Pressure levels (Pa)
42integer altlength ! # of grid point along altitude (of input datasets)
43real,dimension(:),allocatable :: time ! time
44integer timelength ! # of points along time
45real,dimension(:,:,:),allocatable :: ps ! surface pressure
46real,dimension(:,:,:,:),allocatable :: vitv ! meridional wind (in m/s)
47real,dimension(:,:,:,:),allocatable :: za   ! areoid levels (m)
48
49real,dimension(:,:,:,:),allocatable :: rayon ! distance to center (m)
50real,dimension(:,:,:,:),allocatable :: grav ! gravity field (m s-2)
51real,dimension(:,:,:,:),allocatable :: dmass ! mass in cell (kg)
52real,dimension(:,:,:,:),allocatable :: vm ! meridional mass flux
53real,dimension(:,:,:),allocatable :: psi ! stream function
54
55integer ierr,ierr1,ierr2 ! NetCDF routines return codes
56integer i,j,ilon,ilat,ilev,itim ! for loops
57logical :: lmdflag
58
59real :: deltalat,deltalon ! lat and lon intervals in radians
60
61include "planet.h"
62
63!===============================================================================
64! 1. Input parameters
65!===============================================================================
66
67pi = 2.*asin(1.)
68miss_val = miss_val_def
69
70write(*,*) ""
71write(*,*) "You are working on the atmosphere of ",planet
72
73!===============================================================================
74! 1.1 Input file
75!===============================================================================
76
77write(*,*) ""
78write(*,*) " Program valid for Venus or Titan LMD output files"
79write(*,*) "Enter input file name:"
80
81read(*,'(a128)') infile
82write(*,*) ""
83
84! open input file
85
86ierr = NF_OPEN(infile,NF_NOWRITE,infid)
87if (ierr.ne.NF_NOERR) then
88   write(*,*) 'ERROR: Pb opening file ',trim(infile)
89   stop ""
90endif
91
92!===============================================================================
93! 1.2 Get grids in lon,lat,alt(pressure),time
94!===============================================================================
95
96call get_iddim(infid,lat_varid,latlength,lon_varid,lonlength,&
97                     alt_varid,altlength,time_varid,timelength,lmdflag )
98
99allocate(lon(lonlength))
100ierr=NF_GET_VAR_REAL(infid,lon_varid,lon)
101if (ierr.ne.NF_NOERR) stop "Error: Failed reading longitude"
102
103allocate(lat(latlength))
104ierr=NF_GET_VAR_REAL(infid,lat_varid,lat)
105if (ierr.ne.NF_NOERR) stop "Error: Failed reading lat"
106
107allocate(coslat(latlength))
108! Beware of rounding problems at poles...
109coslat(:) = max(0.,cos(lat(:)*pi/180.))
110
111! Lat, lon pressure intervals
112deltalat = abs(lat(2)-lat(1))*pi/180.
113deltalon = abs(lon(2)-lon(1))*pi/180.
114
115allocate(plev(altlength))
116ierr=NF_GET_VAR_REAL(infid,alt_varid,plev)
117if (ierr.ne.NF_NOERR) stop "Error: Failed reading altitude (ie pressure levels)"
118
119allocate(time(timelength))
120ierr=NF_GET_VAR_REAL(infid,time_varid,time)
121if (ierr.ne.NF_NOERR) stop "Error: Failed reading time"
122
123! Time axis IN PLANET DAYS
124
125time=time/localday
126
127!===============================================================================
128! 1.3 Get output file name
129!===============================================================================
130write(*,*) ""
131!write(*,*) "Enter output file name"
132!read(*,*) outfile
133outfile=infile(1:len_trim(infile)-3)//"_PSI.nc"
134write(*,*) "Output file name is: "//trim(outfile)
135
136
137
138!===============================================================================
139! 2.1 Store needed fields
140!===============================================================================
141
142!===============================================================================
143! 2.1.1 Surface pressure
144!===============================================================================
145allocate(ps(lonlength,latlength,timelength))
146
147text="ps"
148call get_var3d(infid,lonlength,latlength,timelength,text,ps,ierr1,ierr2)
149if (ierr1.ne.NF_NOERR) then
150  write(*,*) "  looking for psol instead... "
151  text="psol"
152  call get_var3d(infid,lonlength,latlength,timelength,text,ps,ierr1,ierr2)
153  if (ierr1.ne.NF_NOERR) stop "Error: Failed to get psol ID"
154endif
155if (ierr2.ne.NF_NOERR) stop "Error: Failed reading surface pressure"
156
157!===============================================================================
158! 2.1.3 Winds
159!===============================================================================
160allocate(vitv(lonlength,latlength,altlength,timelength))
161
162! meridional wind vitv (in m/s)
163text="vitv"
164call get_var4d(infid,lonlength,latlength,altlength,timelength,text,vitv,miss_val,ierr1,ierr2)
165if (ierr1.ne.NF_NOERR) stop "Error: Failed to get vitv ID"
166if (ierr2.ne.NF_NOERR) stop "Error: Failed reading meridional wind"
167
168!===============================================================================
169! 2.1.4 Altitude above areoide
170!===============================================================================
171
172allocate(za(lonlength,latlength,altlength,timelength))
173! present only in _P regrided files
174! For others, using geop/g0
175
176text="zareoid"
177call get_var4d(infid,lonlength,latlength,altlength,timelength,text,za,miss_val,ierr1,ierr2)
178if (ierr1.ne.NF_NOERR) then
179  write(*,*) "  looking for geop instead... "
180  text="geop"
181  call get_var4d(infid,lonlength,latlength,altlength,timelength,text,za,miss_val,ierr1,ierr2)
182  if (ierr1.ne.NF_NOERR) stop "Error: Failed to get geop ID"
183do itim=1,timelength
184do ilon=1,lonlength
185 do ilat=1,latlength
186  do ilev=1,altlength
187    if (za(ilon,ilat,ilev,itim).ne.miss_val) then
188        za(ilon,ilat,ilev,itim) = za(ilon,ilat,ilev,itim)/(g0*1000.) ! in km
189    else
190        za(ilon,ilat,ilev,itim) = miss_val
191    endif
192  enddo
193 enddo
194enddo
195enddo
196endif
197if (ierr2.ne.NF_NOERR) stop "Error: Failed reading zareoid/geop"
198
199!===============================================================================
200! 2.2 Computations
201!===============================================================================
202
203!===============================================================================
204! 2.2.2 Mass in cells
205!===============================================================================
206allocate(rayon(lonlength,latlength,altlength,timelength))
207allocate(grav(lonlength,latlength,altlength,timelength))
208allocate(dmass(lonlength,latlength,altlength,timelength))
209
210do itim=1,timelength
211do ilon=1,lonlength
212 do ilat=1,latlength
213  do ilev=1,altlength
214! Need to be consistent with GCM computations
215    if (za(ilon,ilat,ilev,itim).ne.miss_val) then
216     rayon(ilon,ilat,ilev,itim) = a0
217!     rayon(ilon,ilat,ilev,itim) = za(ilon,ilat,ilev,itim) + a0
218      grav(ilon,ilat,ilev,itim) = g0*a0*a0 &
219                 /(rayon(ilon,ilat,ilev,itim)*rayon(ilon,ilat,ilev,itim))
220    else
221     rayon(ilon,ilat,ilev,itim) = miss_val
222      grav(ilon,ilat,ilev,itim) = miss_val
223    endif
224  enddo
225 enddo
226enddo
227enddo ! timelength
228
229call cellmass(infid,latlength,lonlength,altlength,timelength,lmdflag, &
230              miss_val,deltalon,deltalat,coslat,plev,ps,grav,rayon, &
231              dmass )
232
233!===============================================================================
234! 2.2.8 Stream function
235!===============================================================================
236allocate(vm(lonlength,latlength,altlength,timelength))
237allocate(psi(latlength,altlength,timelength))
238
239do itim=1,timelength
240
241do ilat=1,latlength
242 do ilev=1,altlength
243  do ilon=1,lonlength
244    if (dmass(ilon,ilat,ilev,itim).ne.miss_val) then
245      vm(ilon,ilat,ilev,itim) = vitv(ilon,ilat,ilev,itim)  &
246                              * dmass(ilon,ilat,ilev,itim) &
247                              / (rayon(ilon,ilat,ilev,itim)*deltalat)
248    else
249      vm(ilon,ilat,ilev,itim) = miss_val
250    endif
251  enddo
252 enddo
253enddo
254
255
256do ilat=1,latlength
257  psi(ilat,altlength,itim) = 0.
258  do ilon=1,lonlength
259    if (vm(ilon,ilat,altlength,itim).ne.miss_val) then
260      psi(ilat,altlength,itim) = psi(ilat,altlength,itim) &
261           + vm(ilon,ilat,altlength,itim)
262    endif
263  enddo
264 do ilev=altlength-1,1,-1
265  psi(ilat,ilev,itim) = psi(ilat,ilev+1,itim)
266  do ilon=1,lonlength
267    if (vm(ilon,ilat,ilev,itim).ne.miss_val) then
268      psi(ilat,ilev,itim) = psi(ilat,ilev,itim) &
269           + vm(ilon,ilat,ilev,itim)
270    endif
271  enddo
272 enddo
273enddo
274
275enddo ! timelength
276
277print*,"End of computations"
278
279!===============================================================================
280! 3. Create output file
281!===============================================================================
282
283! Create output file
284ierr=NF_CREATE(outfile,NF_CLOBBER,outfid)
285if (ierr.ne.NF_NOERR) then
286  write(*,*)"Error: could not create file ",outfile
287  stop
288endif
289
290!===============================================================================
291! 3.1. Define and write dimensions
292!===============================================================================
293
294call write_dim(outfid,lonlength,latlength,altlength,timelength, &
295    lon,lat,plev,time,lon_dimid,lat_dimid,alt_dimid,time_dimid)
296
297!===============================================================================
298! 3.2. Define and write variables
299!===============================================================================
300
301! 1D Variables
302
303datashape1d=time_dimid
304 
305! 3D variables
306
307datashape3d(1)=lon_dimid
308datashape3d(2)=lat_dimid
309datashape3d(3)=time_dimid
310
311call write_var3d(outfid,datashape3d,lonlength,latlength,timelength,&
312                "ps        ", "Surface pressure    ","Pa        ",miss_val,&
313                 ps )
314
315datashape3d(1)=lat_dimid
316datashape3d(2)=alt_dimid
317datashape3d(3)=time_dimid
318
319call write_var3d(outfid,datashape3d,lonlength,latlength,timelength,&
320                "psi       ", "Stream function     ","kg/s      ",miss_val,&
321                 psi )
322
323! 4D variables
324
325datashape4d(1)=lon_dimid
326datashape4d(2)=lat_dimid
327datashape4d(3)=alt_dimid
328datashape4d(4)=time_dimid
329
330call write_var4d(outfid,datashape4d,lonlength,latlength,altlength,timelength,&
331                "dmass     ", "Mass                ","kg        ",miss_val,&
332                 dmass )
333
334!!!! Close output file
335ierr=NF_CLOSE(outfid)
336if (ierr.ne.NF_NOERR) then
337  write(*,*) 'Error, failed to close output file ',outfile
338endif
339
340
341end program
Note: See TracBrowser for help on using the repository browser.