Subversion Repositories lagranto.um

Rev

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

Rev Author Line No. Line
7 michaesp 1
      PROGRAM startf
2
 
3
c     **************************************************************
4
c     * Create a <startfile> for <lagrangto>. It can be chosen     *
5
c     * whether to start from an isentropic or an isobaric         *
6
c     * surface. The starting points are equidistantly distributed *
7
c     * Michael Sprenger / Autumn 2004                             *
8
c     **************************************************************
9
 
10
      implicit none
11
 
12
 
13
c     --------------------------------------------------------------
14
c     Set parameters
15
c     --------------------------------------------------------------
16
 
17
c     Maximum number of starting positions
18
      integer           nmax
19
      parameter         (nmax=1000000)
20
 
21
c     Maximum number of model levels
22
      integer           nlevmax
23
      parameter         (nlevmax=200)
24
 
25
c     Grid constant (distance in km corresponding to 1 deg at the equator)
26
      real              deltat
27
      parameter         (deltat=111.)
28
 
29
c     Mathematical constant (conversion degree -> radian)
30
      real              pi180
31
      parameter         (pi180=3.14159/180.)
32
 
33
c     Numerical epsilon
34
      real              eps
35
      parameter         (eps=0.00001)
36
 
37
c     --------------------------------------------------------------
38
c     Set variables
39
c     --------------------------------------------------------------
40
 
41
c     Filenames and output format
42
      character*80      pfile0,pfile1                  ! P filenames
43
      character*80      sfile0,sfile1                  ! S filenames
44
      character*80      ofile                          ! Output filename
45
      integer           oformat                        ! Output format
46
      real              timeshift                      ! Time shift relative to data files <*0>
47
      real              timeinc                        ! Time increment between input files
48
 
49
c     Horizontal grid
50
      character*80      hmode                          ! Horizontale mode
51
      real              lat1,lat2,lon1,lon2            ! Lat/lon boundaries
52
      real              ds,dlon,dlat                   ! Distance and lat/lon shifts
53
      character*80      hfile                          ! Filename
54
      integer           hn                             ! Number of entries in lat/lon list 
55
      real              latlist(nmax)                  ! List of latitudes
56
      real              lonlist(nmax)                  ! List of longitudes
57
      integer           pn                             ! Number of entries in lat/lon poly
58
      real              latpoly(500)                   ! List of polygon latitudes
59
      real              lonpoly(500)                   ! List of polygon longitudes
60
      real              loninpoly,latinpoly            ! Lon/lat inside polygon
61
      character*80      regionf                        ! Region file
62
      integer           iregion                        ! Region number
63
      real              xcorner(4),ycorner(4)          ! Vertices of region
64
 
65
c     Vertical grid
66
      character*80      vmode                          ! Vertical mode
67
      real              lev1,lev2,levlist(nmax)        ! Single levels, and list of levels
68
      character*80      vfile                          ! Filename
69
      integer           vn                             ! Number of entries
70
 
71
c     Unit of vertical axis
72
      character*80      umode                          ! Unit of vertical axis
73
 
74
c     Flag for 'no time check'
75
      character*80      timecheck                      ! Either 'no' or 'yes'
76
 
77
c     List of all starting positions
78
      integer           start_n                        ! Number of coordinates
79
      real              start_lat(nmax)                ! Latitudes
80
      real              start_lon(nmax)                ! Longitudes
81
      real              start_lev(nmax)                ! Levels (depending on vertical unit)
82
      real              start_pre(nmax)                ! Level in hPa
83
      integer           reftime(6)                     ! Reference time
84
      character*80      vars(10)                       ! Name of output fields (time,lon,lat,p)
85
      real,allocatable, dimension (:,:,:) :: tra       ! Trajectories (ntra,ntim,ncol)
86
      real              latmin,latmax
87
      real              lonmin,lonmax
88
      real              premin,premax
89
 
90
c     Grid description
91
      real              pollon,pollat                  ! Longitude/latitude of pole
92
      real              ak(nlevmax)                    ! Vertical layers and levels
93
      real              bk(nlevmax)
94
      real              xmin,xmax                      ! Zonal grid extension
95
      real              ymin,ymax                      ! Meridional grid extension
96
      integer           nx,ny,nz                       ! Grid dimensions
97
      real              dx,dy                          ! Horizontal grid resolution
98
      real,allocatable, dimension (:,:,:) :: pr        ! 3d pressure
99
      real,allocatable, dimension (:,:)   :: prs       ! surface pressure
100
      real,allocatable, dimension (:,:,:) :: th        ! 3d potential temperature
101
      real,allocatable, dimension (:,:)   :: ths       ! surface poential temperature
102
      real,allocatable, dimension (:,:,:) :: pv        ! 3d potential vorticity
103
      real,allocatable, dimension (:,:)   :: pvs       ! surface potential vorticiy
104
      character*80      varname                        ! Name of input variable
105
      integer           fid                            ! File identifier
106
      real              stagz                          ! Vertical staggering
107
      real              mdv                            ! Missing data values
108
      real              tstart,tend                    ! Time on P and S file
109
      real              rid,rjd,rkd                    ! Real grid position
110
      integer           rotategrid                     ! Flag whether to rotate grid
111
 
112
c     Auxiliary variable
113
      integer           i,j,k
114
      real              lon,lat,rlon,rlat
115
      real              rd
116
      integer           stat,flag
117
      real              tmp1,tmp2
118
      real              tfrac,frac
119
      real              radius,dist
120
      character*80      string
16 michaesp 121
      character*80      selectstr  
122
      integer           noutside 
7 michaesp 123
      real,allocatable, dimension (:,:,:) :: fld0
124
      real,allocatable, dimension (:,:,:) :: fld1
125
      real,allocatable, dimension (:,:  ) :: sfc0
126
      real,allocatable, dimension (:,:)   :: sfc1
127
 
128
c     Externals 
129
      real              int_index3     ! 3d interpolation
130
      external          int_index3
131
      real              sdis           ! Speherical distance
132
      external          sdis
133
      integer           inregion       ! In/out of region
134
      external          inrehion
135
      real              lmtolms        ! Grid rotation
136
      real              phtophs    
137
      real              lmstolm
138
      real              phstoph        
139
      external          lmtolms,phtophs,lmstolm,phstoph
140
 
141
c     ------------------------------------------------------------------
142
c     Start of program, Read parameters
143
c     ------------------------------------------------------------------
144
 
145
c     Write start message
146
      print*,'========================================================='
147
      print*,'         *** START OF PROGRAM CREATE_STARTF ***'
148
      print*
149
 
150
c     Read parameter file
151
      open(10,file='startf.param')
152
 
153
c      Input P and S file
154
       read(10,*) pfile0,pfile1
155
       read(10,*) sfile0,sfile1
156
       read(10,*) ofile
157
 
158
c      Read name of region file
159
       read(10,*) regionf
160
 
161
c      Reference time
162
       do i=1,6
163
          read(10,*) reftime(i)
164
       enddo
165
 
166
c      Time shift relative to data files <pfile0,sfile0> - format (hh.mm)
167
       read(10,*) timeshift
168
 
169
c      Read timeincrement between input files
170
       read(10,*) timeinc
171
 
172
c      Parameters for horizontal grid
173
       read(10,*) hmode
174
       if ( hmode.eq.'file' ) then                  ! from file
175
          read(10,*) hfile
176
       elseif ( hmode.eq.'line' ) then              ! along a line
177
          read(10,*) lon1,lon2,lat1,lat2,hn
178
       elseif ( hmode.eq.'box.eqd' ) then           ! box: 2d equidistant
179
          read(10,*) lon1,lon2,lat1,lat2,ds
180
       elseif ( hmode.eq.'box.grid' ) then          ! box: 2d grid
181
          read(10,*) lon1,lon2,lat1,lat2
182
       elseif ( hmode.eq.'point' ) then             ! single point
183
          read(10,*) lon1,lat1
184
       elseif ( hmode.eq.'shift' ) then             ! centre + shifted
185
          read(10,*) lon1,lat1,dlon,dlat
186
       elseif ( hmode.eq.'polygon.eqd' ) then       ! polygon: 2d equidistant
187
          read(10,*) hfile,ds
188
       elseif ( hmode.eq.'polygon.grid' ) then      ! polygon: 2d grid
189
          read(10,*) hfile
190
       elseif ( hmode.eq.'circle.eqd' ) then        ! circle: 2d equidistant
191
          read(10,*) lon1,lat1,radius,ds 
192
       elseif ( hmode.eq.'circle.grid' ) then       ! circle: 2d grid
193
          read(10,*) lon1,lat1,radius
194
       elseif ( hmode.eq.'region.eqd' ) then        ! region: 2d equidistant
195
          read(10,*) iregion,ds 
196
       elseif ( hmode.eq.'region.grid' ) then       ! iregion: 2d grid
197
          read(10,*) iregion
198
       else
199
          print*,' ERROR: horizontal mode not supported ',trim(hmode)
