Subversion Repositories pvinversion.ecmwf

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 michaesp 1
      PROGRAM rotate_grid
2
 
3
c     *******************************************************************
4
c     * Rotate to a grid with the PV anomaly at its center              *
5
c     * Michael Sprenger / Autumn 2006                                  *
6
c     *******************************************************************
7
 
8
      implicit none
9
 
10
c     -------------------------------------------------------------------
11
c     Declaration of parameters and variables
12
c     -------------------------------------------------------------------
13
 
14
c     Specification of input parameters
15
      real         clon,clat,rotation
16
      integer      rnx,rny
17
      real         rdx,rdy
18
      integer      nfield
19
      character*80 fieldname(100)
20
 
21
c     Numerical and physical parameters
22
      real                 degrad
23
      parameter            (degrad=0.0174532925)
24
      real                 omegaerd
25
      parameter            (omegaerd=7.292e-5 )
26
      real                 eps
27
      parameter            (eps=0.001)
28
 
29
c     Variables for input Z file : height level
30
      character*80 in_cfn
31
      real         in_varmin(4),in_varmax(4),in_stag(4)
32
      integer      in_vardim(4)
33
      real         in_mdv
34
      integer      in_ndim
35
      integer      in_nx,in_ny,in_nz
36
      real         in_xmin,in_xmax,in_ymin,in_ymax,in_dx,in_dy
37
      integer      in_ntimes
38
      real         in_aklev(500),in_bklev(500)
39
      real         in_aklay(500),in_bklay(500)
40
      real         in_time
41
      real         in_pollon,in_pollat
42
      integer      in_nvars
43
      character*80 in_vnam(100)
44
      integer      in_idate(5)
45
      real,allocatable, dimension (:,:,:) :: in_field3
46
      real,allocatable, dimension (:,:,:) :: in_vect1
47
      real,allocatable, dimension (:,:,:) :: in_vect2
48
 
49
c     Variables for output Z file : height level
50
      character*80 out_cfn
51
      real         out_varmin(4),out_varmax(4),out_stag(4)
52
      integer      out_vardim(4)
53
      real         out_mdv
54
      integer      out_ndim
55
      integer      out_nx,out_ny,out_nz
56
      real         out_xmin,out_xmax,out_ymin,out_ymax,out_dx,out_dy
57
      integer      out_ntimes
58
      real         out_aklev(500),out_bklev(500)
59
      real         out_aklay(500),out_bklay(500)
60
      real         out_time
61
      real         out_pollon,out_pollat
62
      integer      out_idate(5)
63
      real,allocatable, dimension (:,:,:) :: out_field3
64
      real,allocatable, dimension (:,:,:) :: out_vect1
65
      real,allocatable, dimension (:,:,:) :: out_vect2
66
      real,allocatable, dimension (:,:)   :: out_lat,out_lon
67
      real,allocatable, dimension (:,:)   :: out_x,out_y
68
      real,allocatable, dimension (:,:)   :: out_coriol
69
 
70
c     Auxiliary variables
71
      integer      ifield
72
      integer      i,j,k
73
      integer      cdfid,cstid
74
      character*80 cfn
75
      integer      stat,ierr,isok
76
      real         time
77
      character*80 varname,cdfname,varname1,varname2
78
      integer      idate(5),stdate(5),datar(14)
79
      integer      rotmode
80
      integer      i1,i2,i3,i4
81
      integer      isvector
82
      real         lat
83
      character*80 name
84
 
85
c     Externals
86
      real         sdis
87
      external     sdis
88
 
89
c     -------------------------------------------------------------------
90
c     Preparations
91
c     -------------------------------------------------------------------
92
 
93
      print*,'*********************************************************'
94
      print*,'* rotate_grid                                           *'
95
      print*,'*********************************************************'
96
 
97
c     Read parameter file
98
      open(10,file='fort.10')
99
 
100
       read(10,*) in_cfn
101
       read(10,*) out_cfn
102
 
103
       read(10,*) name,rnx
104
       if ( trim(name).ne.'ROT_NX') stop
105
       read(10,*) name,rny
106
       if ( trim(name).ne.'ROT_NY') stop
107
       read(10,*) name,rdx
108
       if ( trim(name).ne.'ROT_DX') stop
109
       read(10,*) name,rdy
110
       if ( trim(name).ne.'ROT_DY') stop
111
       read(10,*) name,clon
112
       if ( trim(name).ne.'CLON'  ) stop
113
       read(10,*) name,clat
114
       if ( trim(name).ne.'CLAT'  ) stop
115
       read(10,*) name,rotation
116
       if ( trim(name).ne.'CROT'  ) stop
117
 
118
       read(10,*) nfield
119
       do i=1,nfield
120
          read(10,*) fieldname(i)
121
       enddo
122
 
123
      close(10)
124
 
125
      print*,clon,clat,rotation
126
      print*,rnx,rny,rdx,rdy
127
      print*,trim(in_cfn),' -> ',trim(out_cfn)
128
 
129
c     Get grid description for input Z file : height level
130
      call cdfopn(in_cfn,cdfid,ierr)
131
      if (ierr.ne.0) goto 998
132
      call getcfn(cdfid,cfn,ierr)
133
      if (ierr.ne.0) goto 998
134
      call cdfopn(cfn,cstid,ierr)
135
      if (ierr.ne.0) goto 998
136
      call getvars(cdfid,in_nvars,in_vnam,ierr)
137
      if (ierr.ne.0) goto 998
138
      isok=0
139
      varname=fieldname(1)
140
      call check_varok (isok,varname,in_vnam,in_nvars)
141
      if (isok.eq.0) goto 998
142
      call getdef(cdfid,varname,in_ndim,in_mdv,in_vardim,
143
     >            in_varmin,in_varmax,in_stag,ierr)
144
      if (ierr.ne.0) goto 998
145
      in_nx  =in_vardim(1)
146
      in_ny  =in_vardim(2)
147
      in_xmin=in_varmin(1)
148
      in_ymin=in_varmin(2)
149
      call getlevs(cstid,in_nz,in_aklev,in_bklev,in_aklay,in_bklay,ierr)
150
      call getgrid(cstid,in_dx,in_dy,ierr)
151
      in_xmax=in_xmin+real(in_nx-1)*in_dx
152
      in_ymax=in_ymin+real(in_ny-1)*in_dy
153
      call gettimes(cdfid,in_time,in_ntimes,ierr)
154
      call getstart(cstid,in_idate,ierr)
155
      call getpole(cstid,in_pollon,in_pollat,ierr)
156
      call clscdf(cstid,ierr)
157
      call clscdf(cdfid,ierr)
158
 
159
c     Set grid description for output file : height level
160
      out_vardim(1) = rnx
161
      out_vardim(2) = rny
162
      out_vardim(3) = in_nz
163
      out_varmin(1) = -real(rnx/2)*rdx
164
      out_varmin(2) = -real(rny/2)*rdy
165
      out_varmin(3) = in_varmin(3)
