Subversion Repositories lagranto.wrf

Rev

Rev 8 | 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
48
      real,allocatable,dimension (:,:)  :: connect1 
49
      integer      connectval1 
50
      real,allocatable,dimension (:,:)  :: connect2 
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 
238
 
239
c     Transform grid specifier into grid coordinates
240
      xmin = 1.
241
      ymin = 1.
242
      dx   = 1.
243
      dy   = 1.
244
 
245
c     Allocate memory for lon/lat on numerical grid
246
      allocate(lon(nx,ny),stat=stat)
247
      if (stat.ne.0) print*,'*** error allocating array lon ***'
248
      allocate(lat(nx,ny),stat=stat)
249
      if (stat.ne.0) print*,'*** error allocating array lat ***'
250
      allocate(p3(nx,ny,nz),stat=stat)
251
      if (stat.ne.0) print*,'*** error allocating array p3  ***'
252
      allocate(z3(nx,ny,nz),stat=stat)
253
      if (stat.ne.0) print*,'*** error allocating array z3  ***'
254
      allocate(zb(nx,ny),stat=stat)
255
      if (stat.ne.0) print*,'*** error allocating array zb  ***'
256
 
257
c     Read lon/lat on the model grid
258
      varname='XLONG'
259
      call input_var_wrf(fid,varname,lon,nx,ny,1)
260
      varname='XLAT'
261
      call input_var_wrf(fid,varname,lat,nx,ny,1)
262
      varname='pressure'
263
      call input_var_wrf(fid,varname,p3 ,nx,ny,nz)
264
      varname='geopot'
265
      call input_var_wrf(fid,varname,z3 ,nx,ny,nz)
266
      varname='geopots'
267
      call input_var_wrf(fid,varname,zb ,nx,ny,1)
268
 
269
c     Transform longitude depending on <anglemode>
270
      if ( anglemode.eq.'greenwich' ) then
271
         do i=1,nx
272
           do j=1,ny
273
              if ( lon(i,j).lt.0. ) lon(i,j) = lon(i,j) + 360.
274
            enddo
275
         enddo
276
      elseif ( anglemode.eq.'dateline' ) then
277
         do i=1,nx
278
            do j=1,ny
279
               if ( lon(i,j).gt.180. ) lon(i,j) = lon(i,j) - 360.
280
            enddo
281
         enddo
282
      else
283
         print*,' ERROR: unsupported angle mode... Stop'
284
         stop
285
      endif
286
 
287
c     Close input file file
288
      call input_close(fid)
289
 
290
c     Check for 'date line' and for pole
291
      do i=2,nx
292
      do j=1,ny
293
        if ( abs( lat(i,j) ).gt.90. ) then
294
           print*,' ERROR: mapping over pole not supported... Stop'
295
           stop
296
        endif
297
        if ( abs( lon(i,j)-lon(i-1,j) ).gt.180. ) then
298
           print*,' ERROR: mapping over date line not supported... Stop'
299
           stop
300
        endif
301
      enddo
302
      enddo
303
 
304
c     Determine the extreme coordinates
305
      latmin  = lat(1,1)
306
      latmax  = lat(1,1)
307
      lonmin  = lon(1,1)
308
      lonmax  = lon(1,1)
309
      do i=1,nx
310
	    do j=1,ny
311
          if ( lat(i,j).lt.latmin ) latmin = lat(i,j)
312
          if ( lat(i,j).gt.latmax ) latmax = lat(i,j)
313
          if ( lon(i,j).lt.lonmin ) lonmin = lon(i,j)
314
          if ( lon(i,j).gt.lonmax ) lonmax = lon(i,j)
315
        enddo
316
      enddo
317
 
318
      print*,' lonmin,max = ',lonmin,lonmax
319
      print*,' latmin,max = ',latmin,latmax
320
 
321
c     Determine the extreme dlon/dlat spacing
322
      dlon = abs( lon(2,1)-lon(1,1) )
323
      do i=2,nx
324
	    do j=1,ny
325
           if ( abs( lon(i,j)-lon(i-1,j) ).lt.dlon ) then
