Subversion Repositories lagranto.icon

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 michaesp 1
      PROGRAM select
2
 
3
c     **************************************************************
4
c     * Select trajectories from LSL file                          *
5
c     * Michael Sprenger / January, February 2008                  *
6
c     **************************************************************
7
 
8
      implicit none
9
 
10
c     -------------------------------------------------------------- 
11
c     Declaration of parameters
12
c     --------------------------------------------------------------
13
 
14
c     Maximum number of columns per trajectory
15
      Integer          maxcol
16
      parameter        (maxcol=100)
17
 
18
c     Maximum number of commands
19
      integer          maxcmd
20
      parameter        (maxcmd=10000)
21
 
22
c     -------------------------------------------------------------- 
23
c     Declaration of variables
24
c     --------------------------------------------------------------
25
 
26
c     Input and output files
27
      character*120     inp_lslfile                  ! Input lsl file
28
      character*120     out_lslfile                  ! Output lsl file
29
      character*120     inp_criteria                 ! Input file with criteria
30
      integer           inpmode                      ! Format of input file
31
      integer           outmode                      ! Format of output file
32
      character*80      outformat                    ! Trajectory/Boolean/Index of output   
33
      character*80      regionf                      ! Name of the regionfile
34
 
35
c     Trajectories
36
      integer          ntim                          ! Number of times 
37
      integer          ncol                          ! Number of columns (including time...)
38
      integer          ntrainp,ntraout               ! Number of trajectories
39
      character*80     vars(maxcol)                  ! Names of trajectory columns
40
      integer          basetime(6)                   ! Base time of trajectory (first line in lsl)
41
      real,allocatable, dimension (:,:,:) :: trainp  ! Input trajectories
42
      real,allocatable, dimension (:,:,:) :: traout  ! Output trajectories
43
      integer,allocatable,dimension (:)   :: selflag ! Flag for selection
44
      real,allocatable, dimension (:)     :: time    ! Times of the trajectory
45
      integer,allocatable,dimension (:,:) :: trigger ! Trigger column 
46
      integer          itrigger                      ! Column index for trigger
47
      character*80     addtrigger                    ! Flag whether to add trigger column
48
 
49
c     Command stack
50
      real             cmd(maxcmd)                   ! Decoded slection criterion
51
      integer          ncmd                          ! Number of commands
52
 
53
c     Common block for initialisation of polygon check
54
      real    tlonv(2000),vlat_c(2000),vlon_c(2000)
55
      rEAL    xlat_c,xlon_c
56
      integer ibndry,nv_c
57
      data    ibndry/0/
58
      common  /spolybndry/vlat_c,vlon_c,nv_c,xlat_c,xlon_c,tlonv,ibndry
59
 
60
c     Auxiliary variables
61
      integer          stat                          ! Logical (state) variable
62
      integer          fid,fod,fcr                   ! File identifier for input and output
63
      integer          i,j,k                         ! Index counter
64
      integer          isok                          ! Flag for selected trajectory
65
      real             param(1000)                   ! List of parameters
66
      integer          nparam                        ! Number of parameters
67
      character*80     specialstr                    ! Name of special command
68
      integer          len
69
      integer,allocatable,dimension (:) :: trigger1  ! Trigger column 
70
      real,allocatable,dimension (:,:) :: trainp1    ! A single trajectory
71
      character        ch
72
      real             varmin,varmax
73
 
74
c     -------------------------------------------------------------- 
75
c     Preparations
76
c     --------------------------------------------------------------
77
 
78
c     Write start message
79
      print*,'========================================================='
80
      print*,'              *** START OF PROGRAM SELECT ***'
81
      print*
82
 
83
c     Read parameter file
84
      open(10,file='select.param')
85
       read(10,*) inp_lslfile
86
       read(10,*) out_lslfile
87
       read(10,*) outformat
88
       read(10,*) inp_criteria
89
       read(10,*) ntrainp
90
       read(10,*) ntim
91
       read(10,*) ncol
92
       read(10,*) regionf
93
       read(10,*) addtrigger
94
      close(10)
95
 
96
c     Set the formats of the input and output files
97
      call mode_tra(inpmode,inp_lslfile)
98
      if (inpmode.eq.-1) inpmode=1
99
      call mode_tra(outmode,out_lslfile)
100
      if ( (outmode.eq.-1).and.(outformat.ne.'startf') ) then
101
         outmode=1
102
      endif
103
 
104
c     Allocate memory for a single trajectory
105
      allocate(trainp(ntrainp,ntim,ncol),stat=stat)
106
      if (stat.ne.0) stop '*** error allocating array trainp   ***'
107
      allocate(time(ntim),stat=stat)
108
      if (stat.ne.0) stop '*** error allocating array time     ***'
109
      allocate(selflag(ntrainp),stat=stat)
110
      if (stat.ne.0) stop '*** error allocating array selflag  ***'
111
      allocate(trigger(ntrainp,ntim),stat=stat)
112
      if (stat.ne.0) stop '*** error allocating array trigger  ***'
113
      allocate(trigger1(ntim),stat=stat)
114
      if (stat.ne.0) stop '*** error allocating array trigger1 ***'
115
      allocate(trainp1(ntim,ncol),stat=stat)
116
      if (stat.ne.0) stop '*** error allocating array trainp1  ***'
117
 
118
c     Read the input trajectory file
119
      call ropen_tra(fid,inp_lslfile,ntrainp,ntim,ncol,
120
     >               basetime,vars,inpmode)
121
      call read_tra (fid,trainp,ntrainp,ntim,ncol,inpmode)
122
      call close_tra(fid,inpmode)
123
 
124
c     Check that first four columns correspond to time,lon,lat,p
125
      if ( (vars(1).ne.'time' ).or.
126
     >     (vars(2).ne.'xpos' ).and.(vars(2).ne.'lon' ).or.
127
     >     (vars(3).ne.'ypos' ).and.(vars(3).ne.'lat' ).or.
128
     >     (vars(4).ne.'zpos' ).and.(vars(4).ne.'z'   ) )
129
     >then
130
         print*,' ERROR: problem with input trajectories ...'
131
         stop
132
      endif
133
      vars(1) = 'time'
134
      vars(2) = 'lon'
135
      vars(3) = 'lat'
136
      vars(4) = 'z'
137
 
138
c     Get the trajectory times from first trajectory
139
      do i=1,ntim
140
         time(i)=trainp(1,i,1)
141
      enddo
142
 
143
c     Init the trigger field - first check whether it is already available
144
      itrigger = 0
145
      do i=1,ncol
146
         if ( vars(i).eq.'TRIGGER' ) itrigger = i
147
      enddo
148
 
149
      if ( itrigger.ne.0 ) then
150
         do i=1,ntrainp
151
            do j=1,ntim
152
               trigger(i,j) = nint( trainp(i,j,itrigger) )
153
            enddo
154
         enddo
155
      else
156
         do i=1,ntrainp
157
            do j=1,ntim
158
               trigger(i,j) = 0
159
            enddo
160
         enddo
161
      endif
162
 
163
c     Write some info about the trajectory
164
      print*,'---- INPUT PARAMETERS -----------------------------------'
165
      write(*,*) 
166
      write(*,*) 'Input file    : ',trim(inp_lslfile)
167
      write(*,*) 'Output file   : ',trim(out_lslfile)
168
      write(*,*) 'Output format : ',trim(outformat)
169
      write(*,*) 'Criteria file : ',trim(inp_criteria)
170
      write(*,*) '# tra         : ',ntrainp
171
      write(*,*) '# time        : ',ntim
172
      write(*,*) '# col         : ',ncol
173
      write(*,*) 'Region file   : ',trim(regionf)
174
      write(*,*) 'Add trigger   : ',trim(addtrigger)
175
 
176
      print*
177
      print*,'---- INPUT TRAJECTORY FILE ------------------------------'
178
      print*
179
      write(*,'(1x,a12,i4,a10)') 'Vars       : ',1,trim(vars(1))
180
      do i=2,ncol
181
         write(*,'(1x,a12,i4,a10)') '             ',i,trim(vars(i))
182
      enddo
183
      print*
184
      write(*,'(1x,a12,i4,f10.2)') 'Time       : ',1,time(1)
185
      do i=2,ntim
186
         write(*,'(1x,a12,i4,f10.2)') '             ',i,time(i)
187
      enddo
188
      print*
189
      write(*,'(1x,a12,i4,i10)') 'Base date  : ',1,basetime(1)
190
      write(*,'(1x,a12,i4,i10)') '             ',2,basetime(2)
191
      write(*,'(1x,a12,i4,i10)') '             ',3,basetime(3)
192
      write(*,'(1x,a12,i4,i10)') '             ',4,basetime(4)
193
      write(*,'(1x,a12,i4,i10)') '             ',5,basetime(5)      
194
      print*
195
      write(*,'(1x,a12,i4,i10)') 'Time range : ',6,basetime(6)
196
      print*
197
      if ( itrigger.ne.0 ) then
198
         print*,'TRIGGER FIELD FOUND IN COLUMN ',itrigger
199
         print*
200
      endif
201
 
202
c     Read and decode the selection criterion
203
      fcr = 10
204
      open(fcr,file=inp_criteria)
205
      ncmd=maxcmd
206
      call decode(fcr,cmd,ncmd,vars,ncol,time,ntim,regionf)
207
      close(fcr)
208
 
209
      print*
210
      print*,'---- PSEUDO CODE FOR SELECTION --------------------------'
211
      print*
212
      call dumpcode(cmd,ncmd,vars,ncol,time,ntim)
213
 
214
c     Init param array
215
      do i=1,1000
216
        param(i) = 0.
217
      enddo
218
 
219
c     -------------------------------------------------------------- 
220
c     Loop over all trajectories - selection
221
c     --------------------------------------------------------------
222
 
223
c     Prepare string and parameters for SPECIAL commands
224
      if ( cmd(1).eq.0 ) then
225
 
226
c        Get command string
227
         j   = 2
228
         len = nint(cmd(j))
229
         specialstr = ''