166
      out_varmax(1) = real(rnx/2)*rdx
167
      out_varmax(2) = real(rny/2)*rdy
168
      out_varmax(3) = in_varmax(3)
169
      do i=1,in_nz
170
         out_aklay(i) = in_aklay(i)
171
         out_bklay(i) = in_bklay(i)
172
         out_aklev(i) = in_aklev(i)
173
         out_bklev(i) = in_bklev(i)
174
      enddo
175
      out_dx       = rdx
176
      out_dy       = rdy
177
      out_time     = in_time
178
      out_ntimes   = in_ntimes
179
      out_ndim     = 4
180
      out_mdv      = in_mdv
181
      out_nx       = out_vardim(1)
182
      out_ny       = out_vardim(2)
183
      out_nz       = out_vardim(3)
184
      out_xmin     = out_varmin(1)
185
      out_ymin     = out_varmin(2)
186
      out_pollon   = clon
187
      out_pollat   = clat
188
      do i=1,5
189
         out_idate(i) = in_idate(i)
190
      enddo
191
 
192
c     Allocate memory for all fields
193
      allocate(in_field3(in_nx,in_ny,in_nz),stat=stat)
194
      if (stat.ne.0) print*,'*** error allocating array in_field3 ***'
195
      allocate(in_vect1(in_nx,in_ny,in_nz),stat=stat)
196
      if (stat.ne.0) print*,'*** error allocating array in_vect1 ***'
197
      allocate(in_vect2(in_nx,in_ny,in_nz),stat=stat)
198
      if (stat.ne.0) print*,'*** error allocating array in_vect2 ***'
199
      allocate(out_field3(out_nx,out_ny,out_nz),stat=stat)
200
      if (stat.ne.0) print*,'*** error allocating array out_field3 ***'
201
      allocate(out_vect1(out_nx,out_ny,out_nz),stat=stat)
202
      if (stat.ne.0) print*,'*** error allocating array out_vect1 ***'
203
      allocate(out_vect2(out_nx,out_ny,out_nz),stat=stat)
204
      if (stat.ne.0) print*,'*** error allocating array out_vect2 ***'
205
      allocate(out_lat(out_nx,out_ny),stat=stat)
206
      if (stat.ne.0) print*,'*** error allocating array out_lat ***'
207
      allocate(out_lon(out_nx,out_ny),stat=stat)
208
      if (stat.ne.0) print*,'*** error allocating array out_lon ***'
209
      allocate(out_x(out_nx,out_ny),stat=stat)
210
      if (stat.ne.0) print*,'*** error allocating array out_x ***'
211
      allocate(out_y(out_nx,out_ny),stat=stat)
212
      if (stat.ne.0) print*,'*** error allocating array out_y ***'
213
      allocate(out_coriol(out_nx,out_ny),stat=stat)
214
      if (stat.ne.0) print*,'*** error allocating array out_coriol ***'
215
 
216
c     Create constants file
217
      datar(1)=out_nx
218
      datar(2)=out_ny
219
      datar(3)=int(1000.*out_varmax(2))
220
      datar(4)=int(1000.*out_varmin(1))
221
      datar(5)=int(1000.*out_varmin(2))
222
      datar(6)=int(1000.*out_varmax(1))
223
      datar(7)=int(1000.*out_dx)
224
      datar(8)=int(1000.*out_dy)
225
      datar(9)=out_nz
226
      datar(10)=1
227
      datar(11)=1      
228
      datar(12)=0      
229
      datar(13)=int(1000.*out_pollon) 
230
      datar(14)=int(1000.*out_pollat) 
231
 
232
      cfn=trim(out_cfn)//'_cst'
233
      call wricst(cfn,datar,out_aklev,out_bklev,
234
     >            out_aklay,out_bklay,out_idate)
235
 
236
      call crecdf(trim(out_cfn),cdfid,out_varmin,out_varmax,
237
     >            out_ndim,trim(cfn),ierr)
238
      if (ierr.ne.0) goto 997
239
      call clscdf(cdfid,ierr)
240
 
241
c     -----------------------------------------------------------------
242
c     Loop through all fields - rotate to new grid
243
c     -----------------------------------------------------------------
244
 
245
      do ifield=1,nfield
246
 
247
c        Check if scalar or vectorial field (X for scalar, U.V for vector)
248
         varname=fieldname(ifield)
249
         i1=1
250
         i2=1
251
         i3=0
252
         i4=0
253
 100     if (varname(i1:i1).eq.' ') then
254
            i1=i1+1
255
            goto 100
256
         endif
257
         i2=i1
258
 101     if ((varname(i2:i2).ne.' ').and.(varname(i2:i2).ne.'.')) then
259
            i2=i2+1
260
            goto 101
261
         endif
262
         if (varname(i2:i2).eq.'.') then
263
            i3=i2+1
264
 102        if (varname(i3:i3).eq.' ') then
265
               i3=i3+1
266
               goto 102
267
            endif
268
            i4=i3
269
 104        if (varname(i4:i4).ne.' ') then
270
               i4=i4+1
271
               goto 104
272
            endif
273
         endif
274
         if ((i3.ne.0).and.(i4.ne.0)) then
275
            isvector=1
276
            i2=i2-1
277
            varname1=varname(i1:i2)
278
            i4=i4-1         
279
            varname2=varname(i3:i4)
280
            print*,'Rotating vector : ',
281
     >             trim(varname1),' / ',trim(varname2)
282
         else
283
            isvector=0
284
            i2=i2-1
285
            varname=varname(i1:i2)
286
            print*,'Rotating scalar : ',trim(varname)
287
         endif
288
 
289
c        Rotate a scalar field
290
         if (isvector.eq.0) then
291
 
292
c           Read input field
293
            call cdfopn(in_cfn,cdfid,ierr)
294
            if (ierr.ne.0) goto 998
295
            call getdef(cdfid,varname,in_ndim,in_mdv,in_vardim,
296
     >                  in_varmin,in_varmax,in_stag,ierr)
297
            in_nz=in_vardim(3)
298
            if (ierr.ne.0) goto 998
299
            call getdat(cdfid,varname,in_time,0,in_field3,ierr)
300
            if (ierr.ne.0) goto 998
301
            call clscdf(cdfid,ierr) 
302
 
303
c           Rotate to new coordinate system
304
            out_nz=in_nz
305
            call getenvir (clon,clat,rotation,0,
306
     >                     in_field3,in_dx,in_dy,
307
     >                     in_xmin,in_ymin,in_nx,in_ny,in_nz,in_mdv,
308
     >                     out_field3,out_dx,out_dy,
309
     >                     out_xmin,out_ymin,out_nx,out_ny,out_nz)
310
 
311
c           Write output scalar field
312
            call cdfwopn(trim(out_cfn),cdfid,ierr)
313
            if (ierr.ne.0) goto 997
314
            out_vardim(3)=out_nz
315
            call putdef(cdfid,varname,4,out_mdv,out_vardim,
316
     >                  out_varmin,out_varmax,out_stag,ierr)         