326
              dlon = abs( lon(i,j)-lon(i-1,j) )
327
           endif
328
         enddo
329
      enddo
330
      dlat = abs( lat(1,2)-lat(1,1) )
331
      do i=1,nx
332
	    do j=2,ny
333
           if ( abs( lat(i,j)-lat(i,j-1) ).lt.dlat ) then
334
              dlat = abs( lat(i,j)-lat(i,j-1) )
335
           endif
336
         enddo
337
      enddo
338
 
339
c     Set dimension of geographical grid 
340
      nlon   = ceiling( (lonmax-lonmin) / dlon + 1. )
341
      nlat   = ceiling( (latmax-latmin) / dlat + 1. )
342
      lonmax = lonmin + real(nlon-1) * dlon
343
      latmax = latmin + real(nlat-1) * dlat
344
 
345
      print*,' dlon,dlat  = ',dlon,dlat
346
      print*,' nlon,nlat  = ',nlon,nlat
347
 
348
c     Allocate memory for x/y on geographical grid
349
      allocate(x(nlon,nlat),stat=stat)
350
      if (stat.ne.0) print*,'*** error allocating array x       ***'
351
      allocate(y(nlon,nlat),stat=stat)
352
      if (stat.ne.0) print*,'*** error allocating array y       ***'
353
      allocate(connect1(nlon,nlat),stat=stat)
354
      if (stat.ne.0) print*,'*** error allocating array connect1***'
355
      allocate(connect2(nlon,nlat),stat=stat)
356
      if (stat.ne.0) print*,'*** error allocating array connect2***'
357
      allocate(xc(nlon,nlat),stat=stat)
358
      if (stat.ne.0) print*,'*** error allocating array xc      ***'
359
      allocate(yc(nlon,nlat),stat=stat)
360
      if (stat.ne.0) print*,'*** error allocating array yc      ***'
361
 
362
c     Init the mapping arrays
363
      connectval1 = 0
364
      connectval2 = 0
365
      do i=1,nlon
366
	do j=1,nlat
367
           x(i,j)        = 0.
368
           y(i,j)        = 0.
369
           xc(i,j)       = 0.
370
           yc(i,j)       = 0.
371
           connect1(i,j) = 1
372
           connect2(i,j) = 1
373
        enddo
374
      enddo
375
 
376
c     Get the good radius for gridding - avoiding gaps
377
      radunit = 'deg'
378
      radius  = 0.
379
      do i=2,nx
380
        do j=2,ny
381
           if ( abs( lat(i,j)-lat(i,j-1) ).gt.radius ) then
382
              radius = abs( lat(i,j)-lat(i,j-1) )
383
           endif
384
           if ( abs( lon(i,j)-lon(i-1,j) ).gt.radius ) then
385
              radius = abs( lon(i,j)-lon(i-1,j) )
386
           endif
387
        enddo
388
      enddo
389
      radius = 3. * radius 
390
 
391
c     Do the mapping
392
      do i=1,nx
393
	do j=1,ny
394
 
395
          connectval1 = connectval1 + 1
396
          call gridding1(lat(i,j),lon(i,j),real(i),radius,radunit,
397
     >                   connect1,connectval1,
398
     >                   x,xc,nlon,nlat,lonmin,latmin,dlon,dlat)
399
 
400
          connectval2 = connectval2 + 1
401
          call gridding1(lat(i,j),lon(i,j),real(j),radius,radunit,
402
     >                   connect2,connectval2,
403
     >                   y,yc,nlon,nlat,lonmin,latmin,dlon,dlat)
404
 
405
 
406
	enddo
407
      enddo
408
 
409
c     Normalize output and set miising data flag
410
      do i=1,nlon
411
         do j=1,nlat
412
            if ( xc(i,j).gt.0. ) then
413
               x(i,j) = x(i,j)/xc(i,j)
414
            else
415
               x(i,j) = mdv
416
            endif
417
            if ( yc(i,j).gt.0. ) then
418
               y(i,j) = y(i,j)/yc(i,j)
419
            else
420
               y(i,j) = mdv
