Subversion Repositories lagranto.wrf

Rev

Rev 8 | Go to most recent revision | Details | 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'
750
      call writecdf2D(cdfname,varname,mpx,0.,1,0,1)
751
      cdfname = mapfile
752
      varname = 'MAPSCALE_Y'
753
      call writecdf2D(cdfname,varname,mpy,0.,
754
     >                dx,dy,xmin,ymin,nx,ny,1,0,1)
755
 
756
 
757
      endif
758
 
759
c     ------------------------------------------------------------
760
c     Convert from pressure to height
761
c     ------------------------------------------------------------
762
 
763
      if ( mode.eq.'-p2z' ) then
764
 
765
c     Allocate memory for input and output lists
766
      allocate(tra(ntra,ntim,ncol),stat=stat)
767
      if (stat.ne.0) print*,'*** error allocating array tra         ***'
768
      allocate(xx0(ntra*ntim),stat=stat)
769
      if (stat.ne.0) print*,'*** error allocating array xx0         ***'
770
      allocate(yy0(ntra*ntim),stat=stat)
771
      if (stat.ne.0) print*,'*** error allocating array yy0         ***'
772
      allocate(zz0(ntra*ntim),stat=stat)
773
      if (stat.ne.0) print*,'*** error allocating array zz0         ***'
774
 
775
c     Get format of input and output file
776
      call mode_tra(inpmode,inpfile)
777
      call mode_tra(outmode,outfile)
778
      if ( outmode.eq.-1) outmode=1
779
 
780
c     Read coordinates from file - Format (x,y,lev)
781
      if (inpmode.eq.-1) then
782
         fid = 10
783
         npoints = 0
784
         open(fid,file=inpfile)
785
          do i=1,ntra
786
             npoints = npoints + 1
787
             read(fid,*) xx0(npoints),yy0(npoints),zz0(npoints)
788
          enddo
789
         close(fid)
790
 
791
c     Read coordinates from trajectory file
792
      else
793
         call ropen_tra(fid,inpfile,ntra,ntim,ncol,refdate,vars,inpmode)
794
         call read_tra (fid,tra,ntra,ntim,ncol,inpmode)
795
         call close_tra(fid,inpmode)
796
 
797
         if ( (vars(2).ne.'x').and.(vars(3).ne.'y') ) then
798
            print*,' ERROR: input must be in x/y format... Stop'
799
            stop
800
         endif
801
 
802
         npoints = 0
803
         do i=1,ntra
804
            do j=1,ntim
805
               npoints = npoints + 1
806
               xx0(npoints) = tra(i,j,2)
807
               yy0(npoints) = tra(i,j,3)
808
               zz0(npoints) = tra(i,j,4)
809
            enddo
810
         enddo
811
      endif
812
 
813
c     Transform coordinates
814
      do i=1,npoints
815
 
816
          call get_index3 (rid,rjd,rkd,xx0(i),yy0(i),-zz0(i),1,
817
     >                     -p3,-ps,nx,ny,nz,xmin,ymin,dx,dy)
818
 
819
          zz0(i) = int_index3(z3,nx,ny,nz,rid,rjd,rkd,mdv)
820
 
821
      enddo
822
 
823
c     Write output to list
824
      if ( outmode.eq.-1 ) then
825
         fid = 10
826
         open(fid,file=outfile)
827
         do i=1,ntra
828
            write(fid,'(f9.2,f8.2,i6)') xx0(i),yy0(i),nint(zz0(i))
829
         enddo
830
         close(fid)
831
 
832
c     Write output to trajectory
833
      else
834
         npoints = 0
835
         do i=1,ntra
836
            do j=1,ntim
837
               npoints = npoints + 1
838
               tra(i,j,2) = xx0(npoints)
839
               tra(i,j,3) = yy0(npoints)
840
               tra(i,j,4) = zz0(npoints)
841
            enddo
842
         enddo
843
         if ( ncol.eq.3 ) ncol = 4
844
         vars(1) = 'time'
845
         vars(2) = 'x'
846
         vars(3) = 'y'
847
         vars(4) = 'z'
848
         call wopen_tra(fid,outfile,ntra,ntim,ncol,refdate,vars,outmode)
849
         call write_tra(fid,tra,ntra,ntim,ncol,outmode)