317
            if (ierr.ne.0) goto 997
318
            call putdat(cdfid,varname,out_time,0,out_field3,ierr)
319
            if (ierr.ne.0) goto 997
320
            call clscdf(cdfid,ierr)
321
 
322
c        Rotate vector field
323
         else if (isvector.eq.1) then
324
 
325
c           Read input vector field
326
            call cdfopn(in_cfn,cdfid,ierr)
327
            if (ierr.ne.0) goto 998
328
            call getdef(cdfid,varname1,in_ndim,in_mdv,in_vardim,
329
     >                  in_varmin,in_varmax,in_stag,ierr)
330
            in_nz=in_vardim(3)
331
            if (ierr.ne.0) goto 998
332
            call getdat(cdfid,varname1,in_time,0,in_vect1,ierr)
333
            if (ierr.ne.0) goto 998
334
            call getdef(cdfid,varname2,in_ndim,in_mdv,in_vardim,
335
     >                  in_varmin,in_varmax,in_stag,ierr)
336
            in_nz=in_vardim(3)
337
            if (ierr.ne.0) goto 998
338
            call getdat(cdfid,varname2,in_time,0,in_vect2,ierr)
339
            if (ierr.ne.0) goto 998
340
            call clscdf(cdfid,ierr) 
341
 
342
c           Get new vector component in x direction
343
            out_nz=in_nz
344
            call getenvir (clon,clat,rotation,1,
345
     >                     in_vect1,in_dx,in_dy,
346
     >                     in_xmin,in_ymin,in_nx,in_ny,in_nz,in_mdv,
347
     >                     out_field3,out_dx,out_dy,
348
     >                     out_xmin,out_ymin,out_nx,out_ny,out_nz)
349
            do i=1,out_nx
350
               do j=1,out_ny
351
                  do k=1,out_nz
352
                     out_vect1(i,j,k)=out_field3(i,j,k)
353
                  enddo
354
               enddo
355
            enddo
356
            call getenvir (clon,clat,rotation,2,
357
     >                     in_vect2,in_dx,in_dy,
358
     >                     in_xmin,in_ymin,in_nx,in_ny,in_nz,in_mdv,
359
     >                     out_field3,out_dx,out_dy,
360
     >                     out_xmin,out_ymin,out_nx,out_ny,out_nz)
361
            do i=1,out_nx
362
               do j=1,out_ny
363
                  do k=1,out_nz
364
                     if ( (abs(out_vect1 (i,j,k)-out_mdv).gt.eps).and.
365
     >                    (abs(out_field3(i,j,k)-out_mdv).gt.eps) ) then
366
                        out_vect1(i,j,k)=out_vect1(i,j,k)-
367
     >                                   out_field3(i,j,k)
368
                     endif
369
                  enddo
370
               enddo
371
            enddo           
372
 
373
c           Get new vector component in y direction
374
            out_nz=in_nz
375
            call getenvir (clon,clat,rotation,2,
376
     >                     in_vect1,in_dx,in_dy,
377
     >                     in_xmin,in_ymin,in_nx,in_ny,in_nz,in_mdv,
378
     >                     out_field3,out_dx,out_dy,
379
     >                     out_xmin,out_ymin,out_nx,out_ny,out_nz)
380
            do i=1,out_nx
381
               do j=1,out_ny
382
                  do k=1,out_nz
383
                     out_vect2(i,j,k)=out_field3(i,j,k)
384
                  enddo
385
               enddo
386
            enddo
387
            call getenvir (clon,clat,rotation,1,
388
     >                     in_vect2,in_dx,in_dy,
389
     >                     in_xmin,in_ymin,in_nx,in_ny,in_nz,in_mdv,
390
     >                     out_field3,out_dx,out_dy,
391
     >                     out_xmin,out_ymin,out_nx,out_ny,out_nz)
392
            do i=1,out_nx
393
               do j=1,out_ny
394
                  do k=1,out_nz
395
                     if ( (abs(out_vect2 (i,j,k)-out_mdv).gt.eps).and.
396
     >                    (abs(out_field3(i,j,k)-out_mdv).gt.eps) ) then
397
                        out_vect2(i,j,k)=out_vect2(i,j,k)+
398
     >                                   out_field3(i,j,k)
399
                     endif
400
                  enddo
401
               enddo
402
            enddo           
403
 
404
c           Write output vector field
405
            call cdfwopn(trim(out_cfn),cdfid,ierr)
406
            if (ierr.ne.0) goto 997
407
            out_vardim(3)=out_nz
408
            call putdef(cdfid,varname1,4,out_mdv,out_vardim,
409
     >                  out_varmin,out_varmax,out_stag,ierr)         
410
            if (ierr.ne.0) goto 997
411
            call putdat(cdfid,varname1,out_time,0,out_vect1,ierr)
412
            if (ierr.ne.0) goto 997
413
            call putdef(cdfid,varname2,4,out_mdv,out_vardim,
414
     >                  out_varmin,out_varmax,out_stag,ierr)         
415
            if (ierr.ne.0) goto 997
416
            call putdat(cdfid,varname2,out_time,0,out_vect2,ierr)
417
            if (ierr.ne.0) goto 997
418
            call clscdf(cdfid,ierr)
419
 
420
         endif
421
 
422
      enddo
423
 
424
c     -----------------------------------------------------------------
425
c     Write additional fields: latitude, longitude, Coriolis parameter
426
c     -----------------------------------------------------------------
427
 
428
c     Open the output file
429
      call cdfwopn(trim(out_cfn),cdfid,ierr)
430
      if (ierr.ne.0) goto 997     
431
 
432
c     Geographical latitude
433
      varname='LAT'
434
      print*,'Rotating scalar : ',trim(varname)
435
      do i=1,in_nx
436
         do j=1,in_ny
437
            in_field3(i,j,1)=in_ymin+real(j-1)*in_dy
438
         enddo
439
      enddo
440
      call getenvir (clon,clat,rotation,0,
441
     >               in_field3,in_dx,in_dy,
442
     >               in_xmin,in_ymin,in_nx,in_ny,1,in_mdv,
443
     >               out_lat,out_dx,out_dy,
444
     >               out_xmin,out_ymin,out_nx,out_ny,1)      
445
      out_vardim(3)=1
446
      call putdef(cdfid,varname,4,out_mdv,out_vardim,
447
     >            out_varmin,out_varmax,out_stag,ierr)         
448
      if (ierr.ne.0) goto 997
449
      call putdat(cdfid,varname,out_time,0,out_lat,ierr)
450
      if (ierr.ne.0) goto 997
451
 
452
c     Geographical longitude
453
      varname='LON'
454
      print*,'Rotating scalar : ',trim(varname)
455
      do i=1,in_nx
456
         do j=1,in_ny
457
            in_field3(i,j,1)=in_xmin+real(i-1)*in_dx
458
         enddo
459
      enddo