421
            endif
422
         enddo
423
      enddo
424
 
425
c     Write data to netCDF
426
      cdfname = mapfile
427
      varname = 'X'
428
      call writecdf2D(cdfname,varname,x,0.,
429
     >                dlon,dlat,lonmin,latmin,nlon,nlat,1,1,1)
430
 
431
      cdfname = mapfile
432
      varname = 'Y'
433
      call writecdf2D(cdfname,varname,y,0.,
434
     >                dlon,dlat,lonmin,latmin,nlon,nlat,1,0,1)
435
 
436
      cdfname = mapfile
437
      varname = 'LON'
438
      call writecdf2D(cdfname,varname,lon,0.,
439
     >                dx,dy,xmin,ymin,nx,ny,1,0,1)
440
 
441
      cdfname = mapfile
442
      varname = 'LAT'
443
      call writecdf2D(cdfname,varname,lat,0.,
444
     >                dx,dy,xmin,ymin,nx,ny,1,0,1)
445
 
446
      cdfname = mapfile
447
      varname = 'Z'
448
      call writecdf2D(cdfname,varname,z3,0.,
449
     >                dx,dy,xmin,ymin,nx,ny,nz,0,1)
450
 
451
      cdfname = mapfile
452
      varname = 'P'
453
      call writecdf2D(cdfname,varname,p3,0.,
454
     >                dx,dy,xmin,ymin,nx,ny,nz,0,1)
455
 
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     ----------------------------------------------------------------------
1182
 
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
 
1198
         arg=sind(yp)*sind(yq)+cosd(yp)*cosd(yq)*cosd(xp-xq)
1199
         if (arg.lt.-1.) arg=-1.
1200
         if (arg.gt.1.) arg=1.
1201
         sdis=re*acos(arg)
1202
 
1203
      elseif ( unit.eq.'deg' ) then
1204
 
1205
         dlon = xp-xq
1206
         if ( dlon.gt. 180. ) dlon = dlon - 360.
1207
         if ( dlon.lt.-180. ) dlon = dlon + 360.
1208
         sdis = sqrt( dlon**2 + (yp-yq)**2 )
1209
 
1210
      elseif ( unit.eq.'km.haversine' ) then
1211
 
1212
        dlat   =  (yp - yq)*deg2rad
1213
        dlon   =  (xp - xq)*deg2rad
1214
        rlat1   =  yp*deg2rad
1215
        rlat2   =  yq*deg2rad
1216
 
1217
        alpha  = ( sin(0.5*dlat)**2 ) +
1218
     >           ( sin(0.5*dlon)**2 )*cos(rlat1)*cos(rlat2)
1219
 
1220
        sdis = 4. * re * atan2( sqrt(alpha),1. + sqrt( 1. - alpha ) )
1221
 
1222
      endif  
1223
 
1224
      end
1225
 
1226
c     ----------------------------------------------------------------------
1227
c     Weight function for the filter mask
1228
c     ----------------------------------------------------------------------
1229
 
1230
      real function weight (r,radius)
1231
 
1232
c     Attribute to each distanc r its corresponding weight in the filter mask
1233
 
1234
      implicit none
1235
 
1236
c     Declaration of subroutine parameters
1237
      real r
1238
      real radius
1239
 
1240
c     Simple 0/1 mask
1241
      if (r.lt.radius) then
1242
          weight=1.-0.65*r/radius 
1243
      else
1244
          weight=0.
1245
      endif
1246
 
1247
      end
1248
 
1249
 
1250
c     ********************************************************************
1251
c     * INPUT / OUTPUT SUBROUTINES                                       *
1252
c     ********************************************************************
1253
 
1254
c     --------------------------------------------------------------------
1255
c     Subroutines to write the netcdf output file
1256
c     --------------------------------------------------------------------
1257
 
1258
      subroutine writecdf2D(cdfname,
1259
     >                      varname,arr,time,
1260
     >                      dx,dy,xmin,ymin,nx,ny,nz,
1261
     >                      crefile,crevar)
1262
 
1263
      IMPLICIT NONE
1264
 