230
         do k=1,len
231
            j = j + 1
232
            specialstr = trim(specialstr)//char(nint(cmd(j)))
233
         enddo
234
 
235
c        Get paramters
236
         j      = j + 1
237
         nparam = nint(cmd(j))
238
         do k=1,nparam
239
            j        = j + 1
240
            param(k) = cmd(j)
241
         enddo
242
 
243
      endif
244
 
245
c     Init the counter for selected trajectories
246
      ntraout = 0
247
 
248
c     Loop over all trajectories
249
      do i=1,ntrainp
250
 
251
c       Decide whether the trajectory is selected (handle SPECIAL commands)
252
        if (cmd(1).ne.0 ) then     
253
 
254
c          Copy a single trajectory to <trainp1> and <trigger1>
255
           do j=1,ntim
256
              do k=1,ncol
257
                 trainp1(j,k) = trainp(i,j,k)
258
              enddo
259
              trigger1(j) = trigger(i,j)
260
           enddo
261
 
262
c          Do the selection
263
           call select_tra (isok,cmd,ncmd,trainp1,trigger1,ntim,ncol)
264
 
265
c          The trigger might be changed in the selection - copy it 
266
           do j=1,ntim
267
              trigger(i,j) = trigger1(j)
268
           enddo
269
 
270
        else
271
           call special    (isok,specialstr,trainp(i,:,:),ntim,ncol,
272
     >                      vars,time,param,nparam,out_lslfile)
273
        endif
274
 
275
c       Set flag for selected trajectories
276
        if (isok.eq.1) then
277
           selflag(i)          = 1
278
           ntraout             = ntraout + 1
279
        else
280
           selflag(i)          = 0
281
        endif
282
 
283
      enddo
284
 
285
c     -------------------------------------------------------------- 
286
c     Write output trajectories
287
c     --------------------------------------------------------------
288
 
289
c     ------ Write output trajectories -----------------------------
290
      if ( outformat.eq.'trajectory' ) then
291
 
292
 
293
c        Define the trigger field if it is not yet defined
294
         if ( ( addtrigger.eq.'-trigger' ).and.(itrigger.eq.0) ) then
295
            ncol       = ncol + 1
296
            vars(ncol) = 'TRIGGER'
297
            itrigger   = ncol
298
         endif
299
 
300
c        Allocate memory for output trajectory
301
         allocate(traout(ntraout,ntim,ncol),stat=stat)
302
         if (stat.ne.0) stop '*** error allocating array apply   ***'
303
 
304
c        Set output trajectories
305
         j = 0
306
         do i=1,ntrainp
307
            if (selflag(i).eq.1) then
308
               j = j + 1
309
               if ( itrigger.eq.ncol) then
310
                   traout(j,1:ntim,1:(ncol-1)) =
311
     >                     trainp(i,1:ntim,1:(ncol-1))
312
               else
313
                   traout(j,1:ntim,1:ncol) =
314
     >                     trainp(i,1:ntim,1:ncol)
315
               endif
316
               if ( itrigger.ne.0 ) then
317
                  traout(j,1:ntim,itrigger) = real(trigger(i,1:ntim))
318
               endif
319
            endif
320
         enddo
321
 
322
c        Write trajectories
323
         call wopen_tra(fod,out_lslfile,ntraout,ntim,ncol,
324
     >        basetime,vars,outmode)
325
         call write_tra(fod,traout,ntraout,ntim,ncol,outmode)
326
         call close_tra(fod,outmode)
327
 
328
c     ------ Write index list -------------------------------------
329
      elseif ( outformat.eq.'index' ) then
330
 
331
         open(10,file=out_lslfile)
332
          do i=1,ntrainp
333
             if ( selflag(i).eq.1) write(10,*) i
334
          enddo
335
         close(10)
336
 
337
c     ------ Write boolean list -----------------------------------
338
      elseif ( outformat.eq.'boolean' ) then
339
 
340
         open(10,file=out_lslfile)
341
          do i=1,ntrainp
342
             write(10,'(i1)') selflag(i)
343
          enddo
344
         close(10)
345
 
346
c     ------ Write count -------------------------------------------
347
      elseif ( outformat.eq.'count' ) then
348
 
349
         open(10,file=out_lslfile)
350
          write(10,'(i7)') ntraout
351
         close(10)
352
 
353
c     ------ Write starting positions -----------------------------
354
      elseif ( outformat.eq.'startf' ) then
355
 
356
c        Allocate memory for output trajectory
357
         allocate(traout(ntraout,1,ncol),stat=stat)
358
         if (stat.ne.0) stop '*** error allocating array apply   ***'
359
 
360
c        Set output trajectories
361
         j = 0
362
         do i=1,ntrainp
363
            if (selflag(i).eq.1) then
364
               j             = j + 1 
365
               traout(j,1,:) = trainp(i,1,:)
366
            endif
367
         enddo
368
 
369
c        Write trajectories
370
         if (outmode.ne.-1) then
371
 
372
           call wopen_tra(fod,out_lslfile,ntraout,1,ncol,
373
     >                    basetime,vars,outmode)
374
           call write_tra(fod,traout,ntraout,1,ncol,outmode)
375
           call close_tra(fod,outmode)       
376
 
377
c        Output as a triple list (corresponding to <startf> file)
378
         else
379
 
380
           fid = 10
381
           open(fid,file=out_lslfile)
382
            do i=1,ntraout
383
              write(fid,'(3f10.3)') traout(i,1,2),   ! longitude
384
     >                            traout(i,1,3),   ! latitude
385
     >                            traout(i,1,4)    ! pressure
386
            enddo
387
           close(fid)
388
 
389
        endif
390
 
391
      endif
392
 
393
c     Write some status information, and end of program message
394
      print*  
395
      print*,'---- STATUS INFORMATION --------------------------------'
396
      print*
397
      print*,' # input trajectories  : ',ntrainp
398
      print*,' # output trajectories : ',ntraout
399
      print*
400
      print*,'              *** END OF PROGRAM SELECT ***'
401
      print*,'========================================================='
402
 
403
      stop
404
 
405
c     Exception handling
406
 100  stop 'select: First column in input trajectory must be <time>'
407
 101  stop 'select: Input trajectory file is empty'
408
 
409
      end
410
 
411
c     -------------------------------------------------------------- 
412
c     Dump the command list
413
c     --------------------------------------------------------------
414
 
415
      subroutine dumpcode(out,n,vars,nvars,times,ntimes)
416
 
417
c     Write the command list to screen. The command list is decoded
418
c     by call to <decode>
419
 
420
      implicit none
421
 
422
c     Declaration of subroutine parameters
423
      integer      n
424
      real         out(n)
425
      integer      nvars
426
      character*80 vars(nvars)
427
      integer      ntimes
428
      real         times(ntimes)
429
 
430
c     A single command
431
      character*80 cmd
432
      character*80 var,mode,strtim
433
      integer      nval
434
      integer      ntim
435
      integer      ivar,imode,icmd,itime
436
 
437
c     Auxiliary variables
438
      integer      i,j
439
 
440
c     Loop through the complete list
441
      i=0
442
 100  if (i.lt.n) then 
443
 
444
         write(*,*) '---------------------------------------'
445
 
446
c        Get command
447
         i=i+1
448
         icmd=nint(out(i))
449
 
450
c        Special handling of SPECIAL commands
451
         if ( icmd.eq.0 ) then
452
 
453
c           Write 'header' for SPECIAL command
454
            write(*,'(i5,f15.4,10x,a10)') i,out(i),'SPECIAL'
455
 
456
c           Write command string
457
            i = i + 1
458
            icmd = nint(out(i))
459
            write(*,'(i5,f15.4,10x,a10)') i,out(i),'LEN(CMD)'
460
            do j=1,icmd
461
               i    = i + 1
462
               ivar = nint(out(i))
463
               write(*,'(i5,f15.4,10x,a10)') i,out(i),char(ivar)
464
            enddo
465
 
466
c           Write parameters
467
            i    = i + 1
468
            nval = nint(out(i))
469
            write(*,'(i5,f15.4,10x,a10)') i,out(i),'#PARAMETER'
470
            do j=1,nval
471
               i=i+1
472
               if ( var.ne.'INPOLYGON' ) then
473
                  write(*,'(i5,f15.4)') i,out(i)
474
               else
475
                  write(*,'(i5,f15.4,a2)') i,out(i),char(nint(out(i)))
476
               endif
477
            enddo
478
 
479
c           Nothing else to do - exit
480
            goto 200
481
 
482
         endif
483
 
484
c        Set the command
485
         if (icmd.eq.  1) cmd='GT'
486
         if (icmd.eq.  2) cmd='LT'
487
         if (icmd.eq.  3) cmd='IN'
488
         if (icmd.eq.  4) cmd='OUT'
489
         if (icmd.eq.  5) cmd='EQ'
490
         if (icmd.eq.  6) cmd='TRUE'
491
         if (icmd.eq.  7) cmd='FALSE'
492
         if (icmd.eq.  8) cmd='ALL'
493
         if (icmd.eq.  9) cmd='ANY'
494
         if (icmd.eq. 10) cmd='NONE'
495
         if (icmd.eq. 11) cmd='CONST'
496
         if (icmd.eq. -1) cmd='BEGIN'
497
         if (icmd.eq. -2) cmd='END'
498
         if (icmd.eq. -3) cmd='AND'
499
         if (icmd.eq. -4) cmd='OR'
500
         write(*,'(i5,f15.4,10x,a10)') i,out(i),trim(cmd)
501
         if (icmd.lt.0) goto 100
502
 
503
c        Get variable
504
         i=i+1
505
         ivar=nint(out(i))
506
         if ( ivar.eq. -1 ) then
507
            var = 'DIST'
508
         elseif ( ivar.eq. -2 ) then
509
            var = 'DIST0'
510
         elseif ( ivar.eq. -3 ) then
511
            var = 'INPOLYGON'
512
         elseif ( ivar.eq. -4 ) then
513
            var = 'INBOX'