850
         call close_tra(fid,outmode)
851
      endif
852
 
853
      endif
854
 
855
c     ------------------------------------------------------------
856
c     Convert single x/y/p to x/y/z
857
c     ------------------------------------------------------------
858
 
859
      if ( mode.eq.'-p2z.single' ) then
860
 
861
c     Transform coordinates - change from descending to ascending (minus sign)
862
      call get_index3 (rid,rjd,rkd,xpos,ypos,-ppos,1,
863
     >                 -p3,-ps,nx,ny,nz,xmin,ymin,dx,dy)
864
 
865
      zpos = int_index3(z3,nx,ny,nz,rid,rjd,rkd,mdv)
866
 
867
c	  Write result to screen
868
      print*,xpos,ypos,zpos
869
 
870
      endif
871
 
872
c     ------------------------------------------------------------
873
c     Convert from height to pressure
874
c     ------------------------------------------------------------
875
 
876
      if ( mode.eq.'-z2p' ) then
877
 
878
c     Allocate memory for input and output lists
879
      allocate(tra(ntra,ntim,ncol),stat=stat)
880
      if (stat.ne.0) print*,'*** error allocating array tra         ***'
881
      allocate(xx0(ntra*ntim),stat=stat)
882
      if (stat.ne.0) print*,'*** error allocating array xx0         ***'
883
      allocate(yy0(ntra*ntim),stat=stat)
884
      if (stat.ne.0) print*,'*** error allocating array yy0         ***'
885
      allocate(zz0(ntra*ntim),stat=stat)
886
      if (stat.ne.0) print*,'*** error allocating array zz0         ***'
887
 
888
c     Get format of input and output file
889
      call mode_tra(inpmode,inpfile)
890
      call mode_tra(outmode,outfile)
891
      if ( outmode.eq.-1) outmode=1
892
 
893
c     Read coordinates from file - Format (x,y,lev)
894
      if (inpmode.eq.-1) then
895
         fid = 10
896
         npoints = 0
897
         open(fid,file=inpfile)
898
          do i=1,ntra
899
             npoints = npoints + 1
900
             read(fid,*) xx0(npoints),yy0(npoints),zz0(npoints)
901
          enddo
902
         close(fid)
903
 
904
c     Read coordinates from trajectory file
905
      else
906
         call ropen_tra(fid,inpfile,ntra,ntim,ncol,refdate,vars,inpmode)
907
         call read_tra (fid,tra,ntra,ntim,ncol,inpmode)
908
         call close_tra(fid,inpmode)
909
 
910
         if ( (vars(2).ne.'x').and.(vars(3).ne.'y') ) then
911
            print*,' ERROR: input must be in x/y format... Stop'
912
            stop
913
         endif
914
 
915
         npoints = 0
916
         do i=1,ntra
917
            do j=1,ntim
918
               npoints = npoints + 1
919
               xx0(npoints) = tra(i,j,2)
920
               yy0(npoints) = tra(i,j,3)
921
               zz0(npoints) = tra(i,j,4)
922
            enddo
923
         enddo
924
      endif
925
 
926
c     Transform coordinates
927
      do i=1,npoints
928
 
929
          call get_index3 (rid,rjd,rkd,xx0(i),yy0(i),zz0(i),1,
930
     >                     z3,zb,nx,ny,nz,xmin,ymin,dx,dy)
931
 
932
          zz0(i) = int_index3(p3,nx,ny,nz,rid,rjd,rkd,mdv)
933
 
934
      enddo
935
 
936
c     Write output to list
937
      if ( outmode.eq.-1 ) then
938
         fid = 10
939
         open(fid,file=outfile)
940
         do i=1,ntra
941
            write(fid,'(f9.2,f8.2,i6)') xx0(i),yy0(i),nint(zz0(i))
942
         enddo
943
         close(fid)
944
 
945
c     Write output to trajectory
946
      else
947
         npoints = 0
948
         do i=1,ntra
949
            do j=1,ntim
950
               npoints = npoints + 1
951
               tra(i,j,2) = xx0(npoints)
952
               tra(i,j,3) = yy0(npoints)
953
               tra(i,j,4) = zz0(npoints)
954
            enddo
955
         enddo
956
         if ( ncol.eq.3 ) ncol = 4
957
         vars(1) = 'time'
