Subversion Repositories lagranto.wrf

Rev

Rev 11 | Rev 20 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 michaesp 1
      PROGRAM wrfmap
2
 
3
c     **********************************************************************
4
c     * Transform between lon/lat and x/y coordinates                      *
5
c     * Michael Sprenger / Spring 2013                                     *
6
c     **********************************************************************
7
 
8
      implicit none
9
 
10
c     ------------------------------------------------------------
11
c     Declaration of parameters and variables
12
c     ------------------------------------------------------------
13
 
14
c     Input parameters
15
      character*80 mode
16
      character*80 inpfile
17
      character*80 outfile
18
      integer      ntra,ntim,ncol
19
      character*80 anglemode
20
 
21
c     Fixed parameters
22
      character*80 mapfile                          ! netCDF file with map transformation
23
      parameter    (mapfile ='wrfmap.nc')
24
      real         mdv                              ! missing data value
25
      parameter    (mdv=-999.)
26
 
27
c     Numerical grid
28
      real         xmin,xmax,ymin,ymax              ! Domain size
29
      real         dx,dy                            ! Horizontal resolution
30
      integer      nx,ny,nz                         ! Grid dimensions
31
      real,allocatable,dimension (:,:)  :: lon,lat  ! lon/lat on numerical grid
32
      real,allocatable,dimension (:,:)  :: mpx,mpy  ! map scale factors in x/y direction
33
 
34
 
35
c     Geographical grid
36
      real         latmin,latmax,lonmin,lonmax      ! Geographical domain
37
      real         dlon,dlat                        ! Minimum spacing in geographical space
38
      integer      nlon,nlat,nlev                        ! Geographical grid dimension
39
      real,allocatable,dimension (:,:)   :: x,y      ! x/y on geographical grid
40
 
41
c     Vertical grid
42
      real,allocatable,dimension (:,:,:)   :: p3    ! 3D pressure
43
      real,allocatable,dimension (:,:)     :: ps    ! surface pressure
44
      real,allocatable,dimension (:,:,:)   :: z3    ! 3D geopotential height
45
      real,allocatable,dimension (:,:)     :: zb    ! surface geopotential height
46
 
47
c     Transformation between numerical and geographical grid
15 michaesp 48
      integer,allocatable,dimension (:,:)  :: connect1 
2 michaesp 49
      integer      connectval1 
15 michaesp 50
      integer,allocatable,dimension (:,:)  :: connect2 
2 michaesp 51
      integer      connectval2
52
      real,allocatable,dimension (:,:)  :: xc,yc
53
      real         radius
54
      real         xval,yval
55
 
56
c     Trajectories
57
      real,allocatable, dimension (:,:,:) :: tra             ! Input start coordinates (ntra,ntim,ncol)
58
      integer                                refdate(6)      ! Reference date
59
      character*80                           vars(200)       ! Field names
60
      real,allocatable, dimension (:)     :: xx0,yy0,zz0     ! Position of air parcels
61
      integer                                inpmode
62
      integer                                outmode
63
      integer                                npoints
64
 
65
c     Auxiliary variables
66
      integer      fid
67
      integer      stat
68
      character*80 varname,cdfname
69
      integer      i,j
70
      character*80 radunit
71
      real         rdummy
72
      real         rid,rjd,rkd
73
      real         xpos,ypos,zpos,ppos,lonpos,latpos
74
      real         lon1,lat1,lon2,lat2
11 michaesp 75
      integer      nfilter
2 michaesp 76
 
77
c     Externals
78
      real         int_index3
79
      external     int_index3
80
      real         sdis
81
      external     sdis
82
 
83
c     ------------------------------------------------------------
84
c     Preparations
85
c     ------------------------------------------------------------
86
 
87
c     Read parameters
88
      open(10,file='wrfmap.param')
89
 
90
       read(10,*) mode
91
 
92
       if ( mode.eq.'-create' ) then         ! create mapping file
93
          read(10,*) inpfile
94
          read(10,*) anglemode
95
       endif
96
 
97
       if ( mode.eq.'-ll2xy'  ) then         ! convert lon/lat -> x/y
98
          read(10,*) inpfile
99
          read(10,*) outfile
100
          read(10,*) ntra,ntim,ncol
101
       endif
102
 
103
       if ( mode.eq.'-ll2xy.single'  ) then   ! convert single lon/lat -> x/y
104
          read(10,*) lonpos,latpos
105
       endif
106
 
107
       if ( mode.eq.'-xy2ll'  ) then         ! convert x/y -> lon/lat
108
          read(10,*) inpfile
109
          read(10,*) outfile
110
          read(10,*) ntra,ntim,ncol
111
       endif
112
 
113
       if ( mode.eq.'-xy2ll.single'  ) then   ! convert single x/y -> lon/lat
114
          read(10,*) xpos,ypos
115
       endif
116
 
117
       if ( mode.eq.'-p2z'  ) then            ! convert x/y/p -> x/y/z
118
          read(10,*) inpfile
119
          read(10,*) outfile
120
          read(10,*) ntra,ntim,ncol
121
       endif
122
 
123
       if ( mode.eq.'-p2z.single'  ) then     ! convert single x/y/p -> x/y/z
124
          read(10,*) xpos,ypos,ppos
125
       endif
126
 
127
       if ( mode.eq.'-z2p'  ) then            ! convert x/y/z -> x/y/p
128
          read(10,*) inpfile
129
          read(10,*) outfile
130
          read(10,*) ntra,ntim,ncol
131
       endif
132
 
133
       if ( mode.eq.'-z2p.single'  ) then     ! convert single x/y/z -> x/y/p
134
          read(10,*) xpos,ypos,zpos
135
       endif
136
 
11 michaesp 137
       if ( mode.eq.'-mapscale'  ) then       ! calculate mapping scale factors
138
          read(10,*) nfilter
139
       endif
140
 
2 michaesp 141
      close(10)
142
 
143
c     Read the mapping file - except for mode '-create'
144
      if ( mode.ne.'-create' ) then
145
 
146
c        Get dimensions 
147
         cdfname = mapfile
148
         varname = 'Z'
149
         nx      = 1
150
         ny      = 1
151
         nz      = 1
152
         call readcdf2D(cdfname,varname,rdummy,0.,
153
     >                  dx,dy,xmin,ymin,nx,ny,nz)
154
 
155
         cdfname = mapfile
156
         varname = 'X'
157
         nlon    = 1
158
         nlat    = 1
159
         nlev    = 1
160
         call readcdf2D(cdfname,varname,rdummy,0.,
161
     >                  dlon,dlat,lonmin,latmin,nlon,nlat,nlev)
162
 
163
c        Allocate memory
164
         allocate(lon(nx,ny),stat=stat)
165
         if (stat.ne.0) print*,'*** error allocating array lon ***'
166
         allocate(lat(nx,ny),stat=stat)
167
         if (stat.ne.0) print*,'*** error allocating array lat ***'
168
         allocate(x(nlon,nlat),stat=stat)
169
         if (stat.ne.0) print*,'*** error allocating array x   ***'
170
         allocate(y(nlon,nlat),stat=stat)
171
         if (stat.ne.0) print*,'*** error allocating array y   ***'
172
         allocate(p3(nx,ny,nz),stat=stat)
173
         if (stat.ne.0) print*,'*** error allocating array p3  ***'
174
         allocate(z3(nx,ny,nz),stat=stat)
175
         if (stat.ne.0) print*,'*** error allocating array z3  ***'
176
         allocate(zb(nx,ny),stat=stat)
177
         if (stat.ne.0) print*,'*** error allocating array zb  ***'
178
         allocate(ps(nx,ny),stat=stat)
179
         if (stat.ne.0) print*,'*** error allocating array ps  ***'
180
 
181
c        Read data
182
         cdfname = mapfile
183
         varname = 'LON'
184
         call readcdf2D(cdfname,varname,lon,0.,
185
     >                  dx,dy,xmin,ymin,nx,ny,1)
186
         cdfname = mapfile
187
         varname = 'LAT'