514
         elseif ( ivar.eq. -5 ) then
515
            var = 'INCIRCLE'
516
         elseif ( ivar.eq. -6 ) then
517
            var = 'INREGION'
518
         elseif ( ivar.eq. -7 ) then
519
            var = 'TRIGGER'
520
         else
521
            var=vars(ivar)
522
         endif
523
         write(*,'(i5,f15.4,10x,a10)') i,out(i),trim(var)
524
 
525
c        Get variable mode
526
         i=i+1
527
         imode=nint(out(i))
528
         if (imode.eq.1) mode='VALUE'
529
         if (imode.eq.2) mode='MEAN'         
530
         if (imode.eq.3) mode='MAX'
531
         if (imode.eq.4) mode='MIN'
532
         if (imode.eq.5) mode='VAR'
533
         if (imode.eq.6) mode='SUM'
534
         if (imode.eq.7) mode='CHANGE'
535
         if (imode.eq.8) mode='DIFF'
536
         if (imode.eq.8) mode='RANGE'
537
         write(*,'(i5,f15.4,10x,a10)') i,out(i),trim(mode)
538
 
539
c        Get values
540
         i=i+1
541
         nval=nint(out(i))
542
         write(*,'(i5,f15.4,10x,a10)') i,out(i),'#PARAMETER'
543
         do j=1,nval
544
            i=i+1
545
 
546
            if ( var.ne.'INPOLYGON' ) then
547
               write(*,'(i5,f15.4)') i,out(i)
548
            else
549
               write(*,'(i5,f15.4,a2)') i,out(i),char(nint(out(i)))
550
            endif
551
         enddo
552
 
553
c        Get times
554
         i=i+1
555
         ntim=nint(out(i))
556
         write(*,'(i5,f15.4,7x,7x,a6)') i,out(i),'#TIMES'
557
         do j=1,ntim
558
            i=i+1
559
            write(*,'(i5,f15.4,f7.0)') i,out(i),times(nint(out(i)))
560
         enddo
561
 
562
c        Get time mode
563
         i=i+1
564
         itime=nint(out(i))
565
         if (itime.eq.1) strtim='ALL'
566
         if (itime.eq.2) strtim='ANY'         
567
         if (itime.eq.3) strtim='NONE'
568
         if (itime.lt.0) strtim='TRIGGER'
569
 
570
         if ( strtim.ne.'TRIGGER' ) then
571
            write(*,'(i5,f15.4,10x,a10)') i,out(i),trim(strtim)
572
         else
573
            write(*,'(i5,f15.4,10x,a10,a3,i3)') i,out(i),trim(strtim),
574
     >                                        ' ->',abs(itime)
575
         endif
576
 
577
         goto 100
578
 
579
      endif
580
 
581
c     Exit point
582
 200  continue
583
 
584
      write(*,*) '---------------------------------------'
585
 
586
      end
587
 
588
 
589
c     -------------------------------------------------------------- 
590
c     Read and decode a selection set
591
c     --------------------------------------------------------------
592
 
593
      subroutine decode(fid,out,n,vars,nvars,times,ntimes,regionf)
594
 
595
c     A selection file is opened with file id <fid> and transformed
596
c     into a set of commands applied to the trajectories. On input
597
c     <n> sets the maximum dimension of <out>, on output it gives the
598
c     total length of the command string. The output is a list of
599
c     commands with the following format:
600
c     
601
c        out(i)             = Command 
602
c        out(i+1)           = Column index of variable
603
c        out(i+2)           = Mode for variable
604
c        out(i+3)           = Number of parameters (n)
605
c        out(i+4:i+4+n)     = Parameters
606
c        out(i+5+n)         = Number of times 
607
c        out(i+6+n:i+6+n+m) = List of time indices (m)
608
c        out(i+7+n+m)       = Time mode
609
c     
610
c     For SPECIAL commands (to be coded in <special.f>) the format is:
611
c     
612
c        out(i)             = Length of command string (n)
613
c        out(i+1:i+n)       = Command string      
614
c        out(i+n+1)         = Number of parameters (m)
615
c        out(i+n+2:i+n+1+m) = List of parameters
616
c     
617
c     The following coding is used
618
c      
619
c        Command        Variable mode    Time mode
620
c        ----------     -------------    ---------
621
c        GT       1     VALUE    1       ALL      1
622
c        LT       2     MEAN     2       ANY      2
623
c        IN       3     MAX      3       NONE     3
624
c        OUT      4     MIN      4       TRIGGER -i (i the trigger index)
625
c        EQ       5     VAR      5
626
c        BEGIN   -1     SUM      6
627
c        END     -2     CHANGE   7 
628
c        AND     -3     DIFF     8
629
c        OR      -4     RANGE    9
630
c        TRUE     6
631
c        FALSE    7
632
c        SPECIAL  0
633
c        ALL      8 (TRIGGER)
634
c        ANY      9 (TRIGGER)
635
c        NONE    10 (TRIGGER)
636
 
637
c     Several "implicit variables" are supported - out(i+1):
638
c     
639
c        DIST      -1 : Path length of the trajectory
640
c        DIST0     -2 : Distance from starting position
641
c        INPOLYGON -3 : Specified polygon region
642
c        INBOX     -4 : Longitude/latitude rectangle
643
c        INCIRCLE  -5 : Within a specified radius 
644
c        INREGION  -6 : Within a specified rehion on the region file
645
c        TRIGGER   -7 : Trigger field
646
c         
647
c     For the special commands BEGIN, END, AND and OR, only one field
648
c     in <out> is used.
649
 
650
      implicit none
651
 
652
c     Declaration of subroutine parameters
653
      integer      fid
654
      integer      n
655
      real         out(n)
656
      integer      nvars
657
      character*80 vars(nvars)
658
      integer      ntimes
659
      real         times(ntimes)
660
      character*80 regionf
661
 
662
c     Numerical epsilon
663
      real         eps
664
      parameter    (eps=0.001)
665
 
666
c     A single command term
667
      character*80 cmd
668
      character*80 var,mode
669
      integer      nval
670
      real         val(1000)
671
      integer      ntim
672
      real         tim(1000)
673
      character*80 tmode
674
 
675
c     Specification of a polygon
676
      character*80 filename
677
      integer      pn                             ! Number of entries in lat/lon poly
678
      real         latpoly(1000)                  ! List of polygon latitudes
679
      real         lonpoly(1000)                  ! List of polygon longitudes
680
      real         loninpoly,latinpoly            ! Lon/lat inside polygon
681
 
682
c     Specification of a region
683
      real         xcorner(4)
684
      real         ycorner(4)
685
      integer      iregion
686
      character*80 string
687
 
688
c     Transformation to UPN (handling of logical operators)
689
      integer      nlogical
690
      integer      ilogical(n)
691
      real         tmp(n)
692
      integer      mlogical
693
      integer      isor
694
 
695
c     Auxiliary variables
696
      integer      i,j
697
      integer      j1,j2
698
      integer      flag(ntimes)
699
      integer      count
700
      integer      ok
701
      integer      itrigger
702
 
703
c     Common block for initialisation of polygon check
704
      real    tlonv(1000),vlat_c(1000),vlon_c(1000)
705
      real    xlat_c,xlon_c
706
      integer ibndry,nv_c
707
      common  /spolybndry/vlat_c,vlon_c,nv_c,xlat_c,xlon_c,tlonv,ibndry
708
 
709
c     ------ Decode single commands ---------------------
710
 
711
c     Reset the filename for polygons
712
      filename='nil'
713
 
714
c     Reset the counter for logical commands
715
      nlogical=0
716
 
717
c     Loop through all commands
718
 100  continue
719
 
720
c       Read next command (handle special cases)
721
        read(fid,*) cmd
722
 
723
c       Special handling of SPECIAL commands
724
        if ( cmd.eq.'SPECIAL' ) then
725
 
726
c          Set the flag for SPECIAL command
727
           n      = 1
728
           out(n) = 0.
729
 
730
c          Read the command string
731
           read(fid,*) var
732
 
733
c          Add the command string
734
           n      = n + 1
735
           out(n) = len_trim(var)
736
           do j=1,len_trim(var)
737
              n      = n + 1
738
              out(n) = ichar(var(j:j))
739
           enddo
740
 
741
c          Read the parameters
742
           read(fid,*) nval
743
           read(fid,*) (val(i),i=1,nval)
744
 
745
c          Add the parameters
746
           n = n + 1
747
           out(n)=real(nval)
748
           do i=1,nval
749
              n=n+1
750
              out(n)=val(i)
751
           enddo
752
 
753
c          Goto exit point - nothing more top do
754
           goto 350
755
 
756
        endif
757
 
758
c       Handle structure commands
759
        if ( cmd.eq.'BEGIN') then
760
           out(1)=-1.
761
           n=1
762
           nlogical=1
763
           ilogical(1)=n
764
           goto 200
765
        elseif ( cmd.eq.'AND'  ) then
766
           n=n+1
767
           out(n)=-3.
768
           nlogical=nlogical+1
769
           ilogical(nlogical)=n
770
           goto 200
771
        elseif ( cmd.eq.'OR'   ) then
772
           n=n+1
773
           out(n)=-4.
774
           nlogical=nlogical+1
775
           ilogical(nlogical)=n
776
           goto 200
777
        elseif ( cmd.eq.'END'  ) then
778
           n=n+1
779
           out(n)=-2.
780
           nlogical=nlogical+1
781
           ilogical(nlogical)=n
782
           goto 300
783
        endif
784
 
785
c       Read other fields associated with the command
786
        read(fid,*) var,mode
787
 
788
c       Read parameter
789
        if ( var.eq.'INPOLYGON' ) then 
790
           read(fid,*) nval
791
           read(fid,*) filename
792
           filename = trim(filename)
793
        else
794
           read(fid,*) nval
795
           read(fid,*) (val(i),i=1,nval)
796
        endif
797
 
798
c       Read times
799
        read(fid,*) ntim
800
        read(fid,*) (tim(i),i=1,ntim)
801
        read(fid,*) tmode
802
 