200
          stop
201
       endif
202
 
203
c      Parameters for vertical grid
204
       read(10,*) vmode
205
       if ( vmode.eq.'file') then                   ! from file
206
          read(10,*) vfile
207
       elseif ( vmode.eq.'level' ) then             ! single level (explicit command)
208
          read(10,*) lev1                         
209
       elseif ( vmode.eq.'list') then               ! a list
210
          read(10,*) vn
211
          read(10,*) (levlist(i),i=1,vn)
212
       elseif ( vmode.eq.'profile') then            ! a profile
213
          read(10,*) lev1,lev2,vn
214
       elseif ( vmode.eq.'nil') then                ! assume that vertzical positions are on file
215
          continue
216
       else
217
          print*,' ERROR: vertical mode not supported ',trim(vmode)
218
          stop
219
       endif
220
 
221
c      Read units of vertical axis
222
       read(10,*) umode
223
       if ( ( umode.ne.'hPa'     ).and.
224
     >      ( umode.ne.'hPa,agl' ).and.   
225
     >      ( umode.ne.'K'       ).and.
226
     >      ( umode.ne.'PVU'     ) ) 
227
     > then  
228
          print*,' ERROR: unit not supported ',trim(umode)
229
          stop
230
       endif
231
 
232
c     Read select string (dummy read)
233
      read(10,*) selectstr
234
 
235
c     Read flag for 'no time check'
236
      read(10,*) timecheck 
237
 
238
c     Close parameter file
239
      close(10)
240
 
241
c     Decide which output format is used (1..4: trajectory format, -1: triple list)
242
      call mode_tra(oformat,ofile)
243
 
244
c     Decide whether all lat/lon/lev coordaintes are read from one file
245
      if ( (hmode.eq.'file').and.(vmode.eq.'nil') ) then
246
         hmode='file3'
247
      elseif ( (hmode.eq.'file').and.(vmode.ne.'nil') ) then
248
         hmode='file2'
249
      endif
250
 
251
c     Convert timeshift (hh.mm) into a fractional time shift
252
      call hhmm2frac(timeshift,tfrac)
253
      if (tfrac.gt.0.) then
254
         tfrac=tfrac/timeinc
255
      else
256
         tfrac=0.
257
      endif
258
 
259
c     Read the region coordinates if needed
260
      if ( (hmode.eq.'region.eqd' ).or.
261
     >     (hmode.eq.'region.grid') ) then
262
 
263
         open(10,file=regionf)
264
 
265
 50       read(10,*,end=51) string
266
 
267
          if ( string(1:1).ne.'#' ) then
268
             call regionsplit(string,i,xcorner,ycorner)
269
             if ( i.eq.iregion ) goto 52
270
          endif
271
 
272
          goto 50
273
 
274
 51      close(10)
275
 
276
         print*,' ERROR: region ',iregion,' not found on ',trim(regionf)
277
         stop
278
 
279
 52      continue
280
 
281
      endif
282
 
283
c     Write some status information
284
      print*,'---- INPUT PARAMETERS -----------------------------------'
285
      print*
286
      if ( timeshift.gt.0. ) then
287
         print*,'  P file                     : ',trim(pfile0),
288
     >                                            ' ',
289
     >                                            trim(pfile1)
290
         print*,'  S file                     : ',trim(sfile0),
291
     >                                            ' ',
292
     >                                            trim(sfile1)
293
      else
294
         print*,'  P file                     : ',trim(pfile0)
295
         print*,'  S file                     : ',trim(sfile0)
296
      endif
297
      print*,'  Output file                : ',trim(ofile) 
298
      print*
299
      if (oformat.eq.-1) then
300
         print*,'  Output format              : (lon,lat,lev)-list'
301
      else
302
         print*,'  Output format              : ',oformat
303
      endif
304
      print*
305
      print*,'  Reference time (year)      : ',reftime(1)
306
      print*,'                 (month)     : ',reftime(2)
307
      print*,'                 (day)       : ',reftime(3)
308
      print*,'                 (hour)      : ',reftime(4)
309
      print*,'                 (min)       : ',reftime(5)
310
      print*,'  Time range                 : ',reftime(6)
311
      print*
312
      print*,'  Time shift                 : ',timeshift,' + ',
313
     >                                         trim(pfile0)
314
      print*,'  Region file                : ',trim(regionf)
315
      print*
316
      print*,'  hmode                      : ',trim(hmode)
317
      if ( hmode.eq.'file2' ) then        
318
        print*,'      filename [lat/lon]      : ',trim(hfile)
319
      elseif ( hmode.eq.'file3' ) then        
320
        print*,'      filename [lat/lon/lev]  : ',trim(hfile)
321
      elseif ( hmode.eq.'line' ) then   
322
        write(*,'(a30,4f10.2,i4)') 
323
     >         '      lon1,lon2,lat1,lat2,n   : ',lon1,lon2,lat1,lat2,hn
324
      elseif ( hmode.eq.'box.eqd' ) then     
325
        write(*,'(a30,5f10.2)') 
326
     >         '      lon1,lon2,lat1,lat2,ds  : ',lon1,lon2,lat1,lat2,ds
327
      elseif ( hmode.eq.'box.grid' ) then    
328
        write(*,'(a30,4f10.2)') 
329
     >         '      lon1,lon2,lat1,lat2     : ',lon1,lon2,lat1,lat2 
330
      elseif ( hmode.eq.'point' ) then   
331
        print*,'      lon,lat                 : ',lon1,lat1
332
      elseif ( hmode.eq.'shift' ) then   
333
        write(*,'(a30,4f10.2)') 
334
     >         '      lon,lat,dlon,dlat       : ',lon1,lat1,dlon,dlat
335
      elseif ( hmode.eq.'polygon.eqd' ) then   
336
        write(*,'(a30,a10,f10.2)') 
337
     >         '      hfile, ds               : ',trim(hfile),ds
338
      elseif ( hmode.eq.'polygon.grid' ) then   
339
        write(*,'(a30,a10)') 
340
     >         '      hfile                   : ',trim(hfile)
341
      elseif ( hmode.eq.'circle.eqd' ) then   
342
        write(*,'(a30,4f10.2)') 
343
     >         '      lonc,latc,radius, ds    : ',lon1,lat1,radius,ds
344
      elseif ( hmode.eq.'circle.grid' ) then   
345
        write(*,'(a30,3f10.2)') 
346
     >         '      lonc,latc,radius        : ',lon1,lat1,radius
347
      elseif ( hmode.eq.'region.eqd' ) then   
348
        write(*,'(a30,i4,1f10.2)') 
349
     >         '      iregion, ds             : ',iregion,ds
350
        write(*,'(a30,4f10.2)')
351
     >         '      xcorner                 : ',(xcorner(i),i=1,4)
352
        write(*,'(a30,4f10.2)')
353
     >         '      ycorner                 : ',(ycorner(i),i=1,4)
354
      elseif ( hmode.eq.'region.grid' ) then   
355
        write(*,'(a30,i4)') 
356
     >         '      iregion                 : ',iregion
357
        write(*,'(a30,4f10.2)')
358
     >         '      xcorner                 : ',(xcorner(i),i=1,4)
359
        write(*,'(a30,4f10.2)')
360
     >         '      ycorner                 : ',(ycorner(i),i=1,4)
361
      endif
362
      print*
363
      print*,'  vmode                      : ',trim(vmode)
364
      if ( vmode.eq.'file') then 
365
         print*,'      filename               : ',trim(vfile)
366
      elseif ( vmode.eq.'level' ) then 
367
         print*,'      level                  : ',lev1                         
368
      elseif ( vmode.eq.'list') then 
369
         print*,'      n                      : ',vn
370
         print*,'      level(i)               : ',(levlist(i),i=1,vn)
371
      elseif ( vmode.eq.'profile') then 
372
         print*,'      lev1,lev2,n            : ',lev1,lev2,vn
373
      endif
374
      print* 
375
      print*,'  umode                      : ',trim(umode)
376
      print*
377
      print*,'  time check                 : ',trim(timecheck)
378
      print*
379
 
380
c     ------------------------------------------------------------------
381
c     Read grid parameters from inital files
382
c     ------------------------------------------------------------------
383
 
16 michaesp 384
c     Init missing data value
385
      mdv = -999.0
386
 
7 michaesp 387
c     Get the time of the first and second data file
388
      tstart = -timeshift                              ! Format hh.mm
389
      call hhmm2frac(tstart,frac)
390
      frac   = frac + timeinc          
391
      call frac2hhmm(frac,tend)                        ! Format hh.mm                  
392
 
393
c     Convert timeshift (hh.mm) into a fractional time shift
394
      tfrac=real(int(timeshift))+
395
     >          100.*(timeshift-real(int(timeshift)))/60.
396
      if (tfrac.gt.0.) then
397
         tfrac=tfrac/timeinc
398
      else
399
         tfrac=0.
400
      endif
401
 