460
      call getenvir (clon,clat,rotation,0,
461
     >               in_field3,in_dx,in_dy,
462
     >               in_xmin,in_ymin,in_nx,in_ny,1,in_mdv,
463
     >               out_lon,out_dx,out_dy,
464
     >               out_xmin,out_ymin,out_nx,out_ny,1)      
465
      out_vardim(3)=1
466
      call putdef(cdfid,varname,4,out_mdv,out_vardim,
467
     >            out_varmin,out_varmax,out_stag,ierr)         
468
      if (ierr.ne.0) goto 997
469
      call putdat(cdfid,varname,out_time,0,out_lon,ierr)
470
      if (ierr.ne.0) goto 997
471
 
472
c     Coriolis parameter
473
      varname='CORIOL'
474
      print*,'Rotating scalar : ',trim(varname)
475
      do i=1,in_nx
476
         do j=1,in_ny
477
            lat=in_ymin+real(j-1)*in_dy
478
            in_field3(i,j,1)=2.*omegaerd*sin(lat*degrad)
479
         enddo
480
      enddo
481
      call getenvir (clon,clat,rotation,0,
482
     >               in_field3,in_dx,in_dy,
483
     >               in_xmin,in_ymin,in_nx,in_ny,1,in_mdv,
484
     >               out_coriol,out_dx,out_dy,
485
     >               out_xmin,out_ymin,out_nx,out_ny,1)      
486
      out_vardim(3)=1
487
      call putdef(cdfid,varname,4,out_mdv,out_vardim,
488
     >            out_varmin,out_varmax,out_stag,ierr)         
489
      if (ierr.ne.0) goto 997
490
      call putdat(cdfid,varname,out_time,0,out_coriol,ierr)
491
      if (ierr.ne.0) goto 997
492
 
493
c     X coordinate
494
      varname='X'
495
      print*,'Getting X grid : ',trim(varname)
496
      do j=1,out_ny
497
         out_x(out_nx/2,j)=0.
498
         do i=out_nx/2+1,out_nx
499
            out_x(i,j)=out_x(i-1,j)+
500
     >                 sdis(out_lon(i-1,j),out_lat(i-1,j),
501
     >                      out_lon(i  ,j),out_lat(i  ,j))
502
         enddo
503
         do i=out_nx/2-1,1,-1
504
            out_x(i,j)=out_x(i+1,j)-
505
     >                 sdis(out_lon(i+1,j),out_lat(i+1,j),
506
     >                      out_lon(i  ,j),out_lat(i  ,j))
507
         enddo
508
      enddo
509
      out_vardim(3)=1
510
      call putdef(cdfid,varname,4,out_mdv,out_vardim,
511
     >            out_varmin,out_varmax,out_stag,ierr)         
512
      if (ierr.ne.0) goto 997
513
      call putdat(cdfid,varname,out_time,0,out_x,ierr)
514
      if (ierr.ne.0) goto 997
515
 
516
c     Y coordinate
517
      varname='Y'
518
      print*,'Getting Y grid : ',trim(varname)
519
      do i=1,out_nx
520
         out_y(i,out_ny/2)=0.
521
         do j=out_ny/2+1,out_ny
522
            out_y(i,j)=out_y(i,j-1)+
523
     >                 sdis(out_lon(i,j-1),out_lat(i,j-1),
524
     >                      out_lon(i  ,j),out_lat(i  ,j))
525
         enddo
526
         do j=out_ny/2-1,1,-1
527
            out_y(i,j)=out_y(i,j+1)-
528
     >                 sdis(out_lon(i,j+1),out_lat(i,j+1),
529
     >                      out_lon(i  ,j),out_lat(i  ,j))
530
         enddo
531
      enddo
532
      out_vardim(3)=1
533
      call putdef(cdfid,varname,4,out_mdv,out_vardim,
534
     >            out_varmin,out_varmax,out_stag,ierr)         
535
      if (ierr.ne.0) goto 997
536
      call putdat(cdfid,varname,out_time,0,out_y,ierr)
537
      if (ierr.ne.0) goto 997
538
c     Close output file
539
      call clscdf(cdfid,ierr)
540
 
541
c     -----------------------------------------------------------------
542
c     Exception handling and format specs
543
c     -----------------------------------------------------------------
544
 
545
      stop
546
 
547
 998  print*,'Z: Problems with input lat/lon grid'
548
      stop
549
 
550
 997  print*,'Z: Problems with output to rotated grid'
551
      stop
552
 
553
      end
554
 
555
 
556
c     ********************************************************************************
557
c     * SUBROUTINE: ROTATION TO LOCAL CARTESIAN COORDINATE SYSTEM                    *
558
c     ********************************************************************************
559
 
560
c     --------------------------------------------------------------------------------
561
c     Subroutine to get environment (vector+scalar)
562
c     --------------------------------------------------------------------------------
563
 
564
      SUBROUTINE getenvir (clon,clat,rotation,rotmode,
565
     >                     inar,  dx, dy, xmin, ymin, nx, ny, nz,mdv,
566
     >                     outar,rdx,rdy,rxmin,rymin,rnx,rny,rnz)
567
 
568
c     Get an input field <inar> and the center <clon,clat> of a structure. The input 
569
c     array is defined on a lat/lon grid with grid specification <dx,dy,xmin,ymin,nx,ny>. 
570
c     The input field is then rotated to an output grid <rdx,rdy,rxmin,rymin,rnx,rny>, 
571
c     whereby the structure <clon,clat> is at the center of the new grid and the output 
572
c     grid is rotated with rotation angle <rotation>. This routine rotates the components
573
c     of a vector field for <rotmode=1|2>: <rotmode=1> refers to the x xomponent of the 
574
c     field, <rotmode=2> to the y component. If <rotmode=0>, scalar field is assumed.
575
 
576
      implicit none
577
 
578
c     Declaration of input parameters
579
      integer     nx,ny,nz
580
      real        dx,dy,xmin,ymin
581
      real        inar(nx,ny,nz)
582
      real        clon,clat,rotation
583
      real        mdv
584
      integer     rotmode
585
 
586
c     Declaration of output parameters
587
      integer     rnx,rny,rnz
588
      real        rdx,rdy,rxmin,rymin
589
      real        outar(rnx,rny,rnz)
590
 
591
c     Set numerical and physical constants
592
      real	  g2r
593
      parameter   (g2r=0.0174533)
594
      real        pi180
595
      parameter   (pi180=3.14159265359/180.)
596
      real        eps
597
      parameter   (eps=0.0001)
598
 
599
 
600
c     Flag for test mode
601
      integer      test
602
      parameter    (test=0)
603
      character*80 testfile
604
      parameter    (testfile='ROTGRID')
605
 
606
c     Auxiliary variables 
607
      real         pollon,pollat
608
      integer      i,j,k,l
609
      real         rlon1(rnx,rny),rlat1(rnx,rny)
610
      real         rlon2(rnx,rny),rlat2(rnx,rny)
611
      real         lon(rnx,rny),lat(rnx,rny)