188
         call readcdf2D(cdfname,varname,lat,0.,
189
     >                  dx,dy,xmin,ymin,nx,ny,1)
190
         cdfname = mapfile
191
         varname = 'X'
192
         call readcdf2D(cdfname,varname,x,0.,
193
     >                  dlon,dlat,lonmin,latmin,nlon,nlat,1)
194
         cdfname = mapfile
195
         varname = 'Y'
196
         call readcdf2D(cdfname,varname,y,0.,
197
     >                  dlon,dlat,lonmin,latmin,nlon,nlat,1)
198
         cdfname = mapfile
199
         varname = 'Z'
200
         call readcdf2D(cdfname,varname,z3,0.,
201
     >                  dx,dy,xmin,ymin,nx,ny,nz)
202
         cdfname = mapfile
203
         varname = 'P'
204
         call readcdf2D(cdfname,varname,p3,0.,
205
     >                  dx,dy,xmin,ymin,nx,ny,nz)
206
         cdfname = mapfile
207
         varname = 'TOPO'
208
         call readcdf2D(cdfname,varname,zb,0.,
209
     >                  dx,dy,xmin,ymin,nx,ny,1)
210
 
211
c	     Set surface prtessure to lowest 3d pressure level
212
         do i=1,nx
213
            do j=1,ny
214
               ps(i,j) = p3(i,j,1)
215
            enddo
216
         enddo
217
 
218
      endif
219
 
220
c     ------------------------------------------------------------
221
c     Create mapping file
222
c     ------------------------------------------------------------
223
 
224
      if ( mode.eq.'-create' ) then
225
 
226
c     Open mapping file
227
      call input_open(fid,inpfile)
228
 
229
c     Get grid description
230
      call input_grid_wrf(fid,
231
     >		          xmin,xmax,ymin,ymax,dx,dy,nx,ny,nz)
232
 
233
c     Write grid information to screen
234
      print*,' xmin,xmax  = ',xmin,xmax
235
      print*,' ymin,ymax  = ',ymin,ymax
236
      print*,' dx,dy      = ',dx,dy
237
      print*,' nx,ny,nz   = ',nx,ny,nz 
15 michaesp 238
      print*,' anglemode  = ',trim(anglemode)
2 michaesp 239
 
240
c     Transform grid specifier into grid coordinates
241
      xmin = 1.
242
      ymin = 1.
243
      dx   = 1.
244
      dy   = 1.
245
 
246
c     Allocate memory for lon/lat on numerical grid
247
      allocate(lon(nx,ny),stat=stat)
248
      if (stat.ne.0) print*,'*** error allocating array lon ***'
249
      allocate(lat(nx,ny),stat=stat)
250
      if (stat.ne.0) print*,'*** error allocating array lat ***'
251
      allocate(p3(nx,ny,nz),stat=stat)
252
      if (stat.ne.0) print*,'*** error allocating array p3  ***'
253
      allocate(z3(nx,ny,nz),stat=stat)
254
      if (stat.ne.0) print*,'*** error allocating array z3  ***'
255
      allocate(zb(nx,ny),stat=stat)
256
      if (stat.ne.0) print*,'*** error allocating array zb  ***'
257
 
258
c     Read lon/lat on the model grid
259
      varname='XLONG'
260
      call input_var_wrf(fid,varname,lon,nx,ny,1)
261
      varname='XLAT'
262
      call input_var_wrf(fid,varname,lat,nx,ny,1)
263
      varname='pressure'
264
      call input_var_wrf(fid,varname,p3 ,nx,ny,nz)
265
      varname='geopot'
266
      call input_var_wrf(fid,varname,z3 ,nx,ny,nz)
267
      varname='geopots'
268
      call input_var_wrf(fid,varname,zb ,nx,ny,1)
269
 
270
c     Transform longitude depending on <anglemode>
271
      if ( anglemode.eq.'greenwich' ) then
272
         do i=1,nx
273
           do j=1,ny
274
              if ( lon(i,j).lt.0. ) lon(i,j) = lon(i,j) + 360.
275
            enddo
276
         enddo
277
      elseif ( anglemode.eq.'dateline' ) then
278
         do i=1,nx
279
            do j=1,ny
280
               if ( lon(i,j).gt.180. ) lon(i,j) = lon(i,j) - 360.
281
            enddo
282
         enddo
283
      else
284
         print*,' ERROR: unsupported angle mode... Stop'
285
         stop
286
      endif
287
 
288
c     Close input file file
289
      call input_close(fid)
290
 
291
c     Check for 'date line' and for pole
292
      do i=2,nx
293
      do j=1,ny
294
        if ( abs( lat(i,j) ).gt.90. ) then
295
           print*,' ERROR: mapping over pole not supported... Stop'
296
           stop
297
        endif
298
        if ( abs( lon(i,j)-lon(i-1,j) ).gt.180. ) then
299
           print*,' ERROR: mapping over date line not supported... Stop'
300
           stop
301
        endif
302
      enddo
303
      enddo
304
 
305
c     Determine the extreme coordinates
306
      latmin  = lat(1,1)
307
      latmax  = lat(1,1)
308
      lonmin  = lon(1,1)
309
      lonmax  = lon(1,1)
310
      do i=1,nx
311
	    do j=1,ny
312
          if ( lat(i,j).lt.latmin ) latmin = lat(i,j)
313
          if ( lat(i,j).gt.latmax ) latmax = lat(i,j)
314
          if ( lon(i,j).lt.lonmin ) lonmin = lon(i,j)
315
          if ( lon(i,j).gt.lonmax ) lonmax = lon(i,j)
316
        enddo
317
      enddo
318
 
319
      print*,' lonmin,max = ',lonmin,lonmax
320
      print*,' latmin,max = ',latmin,latmax
321
 
322
c     Determine the extreme dlon/dlat spacing
323
      dlon = abs( lon(2,1)-lon(1,1) )
324
      do i=2,nx
325
	    do j=1,ny
326
           if ( abs( lon(i,j)-lon(i-1,j) ).lt.dlon ) then
327
              dlon = abs( lon(i,j)-lon(i-1,j) )
328
           endif
329
         enddo
330
      enddo
331
      dlat = abs( lat(1,2)-lat(1,1) )
332
      do i=1,nx
333
	    do j=2,ny
334
           if ( abs( lat(i,j)-lat(i,j-1) ).lt.dlat ) then
335
              dlat = abs( lat(i,j)-lat(i,j-1) )
336
           endif
337
         enddo
338
      enddo
339
 
340
c     Set dimension of geographical grid 
341
      nlon   = ceiling( (lonmax-lonmin) / dlon + 1. )
342
      nlat   = ceiling( (latmax-latmin) / dlat + 1. )
343
      lonmax = lonmin + real(nlon-1) * dlon
344
      latmax = latmin + real(nlat-1) * dlat
345
 
346
      print*,' dlon,dlat  = ',dlon,dlat
347
      print*,' nlon,nlat  = ',nlon,nlat
348
 
349
c     Allocate memory for x/y on geographical grid
350
      allocate(x(nlon,nlat),stat=stat)
351
      if (stat.ne.0) print*,'*** error allocating array x       ***'
352
      allocate(y(nlon,nlat),stat=stat)
353
      if (stat.ne.0) print*,'*** error allocating array y       ***'
354
      allocate(connect1(nlon,nlat),stat=stat)
355
      if (stat.ne.0) print*,'*** error allocating array connect1***'
356
      allocate(connect2(nlon,nlat),stat=stat)
357
      if (stat.ne.0) print*,'*** error allocating array connect2***'
358
      allocate(xc(nlon,nlat),stat=stat)
359
      if (stat.ne.0) print*,'*** error allocating array xc      ***'
360
      allocate(yc(nlon,nlat),stat=stat)
361
      if (stat.ne.0) print*,'*** error allocating array yc      ***'
362
 
363
c     Init the mapping arrays
364
      connectval1 = 0
365
      connectval2 = 0
366
      do i=1,nlon
367
	do j=1,nlat
368
           x(i,j)        = 0.
369
           y(i,j)        = 0.