402
c     Read the constant grid parameters (nx,ny,nz,xmin,xmax,ymin,ymax,
403
c     pollon,pollat) The negative <-fid> of the file identifier is used 
404
c     as a flag for parameter retrieval
405
      varname  = 'U'
406
      call input_open (fid,pfile0)
407
      call input_grid (-fid,varname,xmin,xmax,ymin,ymax,dx,dy,nx,ny,
408
     >                 tstart,pollon,pollat,rd,rd,nz,rd,rd,rd,timecheck)
409
      call input_close(fid)
410
 
411
c     Decide whether the grid has to be rotated
412
      if ( abs(pollat-90.).gt.eps) then
413
         rotategrid = 1
414
      else
415
         rotategrid = 0
416
      endif
417
 
418
c     Check whether region coordinates are within the domain
419
      if ( (hmode.eq.'region.eqd' ).or.
420
     >     (hmode.eq.'region.grid') ) then
421
 
422
c        Rotate coordinates
423
         if ( rotategrid.eq.1) then
424
            do i=1,4
425
               lon = xcorner(i)
426
               lat = ycorner(i)
427
               if ( rotategrid.eq.1) then
428
                  rlon = lmtolms(lat,lon,pollat,pollon)
429
                  rlat = phtophs(lat,lon,pollat,pollon)
430
               else
431
                  rlon = lon
432
                  rlat = lat
433
               endif 
434
               xcorner(i) = rlon
435
               ycorner(i) = rlat
436
            enddo
437
         endif
438
 
439
c        Check 
440
         do i=1,4
441
            if ( (xcorner(i).lt.xmin).or.
442
     >           (ycorner(i).lt.ymin).or.
443
     >           (xcorner(i).gt.xmax).or.
444
     >           (ycorner(i).gt.ymax) )
445
     >      then
446
               print*,' ERROR: region not included in data domain...'
447
               print*,'       ',trim(string)
448
               print*,'  x:   ',(xcorner(j),j=1,4)
449
               print*,'  y:   ',(ycorner(j),j=1,4)
450
               stop
451
            endif
452
 
453
         enddo
454
 
455
c        Write rotated coordinates to logfile
456
         if ( rotategrid.eq.1) then
457
            write(*,'(a30,i4)') 
458
     >         '  Rotated region              : ',iregion
459
            write(*,'(a30,4f10.2)')
460
     >         '      xcorner (rotated)       : ',(xcorner(i),i=1,4)
461
            write(*,'(a30,4f10.2)')
462
     >         '      ycorner (rotated)       : ',(ycorner(i),i=1,4)
463
            print*
464
         endif
465
 
466
c        Rotate coordinates back
467
         if ( rotategrid.eq.1 ) then
468
            do i=1,4
469
               rlon = xcorner(i)
470
               rlat = ycorner(i)
471
               if ( rotategrid.eq.1) then
472
                  lon = lmstolm(rlat,rlon,pollat,pollon)
473
                  lat = phstoph(rlat,rlon,pollat,pollon)
474
               else
475
                  lon = rlon
476
                  lat = rlat
477
               endif 
478
               xcorner(i) = lon
479
               ycorner(i) = lat
480
            enddo
481
         endif
482
 
483
      endif
484
 
485
C     Check if the number of levels is too large
486
      if (nz.gt.nlevmax) goto 993
487
 
488
c     Allocate memory for 3d arrays: pressure, theta, pv
489
      allocate(pr(nx,ny,nz),stat=stat)
490
      if (stat.ne.0) print*,'*** error allocating array pr ***'
491
      allocate(prs(nx,ny),stat=stat)
492
      if (stat.ne.0) print*,'*** error allocating array prs **'
493
      allocate(th(nx,ny,nz),stat=stat)
494
      if (stat.ne.0) print*,'*** error allocating array th ***'
495
      allocate(ths(nx,ny),stat=stat)
496
      if (stat.ne.0) print*,'*** error allocating array ths **'
497
      allocate(pv(nx,ny,nz),stat=stat)
498
      if (stat.ne.0) print*,'*** error allocating array pv ***'
499
      allocate(pvs(nx,ny),stat=stat)
500
      if (stat.ne.0) print*,'*** error allocating array pvs **'
501
 
502
c     Allocate memory for temporary arrays for time interpolation
503
      allocate(fld0(nx,ny,nz),stat=stat)
504
      if (stat.ne.0) print*,'*** error allocating array tmp0 ***'
505
      allocate(fld1(nx,ny,nz),stat=stat)
506
      if (stat.ne.0) print*,'*** error allocating array tmp1 ***'
507
      allocate(sfc0(nx,ny),stat=stat)
508
      if (stat.ne.0) print*,'*** error allocating array sfc0 ***'
509
      allocate(sfc1(nx,ny),stat=stat)
510
      if (stat.ne.0) print*,'*** error allocating array sfc1 ***'
511
 
512
c     ------ Pressure --------------------------------------------------
513
 
514
c     Read pressure from first data file (pfile0) on U-grid 
515
      call input_open (fid,pfile0)
516
      varname='U'
517
      call input_grid                                      
518
     >     (fid,varname,xmin,xmax,ymin,ymax,dx,dy,nx,ny,
519
     >      tstart,pollon,pollat,fld0,sfc0,nz,ak,bk,stagz,timecheck)
520
      call input_close(fid)
521
 
522
c     Read or set pressure for second data file (pfile1)
523
      if ( timeshift.ne.0.) then
524
         call input_open (fid,pfile1)
525
         varname='U'
526
         call input_grid                                      
527
     >        (fid,varname,xmin,xmax,ymin,ymax,dx,dy,nx,ny,
528
     >        tend,pollon,pollat,fld1,sfc1,nz,ak,bk,stagz,timecheck)
529
         call input_close(fid)
530
      else
531
         do i=1,nx
532
            do j=1,ny
533
               do k=1,nz
534
                  fld1(i,j,k) = fld0(i,j,k)
535
               enddo
536
               sfc1(i,j) = sfc0(i,j)
537
            enddo
538
         enddo
539
      endif
540
 
541
c     Time interpolation to get the final pressure field
542
      do i=1,nx
543
         do j=1,ny
544
            do k=1,nz
545
               pr(i,j,k) = (1.-tfrac) * fld0(i,j,k) +
546
     >                     tfrac      * fld1(i,j,k)
547
            enddo
548
            prs(i,j) = (1.-tfrac) * sfc0(i,j) +
549
     >                 tfrac      * sfc1(i,j)
550
         enddo
551
      enddo
552
 
553
c     ------ Potential temperature -------------------------------------
554
 
555
       if ( (umode.eq.'K').or.(umode.eq.'PVU') ) then
556
 
557
c         Read potential temperature from first data file <sfile0>
558
          call input_open (fid,sfile0)
559
          varname='TH'                                      ! Theta                                      
560
          call input_wind
561
     >         (fid,varname,fld0,tstart,stagz,mdv,
562
     >         xmin,xmax,ymin,ymax,dx,dy,nx,ny,nz,timecheck)
563
          call input_close(fid)
564
 
565
c         Read or set potential temperature for second data file (sfile1)
566
          if ( timeshift.ne.0.) then
567
             call input_open (fid,sfile1)
568
             varname='TH' 
569
             call input_wind
570
     >            (fid,varname,fld1,tend,stagz,mdv,
571
     >            xmin,xmax,ymin,ymax,dx,dy,nx,ny,nz,timecheck)
572
             call input_close(fid)
573
          else
574
             do i=1,nx
575
                do j=1,ny
576
                   do k=1,nz
577
                      fld1(i,j,k) = fld0(i,j,k)
578
                   enddo
579
                enddo
580
             enddo
581
          endif
582
 
583
c         Time interpolation to get the final potential temperature field
584
          do i=1,nx
585
             do j=1,ny
586
                do k=1,nz
587
                   th(i,j,k) = (1.-tfrac) * fld0(i,j,k) +
588
     >                         tfrac      * fld1(i,j,k)
589
                enddo
590
             enddo
591
          enddo
592
 
593
c         Set the surface potential temperature
594
          do i=1,nx                            
595
             do j=1,ny
596
                ths(i,j)=th(i,j,1)
597
             enddo
598
          enddo
599
 
600
       endif
601
 
602
 
603
c     ------ Potential vorticity -----------------------------------------
604
 
605
       if ( (umode.eq.'PVU') ) then
606
 
607
c         Read potential vorticity from first data file <sfile0>
608
          call input_open (fid,sfile0)
609
          varname='PV'            
610
          call input_wind
611
     >         (fid,varname,fld0,tstart,stagz,mdv,
612
     >         xmin,xmax,ymin,ymax,dx,dy,nx,ny,nz,timecheck)
613
          call input_close(fid)
614
 
615
c         Read or set potential vorticity for second data file (sfile1)
616
          if ( timeshift.ne.0.) then
617
             call input_open (fid,sfile1)
618
             varname='PV' 
619
             call input_wind