612
      real         rotangle1(rnx,rny),rotangle2(rnx,rny)
613
      real         rotangle(rnx,rny)
614
      real         sinoutar(rnx,rny,rnz),cosoutar(rnx,rny,rnz)
615
      real         xmax,ymax
616
      real         xind,yind,pind
617
      real         outval
618
      integer      ix,iy
619
      real         ax,ay,az,bx,by,bz,zx,zy,zz
620
      real         clon1,clat1,clon2,clat2
621
      real         rindx,rindy
622
      integer      indx,indy,indr,indu
623
      real         frac0i,frac0j,frac1i,frac1j
624
      real         lonmean,latmean
625
      character*80 cdfname,varname,cstname
626
      real         vx1,vx2,vy1,vy2,angle,vx2min
627
      integer      s
628
 
629
c     Externals
630
      real         lmstolm,phstoph
631
      external     lmstolm,phstoph
632
 
633
c     Get rotated coordinates
634
      do i=1,rnx
635
         do j=1,rny               
636
            rlon1(i,j)=rxmin+real(i-1)*rdx
637
            rlat1(i,j)=rymin+real(j-1)*rdy
638
         enddo
639
      enddo
640
 
641
c     First coordinate transformation (make the local coordinate system parallel to equator)
642
      pollon=-180.
643
      pollat=90.+rotation
644
      do i=1,rnx
645
       do j=1,rny
646
         rlon2(i,j)=90.+lmstolm(rlat1(i,j),rlon1(i,j)-90.,pollat,pollon)
647
         rlat2(i,j)=phstoph(rlat1(i,j),rlon1(i,j)-90.,pollat,pollon)            
648
       enddo
649
      enddo
650
 
651
c     Second coordinate transformation (make the local coordinate system parallel to equator)
652
      pollon=clon-180.
653
      if (pollon.lt.-180.) pollon=pollon+360.
654
      pollat=90.-clat
655
      do i=1,rnx
656
         do j=1,rny               
657
            lon(i,j)=lmstolm(rlat2(i,j),rlon2(i,j),pollat,pollon)
658
            lat(i,j)=phstoph(rlat2(i,j),rlon2(i,j),pollat,pollon)            
659
         enddo
660
      enddo
661
 
662
c     Get the angle between the rotated and non-rotated coordinate frame
663
      if ((rotmode.eq.1).or.(rotmode.eq.2)) then
664
         do i=2,rnx-1
665
            do j=2,rny-1
666
 
667
c              Angle between latitude circles
668
               vx1=1.
669
               vy1=0.
670
               vx2min=(lon(i+1,j)-lon(i-1,j))*cos(pi180*lat(i,j))
671
               do s=-1,1,2
672
                  vx2=(lon(i+1,j)-lon(i-1,j)+real(s)*360.)*
673
     >                 cos(pi180*lat(i,j))
674
                  if (abs(vx2).lt.abs(vx2min)) vx2min=vx2
675
               enddo
676
               vx2=vx2min
677
               vy2=lat(i+1,j)-lat(i-1,j)
678
               call getangle(vx1,vy1,vx2,vy2,angle)           
679
               rotangle1(i,j)=angle
680
 
681
c              Angle between longitude circles
682
               vx1=0.
683
               vy1=1.
684
               vx2min=(lon(i,j+1)-lon(i,j-1))*cos(pi180*lat(i,j))
685
               do s=-1,1,2
686
                  vx2=(lon(i+1,j)-lon(i-1,j)+real(s)*360.)*
687
     >                 cos(pi180*lat(i,j))
688
                  if (abs(vx2).lt.abs(vx2min)) vx2min=vx2
689
               enddo
690
               vx2=vx2min
691
               vy2=lat(i,j+1)-lat(i,j-1)
692
               call getangle(vx1,vy1,vx2,vy2,angle)           
693
               rotangle2(i,j)=angle
694
 
695
            enddo
696
         enddo
697
 
698
c        Set the angle at the boundaries
699
         do i=1,rnx
700
            rotangle1(i,rny)=2.0*rotangle1(i,rny-1)-rotangle1(i,rny-2)
701
            rotangle1(i,1)  =2.0*rotangle1(i,2)-rotangle1(i,3)
702
            rotangle2(i,rny)=2.0*rotangle2(i,rny-1)-rotangle2(i,rny-2)
703
            rotangle2(i,1)  =2.0*rotangle2(i,2)-rotangle2(i,3)
704
         enddo
705
         do j=1,rny
706
            rotangle1(rnx,j)=2.0*rotangle1(rnx-1,j)-rotangle1(rnx-2,j)
707
            rotangle1(1,j)  =2.0*rotangle1(2,j)-rotangle1(3,j)
708
            rotangle2(rnx,j)=2.0*rotangle2(rnx-1,j)-rotangle2(rnx-2,j)
709
            rotangle2(1,j)  =2.0*rotangle2(2,j)-rotangle2(3,j)
710
         enddo   
711
 
712
c        Set the final rotation angle
713
         do i=1,rnx
714
            do j=1,rny
715
               rotangle(i,j)=0.5*(rotangle1(i,j)+rotangle2(i,j))
716
            enddo
717
         enddo
718
 
719
      endif
720
 
721
c     Bring longitude into domain of geographical grid (shift by 360 deg)
722
      do i=1,rnx
723
         do j=1,rny
724
 100        if (lon(i,j).lt.xmin) then
725
               lon(i,j)=lon(i,j)+360.
726
               goto 100
727
            endif
728
 102        if (lon(i,j).gt.(xmin+real(nx-1)*dx)) then
729
               lon(i,j)=lon(i,j)-360.
730
               goto 102
731
            endif
732
         enddo
733
      enddo
734
 
735
c     Rotate the scalar or the vector component
736
      do i=1,rnx
737
         do j=1,rny
738
            do k=1,rnz   
739
 
740
c              Get index
741
               rindx=(lon(i,j)-xmin)/dx+1.
742
               rindy=(lat(i,j)-ymin)/dy+1.
743
               indx=int(rindx)
744
               indy=int(rindy)
745
               if ((indx.lt.1).or.(indx.gt.nx).or.
746
     >             (indy.lt.1).or.(indy.gt.ny)) then
747
                  print*,'lat/lon interpolation not possible....'
748
                  print*,i,j,k,indx,indy,lon(i,j),lat(i,j)
749
                  stop
750
               endif
751
 
752
c              Get inidices of left and upper neighbours
753
               indr=indx+1
754
               if (indr.gt.nx) indr=1
755
               indu=indy+1
756
               if (indu.gt.ny) indu=ny
757
 
758
c              Do linear interpolation
759
               if ( ( abs(inar(indx ,indy, k)-mdv).gt.eps ).and.
760
     &              ( abs(inar(indx ,indu, k)-mdv).gt.eps ).and.
761
     &              ( abs(inar(indr ,indy, k)-mdv).gt.eps ).and.
762
     &              ( abs(inar(indr ,indu, k)-mdv).gt.eps ) ) then