803
c       Bring CAPITAL "TIME,LAT,LON,Z" into "time,lat,lon,z"
804
        if (var.eq.'TIME') var='time'
805
        if (var.eq.'LAT' ) var='lat'
806
        if (var.eq.'LON' ) var='lon'
807
        if (var.eq.'Z'   ) var='z'
808
 
809
c       If the time mode is 'TRIGGER', all times of a trajectory
810
c       must be considered
811
        if ( tmode.eq.'TRIGGER' ) then
812
           itrigger = nint(tim(1))
813
           ntim     = 1
814
           tim(1)   = -999.
815
        endif
816
 
817
c       Special times: transform into real time
818
        do i=1,ntim
819
           if ( abs(tim(i)+996.).lt.eps ) tim(i)=times(1)
820
           if ( abs(tim(i)+995.).lt.eps ) tim(i)=times(ntimes)
821
        enddo
822
 
823
c       Check whether times are valid 
824
        ok=0
825
        do i=1,ntim
826
           if ( (abs(tim(i)+994.).gt.eps).and.
827
     >          (abs(tim(i)+999.).gt.eps) )
828
     >     then
829
              do j=1,ntimes
830
                 if ( abs(tim(i)-times(j)).lt.eps ) then
831
                    ok=ok+1
832
                 endif
833
              enddo
834
           else
835
              ok=ok+1
836
           endif
837
        enddo
838
        if (ok.ne.ntim) goto 400
839
 
840
c       Select all times which are included in the criterion
841
        do i=1,ntimes
842
           flag(i)=0
843
        enddo
844
        i=1
845
 150    if (i.le.ntim) then
846
 
847
c          A list of times
848
           if ( (abs(tim(i)+994.).lt.eps) ) then
849
              j1=0
850
              do j=1,ntimes
851
                 if ( abs(tim(i-1)-times(j)).lt.eps ) then
852
                    j1=j
853
                 endif
854
              enddo
855
              j2=0
856
              do j=1,ntimes
857
                 if ( abs(tim(i+1)-times(j)).lt.eps ) then
858
                    j2=j
859
                 endif
860
              enddo   
861
              if ( (j1.eq.0).or.(j2.eq.0) ) goto 400
862
              do j=j1,j2
863
                 flag(j)=1
864
              enddo
865
              i=i+1
866
 
867
c          Explicitly given time value
868
           else
869
              do j=1,ntimes
870
                 if ( abs(tim(i)-times(j)).lt.eps ) then
871
                    flag(j)=1
872
                 endif
873
              enddo
874
 
875
           endif
876
 
877
           i=i+1
878
           goto 150
879
 
880
        endif
881
 
882
c       Write command identifier
883
        n=n+1
884
        if (cmd.eq.'GT'    ) out(n)= 1.
885
        if (cmd.eq.'LT'    ) out(n)= 2.
886
        if (cmd.eq.'IN'    ) out(n)= 3.
887
        if (cmd.eq.'OUT'   ) out(n)= 4.
888
        if (cmd.eq.'EQ'    ) out(n)= 5.
889
        if (cmd.eq.'TRUE'  ) out(n)= 6.
890
        if (cmd.eq.'FALSE' ) out(n)= 7.
891
        if (cmd.eq.'ALL  ' ) out(n)= 8.
892
        if (cmd.eq.'ANY  ' ) out(n)= 9.
893
        if (cmd.eq.'NONE ' ) out(n)=10.
894
 
895
c       Write index for variable - force implicit trigger
896
        ok=0
897
        do j=1,nvars
898
           if (vars(j).eq.var) ok=j
899
        enddo
900
 
901
        if (var.eq.'TRIGGER') ok = 0
902
 
903
        if (ok.eq.0) then
904
           if (var.eq.'DIST') then
905
              ok = -1
906
           elseif (var.eq.'DIST0') then
907
              ok = -2
908
           elseif (var.eq.'INPOLYGON') then
909
              ok = -3
910
           elseif (var.eq.'INBOX') then
911
              ok = -4
912
           elseif (var.eq.'INCIRCLE') then
913
              ok = -5
914
           elseif (var.eq.'INREGION') then
915
              ok = -6
916
           elseif (var.eq.'TRIGGER') then
917
              ok = -7
918
           else
919
             goto 400
920
          endif
921
        endif
922
        n=n+1
923
        out(n)=real(ok)
924
 
925
c       Write mode for variable
926
        ok=0
927
        if (mode.eq.'VALUE'  ) ok=1
928
        if (mode.eq.'MEAN'   ) ok=2
929
        if (mode.eq.'MAX'    ) ok=3
930
        if (mode.eq.'MIN'    ) ok=4
931
        if (mode.eq.'VAR'    ) ok=5
932
        if (mode.eq.'SUM'    ) ok=6
933
        if (mode.eq.'CHANGE' ) ok=7
934
        if (mode.eq.'DIFF'   ) ok=8
935
        if (mode.eq.'RANGE'  ) ok=9
936
        if (ok.eq.0) goto 400
937
        n=n+1
938
        out(n)=real(ok)
939
 
940
c       Write the parameter values: INPOLYGON 
941
        if ( var.eq.'INPOLYGON' ) then
942
 
943
           n      = n+1
944
           out(n) = len_trim(filename)
945
           do j=1,len_trim(filename)
946
              n      = n + 1
947
              out(n) = ichar(filename(j:j))
948
           enddo
949
 
950
c       Write parameter value: INREGION 
951
        elseif ( var.eq.'INREGION' ) then
952
 
953
           iregion = nint(val(1))
954
 
955
           open(fid+1,file=regionf)          
956
 
957
 50        read(fid+1,*,end=51) string
958
 
959
           if ( string(1:1).ne.'#' ) then
960
              call regionsplit(string,i,xcorner,ycorner)
961
              if ( i.eq.iregion ) goto 52
962
           endif
963
 
964
           goto 50
965
 
966
 51        close(fid+1)        
967
 
968
           print*,' ERROR: region ',iregion,' not found on ',
969
     >                                         trim(regionf)
970
           stop
971
 
972
 52        continue
973
 
974
           n      = n + 1
975
           out(n) = 8                   ! Number of parameters
976
           do i=1,4
977
              n      = n + 1
978
              out(n) = xcorner(i)
979
           enddo
980
           do i=1,4
981
              n      = n + 1
982
              out(n) = ycorner(i)
983
           enddo
984
 
985
c       Write parameter values: all other cases
986
        else
987
           n=n+1
988
           out(n)=real(nval)
989
           do i=1,nval
990
              n=n+1
991
              out(n)=val(i)
992
           enddo
993
        endif
994
 
995
c       All times are selected
996
        if ( abs(tim(1)+999.).lt.eps ) then
997
           n=n+1
998
           out(n)=real(ntimes)
999
           do i=1,ntimes
1000
              n=n+1
1001
              out(n)=real(i)
1002
           enddo
1003
 
1004
c       A selection of times is given 
1005
        else
1006
           count=0
1007
           do i=1,ntimes
1008
              count=count+flag(i)
1009
           enddo
1010
           n=n+1
1011
           out(n)=real(count)
1012
           do i=1,ntimes
1013
              if (flag(i).eq.1) then
1014
                 n=n+1
1015
                 out(n)=real(i)
1016
              endif
1017
           enddo
1018
        endif
1019
 
1020
c       Write the time mode
1021
        if ( tmode.eq.'ALL') then
1022
           n=n+1
1023
           out(n)=1.
1024
        elseif ( tmode.eq.'ANY') then
1025
           n=n+1
1026
           out(n)=2.
1027
        elseif ( tmode.eq.'NONE') then
1028
           n=n+1
1029
           out(n)=3.
1030
        elseif ( tmode.eq.'TRIGGER') then
1031
           n=n+1
1032
           out(n)=-real(itrigger)
1033
        endif
1034
 
1035
c     End loop: handle single command
1036
 200  continue
1037
      goto 100
1038
 
1039
c     End loop: loop over all commands 
1040
 300  continue
1041
 
1042
c     ------ Read polygon file, if requested -----------
1043
      if ( filename.ne.'nil' ) then
1044
 
1045
        print*
1046
        print*,
1047
     >     '---- POLYGON --------------------------------------------'
1048
 
1049
           print*
1050
           print*,'Filename = ',trim(filename)
1051
           print*
1052
 
1053
c        Read list of polygon coordinates from file
1054
         pn = 0
1055
         open(fid+1,file=filename)
1056
           read(fid+1,*) loninpoly,latinpoly
1057
           print*,'Inside (lon/lat) =',loninpoly,latinpoly
1058
           print*
1059
 510       continue
1060
              pn = pn + 1
1061
              read(fid+1,*,end=511) lonpoly(pn),
1062
     >                              latpoly(pn)
1063
 
1064
              print*,pn,lonpoly(pn),latpoly(pn)
1065
 
1066
              goto 510
1067
 511       continue
1068
           pn = pn - 1
1069
         close(fid+1)
1070
 
1071
c        Define the polygon boundaries
1072
         call DefSPolyBndry(latpoly,lonpoly,pn,latinpoly,loninpoly)
1073
 
1074
      endif
1075
 
1076
c     ------ Transform to UPN --------------------------
1077
 
1078
c     Check whether logical commands are ok
1079
      mlogical=nint(out(ilogical(1)))
1080
      if ( mlogical.ne.-1) goto 400
1081
      mlogical=nint(out(ilogical(nlogical)))
1082
      if ( mlogical.ne.-2) goto 400
1083
 
1084
c     No transformation necessary if only one command
1085
      if (nlogical.eq.2) goto 350
1086
 
1087
c     Copy the output to temporary list
1088
      do i=1,n
1089
         tmp(i)=out(i)
1090
      enddo
1091
 
1092
c     Set BEGIN statement
1093
      n=1
1094
      out(n)=-1.
1095
 
1096
c     Reorder commands and transform to UPN
1097
      isor=0
1098
      do i=1,nlogical-1
1099
 
1100
c        Get the logical command
1101
         mlogical=nint(out(ilogical(i)))