370
           xc(i,j)       = 0.
371
           yc(i,j)       = 0.
372
           connect1(i,j) = 1
373
           connect2(i,j) = 1
374
        enddo
375
      enddo
376
 
377
c     Get the good radius for gridding - avoiding gaps
378
      radunit = 'deg'
379
      radius  = 0.
380
      do i=2,nx
381
        do j=2,ny
382
           if ( abs( lat(i,j)-lat(i,j-1) ).gt.radius ) then
383
              radius = abs( lat(i,j)-lat(i,j-1) )
384
           endif
385
           if ( abs( lon(i,j)-lon(i-1,j) ).gt.radius ) then
386
              radius = abs( lon(i,j)-lon(i-1,j) )
387
           endif
388
        enddo
389
      enddo
390
      radius = 3. * radius 
391
 
392
c     Do the mapping
393
      do i=1,nx
394
	do j=1,ny
395
 
396
          connectval1 = connectval1 + 1
397
          call gridding1(lat(i,j),lon(i,j),real(i),radius,radunit,
398
     >                   connect1,connectval1,
399
     >                   x,xc,nlon,nlat,lonmin,latmin,dlon,dlat)
400
 
401
          connectval2 = connectval2 + 1
402
          call gridding1(lat(i,j),lon(i,j),real(j),radius,radunit,
403
     >                   connect2,connectval2,
404
     >                   y,yc,nlon,nlat,lonmin,latmin,dlon,dlat)
405
 
406
 
407
	enddo
408
      enddo
409
 
410
c     Normalize output and set miising data flag
411
      do i=1,nlon
412
         do j=1,nlat
413
            if ( xc(i,j).gt.0. ) then
414
               x(i,j) = x(i,j)/xc(i,j)
415
            else
416
               x(i,j) = mdv
417
            endif
418
            if ( yc(i,j).gt.0. ) then
419
               y(i,j) = y(i,j)/yc(i,j)
420
            else
421
               y(i,j) = mdv
422
            endif
423
         enddo
424
      enddo
425
 
426
c     Write data to netCDF
427
      cdfname = mapfile
428
      varname = 'X'
429
      call writecdf2D(cdfname,varname,x,0.,
430
     >                dlon,dlat,lonmin,latmin,nlon,nlat,1,1,1)
431
 
432
      cdfname = mapfile
433
      varname = 'Y'
434
      call writecdf2D(cdfname,varname,y,0.,
435
     >                dlon,dlat,lonmin,latmin,nlon,nlat,1,0,1)
436
 
437
      cdfname = mapfile
438
      varname = 'LON'
439
      call writecdf2D(cdfname,varname,lon,0.,
440
     >                dx,dy,xmin,ymin,nx,ny,1,0,1)
441
 
442
      cdfname = mapfile
443
      varname = 'LAT'
444
      call writecdf2D(cdfname,varname,lat,0.,
445
     >                dx,dy,xmin,ymin,nx,ny,1,0,1)
446
 
447
      cdfname = mapfile
448
      varname = 'Z'
449
      call writecdf2D(cdfname,varname,z3,0.,
450
     >                dx,dy,xmin,ymin,nx,ny,nz,0,1)
451
 
452
      cdfname = mapfile
453
      varname = 'P'
454
      call writecdf2D(cdfname,varname,p3,0.,
455
     >                dx,dy,xmin,ymin,nx,ny,nz,0,1)
456
      cdfname = mapfile
457
      varname = 'TOPO'
458
      call writecdf2D(cdfname,varname,zb,0.,
459
     >                dx,dy,xmin,ymin,nx,ny,1,0,1)
460
 
461
 
462
      endif
463
 
464
 
465
c     ------------------------------------------------------------
466
c     Convert a lat/lon/z list to a x/y/z list
467
c     ------------------------------------------------------------
468
 
469
      if ( mode.eq.'-ll2xy' ) then
470
 
471
c     Allocate memory for input and output lists
472
      allocate(tra(ntra,ntim,ncol),stat=stat)
473
      if (stat.ne.0) print*,'*** error allocating array tra         ***'
474
      allocate(xx0(ntra*ntim),stat=stat)
475
      if (stat.ne.0) print*,'*** error allocating array xx0         ***'
476
      allocate(yy0(ntra*ntim),stat=stat)
477
      if (stat.ne.0) print*,'*** error allocating array yy0         ***'
478
      allocate(zz0(ntra*ntim),stat=stat)
479
      if (stat.ne.0) print*,'*** error allocating array zz0         ***'
480
 
481
c     Get format of input and output file
482
      call mode_tra(inpmode,inpfile)
483
      call mode_tra(outmode,outfile)
11 michaesp 484
      if ( outmode.eq.-1 ) outmode = inpmode
2 michaesp 485
 
486
c     Read coordinates from file - Format (lon,lat,lev)
487
      if (inpmode.eq.-1) then
488
         fid = 10
489
         npoints = 0
490
         open(fid,file=inpfile)
491
          do i=1,ntra
492
             npoints = npoints + 1
493
             read(fid,*) xx0(npoints),yy0(npoints),zz0(npoints)
494
          enddo
495
         close(fid)
496
 
497
c     Read coordinates from trajectory file 
498
      else
499
         call ropen_tra(fid,inpfile,ntra,ntim,ncol,refdate,vars,inpmode)
500
         call read_tra (fid,tra,ntra,ntim,ncol,inpmode)
501
         call close_tra(fid,inpmode)
502
 
503
         if ( (vars(2).ne.'lon').and.(vars(3).ne.'lat') ) then
504
            print*,' ERROR: input must be in lon/lat format... Stop'       
505
            stop
506
         endif
507
 
508
         npoints = 0
509
         do i=1,ntra
510
            do j=1,ntim
511
               npoints = npoints + 1
512
               xx0(npoints) = tra(i,j,2) 
513
               yy0(npoints) = tra(i,j,3) 
514
               zz0(npoints) = tra(i,j,4) 
515
            enddo
516
         enddo
517
      endif 
518
 
519
c     Transform coordinates
520
      do i=1,npoints
521
 
522
          rid=(xx0(i)-lonmin)/dlon+1.
523
          rjd=(yy0(i)-latmin)/dlat+1.
524
 
525
          xx0(i) = int_index3(x,nlon,nlat,1,rid,rjd,1.,mdv)
526
          yy0(i) = int_index3(y,nlon,nlat,1,rid,rjd,1.,mdv)
527
 
528
      enddo
529
 
530
c     Write output to list
531
      if ( outmode.eq.-1 ) then
532
         fid = 10
533
         open(fid,file=outfile)
534
         do i=1,ntra
535
            write(fid,'(f9.2,f8.2,i6)') xx0(i),yy0(i),nint(zz0(i))
536
         enddo
537
         close(fid)
538
 
539
c     Write output to trajectory
540
      else         
541
         npoints = 0
542
         do i=1,ntra
543
            do j=1,ntim
544
               npoints = npoints + 1
545
               tra(i,j,2) = xx0(npoints)
546
               tra(i,j,3) = yy0(npoints)
547
               tra(i,j,4) = zz0(npoints)
548
            enddo
549
         enddo
550
         if ( ncol.eq.3 ) ncol = 4
551
         vars(1) = 'time'
552
         vars(2) = 'x'
553
         vars(3) = 'y'
554
         vars(4) = 'z'
555
         call wopen_tra(fid,outfile,ntra,ntim,ncol,refdate,vars,outmode)
556
         call write_tra(fid,tra,ntra,ntim,ncol,outmode)
557
         call close_tra(fid,outmode)
558
      endif
559
 
560
      endif
561
 
562
c     ------------------------------------------------------------
563
c     Convert a x/y/z list to a lon/lat/z list
564
c     ------------------------------------------------------------
565
 
566
      if ( mode.eq.'-xy2ll' ) then
567
 
568
c     Allocate memory for input and output lists
569
      allocate(tra(ntra,ntim,ncol),stat=stat)
570
      if (stat.ne.0) print*,'*** error allocating array tra         ***'