763
                  frac0i=rindx-float(indx)
764
                  frac0j=rindy-float(indy)
765
                  frac1i=1.-frac0i
766
                  frac1j=1.-frac0j
767
                  outval = inar(indx ,indy, k ) * frac1i * frac1j
768
     &                   + inar(indx ,indu, k ) * frac1i * frac0j
769
     &                   + inar(indr ,indy, k ) * frac0i * frac1j
770
     &                   + inar(indr ,indu, k ) * frac0i * frac0j
771
               else
772
                  outval=mdv
773
               endif                  
774
 
775
c              Update output array
776
               outar(i,j,k)=outval
777
 
778
            enddo            
779
         enddo
780
      enddo      
781
 
782
c     Get components for tests
783
      if (test.eq.1) then
784
         do i=1,rnx
785
            do j=1,rny
786
               do k=1,rnz
787
                  cosoutar(i,j,k)=outar(i,j,k)*cos(pi180*rotangle(i,j))
788
                  sinoutar(i,j,k)=-outar(i,j,k)*sin(pi180*rotangle(i,j))
789
               enddo
790
            enddo
791
         enddo         
792
      endif
793
 
794
c     Get correct component of rotated field
795
      do i=1,rnx
796
         do j=1,rny
797
            do k=1,rnz
798
               if ( abs(outar(i,j,k)-mdv).gt.eps ) then
799
                  if (rotmode.eq.1) then
800
                     outar(i,j,k)= outar(i,j,k)*cos(pi180*rotangle(i,j))
801
                  else if (rotmode.eq.2) then
802
                     outar(i,j,k)=-outar(i,j,k)*sin(pi180*rotangle(i,j))
803
                  else if (rotmode.eq.0) then
804
                     outar(i,j,k)=outar(i,j,k)
805
                  endif
806
               endif
807
            enddo
808
         enddo
809
      enddo
810
 
811
c     Test mode: Write grids to cdf file
812
      if (test.eq.1) then
813
         cdfname=testfile
814
         cstname=trim(testfile)//'_cst'
815
         varname='RLON1'
816
         call  writecdf2D(cdfname,cstname,
817
     >                    varname,rlon1,0.,
818
     >                    rdx,rdy,rxmin,rymin,rnx,rny,
819
     >                    1,1)
820
         cdfname=testfile
821
         cstname=trim(testfile)//'_cst'
822
         varname='RLON2'
823
         call  writecdf2D(cdfname,cstname,
824
     >                    varname,rlon2,0.,
825
     >                    rdx,rdy,rxmin,rymin,rnx,rny,
826
     >                    0,1)
827
         cdfname=testfile
828
         cstname=trim(testfile)//'_cst'
829
         varname='LON'
830
         call  writecdf2D(cdfname,cstname,
831
     >                    varname,lon,0.,
832
     >                    rdx,rdy,rxmin,rymin,rnx,rny,
833
     >                    0,1)
834
         cdfname=testfile
835
         cstname=trim(testfile)//'_cst'
836
         varname='RLAT1'
837
         call  writecdf2D(cdfname,cstname,
838
     >                    varname,rlat1,0.,
839
     >                    rdx,rdy,rxmin,rymin,rnx,rny,
840
     >                    0,1)
841
         cdfname=testfile
842
         cstname=trim(testfile)//'_cst'
843
         varname='RLAT2'
844
         call  writecdf2D(cdfname,cstname,
845
     >                    varname,rlat2,0.,
846
     >                    rdx,rdy,rxmin,rymin,rnx,rny,
847
     >                    0,1)
848
         cdfname=testfile
849
         cstname=trim(testfile)//'_cst'
850
         varname='LAT'
851
         call  writecdf2D(cdfname,cstname,
852
     >                    varname,lat,0.,
853
     >                    rdx,rdy,rxmin,rymin,rnx,rny,
854
     >                    0,1)
855
         cdfname=testfile
856
         cstname=trim(testfile)//'_cst'
857
         varname='ANGLE1'
858
         call  writecdf2D(cdfname,cstname,
859
     >                    varname,rotangle1,0.,
860
     >                    rdx,rdy,rxmin,rymin,rnx,rny,
861
     >                    0,1)
862
         cdfname=testfile
863
         cstname=trim(testfile)//'_cst'
864
         varname='ANGLE2'
865
         call  writecdf2D(cdfname,cstname,
866
     >                    varname,rotangle2,0.,
867
     >                    rdx,rdy,rxmin,rymin,rnx,rny,
868
     >                    0,1)
869
         cdfname=testfile
870
         cstname=trim(testfile)//'_cst'
871
         varname='U'
872
         call  writecdf2D(cdfname,cstname,
873
     >                    varname,cosoutar,0.,
874
     >                    rdx,rdy,rxmin,rymin,rnx,rny,
875
     >                    0,1)
876
         cdfname=testfile
877
         cstname=trim(testfile)//'_cst'
878
         varname='V'
879
         call  writecdf2D(cdfname,cstname,
880
     >                    varname,sinoutar,0.,
881
     >                    rdx,rdy,rxmin,rymin,rnx,rny,
882
     >                    0,1)
883
 
884
      endif
885
 
886
      END
887
 
888
 
889
c     --------------------------------------------------------------------------------
890
c     Auxiliary routines: angle between two vectors
891
c     --------------------------------------------------------------------------------
892
 
893
      SUBROUTINE getangle (vx1,vy1,vx2,vy2,angle)
894
 
895
c     Given two vectors <vx1,vy1> and <vx2,vy2>, determine the angle (in deg)
896
c     between the two vectors.
897
 
898
      implicit none
899
 
900
c     Declaration of subroutine parameters
901
      real vx1,vy1
902
      real vx2,vy2
903
      real angle
904
 
905
c     Auxiliary variables and parameters
906
      real len1,len2,len3
907
      real val1,val2,val3
908
      real pi
909
      parameter (pi=3.14159265359)
910
 
911
      len1=sqrt(vx1*vx1+vy1*vy1)
912
      len2=sqrt(vx2*vx2+vy2*vy2)
913
 
914
      if ((len1.gt.0.).and.(len2.gt.0.)) then
915
         vx1=vx1/len1
916
         vy1=vy1/len1
917
         vx2=vx2/len2
918
         vy2=vy2/len2
919
 
920
         val1=vx1*vx2+vy1*vy2
921
         val2=-vy1*vx2+vx1*vy2
922
 
923
         len3=sqrt(val1*val1+val2*val2)
924
 
925
         if ( (val1.ge.0.).and.(val2.ge.0.) ) then
926
            val3=acos(val1/len3)
927
         else if ( (val1.lt.0.).and.(val2.ge.0.) ) then
928
            val3=pi-acos(abs(val1)/len3)
929
         else if ( (val1.ge.0.).and.(val2.le.0.) ) then
930
            val3=-acos(val1/len3)
931
         else if ( (val1.lt.0.).and.(val2.le.0.) ) then