620
     >            (fid,varname,fld1,tend,stagz,mdv,
621
     >            xmin,xmax,ymin,ymax,dx,dy,nx,ny,nz,timecheck)
622
             call input_close(fid)
623
          else
624
             do i=1,nx
625
                do j=1,ny
626
                   do k=1,nz
627
                      fld1(i,j,k) = fld0(i,j,k)
628
                   enddo
629
                enddo
630
             enddo
631
          endif
632
 
633
c         Time interpolation to get the final potential vorticity field
634
          do i=1,nx
635
             do j=1,ny
636
                do k=1,nz
637
                   pv(i,j,k) = (1.-tfrac) * fld0(i,j,k) +
638
     >                         tfrac      * fld1(i,j,k)
639
                enddo
640
             enddo
641
          enddo
642
 
643
c         Set the surface potential vorticity
644
          do i=1,nx                          
645
             do j=1,ny
646
                pvs(i,j)=pv(i,j,1)
647
             enddo
648
          enddo
649
       endif
650
 
651
c     Write some status information
652
      print*,'---- CONSTANT GRID PARAMETERS ---------------------------'
653
      print*
654
      print*,'  xmin,xmax        : ',xmin,xmax
655
      print*,'  ymin,ymax        : ',ymin,ymax
656
      print*,'  dx,dy            : ',dx,dy
657
      if ( rotategrid.eq.0)  then
658
         print*,'  pollon,pollat    : ',pollon,pollat
659
      else
660
         print*,'  pollon,pollat    : ',pollon,pollat, 'GRID ROTATION'
661
      endif
662
      print*,'  nx,ny,nz         : ',nx,ny,nz
663
      print*
664
      print*,'  Pressure loaded  : ',trim(pfile0),' ',trim(pfile1)
665
      if ( (umode.eq.'K').or.(umode.eq.'PVU') ) then
666
         print*,'  Theta loaded     : ',trim(sfile0),' ',trim(sfile1)
667
      endif
668
      if ( (umode.eq.'PVU') ) then
669
         print*,'  PV loaded        : ',trim(sfile0),' ',trim(sfile1)
670
      endif
671
      print*
672
 
673
c     ------------------------------------------------------------------
674
c     Determine the expanded list of starting coordinates
675
c     ------------------------------------------------------------------
676
 
677
c     Write some status information
678
      print*,'---- EXPAND LIST OF STARTING POSITIONS  -----------------'
679
      print*
680
 
681
c     ------ Read lat/lon/lev from <hfile> -----------------------------
682
      if ( hmode.eq.'file3' ) then
683
         start_n = 0
684
         open(10,file=hfile)
685
 100       continue
686
              start_n = start_n + 1
687
              read(10,*,end=101) start_lon(start_n),
688
     >                           start_lat(start_n),
689
     >                           start_lev(start_n)
690
              goto 100
691
 101       continue
692
           start_n = start_n - 1
693
         close(10)
694
         goto 400
695
      endif
696
 
697
c     ------ Get lat/lon (horizontal) coordinates ---------------------
698
 
699
c     Read lat/lon from <hfile> 
700
      if ( hmode.eq.'file2' ) then
701
         hn = 0
702
         open(10,file=hfile)
703
 200       continue
704
              hn = hn + 1
705
              read(10,*,end=201) lonlist(hn),
706
     >                           latlist(hn)
707
              goto 200
708
 201       continue
709
           hn = hn - 1
710
         close(10)
711
      endif
712
 
713
c     Get lat/lon along a line (linear in lat/lon space)
714
      if ( hmode.eq.'line' ) then
715
         do i=1,hn
716
            lonlist(i) = lon1 + real(i-1)/real(hn-1)*(lon2-lon1)
717
            latlist(i) = lat1 + real(i-1)/real(hn-1)*(lat2-lat1)
718
         enddo
719
      endif
720
 
721
c     Lat/lon box: equidistant
722
      if ( hmode.eq.'box.eqd' ) then
723
         hn  = 0
724
         lat = lat1
725
         do while ( lat.le.lat2 )      
726
           lon = lon1
727
           do while ( lon.le.lon2 ) 
728
             hn          = hn+1
729
             lonlist(hn) = lon
730
             latlist(hn) = lat
731
             lon         = lon+ds/(deltat*cos(pi180*lat))
732
           enddo
733
           lat = lat+ds/deltat
734
        enddo
735
      endif
736
 
737
c     Lat/lon box: grid
738
      if ( hmode.eq.'box.grid' ) then
739
         hn = 0
740
         do j=1,ny
741
            do i=1,nx
742
               rlon = xmin + real(i-1) * dx
743
               rlat = ymin + real(j-1) * dy
744
               if ( rotategrid.eq.1) then
745
                  lon = lmstolm(rlat,rlon,pollat,pollon)
746
                  lat = phstoph(rlat,rlon,pollat,pollon)
747
               else
748
                  lon = rlon
749
                  lat = rlat
750
               endif
751
               if ( (lon.ge.lon1).and.(lon.le.lon2).and.
752
     >              (lat.ge.lat1).and.(lat.le.lat2) )
753
     >         then
754
                  hn          = hn+1
755
                  lonlist(hn) = lon
756
                  latlist(hn) = lat
757
               endif
758
            enddo
759
         enddo
760
      endif
761
 
762
c     Get single starting point
763
      if ( hmode.eq.'point' ) then
764
         hn          = 1
765
         lonlist(hn) = lon1
766
         latlist(hn) = lat1
767
      endif
768
 
769
c     Get shifted and central starting point
770
      if ( hmode.eq.'shift' ) then
771
         hn         = 5
772
         lonlist(1) = lon1
773
         latlist(1) = lat1
774
         lonlist(2) = lon1+dlon
775
         latlist(2) = lat1
776
         lonlist(3) = lon1-dlon
777
         latlist(3) = lat1
778
         lonlist(4) = lon1
779
         latlist(4) = lat1+dlat
780
         lonlist(5) = lon1
781
         latlist(5) = lat1-dlat
782
      endif
783
 
784
c     Lat/lon polygon: grid
785
      if ( hmode.eq.'polygon.grid' ) then
786
 
787
c        Read list of polygon coordinates
788
         pn = 0
789
         open(10,file=hfile)
790
           read(10,*) loninpoly,latinpoly
791
 210       continue
792
              pn = pn + 1
793
              read(10,*,end=211) lonpoly(pn),
794
     >                           latpoly(pn)
795
 
796
              print*,pn,lonpoly(pn),latpoly(pn)
797
 
798
              goto 210
799
 211       continue
800
           pn = pn - 1
801
         close(10)
802
 
803
c        Define the polygon boundaries
804
         call DefSPolyBndry(latpoly,lonpoly,pn,latinpoly,loninpoly)
805
 
806
c        Get the grid points inside the polygon
807
         hn = 0
808
         do j=1,ny
809
            do i=1,nx
810
 
811
               rlon = xmin + real(i-1) * dx
812
               rlat = ymin + real(j-1) * dy
813
               if ( rotategrid.eq.1) then
814
                  lon = lmstolm(rlat,rlon,pollat,pollon)
815
                  lat = phstoph(rlat,rlon,pollat,pollon)
816
               else
817
                  lon = rlon
818
                  lat = rlat
819
               endif
820
 
821
               call LctPtRelBndry(lat,lon,flag)
822
 
823
               if ( (flag.eq.1).or.(flag.eq.2) ) then
824
                  hn          = hn+1
825
                  lonlist(hn) = lon
826
                  latlist(hn) = lat
827
               endif
828
 
829
            enddo
830
         enddo
831
 
832
      endif
833
 
834
c     Lat/lon polygon: equidistant
835
      if ( hmode.eq.'polygon.eqd' ) then
836
 
837
c        Read list of polygon coordinates
838
         pn = 0
839
 
840
         open(10,file=hfile)
841
           read(10,*) loninpoly,latinpoly
842
 220       continue
843
              pn = pn + 1
844
              read(10,*,end=221) lonpoly(pn),
845
     >                           latpoly(pn)
846
              goto 220
847
 221       continue
848
           pn = pn - 1
849
         close(10)
850
 
851
 
852
c        Define the polygon boundaries
853
         call DefSPolyBndry(latpoly,lonpoly,pn,latinpoly,loninpoly)
854
 
855
c        Get the grid points inside the polygon
856
         hn  = 0
857
         lat = -90.
858
         do while ( lat.le.90. )      
859
           lon = -180.
860
           do while ( lon.lt.180. )
861
 
862
              call LctPtRelBndry(lat,lon,flag)
863
 
864
               if ( (flag.eq.1).or.(flag.eq.2) ) then
865
                  hn          = hn+1
866
                  lonlist(hn) = lon
867
                  latlist(hn) = lat
868
 
869
               endif
870
 
871
               lon = lon+ds/(deltat*cos(pi180*lat))
872
           enddo
873
           lat = lat+ds/deltat
874
 
875
        enddo
876
 
877
      endif
878
 