571
      allocate(xx0(ntra*ntim),stat=stat)
572
      if (stat.ne.0) print*,'*** error allocating array xx0         ***'
573
      allocate(yy0(ntra*ntim),stat=stat)
574
      if (stat.ne.0) print*,'*** error allocating array yy0         ***'
575
      allocate(zz0(ntra*ntim),stat=stat)
576
      if (stat.ne.0) print*,'*** error allocating array zz0         ***'
577
 
578
c     Get format of input and output file
579
      call mode_tra(inpmode,inpfile)
580
      call mode_tra(outmode,outfile)
11 michaesp 581
      if ( outmode.eq.-1) outmode=inpmode
2 michaesp 582
 
583
c     Read coordinates from file - Format (x,y,lev)
584
      if (inpmode.eq.-1) then
585
         fid = 10
586
         npoints = 0
587
         open(fid,file=inpfile)
588
          do i=1,ntra
589
             npoints = npoints + 1
590
             read(fid,*) xx0(npoints),yy0(npoints),zz0(npoints)
591
          enddo
592
         close(fid)
593
 
594
c     Read coordinates from trajectory file 
595
      else
596
         call ropen_tra(fid,inpfile,ntra,ntim,ncol,refdate,vars,inpmode)
597
         call read_tra (fid,tra,ntra,ntim,ncol,inpmode)
598
         call close_tra(fid,inpmode)
599
 
600
         if ( (vars(2).ne.'x').and.(vars(3).ne.'y') ) then
601
            print*,' ERROR: input must be in x/y format... Stop'       
602
            stop
603
         endif
604
 
605
         npoints = 0
606
         do i=1,ntra
607
            do j=1,ntim
608
               npoints = npoints + 1
609
               xx0(npoints) = tra(i,j,2) 
610
               yy0(npoints) = tra(i,j,3) 
611
               zz0(npoints) = tra(i,j,4) 
612
            enddo
613
         enddo
614
      endif 
615
 
616
c     Transform coordinates
617
      do i=1,npoints
618
 
619
          rid=(xx0(i)-xmin)/dx+1.
620
          rjd=(yy0(i)-ymin)/dy+1.
621
 
622
          xx0(i) = int_index3(lon,nx,ny,1,rid,rjd,1.,mdv)
623
          yy0(i) = int_index3(lat,nx,ny,1,rid,rjd,1.,mdv)
624
 
625
      enddo
626
 
627
c     Write output to list
628
      if ( outmode.eq.-1 ) then
629
         fid = 10
630
         open(fid,file=outfile)
631
         do i=1,ntra
632
            write(fid,'(f9.2,f8.2,i6)') xx0(i),yy0(i),nint(zz0(i))
633
         enddo
634
         close(fid)
635
 
636
c     Write output to trajectory
637
      else         
638
         npoints = 0
639
         do i=1,ntra
640
            do j=1,ntim
641
               npoints = npoints + 1
642
               tra(i,j,2) = xx0(npoints)
643
               tra(i,j,3) = yy0(npoints)
644
               tra(i,j,4) = zz0(npoints)
645
            enddo
646
         enddo
647
         if ( ncol.eq.3 ) ncol = 4
648
         vars(1) = 'time'
649
         vars(2) = 'lon'
650
         vars(3) = 'lat'
651
         vars(4) = 'z'
652
         call wopen_tra(fid,outfile,ntra,ntim,ncol,refdate,vars,outmode)
653
         call write_tra(fid,tra,ntra,ntim,ncol,outmode)
654
         call close_tra(fid,outmode)
655
      endif
656
 
657
      endif
658
 
659
c     ------------------------------------------------------------
660
c     Convert a single lat/lon/z list to a x/y/z list
661
c     ------------------------------------------------------------
662
 
663
      if ( mode.eq.'-ll2xy.single' ) then
664
 
665
c     Transform coordinates
666
      rid  = (lonpos-lonmin)/dlon+1.
667
      rjd  = (latpos-latmin)/dlat+1.
668
      xpos = int_index3(x,nlon,nlat,1,rid,rjd,1.,mdv)
669
      ypos = int_index3(y,nlon,nlat,1,rid,rjd,1.,mdv)
670
 
671
c	  Write result to screen
672
      print*,xpos,ypos
673
 
674
      endif
675
 
676
c     ------------------------------------------------------------
677
c     Convert a single x/y/z list to a lon/lat/z list
678
c     ------------------------------------------------------------
679
 
680
      if ( mode.eq.'-xy2ll.single' ) then
681
 
682
c     Transform coordinates
683
      rid    = (xpos-xmin)/dx+1.
684
      rjd    = (ypos-ymin)/dy+1.
685
      lonpos = int_index3(lon,nx,ny,1,rid,rjd,1.,mdv)
686
      latpos = int_index3(lat,nx,ny,1,rid,rjd,1.,mdv)
687
 
688
c	  Write result to screen
689
      print*,lonpos,latpos
690
 
691
      endif
692
 
693
c     ------------------------------------------------------------
694
c     Calculate numerically the maps scale factor
695
c     ------------------------------------------------------------
696
 
697
      if ( mode.eq.'-mapscale' ) then
698
 
699
c	  Allocate memory for map scale factors
700
      allocate(mpx(nx,ny),stat=stat)
701
      if (stat.ne.0) print*,'*** error allocating array mpx       ***'
702
      allocate(mpy(nx,ny),stat=stat)
703
      if (stat.ne.0) print*,'*** error allocating array mpy       ***'
704
 
705
c     Get map scale for interior points
706
      do i=2,nx-1
707
         do j=2,ny-1
708
 
709
c           Map scale in x direction
710
            lon1     = lon(i-1,j)
711
            lat1     = lat(i-1,j)
712
            lon2     = lon(i+1,j)
713
            lat2     = lat(i+1,j)
714
            radunit  = 'km.haversine'
715
            mpx(i,j) = 0.5 * 1000. * sdis(lon1,lat1,lon2,lat2,radunit)
716
 
717
c           Map scale in y direction
718
            lon1     = lon(i,j-1)
719
            lat1     = lat(i,j-1)
720
            lon2     = lon(i,j+1)
721
            lat2     = lat(i,j+1)
722
            radunit  = 'km.haversine'
723
            mpy(i,j) = 0.5 * 1000. * sdis(lon1,lat1,lon2,lat2,radunit)
724
 
725
         enddo
726
      enddo
727
 
728
c     Copy map scale for boundary line points
729
      do i=2,nx-1
730
        mpx(i, 1) = mpx(i,   2)
731
        mpx(i,ny) = mpx(i,ny-1)
732
        mpy(i, 1) = mpy(i,   2)
733
        mpy(i,ny) = mpy(i,ny-1)
734
      enddo
735
      do j=2,ny-1
736
        mpx(1, j) = mpx(2,   j)
737
        mpx(nx,j) = mpx(nx-1,j)
738
        mpy(1, j) = mpy(2,   j)
739
        mpy(nx,j) = mpy(nx-1,j)
740
      enddo
741
 
742
c     Copy map scale factor for boundary corner points
743
      mpx( 1, 1) = mpx(   2,   2)
744
      mpy( 1, 1) = mpy(   2,   2)
745
      mpx(nx, 1) = mpx(nx-1,   2)
746
      mpy(nx, 1) = mpy(nx-1,   2)
747
      mpx(nx,ny) = mpx(nx-1,ny-1)
748
      mpy(nx,ny) = mpy(nx-1,ny-1)
749
      mpx( 1,ny) = mpx(   2,ny-1)
750
      mpy( 1,ny) = mpy(   2,ny-1)
751
 
11 michaesp 752
c     Apply a diffuive filter
753
      do i=1,nfilter
754
         call filt2d (mpx,mpx,nx,ny,1.0,-999.,0,0,0,0)
755
         call filt2d (mpy,mpy,nx,ny,1.0,-999.,0,0,0,0)
756
      enddo
757
 
2 michaesp 758
c     Write map factors to mapping file
759
      cdfname = mapfile
760
      varname = 'MAPSCALE_X'