958
         vars(2) = 'x'
959
         vars(3) = 'y'
960
         vars(4) = 'p'
961
         call wopen_tra(fid,outfile,ntra,ntim,ncol,refdate,vars,outmode)
962
         call write_tra(fid,tra,ntra,ntim,ncol,outmode)
963
         call close_tra(fid,outmode)
964
      endif
965
 
966
      endif
967
 
968
c     ------------------------------------------------------------
969
c     Convert single x/y/z to x/y/p
970
c     ------------------------------------------------------------
971
 
972
      if ( mode.eq.'-z2p.single' ) then
973
 
974
c     Transform coordinates - change from descending to ascending (minus sign)
975
      call get_index3 (rid,rjd,rkd,xpos,ypos,zpos,1,
976
     >                 z3,zb,nx,ny,nz,xmin,ymin,dx,dy)
977
 
978
      ppos = int_index3(p3,nx,ny,nz,rid,rjd,rkd,mdv)
979
 
980
c	  Write result to screen
981
      print*,xpos,ypos,ppos
982
 
983
      endif
984
 
985
      end
986
 
987
 
988
c     ********************************************************************
989
c     * GRIDDING SUBROUTINES                                             *
990
c     ********************************************************************
991
 
992
c     ---------------------------------------------------------------------
993
c     Gridding of one single data point (smoothing in km, deg, gridp)
994
c     ---------------------------------------------------------------------
995
 
996
      subroutine gridding1 (lat,lon,addval,radius,unit,
997
     >                      connect,connectval,
998
     >                      out,outc,nx,ny,xmin,ymin,dx,dy)
999
 
1000
      implicit none
1001
 
1002
c     Declaration of subroutine parameters
1003
      real         lat,lon
1004
      integer      nx,ny
1005
      real         xmin,ymin,dx,dy
1006
      real         out(nx,ny),outc(nx,ny)
1007
      real         radius
1008
      character*80 unit
1009
      integer      connectval
1010
      integer      connect(nx,ny)
1011
      real         addval
1012
 
1013
c     Auxiliary variables
1014
      integer   i,j,k
1015
      integer   mu,md,nr,nl,n,m
1016
      integer   stackx(nx*ny),stacky(nx*ny)
1017
      integer   tab_x(nx*ny),tab_y(nx*ny)
1018
      real      tab_r(nx*ny)
1019
      integer   sp
1020
      real      lat2,lon2
1021
      real      dist,sum
1022
      real      xmax
1023
      integer   periodic
1024
      integer   test
1025
      character ch
1026
 
1027
c     Numerical epsilon
1028
      real      eps
1029
      parameter (eps=0.01)
1030
 
1031
c     Externals
1032
      real      sdis,weight
1033
      external  sdis,weight
1034
 
1035
c     Check whether lat/lon point is valid
1036
      xmax=xmin+real(nx-1)*dx
1037
      if (lon.lt.xmin-eps) lon=lon+360.
1038
      if (lon.gt.xmax+eps) lon=lon-360.
1039
      if (abs(lat-90).lt.eps) lat=90.
1040
      if (abs(lat+90).lt.eps) lat=-90.
1041
      if ((abs(lat).gt.(90.+eps)).or.
1042
     >    (lon.lt.xmin-eps).or.(lon.gt.xmax+eps)) then
1043
         print*,'Invalid lat/lon point ',lat,lon
1044
         return
1045
      endif
1046
 
1047
c     Set flag for periodic domain
1048
      if (abs(xmax-xmin-360.).lt.eps) then
1049
         periodic=1
1050
      else if (abs(xmax-xmin-360+dx).lt.eps) then
1051
         periodic=2
1052
      else
1053
         periodic=0
1054
      endif
1055
 
1056
c     Get indices of one coarse grid point within search radius
1057
      i=nint((lon-xmin)/dx)+1
1058
      if ((i.eq.nx).and.(periodic.eq.1)) i=1
1059
      j=nint((lat-ymin)/dy)+1
1060
      lat2=ymin+real(j-1)*dy
1061
      lon2=xmin+real(i-1)*dx
1062
      dist=sdis(lon,lat,lon2,lat2,unit)
1063
      if (dist.gt.radius) then
1064
         print*,'1: Search radius is too small...'
1065
         stop