1102
 
1103
c        Connecting OR
1104
         if (mlogical.eq.-4) then
1105
            if (isor.eq.1) then
1106
               n=n+1
1107
               out(n)=-4.
1108
            else
1109
               isor=1
1110
            endif
1111
         endif
1112
 
1113
c        Put the command onto the stack
1114
         do j=ilogical(i)+1,ilogical(i+1)-1
1115
            n=n+1
1116
            out(n)=tmp(j)
1117
         enddo
1118
 
1119
c        Connecting AND operator
1120
         if ( mlogical.eq.-3 ) then
1121
            n=n+1
1122
            out(n)=-3.
1123
         endif
1124
 
1125
      enddo
1126
 
1127
c     Set final connecting OR
1128
      if (isor.eq.1) then
1129
         n=n+1
1130
         out(n)=-4.
1131
      endif
1132
 
1133
c     Set END statement
1134
      n=n+1
1135
      out(n)=-2.
1136
 
1137
c     ------ Exit point ---------------------------------
1138
 
1139
 350  continue
1140
      return
1141
 
1142
c     ----- Exception handling --------------------------
1143
 400  print*,'Invalid selection criterion... Stop'
1144
      stop
1145
 
1146
      end
1147
 
1148
 
1149
c     -------------------------------------------------------------- 
1150
c     Decide whether a trajectory is selected or not
1151
c     --------------------------------------------------------------
1152
 
1153
      subroutine select_tra (select,cmd,n,tra,trigger,ntim,ncol)
1154
 
1155
c     Decide whether a single trajectory is selected (<select=1>) or
1156
c     is not selected <select=0> according to the selection criterion
1157
c     given in <cmd(ncmd)>. The selection criterion <cmd(ncmd)> is 
1158
c     returned from the call to the subroutine <decode>. The trajectory
1159
c     is given in <tra(ntim,ncol)> where <ntim> is the number of times
1160
c     and <ncol> is the number of columns.
1161
c     
1162
c     Important note: the structure of <tra(ntim,ncol)> must match to the
1163
c     call parameter <vars,nvars,times,ntimes> in subroutine <decode>.
1164
 
1165
      implicit none
1166
 
1167
c     Declaration of subroutine parameters
1168
      integer   select
1169
      integer   n
1170
      real      cmd(n)
1171
      integer   ntim,ncol
1172
      real      tra(ntim,ncol)
1173
      integer   trigger(ntim)
1174
 
1175
c     Numerical epsilon (for test of equality)
1176
      real      eps
1177
      parameter (eps=0.000001)
1178
 
1179
c     A single command and the associated field
1180
      integer   icmd,ivar,imode,itime,nsel,nval
1181
      integer   time(ntim)
1182
      real      param(100)
1183
      real      var   (ntim)
1184
      integer   intvar(ntim)
1185
 
1186
c     Boolean values for a single time, a single command and build-up
1187
      integer   stack(100)
1188
      integer   nstack
1189
      integer   istrue(ntim)
1190
      integer   decision
1191
 
1192
c     Auxiliary variables
1193
      integer   i,j,k
1194
      real      tmp,mea
1195
      integer   istack1,istack2
1196
      real      lat0,lon0,lat1,lon1
1197
      real      length(ntim)
1198
      integer   flag
1199
      real      dist
1200
      real      xcorner(4),ycorner(4)
1201
      integer   iparam
1202
      character ch
1203
      real      varmin,varmax
1204
 
1205
c     Common block for initialisation of polygon check
1206
      real    tlonv(1000),vlat_c(1000),vlon_c(1000)
1207
      real    xlat_c,xlon_c
1208
      integer ibndry,nv_c
1209
      common  /spolybndry/vlat_c,vlon_c,nv_c,xlat_c,xlon_c,tlonv,ibndry
1210
 
1211
c     Externals
1212
      real      sdis           ! Spherical distance
1213
      external  sdis
1214
      integer   inregion       ! Boolean flag for regions
1215
      external  inregion
1216
 
1217
c     Reset the decision stack (with locical values)
1218
      nstack=0
1219
 
1220
c     Loop through the complete command list
1221
      i=0
1222
 100  if (i.lt.n) then  
1223
 
1224
c        --- Get the command -------------------------------
1225
         i=i+1
1226
         icmd=nint(cmd(i))
1227
 
1228
c        --- Handle structural commands (BEGIN, END, AND, OR)
1229
 
1230
c        Handle BEGIN statement
1231
         if ( icmd.eq.-1) then
1232
            nstack=0
1233
            goto 200
1234
         endif
1235
 
1236
c        Handle END statement
1237
         if (icmd.eq.-2) then
1238
            goto 300
1239
         endif
1240
 
1241
c        Handle AND statement
1242
         if (icmd.eq.-3) then
1243
            istack1=stack(nstack)
1244
            nstack=nstack-1
1245
            istack2=stack(nstack)
1246
            if ((istack1.eq.1).and.(istack2.eq.1)) then
1247
               stack(nstack)=1
1248
            else
1249
               stack(nstack)=0
1250
            endif
1251
            goto 200
1252
         endif
1253
 
1254
c        Handle OR statement
1255
         if (icmd.eq.-4) then
1256
            istack1=stack(nstack)
1257
            nstack=nstack-1
1258
            istack2=stack(nstack)
1259
            if ((istack1.eq.1).or.(istack2.eq.1)) then
1260
               stack(nstack)=1
1261
            else
1262
               stack(nstack)=0
1263
            endif
1264
            goto 200
1265
         endif
1266
 
1267
c        --- Get all command details (parameters, modes, times)
1268
 
1269
c        Get variable (<ivar> gets the column index in <tra>)
1270
         i=i+1
1271
         ivar=nint(cmd(i))
1272
 
1273
c        Get variable mode 
1274
         i=i+1
1275
         imode=nint(cmd(i))
1276
 
1277
c        Get parameter values
1278
         i=i+1
1279
         nval=nint(cmd(i))
1280
         do j=1,nval
1281
            i=i+1
1282
            param(j)=cmd(i)
1283
         enddo
1284
 
1285
c        Get times (<time(j)> gets the row indices of <tra>)
1286
         i=i+1
1287
         nsel=nint(cmd(i))
1288
         do j=1,nsel
1289
            i=i+1
1290
            time(j)=nint(cmd(i))
1291
         enddo
1292
 
1293
c        Get time mode
1294
         i=i+1
1295
         itime=nint(cmd(i))
1296
 
1297
c        --- Prepare field values for analysis -----------
1298
 
1299
c        Implicit variable: DIST
1300
         if ( ivar.eq. -1 ) then
1301
            length(1) = 0.
1302
            do j=2,ntim
1303
               lon0      = tra(j-1,2)
1304
               lat0      = tra(j-1,3)
1305
               lon1      = tra(j  ,2)
1306
               lat1      = tra(j  ,3)
1307
               length(j) = length(j-1) + sdis(lon0,lat0,lon1,lat1)
1308
            enddo
1309
            do j=1,nsel
1310
               var(j) = length( time(j) )
1311
            enddo
1312
 
1313
 
1314
c        Implict variable: DIST0
1315
         elseif ( ivar.eq. -2 ) then
1316
            do j=1,nsel
1317
               lon0   = tra(1      ,2)
1318
               lat0   = tra(1      ,3)
1319
               lon1   = tra(time(j),2)
1320
               lat1   = tra(time(j),3)
1321
               var(j) = sdis(lon0,lat0,lon1,lat1)
1322
            enddo
1323
 
1324
c        Implict variable: INPOLYGON
1325
         elseif ( ivar.eq. -3 ) then
1326
            do j=1,nsel
1327
               lon1   = tra(time(j),2)
1328
               lat1   = tra(time(j),3)               
1329
               call LctPtRelBndry(lat1,lon1,flag)
1330
               if ( (flag.eq.1).or.(flag.eq.2) ) then
1331
                  var(j) = 1.
1332
               else
1333
                  var(j) = 0.
1334
               endif
1335
            enddo
1336
 
1337
c        Implict variable: INBOX 
1338
         elseif ( ivar.eq. -4 ) then
1339
            do j=1,nsel
1340
               lon1   = tra(time(j),2)
1341
               lat1   = tra(time(j),3)               
1342
               if ( ( lon1.ge.param(1) ).and.       ! lonmin
1343
     >              ( lon1.le.param(2) ).and.       ! lonmax
1344
     >              ( lat1.ge.param(3) ).and.       ! latmin
1345
     >              ( lat1.le.param(4) ) )          ! latmax
1346
     >         then
1347
                  var(j) = 1
1348
               else
1349
                  var(j) = 0
1350
               endif
1351
            enddo
1352
 
1353
c        Implict variable: INCIRCLE (lonc=param(1),latc=param(2),radius=param(3))
1354
         elseif ( ivar.eq. -5 ) then
1355
            do j=1,nsel
1356
               lon1   = tra(time(j),2)
1357
               lat1   = tra(time(j),3)               
1358
 
1359
               dist = sdis( lon1,lat1,param(1),param(2) ) 
1360
 
1361
               if ( dist.le.param(3) ) then
1362
                  var(j) = 1
1363
               else
1364
                  var(j) = 0
1365
               endif
1366
            enddo
1367
 
1368
c        Implict variable: INREGION (xcorner=param(1..4),ycorner=param(5..8) )
1369
         elseif ( ivar.eq.-6 ) then
1370
 
1371
            do j=1,4
1372
               xcorner(j) = param(j  )
1373
               ycorner(j) = param(j+4)
1374
            enddo
1375
 
1376
            do j=1,nsel
1377
               lon1   = tra(time(j),2)
1378
               lat1   = tra(time(j),3)  
1379
               var(j) = inregion (lon1,lat1,xcorner,ycorner)               
1380
            enddo
1381
 
1382
c        Implict variable: TRIGGER
1383
         elseif ( ivar.eq. -7 ) then
1384
            do j=1,nsel
1385
               intvar(j) = trigger( time(j) ) 
1386
            enddo
1387
 