8 michaesp 761
      call writecdf2D(cdfname,varname,mpx,0.,
762
     >                dx,dy,xmin,ymin,nx,ny,1,0,1)
2 michaesp 763
      cdfname = mapfile
764
      varname = 'MAPSCALE_Y'
765
      call writecdf2D(cdfname,varname,mpy,0.,
766
     >                dx,dy,xmin,ymin,nx,ny,1,0,1)
767
 
768
 
769
      endif
770
 
771
c     ------------------------------------------------------------
772
c     Convert from pressure to height
773
c     ------------------------------------------------------------
774
 
775
      if ( mode.eq.'-p2z' ) then
776
 
777
c     Allocate memory for input and output lists
778
      allocate(tra(ntra,ntim,ncol),stat=stat)
779
      if (stat.ne.0) print*,'*** error allocating array tra         ***'
780
      allocate(xx0(ntra*ntim),stat=stat)
781
      if (stat.ne.0) print*,'*** error allocating array xx0         ***'
782
      allocate(yy0(ntra*ntim),stat=stat)
783
      if (stat.ne.0) print*,'*** error allocating array yy0         ***'
784
      allocate(zz0(ntra*ntim),stat=stat)
785
      if (stat.ne.0) print*,'*** error allocating array zz0         ***'
786
 
787
c     Get format of input and output file
788
      call mode_tra(inpmode,inpfile)
789
      call mode_tra(outmode,outfile)
11 michaesp 790
      if ( outmode.eq.-1) outmode=inpmode
2 michaesp 791
 
792
c     Read coordinates from file - Format (x,y,lev)
793
      if (inpmode.eq.-1) then
794
         fid = 10
795
         npoints = 0
796
         open(fid,file=inpfile)
797
          do i=1,ntra
798
             npoints = npoints + 1
799
             read(fid,*) xx0(npoints),yy0(npoints),zz0(npoints)
800
          enddo
801
         close(fid)
802
 
803
c     Read coordinates from trajectory file
804
      else
805
         call ropen_tra(fid,inpfile,ntra,ntim,ncol,refdate,vars,inpmode)
806
         call read_tra (fid,tra,ntra,ntim,ncol,inpmode)
807
         call close_tra(fid,inpmode)
808
 
809
         if ( (vars(2).ne.'x').and.(vars(3).ne.'y') ) then
810
            print*,' ERROR: input must be in x/y format... Stop'
811
            stop
812
         endif
813
 
814
         npoints = 0
815
         do i=1,ntra
816
            do j=1,ntim
817
               npoints = npoints + 1
818
               xx0(npoints) = tra(i,j,2)
819
               yy0(npoints) = tra(i,j,3)
820
               zz0(npoints) = tra(i,j,4)
821
            enddo
822
         enddo
823
      endif
824
 
825
c     Transform coordinates
826
      do i=1,npoints
827
 
828
          call get_index3 (rid,rjd,rkd,xx0(i),yy0(i),-zz0(i),1,
829
     >                     -p3,-ps,nx,ny,nz,xmin,ymin,dx,dy)
830
 
831
          zz0(i) = int_index3(z3,nx,ny,nz,rid,rjd,rkd,mdv)
832
 
833
      enddo
834
 
835
c     Write output to list
836
      if ( outmode.eq.-1 ) then
837
         fid = 10
838
         open(fid,file=outfile)
839
         do i=1,ntra
840
            write(fid,'(f9.2,f8.2,i6)') xx0(i),yy0(i),nint(zz0(i))
841
         enddo
842
         close(fid)
843
 
844
c     Write output to trajectory
845
      else
846
         npoints = 0
847
         do i=1,ntra
848
            do j=1,ntim
849
               npoints = npoints + 1
850
               tra(i,j,2) = xx0(npoints)
851
               tra(i,j,3) = yy0(npoints)
852
               tra(i,j,4) = zz0(npoints)
853
            enddo
854
         enddo
855
         if ( ncol.eq.3 ) ncol = 4
856
         vars(1) = 'time'
857
         vars(2) = 'x'
858
         vars(3) = 'y'
859
         vars(4) = 'z'
860
         call wopen_tra(fid,outfile,ntra,ntim,ncol,refdate,vars,outmode)
861
         call write_tra(fid,tra,ntra,ntim,ncol,outmode)
862
         call close_tra(fid,outmode)
863
      endif
864
 
865
      endif
866
 
867
c     ------------------------------------------------------------
868
c     Convert single x/y/p to x/y/z
869
c     ------------------------------------------------------------
870
 
871
      if ( mode.eq.'-p2z.single' ) then
872
 
873
c     Transform coordinates - change from descending to ascending (minus sign)
874
      call get_index3 (rid,rjd,rkd,xpos,ypos,-ppos,1,
875
     >                 -p3,-ps,nx,ny,nz,xmin,ymin,dx,dy)
876
 
877
      zpos = int_index3(z3,nx,ny,nz,rid,rjd,rkd,mdv)
878
 
879
c	  Write result to screen
880
      print*,xpos,ypos,zpos
881
 
882
      endif
883
 
884
c     ------------------------------------------------------------
885
c     Convert from height to pressure
886
c     ------------------------------------------------------------
887
 
888
      if ( mode.eq.'-z2p' ) then
889
 
890
c     Allocate memory for input and output lists
891
      allocate(tra(ntra,ntim,ncol),stat=stat)
892
      if (stat.ne.0) print*,'*** error allocating array tra         ***'
893
      allocate(xx0(ntra*ntim),stat=stat)
894
      if (stat.ne.0) print*,'*** error allocating array xx0         ***'
895
      allocate(yy0(ntra*ntim),stat=stat)
896
      if (stat.ne.0) print*,'*** error allocating array yy0         ***'
897
      allocate(zz0(ntra*ntim),stat=stat)
898
      if (stat.ne.0) print*,'*** error allocating array zz0         ***'
899
 
900
c     Get format of input and output file
901
      call mode_tra(inpmode,inpfile)
902
      call mode_tra(outmode,outfile)
11 michaesp 903
      if ( outmode.eq.-1) outmode=inpmode
2 michaesp 904
 
905
c     Read coordinates from file - Format (x,y,lev)
906
      if (inpmode.eq.-1) then
907
         fid = 10
908
         npoints = 0
909
         open(fid,file=inpfile)
910
          do i=1,ntra
911
             npoints = npoints + 1
912
             read(fid,*) xx0(npoints),yy0(npoints),zz0(npoints)
913
          enddo
914
         close(fid)
915
 
916
c     Read coordinates from trajectory file
917
      else
918
         call ropen_tra(fid,inpfile,ntra,ntim,ncol,refdate,vars,inpmode)
919
         call read_tra (fid,tra,ntra,ntim,ncol,inpmode)
920
         call close_tra(fid,inpmode)
921
 
922
         if ( (vars(2).ne.'x').and.(vars(3).ne.'y') ) then
923
            print*,' ERROR: input must be in x/y format... Stop'
924
            stop
925
         endif
926
 
927
         npoints = 0
928
         do i=1,ntra
929
            do j=1,ntim
930
               npoints = npoints + 1
931
               xx0(npoints) = tra(i,j,2)
932
               yy0(npoints) = tra(i,j,3)
933
               zz0(npoints) = tra(i,j,4)
934
            enddo
935
         enddo
936
      endif
937
 
938
c     Transform coordinates
939
      do i=1,npoints
940
 
941
          call get_index3 (rid,rjd,rkd,xx0(i),yy0(i),zz0(i),1,
942
     >                     z3,zb,nx,ny,nz,xmin,ymin,dx,dy)
943
 
944
          zz0(i) = int_index3(p3,nx,ny,nz,rid,rjd,rkd,mdv)
945
 
946
      enddo
947
 
948
c     Write output to list
949
      if ( outmode.eq.-1 ) then
950
         fid = 10
951
         open(fid,file=outfile)
952
         do i=1,ntra
953
            write(fid,'(f9.2,f8.2,i6)') xx0(i),yy0(i),nint(zz0(i))
954
         enddo