1066
      endif
1067
 
1068
c     Get connected points
1069
      k=0
1070
      stackx(1)=i
1071
      stacky(1)=j
1072
      sp    = 1
1073
      do while (sp.ne.0) 
1074
 
1075
c        Get an element from stack
1076
         n=stackx(sp)
1077
         m=stacky(sp)
1078
         sp=sp-1
1079
 
1080
c        Get distance from reference point
1081
         lat2=ymin+real(m-1)*dy
1082
         lon2=xmin+real(n-1)*dx
1083
         dist=sdis(lon,lat,lon2,lat2,unit)
1084
 
1085
c        Check whether distance is smaller than search radius: connected
1086
         if (dist.lt.radius) then
1087
 
1088
c           Make entry in filter mask
1089
            k=k+1
1090
            tab_x(k)=n
1091
            tab_y(k)=m
1092
            tab_r(k)=weight(dist,radius)
1093
 
1094
c           Mark this point as visited
1095
            connect(n,m)=connectval
1096
 
1097
c           Get coordinates of neighbouring points
1098
            nr=n+1
1099
            if ((nr.gt.nx)  .and.(periodic.eq.0)) nr=nx
1100
            if ((nr.gt.nx-1).and.(periodic.eq.1)) nr=1
1101
            if ((nr.gt.nx)  .and.(periodic.eq.2)) nr=1
1102
            nl=n-1
1103
            if ((nl.lt.1).and.(periodic.eq.0)) nl=1
1104
            if ((nl.lt.1).and.(periodic.eq.1)) nl=nx-1
1105
            if ((nl.lt.1).and.(periodic.eq.2)) nl=nx
1106
            mu=m+1
1107
            if (mu.gt.ny) mu=ny
1108
            md=m-1
1109
            if (md.lt.1) md=1
1110
 
1111
c           Update stack
1112
            if (connect(nr,m).ne.connectval) then
1113
               connect(nr,m)=connectval
1114
               sp=sp+1
1115
               stackx(sp)=nr
1116
               stacky(sp)=m
1117
            endif
1118
            if (connect(nl,m).ne.connectval) then
1119
               connect(nl,m)=connectval
1120
               sp=sp+1
1121
               stackx(sp)=nl
1122
               stacky(sp)=m
1123
            endif
1124
            if (connect(n,mu).ne.connectval) then
1125
               connect(n,mu)=connectval
1126
               sp=sp+1
1127
               stackx(sp)=n
1128
               stacky(sp)=mu
1129
            endif
1130
            if (connect(n,md).ne.connectval) then
1131
               connect(n,md)=connectval
1132
               sp=sp+1
1133
               stackx(sp)=n
1134
               stacky(sp)=md
1135
            endif
1136
         endif     
1137
 
1138
      end do
1139
 
1140
      if (k.ge.1) then
1141
         sum=0.
1142
         do i=1,k
1143
            sum=sum+tab_r(i)
1144
         enddo
1145
         do i=1,k
1146
            out (tab_x(i),tab_y(i))=out(tab_x(i),tab_y(i))+
1147
     >                             addval*tab_r(i)/sum
1148
            outc(tab_x(i),tab_y(i))=outc(tab_x(i),tab_y(i))+
1149
     >                             1.*tab_r(i)/sum
1150
 
1151
            if ((tab_x(i).eq.1).and.(periodic.eq.1)) then
1152
               out(nx,tab_y(i))=out(nx,tab_y(i))+
1153
     >                             addval*tab_r(i)/sum
1154
               outc(nx,tab_y(i))=outc(nx,tab_y(i))+
1155
     >                             1.*tab_r(i)/sum
1156
 
1157
            endif
1158
         enddo
1159
      else
1160
         print*,'2: Search radius is too small...'
1161
         stop
1162
      endif
1163
 
1164
      end
1165
 
1166
 
1167
c     ----------------------------------------------------------------------
1168
c     Get spherical distance between lat/lon points
1169
c     ----------------------------------------------------------------------
1170
 
1171
      real function sdis(xp,yp,xq,yq,unit)
1172
 
1173
c     Calculates spherical distance (in km) between two points given
1174
c     by their spherical coordinates (xp,yp) and (xq,yq), respectively.
1175
 
1176
      real,parameter ::       re=6371.229