1265
c     Declaration of input parameters
1266
      character*80 cdfname,varname
1267
      integer nx,ny,nz
1268
      real arr(nx,ny,nz)
1269
      real dx,dy,xmin,ymin
1270
      real time
1271
      integer crefile,crevar
1272
 
1273
c     Further variables
1274
      real varmin(4),varmax(4),stag(4)
1275
      integer ierr,cdfid,ndim,vardim(4)
1276
      character*80 cstname
1277
      real mdv
1278
      integer i
11 michaesp 1279
      integer nvars
1280
      character*80 vars(300)
2 michaesp 1281
 
1282
C     Definitions
1283
      varmin(1)=xmin
1284
      varmin(2)=ymin
1285
      varmin(3)=1050.
1286
      varmax(1)=xmin+real(nx-1)*dx
1287
      varmax(2)=ymin+real(ny-1)*dy
1288
      varmax(3)=1050.
1289
      cstname='no_constants_file'
1290
      ndim=4
1291
      vardim(1)=nx
1292
      vardim(2)=ny
1293
      vardim(3)=nz
1294
      stag(1)=0.
1295
      stag(2)=0.
1296
      stag(3)=0.
1297
      mdv=-999.98999
1298
 
1299
C     Create the file
1300
      if (crefile.eq.0) then
1301
         call cdfwopn(cdfname,cdfid,ierr)
1302
         if (ierr.ne.0) goto 906
1303
      else if (crefile.eq.1) then
1304
         call crecdf(cdfname,cdfid,
1305
     >        varmin,varmax,ndim,cstname,ierr)
1306
         if (ierr.ne.0) goto 903
1307
      endif
1308
 
11 michaesp 1309
c     Check whether the variable is already on the file
1310
      call getvars(cdfid,nvars,vars,ierr)
1311
      if (ierr.ne.0) goto 906
1312
      do i=1,nvars
1313
         if ( vars(i).eq.varname ) crevar = 0
1314
      enddo
1315
 
2 michaesp 1316
c     Write the data to the netcdf file, and close the file
1317
      if (crevar.eq.1) then
1318
         call putdef(cdfid,varname,ndim,mdv,
1319
     >        vardim,varmin,varmax,stag,ierr)
1320
         if (ierr.ne.0) goto 904
1321
      endif
1322
      call putdat(cdfid,varname,time,0,arr,ierr)
1323
      if (ierr.ne.0) goto 905
1324
      call clscdf(cdfid,ierr)
1325
 
1326
      return
1327
 
1328
c     Error handling
1329
 903  print*,'*** Problem to create netcdf file ***'
1330
      stop
1331
 904  print*,'*** Problem to write definition ***'
1332
      stop
1333
 905  print*,'*** Problem to write data ***'
1334
      stop
1335
 906  print*,'*** Problem to open netcdf file ***'
1336
      stop
1337
 
1338
      end
1339
 
1340
 
1341
c     -----------------------------------------------
1342
c     Subroutine to read a netcdf output file
1343
c     -----------------------------------------------
1344
 
1345
      subroutine readcdf2D(cdfname,varname,arr,time,
1346
     >                     dx,dy,xmin,ymin,nx,ny,nz)
1347
 
1348
      implicit none
1349
 
1350
c     Declaration of input parameters
1351
      character*80 cdfname,varname
1352
      integer      nx,ny,nz
1353
      real         arr(nx,ny,nz)
1354
      real         dx,dy,xmin,ymin
1355
      real         time
1356
 
1357
c     Internal variables for the netcdf file
1358
      real         varmin(4),varmax(4),stag(4)
1359
      integer      ierr,cdfid,ndim,vardim(4)
1360
      real         mdv
1361
      real         delx,dely
1362
      real         times(500)
1363
      integer      ntimes,flag
1364
 
1365
c     Numerical epsilon
1366
      real         eps
1367
      parameter    (eps=0.01)
1368
 
1369
c     Auxiliary variables
1370
      integer      i,j,k
1371
 
1372
c     Initialize the ouput array
1373
      do i=1,nx
1374
         do j=1,ny