955
         close(fid)
956
 
957
c     Write output to trajectory
958
      else
959
         npoints = 0
960
         do i=1,ntra
961
            do j=1,ntim
962
               npoints = npoints + 1
963
               tra(i,j,2) = xx0(npoints)
964
               tra(i,j,3) = yy0(npoints)
965
               tra(i,j,4) = zz0(npoints)
966
            enddo
967
         enddo
968
         if ( ncol.eq.3 ) ncol = 4
969
         vars(1) = 'time'
970
         vars(2) = 'x'
971
         vars(3) = 'y'
972
         vars(4) = 'p'
973
         call wopen_tra(fid,outfile,ntra,ntim,ncol,refdate,vars,outmode)
974
         call write_tra(fid,tra,ntra,ntim,ncol,outmode)
975
         call close_tra(fid,outmode)
976
      endif
977
 
978
      endif
979
 
980
c     ------------------------------------------------------------
981
c     Convert single x/y/z to x/y/p
982
c     ------------------------------------------------------------
983
 
984
      if ( mode.eq.'-z2p.single' ) then
985
 
986
c     Transform coordinates - change from descending to ascending (minus sign)
987
      call get_index3 (rid,rjd,rkd,xpos,ypos,zpos,1,
988
     >                 z3,zb,nx,ny,nz,xmin,ymin,dx,dy)
989
 
990
      ppos = int_index3(p3,nx,ny,nz,rid,rjd,rkd,mdv)
991
 
992
c	  Write result to screen
993
      print*,xpos,ypos,ppos
994
 
995
      endif
996
 
997
      end
998
 
999
 
1000
c     ********************************************************************
1001
c     * GRIDDING SUBROUTINES                                             *
1002
c     ********************************************************************
1003
 
1004
c     ---------------------------------------------------------------------
1005
c     Gridding of one single data point (smoothing in km, deg, gridp)
1006
c     ---------------------------------------------------------------------
1007
 
1008
      subroutine gridding1 (lat,lon,addval,radius,unit,
1009
     >                      connect,connectval,
1010
     >                      out,outc,nx,ny,xmin,ymin,dx,dy)
1011
 
1012
      implicit none
1013
 
1014
c     Declaration of subroutine parameters
1015
      real         lat,lon
1016
      integer      nx,ny
1017
      real         xmin,ymin,dx,dy
1018
      real         out(nx,ny),outc(nx,ny)
1019
      real         radius
1020
      character*80 unit
1021
      integer      connectval
1022
      integer      connect(nx,ny)
1023
      real         addval
1024
 
1025
c     Auxiliary variables
1026
      integer   i,j,k
1027
      integer   mu,md,nr,nl,n,m
1028
      integer   stackx(nx*ny),stacky(nx*ny)
1029
      integer   tab_x(nx*ny),tab_y(nx*ny)
1030
      real      tab_r(nx*ny)
1031
      integer   sp
1032
      real      lat2,lon2
1033
      real      dist,sum
1034
      real      xmax
1035
      integer   periodic
1036
      integer   test
1037
      character ch
1038
 
1039
c     Numerical epsilon
1040
      real      eps
1041
      parameter (eps=0.01)
1042
 
1043
c     Externals
1044
      real      sdis,weight
1045
      external  sdis,weight
1046
 
1047
c     Check whether lat/lon point is valid
1048
      xmax=xmin+real(nx-1)*dx
1049
      if (lon.lt.xmin-eps) lon=lon+360.
1050
      if (lon.gt.xmax+eps) lon=lon-360.
1051
      if (abs(lat-90).lt.eps) lat=90.
1052
      if (abs(lat+90).lt.eps) lat=-90.
1053
      if ((abs(lat).gt.(90.+eps)).or.
1054
     >    (lon.lt.xmin-eps).or.(lon.gt.xmax+eps)) then
1055
         print*,'Invalid lat/lon point ',lat,lon
1056
         return
1057
      endif
1058
 
1059
c     Set flag for periodic domain
1060
      if (abs(xmax-xmin-360.).lt.eps) then
1061
         periodic=1
1062
      else if (abs(xmax-xmin-360+dx).lt.eps) then
1063
         periodic=2
1064
      else
1065
         periodic=0
1066
      endif
1067
 
1068
c     Get indices of one coarse grid point within search radius
1069
      i=nint((lon-xmin)/dx)+1
1070
      if ((i.eq.nx).and.(periodic.eq.1)) i=1
1071
      j=nint((lat-ymin)/dy)+1
1072
      lat2=ymin+real(j-1)*dy
1073
      lon2=xmin+real(i-1)*dx
1074
      dist=sdis(lon,lat,lon2,lat2,unit)
1075
      if (dist.gt.radius) then
1076
         print*,'1: Search radius is too small...'
1077
         stop
1078
      endif
1079
 
1080
c     Get connected points
1081
      k=0
1082
      stackx(1)=i
1083
      stacky(1)=j
1084
      sp    = 1
1085
      do while (sp.ne.0) 
1086
 
1087
c        Get an element from stack
1088
         n=stackx(sp)
1089
         m=stacky(sp)
1090
         sp=sp-1
1091
 
1092
c        Get distance from reference point
1093
         lat2=ymin+real(m-1)*dy
1094
         lon2=xmin+real(n-1)*dx
1095
         dist=sdis(lon,lat,lon2,lat2,unit)
1096
 
1097
c        Check whether distance is smaller than search radius: connected
1098
         if (dist.lt.radius) then
1099
 
1100
c           Make entry in filter mask
1101
            k=k+1
1102
            tab_x(k)=n
1103
            tab_y(k)=m
1104
            tab_r(k)=weight(dist,radius)
1105
 
1106
c           Mark this point as visited
1107
            connect(n,m)=connectval
1108
 
1109
c           Get coordinates of neighbouring points
1110
            nr=n+1
1111
            if ((nr.gt.nx)  .and.(periodic.eq.0)) nr=nx
1112
            if ((nr.gt.nx-1).and.(periodic.eq.1)) nr=1
1113
            if ((nr.gt.nx)  .and.(periodic.eq.2)) nr=1
1114
            nl=n-1
1115
            if ((nl.lt.1).and.(periodic.eq.0)) nl=1
1116
            if ((nl.lt.1).and.(periodic.eq.1)) nl=nx-1
1117
            if ((nl.lt.1).and.(periodic.eq.2)) nl=nx
1118
            mu=m+1
1119
            if (mu.gt.ny) mu=ny
1120
            md=m-1
1121
            if (md.lt.1) md=1
1122
 
1123
c           Update stack
1124
            if (connect(nr,m).ne.connectval) then
1125
               connect(nr,m)=connectval
1126
               sp=sp+1
1127
               stackx(sp)=nr
1128
               stacky(sp)=m
1129
            endif
1130
            if (connect(nl,m).ne.connectval) then
1131
               connect(nl,m)=connectval
1132
               sp=sp+1
1133
               stackx(sp)=nl
1134
               stacky(sp)=m
1135
            endif
1136
            if (connect(n,mu).ne.connectval) then
1137
               connect(n,mu)=connectval
1138
               sp=sp+1
1139
               stackx(sp)=n
1140
               stacky(sp)=mu
1141
            endif
1142
            if (connect(n,md).ne.connectval) then
1143
               connect(n,md)=connectval
1144
               sp=sp+1
1145
               stackx(sp)=n
1146
               stacky(sp)=md
1147
            endif
1148
         endif     
1149
 
1150
      end do
1151
 
1152
      if (k.ge.1) then
1153
         sum=0.
1154
         do i=1,k
1155
            sum=sum+tab_r(i)
1156
         enddo
1157
         do i=1,k
1158
            out (tab_x(i),tab_y(i))=out(tab_x(i),tab_y(i))+
1159
     >                             addval*tab_r(i)/sum
1160
            outc(tab_x(i),tab_y(i))=outc(tab_x(i),tab_y(i))+
1161
     >                             1.*tab_r(i)/sum
1162
 
1163
            if ((tab_x(i).eq.1).and.(periodic.eq.1)) then