1177
      real,parameter ::       rad2deg=180./3.14159265
1178
      real,parameter ::       deg2rad=3.141592654/180.
1179
 
1180
      real         xp,yp,xq,yq,arg
1181
      character*80 unit
1182
      real         dlon,dlat,alpha,rlat1,ralt2
1183
 
1184
      if ( unit.eq.'km' ) then
1185
 
1186
         arg=sind(yp)*sind(yq)+cosd(yp)*cosd(yq)*cosd(xp-xq)
1187
         if (arg.lt.-1.) arg=-1.
1188
         if (arg.gt.1.) arg=1.
1189
         sdis=re*acos(arg)
1190
 
1191
      elseif ( unit.eq.'deg' ) then
1192
 
1193
         dlon = xp-xq
1194
         if ( dlon.gt. 180. ) dlon = dlon - 360.
1195
         if ( dlon.lt.-180. ) dlon = dlon + 360.
1196
         sdis = sqrt( dlon**2 + (yp-yq)**2 )
1197
 
1198
      elseif ( unit.eq.'km.haversine' ) then
1199
 
1200
        dlat   =  (yp - yq)*deg2rad
1201
        dlon   =  (xp - xq)*deg2rad
1202
        rlat1   =  yp*deg2rad
1203
        rlat2   =  yq*deg2rad
1204
 
1205
        alpha  = ( sin(0.5*dlat)**2 ) +
1206
     >           ( sin(0.5*dlon)**2 )*cos(rlat1)*cos(rlat2)
1207
 
1208
        sdis = 4. * re * atan2( sqrt(alpha),1. + sqrt( 1. - alpha ) )
1209
 
1210
      endif  
1211
 
1212
      end
1213
 
1214
c     ----------------------------------------------------------------------
1215
c     Weight function for the filter mask
1216
c     ----------------------------------------------------------------------
1217
 
1218
      real function weight (r,radius)
1219
 
1220
c     Attribute to each distanc r its corresponding weight in the filter mask
1221
 
1222
      implicit none
1223
 
1224
c     Declaration of subroutine parameters
1225
      real r
1226
      real radius
1227
 
1228
c     Simple 0/1 mask
1229
      if (r.lt.radius) then
1230
          weight=1.-0.65*r/radius 
1231
      else
1232
          weight=0.
1233
      endif
1234
 
1235
      end
1236
 
1237
 
1238
c     ********************************************************************
1239
c     * INPUT / OUTPUT SUBROUTINES                                       *
1240
c     ********************************************************************
1241
 
1242
c     --------------------------------------------------------------------
1243
c     Subroutines to write the netcdf output file
1244
c     --------------------------------------------------------------------
1245
 
1246
      subroutine writecdf2D(cdfname,
1247
     >                      varname,arr,time,
1248
     >                      dx,dy,xmin,ymin,nx,ny,nz,
1249
     >                      crefile,crevar)
1250
 
1251
      IMPLICIT NONE
1252
 
1253
c     Declaration of input parameters
1254
      character*80 cdfname,varname
1255
      integer nx,ny,nz
1256
      real arr(nx,ny,nz)
1257
      real dx,dy,xmin,ymin
1258
      real time
1259
      integer crefile,crevar
1260
 
1261
c     Further variables
1262
      real varmin(4),varmax(4),stag(4)
1263
      integer ierr,cdfid,ndim,vardim(4)
1264
      character*80 cstname
1265
      real mdv
1266
      integer i
1267
 
1268
C     Definitions
1269
      varmin(1)=xmin
1270
      varmin(2)=ymin
1271
      varmin(3)=1050.
1272
      varmax(1)=xmin+real(nx-1)*dx
1273
      varmax(2)=ymin+real(ny-1)*dy
1274
      varmax(3)=1050.
1275
      cstname='no_constants_file'
1276
      ndim=4
1277
      vardim(1)=nx
1278
      vardim(2)=ny
1279
      vardim(3)=nz
1280
      stag(1)=0.
1281
      stag(2)=0.
1282
      stag(3)=0.
1283
      mdv=-999.98999
1284
 
1285
C     Create the file
1286
      if (crefile.eq.0) then
1287
         call cdfwopn(cdfname,cdfid,ierr)
1288
         if (ierr.ne.0) goto 906