1375
            do k=1,nz
1376
               arr(i,j,k)=0.
1377
            enddo
1378
         enddo
1379
      enddo
1380
 
1381
c     Try to open the netcdf file and to read the variable
1382
      call cdfopn(cdfname,cdfid,ierr)
1383
      if (ierr.ne.0) goto 801
1384
 
1385
c     Check whether the specifieed time is available
1386
      call gettimes(cdfid,times,ntimes,ierr)
1387
      if (ierr.ne.0) goto 801
1388
      flag=0
1389
      do i=1,ntimes
1390
          if (abs(times(i)-time).lt.eps) flag=1
1391
      enddo
1392
      if (flag.eq.0) then
1393
         print*,'No such time on cdf',time
1394
         stop
1395
      endif
1396
 
1397
c     Get the variable definition, and the grid
1398
      call getdef(cdfid,varname,ndim,mdv,vardim,varmin,varmax,
1399
     >     stag,ierr)
1400
      if (ierr.ne.0) goto 801
1401
 
1402
c     Set parameters or read parameters - depending on nx,ny
1403
      if ( (nx.eq.1).and.(ny.eq.1) ) then
1404
         dx   = (varmax(1)-varmin(1))/real(vardim(1)-1)
1405
         dy   = (varmax(2)-varmin(2))/real(vardim(2)-1)
1406
         nx   = vardim(1)
1407
         ny   = vardim(2)
1408
         nz   = vardim(3)
1409
         xmin = varmin(1)
1410
         ymin = varmin(2)
1411
      else
1412
         call getdat(cdfid,varname,time,0,arr,ierr)
1413
         if (ierr.ne.0) goto 801
1414
      endif
1415
 
1416
c     Close data file
1417
      call clscdf(cdfid,ierr)
1418
 
1419
      return
1420
 
1421
c     Exception handling
1422
 801  print*,'Problems in reading netcdf file'
1423
      stop
1424
 
1425
      end
1426
 
1427
 
11 michaesp 1428
c     -----------------------------------------------
1429
c     Diffusive filter
1430
c     -----------------------------------------------
2 michaesp 1431
 
11 michaesp 1432
      subroutine filt2d (a,af,nx,ny,fil,misdat,
1433
     &                   iperx,ipery,ispol,inpol)
2 michaesp 1434
 
11 michaesp 1435
c     Apply a conservative diffusion operator onto the 2d field a,
1436
c     with full missing data checking.
1437
c
1438
c     a     real   inp  array to be filtered, dimensioned (nx,ny)
1439
c     af    real   out  filtered array, dimensioned (nx,ny), can be
1440
c                       equivalenced with array a in the calling routine
1441
c     f1    real        workarray, dimensioned (nx+1,ny)
1442
c     f2    real        workarray, dimensioned (nx,ny+1)
1443
c     fil   real   inp  filter-coeff., 0<afil<=1. Maximum filtering with afil=1
1444
c                       corresponds to one application of the linear filter.
1445
c     misdat real  inp  missing-data value, a(i,j)=misdat indicates that
1446
c                       the corresponding value is not available. The
1447
c                       misdat-checking can be switched off with with misdat=0.
1448
c     iperx int    inp  periodic boundaries in the x-direction (1=yes,0=no)
1449
c     ipery int    inp  periodic boundaries in the y-direction (1=yes,0=no)
1450
c     inpol int    inp  northpole at j=ny  (1=yes,0=no)
1451
c     ispol int    inp  southpole at j=1   (1=yes,0=no)
1452
c
1453
c     Christoph Schaer, 1993
2 michaesp 1454
 
11 michaesp 1455
c     argument declaration
1456
      integer     nx,ny
1457
      real        a(nx,ny),af(nx,ny),fil,misdat
1458
      integer     iperx,ipery,inpol,ispol
2 michaesp 1459
 
11 michaesp 1460
c     local variable declaration
1461
      integer     i,j,is
1462
      real        fh
1463
      real        f1(nx+1,ny),f2(nx,ny+1)
2 michaesp 1464
 
11 michaesp 1465
c     compute constant fh
1466
      fh=0.125*fil