1388
 
1389
c        Explicit variable (column index <ivar>)
1390
         else
1391
            do j=1,nsel
1392
               var(j) = tra(time(j),ivar)
1393
            enddo
1394
 
1395
         endif
1396
 
1397
c        Take MEAN of the variable (mean of selected times)
1398
         if (imode.eq.2) then
1399
            tmp=0.
1400
            do j=1,nsel
1401
               tmp=tmp+var(j)
1402
            enddo
1403
            var(1)=tmp/real(nsel)
1404
            nsel=1
1405
 
1406
c        Take MAX of the variable (maximum of selected times)
1407
         elseif (imode.eq.3) then
1408
            tmp=var(1)
1409
            do j=2,nsel
1410
               if (var(j).gt.tmp) tmp=var(j)
1411
            enddo
1412
            var(1)=tmp
1413
            nsel=1
1414
 
1415
c        Take MIN of the variable (minimum of selected times)
1416
         elseif (imode.eq.4) then
1417
            tmp=var(1)
1418
            do j=2,nsel
1419
               if (var(j).lt.tmp) tmp=var(j)
1420
            enddo
1421
            var(1)=tmp
1422
            nsel=1
1423
 
1424
c        Take VAR of the variable (variance over all selected times)
1425
         elseif (imode.eq.5) then
1426
            tmp=0.
1427
            do j=1,nsel
1428
               tmp=tmp+var(j)
1429
            enddo
1430
            mea=tmp/real(nsel)
1431
            do j=1,nsel
1432
              tmp=tmp+(var(j)-mea)**2
1433
            enddo
1434
            var(1)=1./real(nsel-1)*tmp
1435
            nsel=1
1436
 
1437
c        Take SUM of the variable (sum over all selected times)
1438
         elseif (imode.eq.6) then
1439
            tmp=0.
1440
            do j=1,nsel
1441
               tmp=tmp+var(j)
1442
            enddo
1443
            var(1)=tmp
1444
            nsel=1
1445
 
1446
c        Take CHANGE of the variable (change between first and last time)
1447
         elseif (imode.eq.7) then
1448
            varmin = var(1)
1449
            varmax = var(1)
1450
            do j=2,nsel
1451
               if ( var(j).lt.varmin ) varmin = var(j)
1452
               if ( var(j).gt.varmax ) varmax = var(j)
1453
            enddo
1454
            var(1)=varmax - varmin
1455
            nsel=1
1456
 
1457
c        Take DIFF of the variable (first minus last time)
1458
         elseif (imode.eq.8) then
1459
            var(1)=var(1)-var(nsel)
1460
            nsel=1
1461
 
1462
c        Take RANGE of the variable
1463
         elseif (imode.eq.9) then
1464
            varmax=var(1)
1465
            varmin=var(1)
1466
            do j=2,nsel
1467
               if (var(j).gt.varmax) varmax=var(j)
1468
               if (var(j).lt.varmin) varmin=var(j)
1469
            enddo
1470
            var(1) = varmax - varmin
1471
            nsel=1
1472
         endif
1473
 
1474
c        --- Apply the operators to the single values ---
1475
 
1476
         do j=1,nsel
1477
 
1478
c           GT
1479
            if (icmd.eq.1) then
1480
               if (var(j).gt.param(1)) then
1481
                  istrue(j)=1
1482
               else
1483
                  istrue(j)=0
1484
               endif
1485
 
1486
c           LT
1487
            elseif (icmd.eq.2) then
1488
               if (var(j).lt.param(1)) then
1489
                  istrue(j)=1
1490
               else
1491
                  istrue(j)=0
1492
               endif
1493
 
1494
c           IN
1495
            elseif (icmd.eq.3) then
1496
               if ( (var(j).gt.param(1)).and.
1497
     >              (var(j).lt.param(2)) ) 
1498
     >         then
1499
                  istrue(j)=1
1500
               else
1501
                  istrue(j)=0
1502
               endif
1503
 
1504
c           OUT
1505
            elseif (icmd.eq.4) then
1506
               if ( (var(j).lt.param(1)).or.
1507
     >              (var(j).gt.param(2)) ) 
1508
     >         then
1509
                  istrue(j)=1
1510
               else
1511
                  istrue(j)=0
1512
               endif
1513
 
1514
c           EQ
1515
            elseif (icmd.eq.5) then
1516
               if (abs(var(j)-param(1)).lt.eps) then
1517
                  istrue(j)=1
1518
               else
1519
                  istrue(j)=0
1520
               endif
1521
 
1522
c           TRUE
1523
            elseif (icmd.eq.6) then
1524
               if (abs(var(j)).lt.eps) then
1525
                  istrue(j)=0
1526
               else
1527
                  istrue(j)=1
1528
               endif
1529
 
1530
c           FALSE
1531
            elseif (icmd.eq.7) then
1532
               if (abs(var(j)).lt.eps) then
1533
                  istrue(j)=1
1534
               else
1535
                  istrue(j)=0
1536
               endif
1537
 
1538
c           ALL
1539
            elseif (icmd.eq.8) then
1540
               istrue(j) = 1
1541
               do k=1,nval
1542
                  iparam = nint(param(k))-1
1543
                  if (btest(intvar(j),iparam).eqv..false.) then
1544
                     istrue(j) = 0
1545
                  endif
1546
               enddo
1547
 
1548
c           ANY
1549
            elseif (icmd.eq.9) then
1550
               istrue(j) = 0
1551
               do k=1,nval
1552
                  iparam = nint(param(k))-1
1553
                  if (btest(intvar(j),iparam).eqv..true.) then
1554
                     istrue(j) = 1
1555
                  endif
1556
               enddo
1557
 
1558
c           NONE
1559
            elseif (icmd.eq.10) then
1560
               istrue(j) = 1
1561
               do k=1,nval
1562
                  iparam = nint(param(k))-1
1563
                  if (btest(intvar(j),iparam).eqv..true.) then
1564
                     istrue(j) = 0
1565
                  endif
1566
               enddo
1567
 
1568
            endif
1569
 
1570
         enddo
1571
 
1572
c        --- Determine the overall boolean value ----------
1573
 
1574
c        ALL
1575
         if (itime.eq.1) then
1576
            decision=1
1577
            do j=1,nsel
1578
               if (istrue(j).eq.0) then
1579
                  decision=0
1580
                  goto 110
1581
               endif
1582
            enddo
1583
 110        continue
1584
 
1585
c        ANY
1586
         elseif (itime.eq.2) then
1587
            decision=0
1588
            do j=1,nsel
1589
               if (istrue(j).eq.1) then
1590
                  decision=1
1591
                  goto 120
1592
               endif
1593
            enddo
1594
 120        continue
1595
 
1596
c        NONE
1597
         elseif (itime.eq.3) then
1598
            decision=1
1599
            do j=1,nsel
1600
               if (istrue(j).eq.1) then
1601
                  decision=0
1602
                  goto 130
1603
               endif
1604
            enddo
1605
 130        continue
1606
 
1607
c        TRIGGER
1608
         elseif (itime.lt.0) then
1609
            decision=1
1610
            do j=1,nsel
1611
               if (istrue(j).eq.1) then
1612
                  trigger(j) = ior( trigger(j), 2**(abs(itime)-1) )
1613
               endif
1614
            enddo
1615
 
1616
         endif
1617
 
1618
c        --- Put the new boolean value onto the stack
1619
 
1620
         nstack=nstack+1
1621
         stack(nstack)=decision
1622
 
1623
c        Exit point for loop
1624
 200     continue
1625
         goto 100
1626
 
1627
      endif
1628
 
1629
c     Return the decision (selected or non-selected)
1630
 300  continue
1631
 
1632
      select=stack(1)
1633
 
1634
      end
1635
 
1636
 
1637
c     --------------------------------------------------------------------------
1638
c     Split a region string and get corners of the domain
1639
c     --------------------------------------------------------------------------
1640
 
1641
      subroutine regionsplit(string,iregion,xcorner,ycorner)
1642
 
1643
c     The region string comes either as <lonw,lone,lats,latn> or as <lon1,lat1,
1644
c     lon2,lat2,lon3,lat3,lon4,lat4>: split it into ints components and get the
1645
c     four coordinates for the region
1646
 
1647
      implicit none
1648
 
1649
c     Declaration of subroutine parameters
1650
      character*80    string
1651
      real            xcorner(4),ycorner(4)
1652
      integer         iregion
1653
 
1654
c     Local variables
1655
      integer         i,n
1656
      integer         il,ir
1657
      real            subfloat (80)
1658
      integer         stat
1659
      integer         len
1660
 
1661
c     ------- Split the string
1662
      i    = 1
1663
      n    = 0
1664
      stat = 0
1665
      il   = 1
1666
      len  = len_trim(string)
1667
 
1668
 100  continue
1669
 
1670
c     Find start of a substring
1671
      do while ( stat.eq.0 )
1672
         if ( string(i:i).ne.' ' ) then
1673
            stat = 1
1674
            il   = i
1675
         else
1676
            i = i + 1
1677
         endif
1678
      enddo
1679
 
1680
c     Find end of substring
1681
      do while ( stat.eq.1 )         
1682
         if ( ( string(i:i).eq.' ' ) .or. ( i.eq.len ) ) then
1683
            stat = 2
1684
            ir   = i
1685
         else
1686
            i    = i + 1
1687
         endif
1688
      enddo
1689
 
1690
c     Convert the substring into a number
1691
      if ( stat.eq.2 ) then
1692
         n = n + 1
1693
         read(string(il:ir),*) subfloat(n)
1694
         stat = 0
1695
      endif
1696
 
1697
      if ( i.lt.len ) goto 100
1698
 
1699
 
1700
c     -------- Get the region number
1701
 
1702
      iregion = nint(subfloat(1))
1703
 
1704
c     -------- Get the corners of the region
1705
 
1706
      if ( n.eq.5 ) then     ! lonw(2),lone(3),lats(4),latn(5)
1707
 
1708
         xcorner(1) = subfloat(2)