1289
      else if (crefile.eq.1) then
1290
         call crecdf(cdfname,cdfid,
1291
     >        varmin,varmax,ndim,cstname,ierr)
1292
         if (ierr.ne.0) goto 903
1293
      endif
1294
 
1295
c     Write the data to the netcdf file, and close the file
1296
      if (crevar.eq.1) then
1297
         call putdef(cdfid,varname,ndim,mdv,
1298
     >        vardim,varmin,varmax,stag,ierr)
1299
         if (ierr.ne.0) goto 904
1300
      endif
1301
      call putdat(cdfid,varname,time,0,arr,ierr)
1302
      if (ierr.ne.0) goto 905
1303
      call clscdf(cdfid,ierr)
1304
 
1305
      return
1306
 
1307
c     Error handling
1308
 903  print*,'*** Problem to create netcdf file ***'
1309
      stop
1310
 904  print*,'*** Problem to write definition ***'
1311
      stop
1312
 905  print*,'*** Problem to write data ***'
1313
      stop
1314
 906  print*,'*** Problem to open netcdf file ***'
1315
      stop
1316
 
1317
      end
1318
 
1319
 
1320
c     -----------------------------------------------
1321
c     Subroutine to read a netcdf output file
1322
c     -----------------------------------------------
1323
 
1324
      subroutine readcdf2D(cdfname,varname,arr,time,
1325
     >                     dx,dy,xmin,ymin,nx,ny,nz)
1326
 
1327
      implicit none
1328
 
1329
c     Declaration of input parameters
1330
      character*80 cdfname,varname
1331
      integer      nx,ny,nz
1332
      real         arr(nx,ny,nz)
1333
      real         dx,dy,xmin,ymin
1334
      real         time
1335
 
1336
c     Internal variables for the netcdf file
1337
      real         varmin(4),varmax(4),stag(4)
1338
      integer      ierr,cdfid,ndim,vardim(4)
1339
      real         mdv
1340
      real         delx,dely
1341
      real         times(500)
1342
      integer      ntimes,flag
1343
 
1344
c     Numerical epsilon
1345
      real         eps
1346
      parameter    (eps=0.01)
1347
 
1348
c     Auxiliary variables
1349
      integer      i,j,k
1350
 
1351
c     Initialize the ouput array
1352
      do i=1,nx
1353
         do j=1,ny
1354
            do k=1,nz
1355
               arr(i,j,k)=0.
1356
            enddo
1357
         enddo
1358
      enddo
1359
 
1360
c     Try to open the netcdf file and to read the variable
1361
      call cdfopn(cdfname,cdfid,ierr)
1362
      if (ierr.ne.0) goto 801
1363
 
1364
c     Check whether the specifieed time is available
1365
      call gettimes(cdfid,times,ntimes,ierr)
1366
      if (ierr.ne.0) goto 801
1367
      flag=0
1368
      do i=1,ntimes
1369
          if (abs(times(i)-time).lt.eps) flag=1
1370
      enddo
1371
      if (flag.eq.0) then
1372
         print*,'No such time on cdf',time
1373
         stop
1374
      endif
1375
 
1376
c     Get the variable definition, and the grid
1377
      call getdef(cdfid,varname,ndim,mdv,vardim,varmin,varmax,
1378
     >     stag,ierr)
1379
      if (ierr.ne.0) goto 801
1380
 
1381
c     Set parameters or read parameters - depending on nx,ny
1382
      if ( (nx.eq.1).and.(ny.eq.1) ) then
1383
         dx   = (varmax(1)-varmin(1))/real(vardim(1)-1)
1384
         dy   = (varmax(2)-varmin(2))/real(vardim(2)-1)
1385
         nx   = vardim(1)
1386
         ny   = vardim(2)
1387
         nz   = vardim(3)
1388
         xmin = varmin(1)
1389
         ymin = varmin(2)
1390
      else
1391
         call getdat(cdfid,varname,time,0,arr,ierr)
1392
         if (ierr.ne.0) goto 801
1393
      endif
1394
 
1395
c     Close data file
1396
      call clscdf(cdfid,ierr)
1397
 
1398
      return
1399
 
1400
c     Exception handling
1401
 801  print*,'Problems in reading netcdf file'
1402
      stop
1403
 
1404
      end
1405
 
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