932
            val3=-pi+acos(abs(val1)/len3)
933
         endif
934
      else
935
         val3=0.
936
      endif
937
 
938
      angle=180./pi*val3
939
 
940
      END
941
 
942
c     --------------------------------------------------------------------------------
943
c     Transformation routine: LMSTOLM and PHSTOPH from library gm2em
944
c     --------------------------------------------------------------------------------
945
 
946
      REAL FUNCTION LMSTOLM (PHIS, LAMS, POLPHI, POLLAM)
947
C
948
C**** LMSTOLM  -   FC:BERECHNUNG DER WAHREN GEOGRAPHISCHEN LAENGE FUER
949
C****                 EINEN PUNKT MIT DEN KOORDINATEN (PHIS, LAMS)
950
C****                 IM ROTIERTEN SYSTEM. DER NORDPOL DES SYSTEMS HAT
951
C****                 DIE WAHREN KOORDINATEN (POLPHI, POLLAM)
952
C**   AUFRUF   :   LAM = LMSTOLM (PHIS, LAMS, POLPHI, POLLAM)
953
C**   ENTRIES  :   KEINE
954
C**   ZWECK    :   BERECHNUNG DER WAHREN GEOGRAPHISCHEN LAENGE FUER
955
C**                EINEN PUNKT MIT DEN KOORDINATEN (PHIS, LAMS)
956
C**                IM ROTIERTEN SYSTEM. DER NORDPOL DIESES SYSTEMS HAT
957
C**                DIE WAHREN KOORDINATEN (POLPHI, POLLAM)
958
C**   VERSIONS-
959
C**   DATUM    :   03.05.90
960
C**
961
C**   EXTERNALS:   KEINE
962
C**   EINGABE-
963
C**   PARAMETER:   PHIS     REAL   GEOGR. BREITE DES PUNKTES IM ROT.SYS.
964
C**                LAMS     REAL   GEOGR. LAENGE DES PUNKTES IM ROT.SYS.
965
C**                POLPHI   REAL   WAHRE GEOGR. BREITE DES NORDPOLS
966
C**                POLLAM   REAL   WAHRE GEOGR. LAENGE DES NORDPOLS
967
C**   AUSGABE-
968
C**   PARAMETER:   WAHRE GEOGRAPHISCHE LAENGE ALS WERT DER FUNKTION
969
C**                ALLE WINKEL IN GRAD (NORDEN>0, OSTEN>0)
970
C**
971
C**   COMMON-
972
C**   BLOECKE  :   KEINE
973
C**
974
C**   FEHLERBE-
975
C**   HANDLUNG :   KEINE
976
C**   VERFASSER:   D.MAJEWSKI
977
 
978
      REAL        LAMS,PHIS,POLPHI,POLLAM
979
 
980
      DATA        ZRPI18 , ZPIR18  / 57.2957795 , 0.0174532925 /
981
 
982
      ZSINPOL = SIN(ZPIR18*POLPHI)
983
      ZCOSPOL = COS(ZPIR18*POLPHI)
984
      ZLAMPOL = ZPIR18*POLLAM
985
      ZPHIS   = ZPIR18*PHIS
986
      ZLAMS   = LAMS
987
      IF(ZLAMS.GT.180.0) ZLAMS = ZLAMS - 360.0
988
      ZLAMS   = ZPIR18*ZLAMS
989
 
990
      ZARG1   = SIN(ZLAMPOL)*(- ZSINPOL*COS(ZLAMS)*COS(ZPHIS)  +
991
     1                          ZCOSPOL*           SIN(ZPHIS)) -
992
     2          COS(ZLAMPOL)*           SIN(ZLAMS)*COS(ZPHIS)
993
      ZARG2   = COS(ZLAMPOL)*(- ZSINPOL*COS(ZLAMS)*COS(ZPHIS)  +
994
     1                          ZCOSPOL*           SIN(ZPHIS)) +
995
     2          SIN(ZLAMPOL)*           SIN(ZLAMS)*COS(ZPHIS)
996
      IF (ABS(ZARG2).LT.1.E-30) THEN
997
        IF (ABS(ZARG1).LT.1.E-30) THEN
998
          LMSTOLM =   0.0
999
        ELSEIF (ZARG1.GT.0.) THEN
1000
              LMSTOLAM =  90.0
1001
            ELSE
1002
              LMSTOLAM = -90.0
1003
            ENDIF
1004
      ELSE
1005
        LMSTOLM = ZRPI18*ATAN2(ZARG1,ZARG2)
1006
      ENDIF
1007
 
1008
      RETURN
1009
      END
1010
 
1011
 
1012
      REAL FUNCTION PHSTOPH (PHIS, LAMS, POLPHI, POLLAM)
1013
C
1014
C**** PHSTOPH  -   FC:BERECHNUNG DER WAHREN GEOGRAPHISCHEN BREITE FUER
1015
C****                 EINEN PUNKT MIT DEN KOORDINATEN (PHIS, LAMS) IM
1016
C****                 ROTIERTEN SYSTEM. DER NORDPOL DIESES SYSTEMS HAT
1017
C****                 DIE WAHREN KOORDINATEN (POLPHI, POLLAM)
1018
C**   AUFRUF   :   PHI = PHSTOPH (PHIS, LAMS, POLPHI, POLLAM)
1019
C**   ENTRIES  :   KEINE
1020
C**   ZWECK    :   BERECHNUNG DER WAHREN GEOGRAPHISCHEN BREITE FUER
1021
C**                EINEN PUNKT MIT DEN KOORDINATEN (PHIS, LAMS) IM
1022
C**                ROTIERTEN SYSTEM. DER NORDPOL DIESES SYSTEMS HAT
1023
C**                DIE WAHREN KOORDINATEN (POLPHI, POLLAM)
1024
C**   VERSIONS-
1025
C**   DATUM    :   03.05.90
1026
C**
1027
C**   EXTERNALS:   KEINE
1028
C**   EINGABE-
1029
C**   PARAMETER:   PHIS     REAL   GEOGR. BREITE DES PUNKTES IM ROT.SYS.
1030
C**                LAMS     REAL   GEOGR. LAENGE DES PUNKTES IM ROT.SYS.
1031
C**                POLPHI   REAL   WAHRE GEOGR. BREITE DES NORDPOLS
1032
C**                POLLAM   REAL   WAHRE GEOGR. LAENGE DES NORDPOLS
1033
C**   AUSGABE-
1034
C**   PARAMETER:   WAHRE GEOGRAPHISCHE BREITE ALS WERT DER FUNKTION
1035
C**                ALLE WINKEL IN GRAD (NORDEN>0, OSTEN>0)
1036
C**
1037
C**   COMMON-
1038
C**   BLOECKE  :   KEINE
1039
C**
1040
C**   FEHLERBE-
1041
C**   HANDLUNG :   KEINE
1042
C**   VERFASSER:   D.MAJEWSKI
1043
 
