Subversion Repositories lagranto.wrf

Rev

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