879
c     Circle: equidistant
880
      if ( hmode.eq.'circle.eqd' ) then
881
         hn  = 0
882
         lat = -90.
883
         do while ( lat.le.90. )      
884
           lon = -180.
885
           do while ( lon.le.180. ) 
886
              dist = sdis(lon1,lat1,lon,lat)
887
              if ( dist.le.radius ) then
888
                 hn          = hn+1
889
                 lonlist(hn) = lon
890
                 latlist(hn) = lat
891
              endif
892
              lon = lon+ds/(deltat*cos(pi180*lat))
893
           enddo
894
           lat = lat+ds/deltat
895
        enddo
896
      endif
897
 
898
c     Circle: grid
899
      if ( hmode.eq.'circle.grid' ) then
900
         hn = 0
901
         do j=1,ny
902
            do i=1,nx
903
 
904
               rlon = xmin + real(i-1) * dx
905
               rlat = ymin + real(j-1) * dy
906
               if ( rotategrid.eq.1) then
907
                  lon = lmstolm(rlat,rlon,pollat,pollon)
908
                  lat = phstoph(rlat,rlon,pollat,pollon)
909
               else
910
                  lon = rlon
911
                  lat = rlat
912
               endif
913
 
914
               dist = sdis(lon1,lat1,lon,lat)
915
               if ( dist.le.radius ) then
916
                  hn          = hn+1
917
                  lonlist(hn) = lon
918
                  latlist(hn) = lat
919
               endif
920
            enddo
921
         enddo
922
 
923
      endif
924
 
925
c     Region: equidistant
926
      if ( hmode.eq.'region.eqd' ) then
927
         hn  = 0
928
         lat = -90.
929
         do while ( lat.le.90. )      
930
           lon = -180.
931
           do while ( lon.le.180. ) 
932
              flag = inregion(lon,lat,xcorner,ycorner)
933
              if ( flag.eq.1 ) then
934
                 hn          = hn+1
935
                 lonlist(hn) = lon
936
                 latlist(hn) = lat
937
              endif
938
              lon = lon+ds/(deltat*cos(pi180*lat))
939
           enddo
940
           lat = lat+ds/deltat
941
        enddo
942
      endif
943
 
944
c     Region: grid
945
      if ( hmode.eq.'region.grid' ) then
946
         hn = 0
947
         do j=1,ny
948
            do i=1,nx
949
 
950
               rlon  = xmin + real(i-1) * dx
951
               rlat  = ymin + real(j-1) * dy
952
               if ( rotategrid.eq.1) then
953
                  lon = lmstolm(rlat,rlon,pollat,pollon)
954
                  lat = phstoph(rlat,rlon,pollat,pollon)
955
               else
956
                  lon = rlon
957
                  lat = rlat
958
               endif
959
               flag = inregion(lon,lat,xcorner,ycorner)
960
               if ( flag.eq.1 ) then
961
                  hn          = hn+1
962
                  lonlist(hn) = lon
963
                  latlist(hn) = lat
964
               endif
965
            enddo
966
         enddo
967
 
968
      endif
969
 
970
c     ------ Get lev (vertical) coordinates -------------------------
971
 
972
c     Read level list from file
973
      if ( vmode.eq.'file' ) then
974
         vn = 0
975
         open(10,file=vfile)
976
 300       continue
977
              vn = vn + 1
978
              read(10,*,end=301) levlist(vn)
979
              goto 300
980
 301       continue
981
           vn = vn - 1
982
         close(10)
983
      endif
984
 
985
c     Get single starting level
986
      if ( vmode.eq.'level' ) then
987
         vn          = 1
988
         levlist(vn) = lev1
989
      endif
990
 
991
c     Get level profile
992
      if ( vmode.eq.'profile' ) then
993
         do i=1,vn
994
            levlist(i) = lev1 + real(i-1)/real(vn-1)*(lev2-lev1)
995
         enddo
996
      endif
997
 
998
c     ------ Compile the complete list of starting positions  ------
999
 
1000
c     Get all starting points in specified vertical coordinate system
1001
      start_n = 0
1002
      do i=1,vn
1003
         do j=1,hn
1004
            start_n = start_n + 1
1005
            start_lon(start_n) = lonlist(j)
1006
            start_lat(start_n) = latlist(j)
1007
            start_lev(start_n) = levlist(i)
1008
         enddo
1009
      enddo
1010
 
1011
c     ------- Rotate coordinates -----------------------------------
1012
      do i=1,start_n
1013
 
1014
         lon = start_lon(i)
1015
         lat = start_lat(i)
1016
 
1017
         if ( rotategrid.eq.1) then
1018
            rlon = lmtolms(lat,lon,pollat,pollon)
1019
            rlat = phtophs(lat,lon,pollat,pollon)
1020
         else
1021
            rlon = lon
1022
            rlat = lat
1023
         endif
1024
 
1025
         start_lon(i) = rlon
1026
         start_lat(i) = rlat
1027
 
1028
      enddo
1029
 
1030
c     ------ Exit point of this section -----------------------------
1031
 400  continue
1032
 
1033
c     Wriet status information
1034
      print*,'  # expanded points : ', start_n
1035
      print*
1036
 
1037
c     ------------------------------------------------------------------
1038
c     Transform starting levels into pressure
1039
c     ------------------------------------------------------------------
1040
 
1041
c     Write some status information
1042
      print*,'---- STARTING POSITIONS ---------------------------------'
1043
      print*
1044
 
1045
c     Vertical mode <hPa,asl> or simply <hPa>
1046
      if ( (umode.eq.'hPa,asl').or.(umode.eq.'hPa') ) then
1047
 
1048
         do i=1,start_n
1049
            start_pre(i) = start_lev(i)
1050
         enddo
1051
 
1052
c     Vertical mode <hPa,agl>
1053
      elseif ( umode.eq.'hPa,agl' ) then
1054
 
1055
         do i=1,start_n
1056
            call get_index3(rid,rjd,rkd,start_lon(i),start_lat(i),1050.,
1057
     >                      3,pr,prs,nx,ny,nz,xmin,ymin,dx,dy)
1058
            tmp1 = int_index3 (prs,nx,ny,1,rid,rjd,1,mdv)
1059
            start_pre(i) = tmp1 - start_lev(i) 
1060
         enddo
1061
 
1062
c     Vertical mode <K>
1063
      elseif ( umode.eq.'K' ) then
1064
 
1065
         do i=1,start_n
1066
            call get_index3(rid,rjd,rkd,start_lon(i),start_lat(i),
1067
     >                start_lev(i),1,th,ths,nx,ny,nz,xmin,ymin,dx,dy)
1068
            tmp1 = int_index3 (pr,nx,ny,nz,rid,rjd,rkd,mdv)
1069
            start_pre(i) = tmp1
1070
         enddo
1071
 
1072
c     Vertical mode <PVU>
1073
      elseif ( umode.eq.'PVU' ) then
1074
 
1075
         do i=1,start_n
1076
            call get_index3(rid,rjd,rkd,start_lon(i),start_lat(i),
1077
     >               start_lev(i),2,pv,pvs,nx,ny,nz,xmin,ymin,dx,dy)
1078
            tmp1 = int_index3 (pr,nx,ny,nz,rid,rjd,rkd,mdv)
1079
            start_pre(i) = tmp1
1080
         enddo
1081
 
1082
      endif
1083
 
1084
c     Check whether the starting levels are valid (in data domain)
1085
      do i=1,start_n
1086
 
1087
         call get_index3(rid,rjd,rkd,start_lon(i),start_lat(i),1050.,
1088
     >                   3,pr,prs,nx,ny,nz,xmin,ymin,dx,dy)
1089
         tmp1 = int_index3 (prs,nx,ny, 1,rid,rjd,real( 1),mdv)           ! Surface
1090
         tmp2 = int_index3 (pr ,nx,ny,nz,rid,rjd,real(nz),mdv)           ! Top of domain
1091
 
1092
         if ( (start_pre(i).gt.tmp1).or.
1093
     >        (start_pre(i).lt.tmp2).or.
1094
     >        (start_lon(i).lt.xmin).or. 
1095
     >        (start_lon(i).gt.xmax).or. 
1096
     >        (start_lat(i).lt.ymin).or.
1097
     >        (start_lat(i).gt.ymax) )
1098
     >   then
1099
            start_lon(i) = mdv
1100
            start_lat(i) = mdv
1101
            start_pre(i) = mdv
1102
         endif
1103
 
1104
      enddo
1105
 
1106
c     Remove all starting points outside the domain
1107
      i        = 1
16 michaesp 1108
      noutside = 0
7 michaesp 1109
      do while ( i.le.start_n )
1110
 
1111
         if ( abs(start_pre(i)-mdv).lt.eps ) then
1112
 
16 michaesp 1113
            noutside = noutside +1
1114
            if ( noutside.lt.10 ) then
1115
                print*,'  Outside ', 
1116
     >           start_lon(i),start_lat(i),start_lev(i)