2 michaesp 1467
 
11 michaesp 1468
c     compute fluxes in x-direction
1469
      if (misdat.eq.0.) then
1470
        do j=1,ny
1471
        do i=2,nx
1472
          f1(i,j)=a(i-1,j)-a(i,j)
1473
        enddo
1474
        enddo
1475
      else
1476
        do j=1,ny
1477
        do i=2,nx
1478
          if ((a(i,j).eq.misdat).or.(a(i-1,j).eq.misdat)) then
1479
            f1(i,j)=0.
1480
          else
1481
            f1(i,j)=a(i-1,j)-a(i,j)
1482
          endif
1483
        enddo
1484
        enddo
1485
      endif
1486
      if (iperx.eq.1) then
1487
c       do periodic boundaries in the x-direction
1488
        do j=1,ny
1489
          f1(1,j)=f1(nx,j)
1490
          f1(nx+1,j)=f1(2,j)
1491
        enddo
1492
      else
1493
c       set boundary-fluxes to zero
1494
        do j=1,ny
1495
          f1(1,j)=0.
1496
          f1(nx+1,j)=0.
1497
        enddo
1498
      endif
2 michaesp 1499
 
11 michaesp 1500
c     compute fluxes in y-direction
1501
      if (misdat.eq.0.) then
1502
        do j=2,ny
1503
        do i=1,nx
1504
          f2(i,j)=a(i,j-1)-a(i,j)
1505
        enddo
1506
        enddo
1507
      else
1508
        do j=2,ny
1509
        do i=1,nx
1510
          if ((a(i,j).eq.misdat).or.(a(i,j-1).eq.misdat)) then
1511
            f2(i,j)=0.
1512
          else
1513
            f2(i,j)=a(i,j-1)-a(i,j)
1514
          endif
1515
        enddo
1516
        enddo
1517
      endif
1518
c     set boundary-fluxes to zero
1519
      do i=1,nx
1520
        f2(i,1)=0.
1521
        f2(i,ny+1)=0.
1522
      enddo
1523
      if (ipery.eq.1) then
1524
c       do periodic boundaries in the x-direction
1525
        do i=1,nx
1526
          f2(i,1)=f2(i,ny)
1527
          f2(i,ny+1)=f2(i,2)
1528
        enddo
1529
      endif
1530
      if (iperx.eq.1) then
1531
        if (ispol.eq.1) then
1532
c         do south-pole
1533
          is=(nx-1)/2
1534
          do i=1,nx
1535
            f2(i,1)=-f2(mod(i-1+is,nx)+1,2)
1536
          enddo
1537
        endif
1538
        if (inpol.eq.1) then
1539
c         do north-pole
1540
          is=(nx-1)/2
1541
          do i=1,nx
1542
            f2(i,ny+1)=-f2(mod(i-1+is,nx)+1,ny)
1543
          enddo
1544
        endif
1545
      endif
2 michaesp 1546
 
11 michaesp 1547
c     compute flux-convergence -> filter
1548
      if (misdat.eq.0.) then
1549
        do j=1,ny
1550
        do i=1,nx
1551
            af(i,j)=a(i,j)+fh*(f1(i,j)-f1(i+1,j)+f2(i,j)-f2(i,j+1))
1552
        enddo
1553
        enddo
1554
      else
1555
        do j=1,ny
1556
        do i=1,nx
1557
          if (a(i,j).eq.misdat) then
1558
            af(i,j)=misdat
1559
          else
1560
            af(i,j)=a(i,j)+fh*(f1(i,j)-f1(i+1,j)+f2(i,j)-f2(i,j+1))
1561
          endif
1562
        enddo
1563
        enddo
1564
      endif
1565
      end
2 michaesp 1566
 
1567
 
1568
 
1569
 
1570
 
1571
 
1572
 
1573
 
1574
 
1575
 
1576
 
1577
 
1578
 
1579
 
1580
 
1581
 
1582
 
1583
 
1584
 
11 michaesp 1585
 
1586
 
1587
 
1588
 
1589
 
1590
 
1591