1044
      REAL        LAMS,PHIS,POLPHI,POLLAM
1045
 
1046
      DATA        ZRPI18 , ZPIR18  / 57.2957795 , 0.0174532925 /
1047
 
1048
      SINPOL = SIN(ZPIR18*POLPHI)
1049
      COSPOL = COS(ZPIR18*POLPHI)
1050
      ZPHIS  = ZPIR18*PHIS
1051
      ZLAMS  = LAMS
1052
      IF(ZLAMS.GT.180.0) ZLAMS = ZLAMS - 360.0
1053
      ZLAMS  = ZPIR18*ZLAMS
1054
      ARG     = COSPOL*COS(ZPHIS)*COS(ZLAMS) + SINPOL*SIN(ZPHIS)
1055
 
1056
      PHSTOPH = ZRPI18*ASIN(ARG)
1057
 
1058
      RETURN
1059
      END
1060
 
1061
 
1062
c     ---------------------------------------------------------
1063
c     Spherical distance between two lat/lon points
1064
c     ---------------------------------------------------------
1065
 
1066
      real function sdis(xp,yp,xq,yq)
1067
c
1068
c     calculates spherical distance (in km) between two points given
1069
c     by their spherical coordinates (xp,yp) and (xq,yq), respectively.
1070
c
1071
      real      re
1072
      parameter (re=6370.)
1073
      real      xp,yp,xq,yq,arg
1074
 
1075
      arg=sind(yp)*sind(yq)+cosd(yp)*cosd(yq)*cosd(xp-xq)
1076
      if (arg.lt.-1.) arg=-1.
1077
      if (arg.gt.1.) arg=1.
1078
      sdis=re*acos(arg)
1079
 
1080
      end
1081
 
1082
 
1083
c     ********************************************************************************
1084
c     * NETCDF INPUT/OUTPUT                                                          *
1085
c     ********************************************************************************
1086
 
1087
c     ---------------------------------------------------------
1088
c     Subroutines to write the netcdf output file
1089
c     ---------------------------------------------------------
1090
 
1091
      subroutine writecdf2D(cdfname,cstname,
1092
     >                      varname,arr,ctime,
1093
     >                      dx,dy,xmin,ymin,nx,ny,
1094
     >                      crefile,crevar)
1095
 
1096
c     Create and write to the netcdf file <cdfname>. The variable
1097
c     with name <varname> and with time <time> is written. The data
1098
c     are in the two-dimensional array <arr>. The list <dx,dy,xmin,
1099
c     ymin,nx,ny> specifies the output grid. The flags <crefile> and
1100
c     <crevar> determine whether the file and/or the variable should
1101
c     be created. 1: create / 0: not created
1102
 
1103
      IMPLICIT NONE
1104
 
1105
c     Declaration of input parameters
1106
      character*80 cdfname,cstname,varname
1107
      integer      nx,ny
1108
      real         arr(nx,ny)
1109
      real         dx,dy,xmin,ymin
1110
      integer      ctime
1111
      integer      crefile,crevar
1112
 
1113
c     Further variables
1114
      real         varmin(4),varmax(4),stag(4)
1115
      integer      ierr,cdfid,ndim,vardim(4)
1116
      real         mdv
1117
      integer      datar(14),stdate(5)
1118
      integer      i
1119
      real         time
1120
 
1121
C     Definitions 
1122
      varmin(1)=xmin
1123
      varmin(2)=ymin
1124
      varmin(3)=1050.
1125
      varmax(1)=xmin+real(nx-1)*dx
1126
      varmax(2)=ymin+real(ny-1)*dy
1127
      varmax(3)=1050.
1128
      ndim=4
1129
      vardim(1)=nx
1130
      vardim(2)=ny
1131
      vardim(3)=1
1132
      stag(1)=0.
1133
      stag(2)=0.
1134
      stag(3)=0.
1135
      mdv=-999.98999
1136
      time=real(ctime)
1137
 
1138
C     Create the file
1139
      if (crefile.eq.0) then
1140
         call cdfwopn(cdfname,cdfid,ierr)
1141
         if (ierr.ne.0) goto 906
1142
      else if (crefile.eq.1) then
1143
         call crecdf(cdfname,cdfid,
1144
     >        varmin,varmax,ndim,cstname,ierr)
1145
         if (ierr.ne.0) goto 903 
1146
 
1147
C        Write the constants file
1148
         datar(1)=vardim(1)
1149
         datar(2)=vardim(2)
1150
         datar(3)=int(1000.*varmax(2))
1151
         datar(4)=int(1000.*varmin(1))
1152
         datar(5)=int(1000.*varmin(2))
1153
         datar(6)=int(1000.*varmax(1))
1154
         datar(7)=int(1000.*dx)
1155
         datar(8)=int(1000.*dy)
1156
         datar(9)=1
1157
         datar(10)=1
1158
         datar(11)=0            ! data version
1159
         datar(12)=0            ! cstfile version
1160
         datar(13)=0            ! longitude of pole
1161
         datar(14)=90000        ! latitude of pole     
1162
         do i=1,5
1163
            stdate(i)=0
1164
         enddo
1165
         call wricst(cstname,datar,0.,0.,0.,0.,stdate)
1166
      endif
1167
 
1168
c     Write the data to the netcdf file, and close the file
1169
      if (crevar.eq.1) then
1170
         call putdef(cdfid,varname,ndim,mdv,
1171
     >        vardim,varmin,varmax,stag,ierr)
1172
         if (ierr.ne.0) goto 904
1173
      endif
1174
      call putdat(cdfid,varname,time,0,arr,ierr)
1175
      if (ierr.ne.0) goto 905
1176
      call clscdf(cdfid,ierr)
1177
 
1178
      return
1179
 
1180
c     Error handling
1181
 903  print*,'*** Problem to create netcdf file ***'
1182
      stop
1183
 904  print*,'*** Problem to write definition ***'
1184
      stop
1185
 905  print*,'*** Problem to write data ***'
1186
      stop
1187
 906  print*,'*** Problem to open netcdf file ***'
1188
      stop
1189
 
1190
      END
1191
 
1192
c     ----------------------------------------------------------------
1193
c     Check whether variable is found on netcdf file
1194
c     ----------------------------------------------------------------
1195
 
1196
      subroutine check_varok (isok,varname,varlist,nvars)
1197
 
1198
c     Check whether the variable <varname> is in the list <varlist(nvars)>.
1199
c     If this is the case, <isok> is incremented by 1. Otherwise <isok>
1200
c     keeps its value.
1201
 
1202
      implicit none
1203
 
1204
c     Declaraion of subroutine parameters
1205
      integer      isok
1206
      integer      nvars
1207
      character*80 varname
1208
      character*80 varlist(nvars)
1209
 
1210
c     Auxiliary variables
1211
      integer      i
1212
 
1213
c     Main
1214
      do i=1,nvars
1215
         if (trim(varname).eq.trim(varlist(i))) isok=isok+1
1216
      enddo
1217
 
1218
      end