1117
            else if ( noutside.eq.10 ) then
1118
                print*,'  Outside > 10 starting points'
1119
            endif
7 michaesp 1120
 
1121
            do j=i,start_n
1122
               start_lon(j) = start_lon(j+1)
1123
               start_lat(j) = start_lat(j+1)
1124
               start_pre(j) = start_pre(j+1)
1125
               start_lev(j) = start_lev(j+1)
1126
            enddo
1127
            start_n = start_n - 1
1128
 
1129
         else
1130
 
1131
            i = i + 1
1132
 
1133
         endif
1134
 
1135
      enddo
1136
 
1137
c     Write some status information
1138
      latmin = start_lat(1)
1139
      latmax = start_lat(1)
1140
      lonmin = start_lon(1)
1141
      lonmax = start_lon(1)
1142
      premin = start_pre(1)
1143
      premax = start_pre(1)
1144
      do i=1,start_n
1145
         if (start_lat(i).lt.latmin) latmin = start_lat(i)
1146
         if (start_lat(i).gt.latmax) latmax = start_lat(i)
1147
         if (start_lon(i).lt.lonmin) lonmin = start_lon(i)
1148
         if (start_lon(i).gt.lonmax) lonmax = start_lon(i)
1149
         if (start_pre(i).lt.premin) premin = start_pre(i)
1150
         if (start_pre(i).gt.premax) premax = start_pre(i)
1151
      enddo
1152
      print*,'  min(lat),max(lat) : ', latmin,latmax
1153
      print*,'  min(lon),max(lon) : ', lonmin,lonmax
1154
      print*,'  min(pre),max(pre) : ', premin,premax
1155
      print*
1156
      print*,'  # starting points : ', start_n
1157
      print*
1158
 
1159
 
1160
c     ------------------------------------------------------------------
1161
c     Write starting positions to output file
1162
c     ------------------------------------------------------------------
1163
 
1164
c     Rotate coordinates
1165
      do i=1,start_n
1166
 
1167
         rlon = start_lon(i)
1168
         rlat = start_lat(i)
1169
 
1170
         if ( rotategrid.eq.1) then
1171
            lon = lmstolm(rlat,rlon,pollat,pollon)
1172
            lat = phstoph(rlat,rlon,pollat,pollon)
1173
         else
1174
            lon = rlon
1175
            lat = rlat
1176
         endif
1177
 
1178
         start_lon(i) = lon
1179
         start_lat(i) = lat
1180
 
1181
      enddo
1182
 
1183
c     Output as a trajectory file (with only one time == 0)
1184
      if (oformat.ne.-1) then
1185
 
1186
         allocate(tra(start_n,1,5),stat=stat)
1187
 
1188
         vars(1)  ='time'
1189
         vars(2)  ='lon'
1190
         vars(3)  ='lat'
1191
         vars(4)  ='p'
1192
         vars(5)  ='level'
1193
         call wopen_tra(fid,ofile,start_n,1,5,reftime,vars,oformat)
1194
 
1195
         do i=1,start_n
1196
            tra(i,1,1) = 0.
1197
            tra(i,1,2) = start_lon(i)
1198
            tra(i,1,3) = start_lat(i)
1199
            tra(i,1,4) = start_pre(i)
1200
            tra(i,1,5) = start_lev(i)
1201
         enddo
1202
         call write_tra(fid,tra,start_n,1,5,oformat)
1203
 
1204
         call close_tra(fid,oformat)
1205
 
1206
c     Output as a triple list (corresponding to <startf> file)
1207
      else
1208
 
1209
         fid = 10
1210
         open(fid,file=ofile)
1211
          do i=1,start_n
1212
             write(fid,'(3f10.3)') start_lon(i),start_lat(i),
1213
     >                             start_pre(i) 
1214
          enddo
1215
         close(fid)
1216
 
1217
      endif
1218
 
1219
c     Write some status information, and end of program message
1220
      print*  
1221
      print*,'---- STATUS INFORMATION --------------------------------'
1222
      print*
1223
      print*,'ok'
1224
      print*
1225
      print*,'       *** END OF PROGRAM CREATE_STARTF ***'
1226
      print*,'========================================================='
1227
 
1228
c     ------------------------------------------------------------------
1229
c     Exception handling
1230
c     ------------------------------------------------------------------
1231
 
1232
      stop
1233
 
1234
 993  write(*,*) '*** ERROR: problems with array size'
1235
      call exit(1)
1236
 
1237
      end
1238
 
1239
c     --------------------------------------------------------------------------
1240
c     Split a region string and get corners of the domain
1241
c     --------------------------------------------------------------------------
1242
 
1243
      subroutine regionsplit(string,iregion,xcorner,ycorner)
1244
 
1245
c     The region string comes either as <lonw,lone,lats,latn> or as <lon1,lat1,
1246
c     lon2,lat2,lon3,lat3,lon4,lat4>: split it into ints components and get the
1247
c     four coordinates for the region
1248
 
1249
      implicit none
1250
 
1251
c     Declaration of subroutine parameters
1252
      character*80    string
1253
      real            xcorner(4),ycorner(4)
1254
      integer         iregion
1255
 
1256
c     Local variables
1257
      integer         i,n
1258
      integer         il,ir
1259
      real            subfloat (80)
1260
      integer         stat
1261
      integer         len
1262
 
1263
c     ------- Split the string
1264
      i    = 1
1265
      n    = 0
1266
      stat = 0
1267
      il   = 1
1268
      len  = len_trim(string)
1269
 
1270
 100  continue
1271
 
1272
c     Find start of a substring
1273
      do while ( stat.eq.0 )
1274
         if ( string(i:i).ne.' ' ) then
1275
            stat = 1
1276
            il   = i
1277
         else
1278
            i = i + 1
1279
         endif
1280
      enddo
1281
 
1282
c     Find end of substring
1283
      do while ( stat.eq.1 )         
1284
         if ( ( string(i:i).eq.' ' ) .or. ( i.eq.len ) ) then
1285
            stat = 2
1286
            ir   = i
1287
         else
1288
            i    = i + 1
1289
         endif
1290
      enddo
1291
 
1292
c     Convert the substring into a number
1293
      if ( stat.eq.2 ) then
1294
         n = n + 1
1295
         read(string(il:ir),*) subfloat(n)
1296
         stat = 0
1297
      endif
1298
 
1299
      if ( i.lt.len ) goto 100
1300
 
1301
 
1302
c     -------- Get the region number
1303
 
1304
      iregion = nint(subfloat(1))
1305
 
1306
c     -------- Get the corners of the region
1307
 
1308
      if ( n.eq.5 ) then     ! lonw(2),lone(3),lats(4),latn(5)
1309
 
1310
         xcorner(1) = subfloat(2)
1311
         ycorner(1) = subfloat(4)
1312
 
1313
         xcorner(2) = subfloat(3)
1314
         ycorner(2) = subfloat(4)
1315
 
1316
         xcorner(3) = subfloat(3)
1317
         ycorner(3) = subfloat(5)
1318
 
1319
         xcorner(4) = subfloat(2)
1320
         ycorner(4) = subfloat(5)
1321
 
1322
      elseif ( n.eq.9 ) then     ! lon1,lat1,lon2,lat2,lon3,lon4,lat4
1323
 
1324
         xcorner(1) = subfloat(2)
1325
         ycorner(1) = subfloat(3)
1326
 
1327
         xcorner(2) = subfloat(4)
1328
         ycorner(2) = subfloat(5)
1329
 
1330
         xcorner(3) = subfloat(6)
1331
         ycorner(3) = subfloat(7)
1332
 
1333
         xcorner(4) = subfloat(8)
1334
         ycorner(4) = subfloat(9)
1335
 
1336
      else
1337
 
1338
         print*,' ERROR: invalid region specification '
1339
         print*,'     ',trim(string)
1340
         stop
1341
 
1342
      endif
1343
 
1344
 
1345
      end
1346
 
1347
c     --------------------------------------------------------------------------
1348
c     Decide whether lat/lon point is in or out of region
1349
c     --------------------------------------------------------------------------
1350
 
1351
      integer function inregion (lon,lat,xcorner,ycorner)
1352
 
1353
c     Decide whether point (lon/lat) is in the region specified by <xcorner(1..4),
1354
c     ycorner(1..4).
1355
 
1356
      implicit none
1357
 
1358
c     Declaration of subroutine parameters
1359
      real    lon,lat
1360
      real    xcorner(4),ycorner(4)
1361
 
1362
c     Local variables
1363
      integer flag
1364
      real    xmin,xmax,ymin,ymax
1365
      integer i
1366
 
1367
c     Reset the flag
1368
      flag = 0
1369
 
1370
c     Set some boundaries
1371
      xmax = xcorner(1)
1372
      xmin = xcorner(1)
1373
      ymax = ycorner(1)
1374
      ymin = ycorner(1)
1375
      do i=2,4
1376
        if (xcorner(i).lt.xmin) xmin = xcorner(i)