1709
         ycorner(1) = subfloat(4)
1710
 
1711
         xcorner(2) = subfloat(3)
1712
         ycorner(2) = subfloat(4)
1713
 
1714
         xcorner(3) = subfloat(3)
1715
         ycorner(3) = subfloat(5)
1716
 
1717
         xcorner(4) = subfloat(2)
1718
         ycorner(4) = subfloat(5)
1719
 
1720
      elseif ( n.eq.9 ) then     ! lon1,lat1,lon2,lat2,lon3,lon4,lat4
1721
 
1722
         xcorner(1) = subfloat(2)
1723
         ycorner(1) = subfloat(3)
1724
 
1725
         xcorner(2) = subfloat(4)
1726
         ycorner(2) = subfloat(5)
1727
 
1728
         xcorner(3) = subfloat(6)
1729
         ycorner(3) = subfloat(7)
1730
 
1731
         xcorner(4) = subfloat(8)
1732
         ycorner(4) = subfloat(9)
1733
 
1734
      else
1735
 
1736
         print*,' ERROR: invalid region specification '
1737
         print*,'     ',trim(string)
1738
         stop
1739
 
1740
      endif
1741
 
1742
 
1743
      end
1744
 
1745
c     --------------------------------------------------------------------------
1746
c     Decide whether lat/lon point is in or out of region
1747
c     --------------------------------------------------------------------------
1748
 
1749
      integer function inregion (lon,lat,xcorner,ycorner)
1750
 
1751
c     Decide whether point (lon/lat) is in the region specified by <xcorner(1..4),
1752
c     ycorner(1..4).
1753
 
1754
      implicit none
1755
 
1756
c     Declaration of subroutine parameters
1757
      real    lon,lat
1758
      real    xcorner(4),ycorner(4)
1759
 
1760
c     Local variables
1761
      integer flag
1762
      real    xmin,xmax,ymin,ymax
1763
      integer i
1764
 
1765
c     Reset the flag
1766
      flag = 0
1767
 
1768
c     Set some boundaries
1769
      xmax = xcorner(1)
1770
      xmin = xcorner(1)
1771
      ymax = ycorner(1)
1772
      ymin = ycorner(1)
1773
      do i=2,4
1774
        if (xcorner(i).lt.xmin) xmin = xcorner(i)
1775
        if (xcorner(i).gt.xmax) xmax = xcorner(i)
1776
        if (ycorner(i).lt.ymin) ymin = ycorner(i)
1777
        if (ycorner(i).gt.ymax) ymax = ycorner(i)
1778
      enddo
1779
 
1780
c     Do the tests - set flag=1 if all tests pased
1781
      if (lon.lt.xmin) goto 970
1782
      if (lon.gt.xmax) goto 970
1783
      if (lat.lt.ymin) goto 970
1784
      if (lat.gt.ymax) goto 970
1785
 
1786
      if ((lon-xcorner(1))*(ycorner(2)-ycorner(1))-
1787
     >    (lat-ycorner(1))*(xcorner(2)-xcorner(1)).gt.0.) goto 970
1788
      if ((lon-xcorner(2))*(ycorner(3)-ycorner(2))-
1789
     >    (lat-ycorner(2))*(xcorner(3)-xcorner(2)).gt.0.) goto 970
1790
      if ((lon-xcorner(3))*(ycorner(4)-ycorner(3))-
1791
     >    (lat-ycorner(3))*(xcorner(4)-xcorner(3)).gt.0.) goto 970
1792
      if ((lon-xcorner(4))*(ycorner(1)-ycorner(4))-
1793
     >    (lat-ycorner(4))*(xcorner(1)-xcorner(4)).gt.0.) goto 970
1794
 
1795
      flag = 1
1796
 
1797
c     Return the value
1798
 970  continue
1799
 
1800
      inregion = flag
1801
 
1802
      return
1803
 
1804
      end
1805
 
1806
 
1807
c     --------------------------------------------------------------------------
1808
c     Spherical distance between lat/lon points                                                       
1809
c     --------------------------------------------------------------------------
1810
 
1811
      real function sdis(xp,yp,xq,yq)
1812
c
1813
c     calculates spherical distance (in km) between two points given
1814
c     by their spherical coordinates (xp,yp) and (xq,yq), respectively.
1815
c
1816
      real      re
1817
      parameter (re=6370.)
1818
      real      pi180
1819
      parameter (pi180=3.14159/180.)
1820
      real      xp,yp,xq,yq,arg
1821
 
1822
      arg=sin(pi180*yp)*sin(pi180*yq)+
1823
     >    cos(pi180*yp)*cos(pi180*yq)*cos(pi180*(xp-xq))
1824
      if (arg.lt.-1.) arg=-1.
1825
      if (arg.gt.1.) arg=1.
1826
 
1827
      sdis=re*acos(arg)
1828
 
1829
      end
1830
 
1831
 
1832
c     ****************************************************************
1833
c     * Given some spherical polygon S and some point X known to be  *
1834
c     * located inside S, these routines will determine if an arbit- *
1835
c     * -rary point P lies inside S, outside S, or on its boundary.  *
1836
c     * The calling program must first call DefSPolyBndry to define  *
1837
c     * the boundary of S and the point X. Any subsequent call to    *
1838
c     * subroutine LctPtRelBndry will determine if some point P lies *
1839
c     * inside or outside S, or on its boundary. (Usually            *
1840
c     * DefSPolyBndry is called once, then LctPrRelBndry is called   *
1841
c     * many times).                                                 *
1842
c     *                                                              * 
1843
c     * REFERENCE:            Bevis, M. and Chatelain, J.-L. (1989)  * 
1844
c     *                       Maflaematical Geology, vol 21.         *
1845
c     * VERSION 1.0                                                  *
1846
c     ****************************************************************
1847
 
1848
      Subroutine DefSPolyBndry(vlat,vlon,nv,xlat, xlon)
1849
 
1850
c     ****************************************************************
1851
c     * This mmn entry point is used m define ~e spheric~ polygon S  *
1852
c     * and the point X.                                             *
1853
c     * ARGUMENTS:                                                   *
1854
c     * vlat,vlon (sent) ... vectors containing the latitude and     * 
1855
c     *                      longitude of each vertex of the         *
1856
c     *                      spherical polygon S. The ith.vertex is  *
1857
c     *                      located at [vlat(i),vlon(i)].           *
1858
c     * nv        (sent) ... the number of vertices and sides in the *
1859
c     *                      spherical polygon S                     *
1860
c     * xlat,xlon (sent) ... latitude and longitude of some point X  *
1861
c     *                      located inside S. X must not be located *
1862
c     *                      on any great circle that includes two   *
1863
c     *                      vertices of S.                          *
1864
c     *                                                              *
1865
c     * UNITS AND SIGN CONVENTION:                                   *
1866
c     *  Latitudes and longitudes are specified in degrees.          *
1867
c     *  Latitudes are positive to the north and negative to the     *
1868
c     *  south.                                                      *
1869
c     *  Longitudes are positive to the east and negative to the     *
1870
c     *  west.                                                       *
1871
c     *                                                              * 
1872
c     * VERTEX ENUMERATION:                                          * 
1873
c     * The vertices of S should be numbered sequentially around the *
1874
c     * border of the spherical polygon. Vertex 1 lies between vertex*
1875
c     * nv and vertex 2. Neighbouring vertices must be seperated by  *
1876
c     * less than 180 degrees. (In order to generate a polygon side  *
1877
c     * whose arc length equals or exceeds 180 degrees simply        *
1878
c     * introduce an additional (pseudo)vertex). Having chosen       *
1879
c     * vertex 1, the user may number the remaining vertices in      *
1880
c     * either direction. However if the user wishes to use the      *
1881
c     * subroutine SPA to determine the area of the polygon S (Bevis *
1882
c     * & Cambareri, 1987, Math. Geol., v.19, p. 335-346) then he or *
1883
c     * she must follow the convention whereby in moving around the  *
1884
c     * polygon border in the direction of increasing vertex number  *
1885
c     * clockwise bends occur at salient vertices. A vertex is       *
1886
c     * salient if the interior angle is less than 180 degrees.      *
1887
c     * (In the case of a convex polygon this convention implies     *
1888
c     * that vertices are numbered in clockwise sequence).           *
1889
c     ****************************************************************
1890
 
1891
      implicit none
1892
 
1893
      integer mxnv,nv
1894
 
1895
c     ----------------------------------------------------------------
1896
c     Edit next statement to increase maximum number of vertices that 
1897
c     may be used to define the spherical polygon S               
1898
c     The value of parameter mxnv in subroutine LctPtRelBndry must match
1899
c     that of parameter mxnv in this subroutine, as assigned above.
1900
c     ----------------------------------------------------------------
1901
      parameter (mxnv=2000)
1902
 
1903
      real  vlat(nv),vlon(nv),xlat,xlon,dellon
1904
      real  tlonv(mxnv),vlat_c(mxnv),vlon_c(mxnv),xlat_c,xlon_c
1905
      integer i,ibndry,nv_c,ip
1906
 
1907
      data ibndry/0/
1908
 
1909
      common/spolybndry/vlat_c,vlon_c,nv_c,xlat_c,xlon_c,tlonv,ibndry
1910
 
1911
      if (nv.gt.mxnv) then
1912
         print *,'nv exceeds maximum allowed value'
1913
         print *,'adjust parameter mxnv in subroutine DefSPolyBndry'
1914
         stop
1915
      endif
1916
 
1917
      ibndry=1                  ! boundary defined at least once (flag)
1918
      nv_c=nv                   ! copy for named common
1919
      xlat_c=xlat               ! . . . .
1920
      xlon_c=xlon               !
1921
 
1922
      do i=1,nv
1923
         vlat_c(i)=vlat(i)      ! "
1924
         vlon_c(i)=vlon(i)      !
1925
 
1926
         call TrnsfmLon(xlat,xlon,vlat(i),vlon(i),tlonv(i))
1927
 
1928
         if (i.gt.1) then
1929
            ip=i-1
1930
         else
