Subversion Repositories lagranto.wrf

Rev

Rev 8 | Details | Compare with Previous | Last modification | View Log | RSS feed

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