1377
        if (xcorner(i).gt.xmax) xmax = xcorner(i)
1378
        if (ycorner(i).lt.ymin) ymin = ycorner(i)
1379
        if (ycorner(i).gt.ymax) ymax = ycorner(i)
1380
      enddo
1381
 
1382
c     Do the tests - set flag=1 if all tests pased
1383
      if (lon.lt.xmin) goto 970
1384
      if (lon.gt.xmax) goto 970
1385
      if (lat.lt.ymin) goto 970
1386
      if (lat.gt.ymax) goto 970
1387
 
1388
      if ((lon-xcorner(1))*(ycorner(2)-ycorner(1))-
1389
     >    (lat-ycorner(1))*(xcorner(2)-xcorner(1)).gt.0.) goto 970
1390
      if ((lon-xcorner(2))*(ycorner(3)-ycorner(2))-
1391
     >    (lat-ycorner(2))*(xcorner(3)-xcorner(2)).gt.0.) goto 970
1392
      if ((lon-xcorner(3))*(ycorner(4)-ycorner(3))-
1393
     >    (lat-ycorner(3))*(xcorner(4)-xcorner(3)).gt.0.) goto 970
1394
      if ((lon-xcorner(4))*(ycorner(1)-ycorner(4))-
1395
     >    (lat-ycorner(4))*(xcorner(1)-xcorner(4)).gt.0.) goto 970
1396
 
1397
      flag = 1
1398
 
1399
c     Return the value
1400
 970  continue
1401
 
1402
      inregion = flag
1403
 
1404
      return
1405
 
1406
      end
1407
 
1408
c     --------------------------------------------------------------------------
1409
c     Spherical distance between lat/lon points                                                       
1410
c     --------------------------------------------------------------------------
1411
 
1412
      real function sdis(xp,yp,xq,yq)
1413
c
1414
c     calculates spherical distance (in km) between two points given
1415
c     by their spherical coordinates (xp,yp) and (xq,yq), respectively.
1416
c
1417
      real      re
1418
      parameter (re=6370.)
1419
      real      pi180
1420
      parameter (pi180=3.14159/180.)
1421
      real      xp,yp,xq,yq,arg
1422
 
1423
      arg=sin(pi180*yp)*sin(pi180*yq)+
1424
     >    cos(pi180*yp)*cos(pi180*yq)*cos(pi180*(xp-xq))
1425
      if (arg.lt.-1.) arg=-1.
1426
      if (arg.gt.1.) arg=1.
1427
 
1428
      sdis=re*acos(arg)
1429
 
1430
      end
1431
 
1432
 
1433
c     ****************************************************************
1434
c     * Given some spherical polygon S and some point X known to be  *
1435
c     * located inside S, these routines will determine if an arbit- *
1436
c     * -rary point P lies inside S, outside S, or on its boundary.  *
1437
c     * The calling program must first call DefSPolyBndry to define  *
1438
c     * the boundary of S and the point X. Any subsequent call to    *
1439
c     * subroutine LctPtRelBndry will determine if some point P lies *
1440
c     * inside or outside S, or on its boundary. (Usually            *
1441
c     * DefSPolyBndry is called once, then LctPrRelBndry is called   *
1442
c     * many times).                                                 *
1443
c     *                                                              * 
1444
c     * REFERENCE:            Bevis, M. and Chatelain, J.-L. (1989)  * 
1445
c     *                       Maflaematical Geology, vol 21.         *
1446
c     * VERSION 1.0                                                  *
1447
c     ****************************************************************
1448
 
1449
      Subroutine DefSPolyBndry(vlat,vlon,nv,xlat, xlon)
1450
 
1451
c     ****************************************************************
1452
c     * This mmn entry point is used m define ~e spheric~ polygon S  *
1453
c     * and the point X.                                             *
1454
c     * ARGUMENTS:                                                   *
1455
c     * vlat,vlon (sent) ... vectors containing the latitude and     * 
1456
c     *                      longitude of each vertex of the         *
1457
c     *                      spherical polygon S. The ith.vertex is  *
1458
c     *                      located at [vlat(i),vlon(i)].           *
1459
c     * nv        (sent) ... the number of vertices and sides in the *
1460
c     *                      spherical polygon S                     *
1461
c     * xlat,xlon (sent) ... latitude and longitude of some point X  *
1462
c     *                      located inside S. X must not be located *
1463
c     *                      on any great circle that includes two   *
1464
c     *                      vertices of S.                          *
1465
c     *                                                              *
1466
c     * UNITS AND SIGN CONVENTION:                                   *
1467
c     *  Latitudes and longitudes are specified in degrees.          *
1468
c     *  Latitudes are positive to the north and negative to the     *
1469
c     *  south.                                                      *
1470
c     *  Longitudes are positive to the east and negative to the     *
1471
c     *  west.                                                       *
1472
c     *                                                              * 
1473
c     * VERTEX ENUMERATION:                                          * 
1474
c     * The vertices of S should be numbered sequentially around the *
1475
c     * border of the spherical polygon. Vertex 1 lies between vertex*
1476
c     * nv and vertex 2. Neighbouring vertices must be seperated by  *
1477
c     * less than 180 degrees. (In order to generate a polygon side  *
1478
c     * whose arc length equals or exceeds 180 degrees simply        *
1479
c     * introduce an additional (pseudo)vertex). Having chosen       *
1480
c     * vertex 1, the user may number the remaining vertices in      *
1481
c     * either direction. However if the user wishes to use the      *
1482
c     * subroutine SPA to determine the area of the polygon S (Bevis *
1483
c     * & Cambareri, 1987, Math. Geol., v.19, p. 335-346) then he or *
1484
c     * she must follow the convention whereby in moving around the  *
1485
c     * polygon border in the direction of increasing vertex number  *
1486
c     * clockwise bends occur at salient vertices. A vertex is       *
1487
c     * salient if the interior angle is less than 180 degrees.      *
1488
c     * (In the case of a convex polygon this convention implies     *
1489
c     * that vertices are numbered in clockwise sequence).           *
1490
c     ****************************************************************
1491
 
1492
      implicit none
1493
 
1494
      integer mxnv,nv
1495
 
1496
c     ----------------------------------------------------------------
1497
c     Edit next statement to increase maximum number of vertices that 
1498
c     may be used to define the spherical polygon S               
1499
c     The value of parameter mxnv in subroutine LctPtRelBndry must match
1500
c     that of parameter mxnv in this subroutine, as assigned above.
1501
c     ----------------------------------------------------------------
1502
      parameter (mxnv=500)
1503
 
1504
      real  vlat(nv),vlon(nv),xlat,xlon,dellon
1505
      real  tlonv(mxnv),vlat_c(mxnv),vlon_c(mxnv),xlat_c,xlon_c
1506
      integer i,ibndry,nv_c,ip
1507
 
1508
      data ibndry/0/
1509
 
1510
      common/spolybndry/vlat_c,vlon_c,nv_c,xlat_c,xlon_c,tlonv,ibndry
1511
 
1512
      if (nv.gt.mxnv) then
1513
         print *,'nv exceeds maximum allowed value'
1514
         print *,'adjust parameter mxnv in subroutine DefSPolyBndry'
1515
         stop
1516
      endif
1517
 
1518
      ibndry=1                  ! boundary defined at least once (flag)
1519
      nv_c=nv                   ! copy for named common
1520
      xlat_c=xlat               ! . . . .
1521
      xlon_c=xlon               !
1522
 
1523
      do i=1,nv
1524
         vlat_c(i)=vlat(i)      ! "
1525
         vlon_c(i)=vlon(i)      !
1526
 
1527
         call TrnsfmLon(xlat,xlon,vlat(i),vlon(i),tlonv(i))
1528
 
1529
         if (i.gt.1) then
1530
            ip=i-1
1531
         else
1532
            ip=nv
1533
         endif
1534
 
1535
         if ((vlat(i).eq.vlat(ip)).and.(vlon(i).eq.vlon(ip))) then
1536
            print *,'DefSPolyBndry detects user error:'
1537
            print *,'vertices ',i,' and ',ip,' are not distinct'
1538
            print*,'lat ',i,ip,vlat(i),vlat(ip)
1539
            print*,'lon ',i,ip,vlon(i),vlon(ip)            
1540
            stop
1541
         endif
1542
 
1543
         if (tlonv(i).eq.tlonv(ip)) then
1544
            print *,'DefSPolyBndry detects user error:'
1545
            print *,'vertices ',i,' & ',ip,' on same gt. circle as X'
1546
            stop
1547
         endif
1548
 
1549
         if (vlat(i).eq.(-vlat(ip))) then
1550
            dellon=vlon(i)-vlon(ip)
1551
            if (dellon.gt.+180.) dellon=dellon-360.
1552
            if (dellon.lt.-180.) dellon=dellon-360.
1553
            if ((dellon.eq.+180.0).or.(dellon.eq.-180.0)) then