1164
               out(nx,tab_y(i))=out(nx,tab_y(i))+
1165
     >                             addval*tab_r(i)/sum
1166
               outc(nx,tab_y(i))=outc(nx,tab_y(i))+
1167
     >                             1.*tab_r(i)/sum
1168
 
1169
            endif
1170
         enddo
1171
      else
1172
         print*,'2: Search radius is too small...'
1173
         stop
1174
      endif
1175
 
1176
      end
1177
 
1178
 
1179
c     ----------------------------------------------------------------------
1180
c     Get spherical distance between lat/lon points
1181
c     ----------------------------------------------------------------------
15 michaesp 1182
 
2 michaesp 1183
      real function sdis(xp,yp,xq,yq,unit)
1184
 
1185
c     Calculates spherical distance (in km) between two points given
1186
c     by their spherical coordinates (xp,yp) and (xq,yq), respectively.
1187
 
1188
      real,parameter ::       re=6371.229
1189
      real,parameter ::       rad2deg=180./3.14159265
1190
      real,parameter ::       deg2rad=3.141592654/180.
1191
 
1192
      real         xp,yp,xq,yq,arg
1193
      character*80 unit
1194
      real         dlon,dlat,alpha,rlat1,ralt2
1195
 
1196
      if ( unit.eq.'km' ) then
1197
 
15 michaesp 1198
         arg=sin(yp*deg2rad)*sin(yq*deg2rad)+
1199
     >           cos(yp*deg2rad)*cos(yq*deg2rad)*cos((xp-xq)*deg2rad)
2 michaesp 1200
         if (arg.lt.-1.) arg=-1.
1201
         if (arg.gt.1.) arg=1.
1202
         sdis=re*acos(arg)
1203
 
1204
      elseif ( unit.eq.'deg' ) then
1205
 
1206
         dlon = xp-xq
1207
         if ( dlon.gt. 180. ) dlon = dlon - 360.
1208
         if ( dlon.lt.-180. ) dlon = dlon + 360.
1209
         sdis = sqrt( dlon**2 + (yp-yq)**2 )
1210
 
1211
      elseif ( unit.eq.'km.haversine' ) then
1212
 
1213
        dlat   =  (yp - yq)*deg2rad
1214
        dlon   =  (xp - xq)*deg2rad
1215
        rlat1   =  yp*deg2rad
1216
        rlat2   =  yq*deg2rad
1217
 
1218
        alpha  = ( sin(0.5*dlat)**2 ) +
1219
     >           ( sin(0.5*dlon)**2 )*cos(rlat1)*cos(rlat2)
1220
 
1221
        sdis = 4. * re * atan2( sqrt(alpha),1. + sqrt( 1. - alpha ) )
1222
 
1223
      endif  
1224
 
1225
      end
1226
 
1227
c     ----------------------------------------------------------------------
1228
c     Weight function for the filter mask
1229
c     ----------------------------------------------------------------------
1230
 
1231
      real function weight (r,radius)
1232
 
1233
c     Attribute to each distanc r its corresponding weight in the filter mask
1234
 
1235
      implicit none
1236
 
1237
c     Declaration of subroutine parameters
1238
      real r
1239
      real radius
1240
 
1241
c     Simple 0/1 mask
1242
      if (r.lt.radius) then
1243
          weight=1.-0.65*r/radius 
1244
      else
1245
          weight=0.
1246
      endif
1247
 
1248
      end
1249
 
1250
 
1251
c     ********************************************************************
1252
c     * INPUT / OUTPUT SUBROUTINES                                       *
1253
c     ********************************************************************
1254
 
1255
c     --------------------------------------------------------------------
1256
c     Subroutines to write the netcdf output file
1257
c     --------------------------------------------------------------------
1258
 
1259
      subroutine writecdf2D(cdfname,
1260
     >                      varname,arr,time,
1261
     >                      dx,dy,xmin,ymin,nx,ny,nz,
1262
     >                      crefile,crevar)
1263
 
1264
      IMPLICIT NONE
1265
 
1266
c     Declaration of input parameters
1267
      character*80 cdfname,varname
1268
      integer nx,ny,nz
1269
      real arr(nx,ny,nz)
1270
      real dx,dy,xmin,ymin
1271
      real time
1272
      integer crefile,crevar
1273
 
1274
c     Further variables
1275
      real varmin(4),varmax(4),stag(4)
1276
      integer ierr,cdfid,ndim,vardim(4)
1277
      character*80 cstname
1278
      real mdv
1279
      integer i
11 michaesp 1280
      integer nvars
1281
      character*80 vars(300)
2 michaesp 1282
 
1283
C     Definitions
1284
      varmin(1)=xmin
1285
      varmin(2)=ymin
1286
      varmin(3)=1050.
1287
      varmax(1)=xmin+real(nx-1)*dx
1288
      varmax(2)=ymin+real(ny-1)*dy
1289
      varmax(3)=1050.
1290
      cstname='no_constants_file'
1291
      ndim=4
1292
      vardim(1)=nx
1293
      vardim(2)=ny
1294
      vardim(3)=nz
1295
      stag(1)=0.
1296
      stag(2)=0.
1297
      stag(3)=0.
1298
      mdv=-999.98999
1299
 
1300
C     Create the file
1301
      if (crefile.eq.0) then
1302
         call cdfwopn(cdfname,cdfid,ierr)
1303
         if (ierr.ne.0) goto 906
1304
      else if (crefile.eq.1) then
1305
         call crecdf(cdfname,cdfid,
1306
     >        varmin,varmax,ndim,cstname,ierr)
1307
         if (ierr.ne.0) goto 903
1308
      endif
1309
 
11 michaesp 1310
c     Check whether the variable is already on the file
1311
      call getvars(cdfid,nvars,vars,ierr)
1312
      if (ierr.ne.0) goto 906
1313
      do i=1,nvars
1314
         if ( vars(i).eq.varname ) crevar = 0
1315
      enddo
1316
 
2 michaesp 1317
c     Write the data to the netcdf file, and close the file
1318
      if (crevar.eq.1) then
1319
         call putdef(cdfid,varname,ndim,mdv,
1320
     >        vardim,varmin,varmax,stag,ierr)
1321
         if (ierr.ne.0) goto 904
1322
      endif
1323
      call putdat(cdfid,varname,time,0,arr,ierr)
1324
      if (ierr.ne.0) goto 905
1325
      call clscdf(cdfid,ierr)
1326
 
1327
      return
1328
 
1329
c     Error handling
1330
 903  print*,'*** Problem to create netcdf file ***'
1331
      stop
1332
 904  print*,'*** Problem to write definition ***'
1333
      stop
1334
 905  print*,'*** Problem to write data ***'
1335
      stop
1336
 906  print*,'*** Problem to open netcdf file ***'
1337
      stop
1338
 
1339
      end
1340
 
1341
 
1342
c     -----------------------------------------------
1343
c     Subroutine to read a netcdf output file
1344
c     -----------------------------------------------
1345
 
1346
      subroutine readcdf2D(cdfname,varname,arr,time,
1347
     >                     dx,dy,xmin,ymin,nx,ny,nz)
1348
 
1349
      implicit none
1350
 
1351
c     Declaration of input parameters
1352
      character*80 cdfname,varname
1353
      integer      nx,ny,nz
1354
      real         arr(nx,ny,nz)
1355
      real         dx,dy,xmin,ymin
1356
      real         time
1357
 
1358
c     Internal variables for the netcdf file
1359
      real         varmin(4),varmax(4),stag(4)
1360
      integer      ierr,cdfid,ndim,vardim(4)
1361
      real         mdv
1362
      real         delx,dely
1363
      real         times(500)
1364
      integer      ntimes,flag
1365
 
1366
c     Numerical epsilon
1367
      real         eps
1368
      parameter    (eps=0.01)
1369
 
1370
c     Auxiliary variables
1371
      integer      i,j,k
1372
 
1373
c     Initialize the ouput array
1374
      do i=1,nx
1375
         do j=1,ny
1376
            do k=1,nz
