Subversion Repositories lagranto.wrf

Rev

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