1931
            ip=nv
1932
         endif
1933
 
1934
         if ((vlat(i).eq.vlat(ip)).and.(vlon(i).eq.vlon(ip))) then
1935
            print *,'DefSPolyBndry detects user error:'
1936
            print *,'vertices ',i,' and ',ip,' are not distinct'
1937
            print*,'lat ',i,ip,vlat(i),vlat(ip)
1938
            print*,'lon ',i,ip,vlon(i),vlon(ip)            
1939
            stop
1940
         endif
1941
 
1942
         if (tlonv(i).eq.tlonv(ip)) then
1943
            print *,'DefSPolyBndry detects user error:'
1944
            print *,'vertices ',i,' & ',ip,' on same gt. circle as X'
1945
            stop
1946
         endif
1947
 
1948
         if (vlat(i).eq.(-vlat(ip))) then
1949
            dellon=vlon(i)-vlon(ip)
1950
            if (dellon.gt.+180.) dellon=dellon-360.
1951
            if (dellon.lt.-180.) dellon=dellon-360.
1952
            if ((dellon.eq.+180.0).or.(dellon.eq.-180.0)) then
1953
               print *,'DefSPolyBndry detects user error:'
1954
               print *,'vertices ',i,' and ',ip,' are antipodal'
1955
               stop
1956
            endif
1957
         endif
1958
      enddo
1959
 
1960
      return
1961
 
1962
      end
1963
 
1964
 
1965
c     ****************************************************************
1966
 
1967
      Subroutine LctPtRelBndry(plat,plon,location)
1968
 
1969
c     ****************************************************************
1970
 
1971
c     ****************************************************************
1972
c     * This routine is used to see if some point P is located       *
1973
c     * inside, outside or on the boundary of the spherical polygon  *
1974
c     * S previously defined by a call to subroutine DefSPolyBndry.  *
1975
c     * There is a single restriction on point P: it must not be     *
1976
c     * antipodal to the point X defined in the call to DefSPolyBndry*
1977
c     * (ie.P and X cannot be seperated by exactly 180 degrees).     *
1978
c     * ARGUMENTS:                                                   *  
1979
c     * plat,plon (sent)... the latitude and longitude of point P    *
1980
c     * location (returned)... specifies the location of P:          *
1981
c     *                        location=0 implies P is outside of S  *
1982
c     *                        location=1 implies P is inside of S   *
1983
c     *                        location=2 implies P on boundary of S *
1984
c     *                        location=3 implies user error (P is   *
1985
c     *                                     antipodal to X)          *
1986
c     * UNFfS AND SIGN CONVENTION:                                   * 
1987
c     *  Latitudes and longitudes are specified in degrees.          *
1988
c     *  Latitudes are positive to the north and negative to the     *
1989
c     *  south.                                                      *    
1990
c     *  Longitudes are positive to the east and negative to the     *
1991
c     *  west.                                                       *
1992
c     ****************************************************************
1993
 
1994
      implicit none
1995
 
1996
      integer mxnv
1997
 
1998
c     ----------------------------------------------------------------
1999
c     The statement below must match that in subroutine DefSPolyBndry
2000
c     ----------------------------------------------------------------
2001
 
2002
      parameter (mxnv=2000)
2003
 
2004
      real tlonv(mxnv),vlat_c(mxnv),vlon_c(mxnv),xlat_c,xlon_c
2005
      real plat,plon,vAlat,vAlon,vBlat,vBlon,tlonA,tlonB,tlonP
2006
      real tlon_X,tlon_P,tlon_B,dellon
2007
      integer i,ibndry,nv_c,location,icross,ibrngAB,ibrngAP,ibrngPB
2008
      integer ibrng_BX,ibrng_BP,istrike
2009
 
2010
      common/spolybndry/vlat_c,vlon_c,nv_c,xlat_c,xlon_c,tlonv,ibndry
2011
 
2012
      if (ibndry.eq.0) then     ! user has never defined the bndry
2013
         print*,'Subroutine LctPtRelBndry detects user error:'
2014
         print*,'Subroutine DefSPolyBndry must be called before'
2015
         print*,'subroutine LctPtRelBndry can be called'
2016
         stop
2017
      endif
2018
 
2019
      if (plat.eq.(-xlat_c)) then
2020
         dellon=plon-xlon_c
2021
         if (dellon.lt.(-180.)) dellon=dellon+360.
2022
         if (dellon.gt.+180.) dellon=dellon-360.
2023
         if ((dellon.eq.+180.0).or.(dellon.eq.-180.)) then
2024
            print*,'Warning: LctPtRelBndry detects case P antipodal
2025
     >           to X'
2026
            print*,'location of P relative to S is undetermined'
2027
            location=3
2028
            return
2029
         endif
2030
      endif 
2031
 
2032
      location=0                ! default ( P is outside S)
2033
      icross=0                  ! initialize counter
2034
 
2035
      if ((plat.eq.xlat_c).and.(plon.eq.xlon_c)) then
2036
         location=1
2037
         return
2038
      endif
2039
 
2040
 
2041
      call TrnsfmLon (xlat_c,xlon_c,plat,plon,tlonP)
2042
 
2043
      do i=1,nv_c              ! start of loop over sides of S 
2044
 
2045
         vAlat=vlat_c(i)
2046
         vAlon=vlon_c(i)
2047
         tlonA=tlonv(i)
2048
 
2049
         if (i.lt.nv_c) then
2050
            vBlat=vlat_c(i+1)
2051
            vBlon=vlon_c(i+1)
2052
            tlonB=tlonv(i+1)
2053
         else
2054
            vBlat=vlat_c(1)
2055
            vBlon=vlon_c(1)
2056
            tlonB=tlonv(1)
2057
         endif
2058
 
2059
         istrike=0
2060
 
2061
         if (tlonP.eq.tlonA) then
2062
            istrike=1
2063
         else
2064
            call EastOrWest(tlonA,tlonB,ibrngAB)
2065
            call EastOrWest(tlonA,tlonP,ibrngAP)
2066
            call EastOrWest(tlonP,tlonB,ibrngPB)
2067
 
2068
 
2069
            if((ibrngAP.eq.ibrngAB).and.(ibrngPB.eq.ibrngAB)) istrike=1
2070
         endif
2071
 
2072
 
2073
         if (istrike.eq.1) then
2074
 
2075
            if ((plat.eq.vAlat).and.(plon.eq.vAlon)) then
2076
               location=2       ! P lies on a vertex of S
2077
               return
2078
            endif
2079
            call TrnsfmLon(vAlat,vAlon,xlat_c,xlon_c,tlon_X)
2080
            call TrnsfmLon(vAlat,vAlon,vBlat,vBlon,tlon_B)
2081
            call TrnsfmLon(vAlat,vAlon,plat,plon,tlon_P)
2082
 
2083
            if (tlon_P.eq.tlon_B) then
2084
               location=2       ! P lies on side of S
2085
               return 
2086
            else
2087
               call EastOrWest(tlon_B,tlon_X,ibrng_BX)
2088
               call EastOrWest(tlon_B,tlon_P,ibrng_BP)
2089
               if(ibrng_BX.eq.(-ibrng_BP)) icross=icross+1
2090
            endif
2091
 
2092
         endif
2093
      enddo                     ! end of loop over the sides of S
2094
 
2095
 
2096
c     if the arc XP crosses the boundary S an even number of times then P
2097
c     is in S
2098
 
2099
      if (mod(icross,2).eq.0) location=1
2100
 
2101
      return
2102
 
2103
      end
2104
 
2105
 
2106
c     ****************************************************************
2107
 
2108
      subroutine TrnsfmLon(plat,plon,qlat,qlon,tranlon)
2109
 
2110
c     ****************************************************************
2111
c     * This subroutine is required by subroutines DefSPolyBndry &   *
2112
c     * LctPtRelBndry. It finds the 'longitude' of point Q in a      *
2113
c     * geographic coordinate system for which point P acts as a     *
2114
c     * 'north pole'. SENT: plat,plon,qlat,qlon, in degrees.         *
2115
c     * RETURNED: tranlon, in degrees.                               *
2116
c     ****************************************************************
2117
 
2118
      implicit none
2119
 
2120
      real pi,dtr,plat,plon,qlat,qlon,tranlon,t,b
2121
      parameter (pi=3.141592654,dtr=pi/180.0)
2122
 
2123
      if (plat.eq.90.) then
2124
         tranlon=qlon
2125
      else
2126
         t=sin((qlon-plon)*dtr)*cos(qlat*dtr)
2127
         b=sin(dtr*qlat)*cos(plat*dtr)-cos(qlat*dtr)*sin(plat*dtr)
2128
     >    *cos((qlon-plon)*dtr)
2129
         tranlon=atan2(t,b)/dtr
2130
      endif
2131
 
2132
      return
2133
      end
2134
 
2135
c     ****************************************************************
2136
 
2137
      subroutine EastOrWest(clon,dlon,ibrng)
2138
 
2139
c     ****************************************************************
2140
c     * This subroutine is required by subroutine LctPtRelBndry.     *
2141
c     * This routine determines if in travelling the shortest path   *
2142
c     * from point C (at longitude clon) to point D (at longitude    *
2143
c     * dlon) one is heading east, west or neither.                  *
2144
c     * SENT: clon,dlon; in degrees. RETURNED: ibrng                 *
2145
c     * (1=east,-1=west, 0=neither).                                 *
2146
c     ****************************************************************
2147
 
2148
      implicit none
2149
      real clon,dlon,del
2150
      integer ibrng
2151
      del=dlon-clon
2152
      if (del.gt.180.) del=del-360.
2153
      if (del.lt.-180.) del=del+360.
2154
      if ((del.gt.0.0).and.(del.ne.180.)) then
2155
         ibrng=-1               ! (D is west of C)
2156
      elseif ((del.lt.0.0).and.(del.ne.-180.)) then
2157
         ibrng=+1               ! (D is east of C)
2158
      else
2159
         ibrng=0                ! (D north or south of C)
2160
      endif
2161
      return
2162
      end