1554
               print *,'DefSPolyBndry detects user error:'
1555
               print *,'vertices ',i,' and ',ip,' are antipodal'
1556
               stop
1557
            endif
1558
         endif
1559
      enddo
1560
 
1561
      return
1562
 
1563
      end
1564
 
1565
 
1566
c     ****************************************************************
1567
 
1568
      Subroutine LctPtRelBndry(plat,plon,location)
1569
 
1570
c     ****************************************************************
1571
 
1572
c     ****************************************************************
1573
c     * This routine is used to see if some point P is located       *
1574
c     * inside, outside or on the boundary of the spherical polygon  *
1575
c     * S previously defined by a call to subroutine DefSPolyBndry.  *
1576
c     * There is a single restriction on point P: it must not be     *
1577
c     * antipodal to the point X defined in the call to DefSPolyBndry*
1578
c     * (ie.P and X cannot be seperated by exactly 180 degrees).     *
1579
c     * ARGUMENTS:                                                   *  
1580
c     * plat,plon (sent)... the latitude and longitude of point P    *
1581
c     * location (returned)... specifies the location of P:          *
1582
c     *                        location=0 implies P is outside of S  *
1583
c     *                        location=1 implies P is inside of S   *
1584
c     *                        location=2 implies P on boundary of S *
1585
c     *                        location=3 implies user error (P is   *
1586
c     *                                     antipodal to X)          *
1587
c     * UNFfS AND SIGN CONVENTION:                                   * 
1588
c     *  Latitudes and longitudes are specified in degrees.          *
1589
c     *  Latitudes are positive to the north and negative to the     *
1590
c     *  south.                                                      *    
1591
c     *  Longitudes are positive to the east and negative to the     *
1592
c     *  west.                                                       *
1593
c     ****************************************************************
1594
 
1595
      implicit none
1596
 
1597
      integer mxnv
1598
 
1599
c     ----------------------------------------------------------------
1600
c     The statement below must match that in subroutine DefSPolyBndry
1601
c     ----------------------------------------------------------------
1602
 
1603
      parameter (mxnv=500)
1604
 
1605
      real tlonv(mxnv),vlat_c(mxnv),vlon_c(mxnv),xlat_c,xlon_c
1606
      real plat,plon,vAlat,vAlon,vBlat,vBlon,tlonA,tlonB,tlonP
1607
      real tlon_X,tlon_P,tlon_B,dellon
1608
      integer i,ibndry,nv_c,location,icross,ibrngAB,ibrngAP,ibrngPB
1609
      integer ibrng_BX,ibrng_BP,istrike
1610
 
1611
      common/spolybndry/vlat_c,vlon_c,nv_c,xlat_c,xlon_c,tlonv,ibndry
1612
 
1613
      if (ibndry.eq.0) then     ! user has never defined the bndry
1614
         print*,'Subroutine LctPtRelBndry detects user error:'
1615
         print*,'Subroutine DefSPolyBndry must be called before'
1616
         print*,'subroutine LctPtRelBndry can be called'
1617
         stop
1618
      endif
1619
 
1620
      if (plat.eq.(-xlat_c)) then
1621
         dellon=plon-xlon_c
1622
         if (dellon.lt.(-180.)) dellon=dellon+360.
1623
         if (dellon.gt.+180.) dellon=dellon-360.
1624
         if ((dellon.eq.+180.0).or.(dellon.eq.-180.)) then
1625
            print*,'Warning: LctPtRelBndry detects case P antipodal
1626
     >           to X'
1627
            print*,'location of P relative to S is undetermined'
1628
            location=3
1629
            return
1630
         endif
1631
      endif 
1632
 
1633
      location=0                ! default ( P is outside S)
1634
      icross=0                  ! initialize counter
1635
 
1636
      if ((plat.eq.xlat_c).and.(plon.eq.xlon_c)) then
1637
         location=1
1638
         return
1639
      endif
1640
 
1641
 
1642
      call TrnsfmLon (xlat_c,xlon_c,plat,plon,tlonP)
1643
 
1644
      do i=1,nv_c              ! start of loop over sides of S 
1645
 
1646
         vAlat=vlat_c(i)
1647
         vAlon=vlon_c(i)
1648
         tlonA=tlonv(i)
1649
 
1650
         if (i.lt.nv_c) then
1651
            vBlat=vlat_c(i+1)
1652
            vBlon=vlon_c(i+1)
1653
            tlonB=tlonv(i+1)
1654
         else
1655
            vBlat=vlat_c(1)
1656
            vBlon=vlon_c(1)
1657
            tlonB=tlonv(1)
1658
         endif
1659
 
1660
         istrike=0
1661
 
1662
         if (tlonP.eq.tlonA) then
1663
            istrike=1
1664
         else
1665
            call EastOrWest(tlonA,tlonB,ibrngAB)
1666
            call EastOrWest(tlonA,tlonP,ibrngAP)
1667
            call EastOrWest(tlonP,tlonB,ibrngPB)
1668
 
1669
 
1670
            if((ibrngAP.eq.ibrngAB).and.(ibrngPB.eq.ibrngAB)) istrike=1
1671
         endif
1672
 
1673
 
1674
         if (istrike.eq.1) then
1675
 
1676
            if ((plat.eq.vAlat).and.(plon.eq.vAlon)) then
1677
               location=2       ! P lies on a vertex of S
1678
               return
1679
            endif
1680
            call TrnsfmLon(vAlat,vAlon,xlat_c,xlon_c,tlon_X)
1681
            call TrnsfmLon(vAlat,vAlon,vBlat,vBlon,tlon_B)
1682
            call TrnsfmLon(vAlat,vAlon,plat,plon,tlon_P)
1683
 
1684
            if (tlon_P.eq.tlon_B) then
1685
               location=2       ! P lies on side of S
1686
               return 
1687
            else
1688
               call EastOrWest(tlon_B,tlon_X,ibrng_BX)
1689
               call EastOrWest(tlon_B,tlon_P,ibrng_BP)
1690
               if(ibrng_BX.eq.(-ibrng_BP)) icross=icross+1
1691
            endif
1692
 
1693
         endif
1694
      enddo                     ! end of loop over the sides of S
1695
 
1696
 
1697
c     if the arc XP crosses the boundary S an even number of times then P
1698
c     is in S
1699
 
1700
      if (mod(icross,2).eq.0) location=1
1701
 
1702
      return
1703
 
1704
      end
1705
 
1706
 
1707
c     ****************************************************************
1708
 
1709
      subroutine TrnsfmLon(plat,plon,qlat,qlon,tranlon)
1710
 
1711
c     ****************************************************************
1712
c     * This subroutine is required by subroutines DefSPolyBndry &   *
1713
c     * LctPtRelBndry. It finds the 'longitude' of point Q in a      *
1714
c     * geographic coordinate system for which point P acts as a     *
1715
c     * 'north pole'. SENT: plat,plon,qlat,qlon, in degrees.         *
1716
c     * RETURNED: tranlon, in degrees.                               *
1717
c     ****************************************************************
1718
 
1719
      implicit none
1720
 
1721
      real pi,dtr,plat,plon,qlat,qlon,tranlon,t,b
1722
      parameter (pi=3.141592654,dtr=pi/180.0)
1723
 
1724
      if (plat.eq.90.) then
1725
         tranlon=qlon
1726
      else
1727
         t=sin((qlon-plon)*dtr)*cos(qlat*dtr)
1728
         b=sin(dtr*qlat)*cos(plat*dtr)-cos(qlat*dtr)*sin(plat*dtr)
1729
     >    *cos((qlon-plon)*dtr)
1730
         tranlon=atan2(t,b)/dtr
1731
      endif
1732
 
1733
      return
1734
      end
1735
 
1736
c     ****************************************************************
1737
 
1738
      subroutine EastOrWest(clon,dlon,ibrng)
1739
 
1740
c     ****************************************************************
1741
c     * This subroutine is required by subroutine LctPtRelBndry.     *
1742
c     * This routine determines if in travelling the shortest path   *
1743
c     * from point C (at longitude clon) to point D (at longitude    *
1744
c     * dlon) one is heading east, west or neither.                  *
1745
c     * SENT: clon,dlon; in degrees. RETURNED: ibrng                 *
1746
c     * (1=east,-1=west, 0=neither).                                 *
1747
c     ****************************************************************
1748
 
1749
      implicit none
1750
      real clon,dlon,del
1751
      integer ibrng
1752
      del=dlon-clon
1753
      if (del.gt.180.) del=del-360.
1754
      if (del.lt.-180.) del=del+360.
1755
      if ((del.gt.0.0).and.(del.ne.180.)) then
1756
         ibrng=-1               ! (D is west of C)
1757
      elseif ((del.lt.0.0).and.(del.ne.-180.)) then
1758
         ibrng=+1               ! (D is east of C)
1759
      else
1760
         ibrng=0                ! (D north or south of C)
1761
      endif
1762
      return
1763
      end
1764
 
1765