1377
               arr(i,j,k)=0.
1378
            enddo
1379
         enddo
1380
      enddo
1381
 
1382
c     Try to open the netcdf file and to read the variable
1383
      call cdfopn(cdfname,cdfid,ierr)
1384
      if (ierr.ne.0) goto 801
1385
 
1386
c     Check whether the specifieed time is available
1387
      call gettimes(cdfid,times,ntimes,ierr)
1388
      if (ierr.ne.0) goto 801
1389
      flag=0
1390
      do i=1,ntimes
1391
          if (abs(times(i)-time).lt.eps) flag=1
1392
      enddo
1393
      if (flag.eq.0) then
1394
         print*,'No such time on cdf',time
1395
         stop
1396
      endif
1397
 
1398
c     Get the variable definition, and the grid
1399
      call getdef(cdfid,varname,ndim,mdv,vardim,varmin,varmax,
1400
     >     stag,ierr)
1401
      if (ierr.ne.0) goto 801
1402
 
1403
c     Set parameters or read parameters - depending on nx,ny
1404
      if ( (nx.eq.1).and.(ny.eq.1) ) then
1405
         dx   = (varmax(1)-varmin(1))/real(vardim(1)-1)
1406
         dy   = (varmax(2)-varmin(2))/real(vardim(2)-1)
1407
         nx   = vardim(1)
1408
         ny   = vardim(2)
1409
         nz   = vardim(3)
1410
         xmin = varmin(1)
1411
         ymin = varmin(2)
1412
      else
1413
         call getdat(cdfid,varname,time,0,arr,ierr)
1414
         if (ierr.ne.0) goto 801
1415
      endif
1416
 
1417
c     Close data file
1418
      call clscdf(cdfid,ierr)
1419
 
1420
      return
1421
 
1422
c     Exception handling
1423
 801  print*,'Problems in reading netcdf file'
1424
      stop
1425
 
1426
      end
1427
 
1428
 
11 michaesp 1429
c     -----------------------------------------------
1430
c     Diffusive filter
1431
c     -----------------------------------------------
2 michaesp 1432
 
11 michaesp 1433
      subroutine filt2d (a,af,nx,ny,fil,misdat,
1434
     &                   iperx,ipery,ispol,inpol)
2 michaesp 1435
 
11 michaesp 1436
c     Apply a conservative diffusion operator onto the 2d field a,
1437
c     with full missing data checking.
1438
c
1439
c     a     real   inp  array to be filtered, dimensioned (nx,ny)
1440
c     af    real   out  filtered array, dimensioned (nx,ny), can be
1441
c                       equivalenced with array a in the calling routine
1442
c     f1    real        workarray, dimensioned (nx+1,ny)
1443
c     f2    real        workarray, dimensioned (nx,ny+1)
1444
c     fil   real   inp  filter-coeff., 0<afil<=1. Maximum filtering with afil=1
1445
c                       corresponds to one application of the linear filter.
1446
c     misdat real  inp  missing-data value, a(i,j)=misdat indicates that
1447
c                       the corresponding value is not available. The
1448
c                       misdat-checking can be switched off with with misdat=0.
1449
c     iperx int    inp  periodic boundaries in the x-direction (1=yes,0=no)
1450
c     ipery int    inp  periodic boundaries in the y-direction (1=yes,0=no)
1451
c     inpol int    inp  northpole at j=ny  (1=yes,0=no)
1452
c     ispol int    inp  southpole at j=1   (1=yes,0=no)
1453
c
1454
c     Christoph Schaer, 1993
2 michaesp 1455
 
11 michaesp 1456
c     argument declaration
1457
      integer     nx,ny
1458
      real        a(nx,ny),af(nx,ny),fil,misdat
1459
      integer     iperx,ipery,inpol,ispol
2 michaesp 1460
 
11 michaesp 1461
c     local variable declaration
1462
      integer     i,j,is
1463
      real        fh
1464
      real        f1(nx+1,ny),f2(nx,ny+1)
2 michaesp 1465
 
11 michaesp 1466
c     compute constant fh
1467
      fh=0.125*fil
2 michaesp 1468
 
11 michaesp 1469
c     compute fluxes in x-direction
1470
      if (misdat.eq.0.) then
1471
        do j=1,ny
1472
        do i=2,nx
1473
          f1(i,j)=a(i-1,j)-a(i,j)
1474
        enddo
1475
        enddo
1476
      else
1477
        do j=1,ny
1478
        do i=2,nx
1479
          if ((a(i,j).eq.misdat).or.(a(i-1,j).eq.misdat)) then
1480
            f1(i,j)=0.
1481
          else
1482
            f1(i,j)=a(i-1,j)-a(i,j)
1483
          endif
1484
        enddo
1485
        enddo
1486
      endif
1487
      if (iperx.eq.1) then
1488
c       do periodic boundaries in the x-direction
1489
        do j=1,ny
1490
          f1(1,j)=f1(nx,j)
1491
          f1(nx+1,j)=f1(2,j)
1492
        enddo
1493
      else
1494
c       set boundary-fluxes to zero
1495
        do j=1,ny
1496
          f1(1,j)=0.
1497
          f1(nx+1,j)=0.
1498
        enddo
1499
      endif
2 michaesp 1500
 
11 michaesp 1501
c     compute fluxes in y-direction
1502
      if (misdat.eq.0.) then
1503
        do j=2,ny
1504
        do i=1,nx
1505
          f2(i,j)=a(i,j-1)-a(i,j)
1506
        enddo
1507
        enddo
1508
      else
1509
        do j=2,ny
1510
        do i=1,nx
1511
          if ((a(i,j).eq.misdat).or.(a(i,j-1).eq.misdat)) then
1512
            f2(i,j)=0.
1513
          else
1514
            f2(i,j)=a(i,j-1)-a(i,j)
1515
          endif
1516
        enddo
1517
        enddo
1518
      endif
1519
c     set boundary-fluxes to zero
1520
      do i=1,nx
1521
        f2(i,1)=0.
1522
        f2(i,ny+1)=0.
1523
      enddo
1524
      if (ipery.eq.1) then
1525
c       do periodic boundaries in the x-direction
1526
        do i=1,nx
1527
          f2(i,1)=f2(i,ny)
1528
          f2(i,ny+1)=f2(i,2)
1529
        enddo
1530
      endif
1531
      if (iperx.eq.1) then
1532
        if (ispol.eq.1) then
1533
c         do south-pole
1534
          is=(nx-1)/2
1535
          do i=1,nx
1536
            f2(i,1)=-f2(mod(i-1+is,nx)+1,2)
1537
          enddo
1538
        endif
1539
        if (inpol.eq.1) then
1540
c         do north-pole
1541
          is=(nx-1)/2
1542
          do i=1,nx
1543
            f2(i,ny+1)=-f2(mod(i-1+is,nx)+1,ny)
1544
          enddo
1545
        endif
1546
      endif
2 michaesp 1547
 
11 michaesp 1548
c     compute flux-convergence -> filter
1549
      if (misdat.eq.0.) then
1550
        do j=1,ny
1551
        do i=1,nx
1552
            af(i,j)=a(i,j)+fh*(f1(i,j)-f1(i+1,j)+f2(i,j)-f2(i,j+1))
1553
        enddo
1554
        enddo
1555
      else
1556
        do j=1,ny
1557
        do i=1,nx
1558
          if (a(i,j).eq.misdat) then
1559
            af(i,j)=misdat
1560
          else
1561
            af(i,j)=a(i,j)+fh*(f1(i,j)-f1(i+1,j)+f2(i,j)-f2(i,j+1))
1562
          endif
1563
        enddo
1564
        enddo
1565
      endif
1566
      end
2 michaesp 1567
 
1568
 
1569
 
1570
 
1571
 
1572
 
1573
 
1574
 
1575
 
1576
 
1577
 
1578
 
1579
 
1580
 
1581
 
1582
 
1583
 
1584
 
1585
 
11 michaesp 1586
 
1587
 
1588
 
1589
 
1590
 
1591
 
1592