Subversion Repositories lagranto.ecmwf

Rev

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

Rev Author Line No. Line
3 michaesp 1
PROGRAM trace_label_circle
2
 
3
  ! ********************************************************************
4
  ! *                                                                  *
5
  ! * Trace fields along trajectories                                  *
6
  ! *                                                                  *
7
  ! * Heini Wernli       first version:       April 1993               *
8
  ! * Michael Sprenger   major upgrade:       2008-2009                *
9
  ! * Bojan Skerlak      clustering option:   March 2012               *
10
  ! * Bojan Skerlak      circle option:       November 2012            *
11
  ! *                                                                  *
12
  ! ********************************************************************
13
 
14
  implicit none
15
 
16
  ! --------------------------------------------------------------------
17
  ! Declaration of parameters
18
  ! --------------------------------------------------------------------
19
 
20
  ! Maximum number of levels for input files
21
  integer :: nlevmax
22
  parameter (nlevmax=100)
23
 
24
  ! Maximum number of input files (dates, length of trajectories)
25
  integer :: ndatmax
26
  parameter (ndatmax=500)
27
 
28
  ! Numerical epsilon (for float comparison)
29
  real :: eps
30
  parameter (eps=0.001)
31
 
32
  ! Conversion factors
33
  real :: pi180                                   ! deg -> rad
34
  parameter (pi180=3.14159/180.)
35
  real :: deg2km                                  ! deg -> km (at equator)
36
  parameter (deg2km=111.)
37
  real :: pir
38
  parameter (pir=255032235.95489)                 ! 2*Pi*R^2 (Bojan)
39
 
40
  ! Prefix for primary and secondary fields
41
  character :: charp
42
  character :: chars
43
  parameter (charp='P')
44
  parameter (chars='S')
45
 
46
  ! --------------------------------------------------------------------
47
  ! Declaration of variables
48
  ! --------------------------------------------------------------------
49
 
50
  ! Input and output format for trajectories (see iotra.f)
51
  integer :: inpmode
52
  integer :: outmode
53
 
54
  ! Input parameters
55
  character(len=80) :: inpfile         ! Input trajectory file
56
  character(len=80) :: outfile         ! Output trajectory file
57
  integer :: ntra                      ! Number of trajectories
58
  integer :: ncol                      ! Number of columns (including time, lon, lat, p)
59
  integer :: ntim                      ! Number of times per trajectory
60
  integer :: ntrace0                   ! Number of trace variables
61
  character(len=80) :: tvar0(200)      ! Tracing variable (with mode specification)
62
  character(len=80) :: tvar(200)       ! Tracing variable name (only the variable)
63
  character(len=1)  :: tfil(200)       ! Filename prefix
64
  real :: fac(200)                     ! Scaling factor
65
  real :: shift_val(200)               ! Shift in space and time relative to trajectory position
66
  character(len=80) :: shift_dir(200)  ! Direction of shift
67
  integer :: compfl(200)               ! Computation flag (1=compute)
68
  integer :: numdat                    ! Number of input files
69
  character(len=11) :: dat(ndatmax)    ! Dates of input files
70
  real :: timeinc                      ! Time increment between input files
71
  real :: tst                          ! Time shift of start relative to first data file
72
  real :: ten                          ! Time shift of end relatiev to first data file
73
  character(len=20) :: startdate       ! First time/date on trajectory
74
  character(len=20) :: enddate         ! Last time/date on trajectory
75
  integer :: ntrace1                   ! Count trace and additional variables
76
  character(len=80) :: timecheck       ! Either 'yes' or 'no'
77
  character(len=80) :: intmode         ! Interpolation mode ('normal', 'nearest') Bojan ('clustering','circle_avg','circle_max','circle_min')
78
 
79
  ! Trajectories
80
  real,allocatable, dimension (:,:,:) :: trainp          ! Input trajectories (ntra,ntim,ncol)
81
  real,allocatable, dimension (:,:,:) :: traint          ! Internal trajectories (ntra,ntim,ncol+ntrace1)
82
  real,allocatable, dimension (:,:,:) :: traout          ! Output trajectories (ntra,ntim,ncol+ntrace0)
83
  integer :: reftime(6)                                  ! Reference date
84
  character(len=80) :: varsinp(100)                      ! Field names for input trajectory
85
  character(len=80) :: varsint(100)                      ! Field names for internal trajectory
86
  character(len=80) :: varsout(100)                      ! Field names for output trajectory
87
  integer :: fid,fod                                     ! File identifier for inp and out trajectories
88
  real :: x0,y0,p0                                       ! Position of air parcel (physical space)
89
  real :: reltpos0                                       ! Relative time of air parcel
90
  real :: xind,yind,pind                                 ! Position of air parcel (grid space)
91
  integer :: fbflag                                      ! Flag for forward (1) or backward (-1) trajectories
92
  integer :: fok(100)                                    ! Flag whether field is ready
93
 
94
  ! Meteorological fields
95
  real,allocatable, dimension (:)     :: spt0,spt1       ! Surface pressure
96
  real,allocatable, dimension (:)     :: p3t0,p3t1       ! 3d-pressure
97
  real,allocatable, dimension (:)     :: f3t0,f3t1       ! 3d field for tracing
98
  character(len=80) :: svars(100)                        ! List of variables on S file
99
  character(len=80) :: pvars(100)                        ! List of variables on P file
100
  integer :: n_svars                                     ! Number of variables on S file
101
  integer :: n_pvars                                     ! Number of variables on P file
102
 
103
  ! Grid description
104
  real :: pollon,pollat   ! Longitude/latitude of pole
105
  real :: ak(100)         ! Vertical layers and levels
106
  real :: bk(100)
107
  real :: xmin,xmax       ! Zonal grid extension
108
  real :: ymin,ymax       ! Meridional grid extension
109
  integer :: nx,ny,nz     ! Grid dimensions
110
  real :: dx,dy           ! Horizontal grid resolution
111
  integer :: hem          ! Flag for hemispheric domain
112
  integer :: per          ! Flag for periodic domain
113
  real :: stagz           ! Vertical staggering
114
  real :: mdv             ! Missing data value
115
 
116
  ! Auxiliary variables
117
  integer :: i,j,k,l,m,n
118
  real :: rd
119
  character(len=80) :: filename,varname
120
  real :: time0,time1,reltpos
121
  integer :: itime0,itime1
122
  integer :: stat
123
  real :: tstart
124
  integer :: iloaded0,iloaded1
125
  real :: f0
126
  real :: frac
127
  real :: tload,tfrac
128
  integer :: isok
129
  character :: ch
130
  integer :: ind
131
  integer :: ind1,ind2,ind3,ind4,ind5
132
  integer :: ind6,ind7,ind8,ind9,ind0
133
  integer :: noutside
134
  real :: delta
135
  integer :: itrace0
136
  character(len=80) :: string
137
 
138
  ! Bojan
139
  real    :: dist,circlesum,circlemax,circlemin,circleavg,radius       ! distance (great circle), sum/max/min/avg in circle, radius of circle
140
  integer :: ist,jst,kst,sp,ml,mr,nd,nu                                ! ijk in stack, sp=stack counter, ml (left), mr (right), nd (down), nu (up)
141
  integer :: lci,lcj,xindb,xindf                                       ! label count i and j, xind back, xind forward
142
  integer :: yindb,yindf,pindb,pindf                                   ! yind back, yind forward, pind back, pind forward
143
  integer :: pvpos,thpos                                               ! position of variables PV and TH in trajectory
144
  integer, allocatable, dimension (:)   :: stackx,stacky               ! lon/lat of stack
145
  integer, allocatable, dimension (:)   :: lblcount                    ! counter for label
146
  integer, allocatable, dimension (:,:) :: connect                     ! array that keeps track of the visited grid points
147
  real, allocatable, dimension (:)      :: lbl                         ! label
148
  real, allocatable, dimension (:)      :: circlelon,circlelat         ! value of f, lon and lat in circle
149
  real, allocatable, dimension (:)      :: circlef,circlearea          ! value of f, lon and lat in circle
150
  real, allocatable, dimension (:)      :: longrid,latgrid             ! arrays of longitude and latitude of grid points
151
  ! Bojan
152
 
153
  ! Externals
154
  real :: int_index4
155
  external int_index4
156
  real :: sdis   
157
  external sdis 
158
 
159
  ! --------------------------------------------------------------------
160
  ! Start of program, Read parameters, get grid parameters
161
  ! --------------------------------------------------------------------
162
 
163
  ! Write start message
164
  print*,'========================================================='
165
  print*,'              *** START OF PROGRAM TRACE ***'
166
  print*
167
 
168
  ! Read parameters
169
  open(10,file='trace.param')
170
   read(10,*) inpfile
171
   read(10,*) outfile
172
   read(10,*) startdate
173
   read(10,*) enddate
174
   read(10,*) fbflag
175
   read(10,*) numdat
176
   if ( fbflag.eq.1) then
177
      do i=1,numdat
178
         read(10,'(a11)') dat(i)
179
      enddo
180
   else
181
      do i=numdat,1,-1
182
         read(10,'(a11)') dat(i)
183
      enddo
184
   endif
185
   read(10,*) timeinc
186
   read(10,*) tst
187
   read(10,*) ten
188
   read(10,*) ntra
189
   read(10,*) ntim
190
   read(10,*) ncol
191
   read(10,*) ntrace0
192
   do i=1,ntrace0
193
      read(10,*) tvar(i), fac(i), compfl(i), tfil(i)
194
   enddo
195
   read(10,*) n_pvars
196
   do i=1,n_pvars
197
      read(10,*) pvars(i)
198
   enddo
199
   read(10,*) n_svars
200
   do i=1,n_svars
201
      read(10,*) svars(i)
202
   enddo
203
   read(10,*) timecheck
204
   read(10,*) intmode
205
   read(10,*) radius
206
  close(10)
207
 
208
  ! Bojan: error if radius < 0
209
  if (radius .lt. 0) then
210
     print*,'ERROR (circle): radius < 0!'
211
     stop
212
  endif
213
 
214
  ! Remove commented tracing fields
215
  itrace0 = 1
216
  do while ( itrace0.le.ntrace0)
217
     string = tvar(itrace0)
218
     if ( string(1:1).eq.'#' ) then
219
        do i=itrace0,ntrace0-1
220
           tvar(i)   = tvar(i+1)
221
           fac(i)    = fac(i+1)
222
           compfl(i) = compfl(i+1)
223
           tfil(i)   = tfil(i+1)
224
        enddo
225
        ntrace0 = ntrace0 - 1
226
     else
227
        itrace0 = itrace0 + 1
228
     endif
229
  enddo
230
 
231
  ! Save the tracing variable (including all mode specifications)
232
  do i=1,ntrace0
233
     tvar0(i) = tvar(i)
234
  enddo
235
 
236
  ! Set the formats of the input and output files
237
  call mode_tra(inpmode,inpfile)
238
  if (inpmode.eq.-1) inpmode=1
239
  call mode_tra(outmode,outfile)
240
  if (outmode.eq.-1) outmode=1
241
 
242
  ! Convert time shifts <tst,ten> from <hh.mm> into fractional time
243
  call hhmm2frac(tst,frac)
244
  tst = frac
245
  call hhmm2frac(ten,frac)
246
  ten = frac
247
 
248
  ! Set the time for the first data file (depending on forward/backward mode)
249
  if (fbflag.eq.1) then
250
    tstart = -tst
251
  else
252
    tstart = tst
253
  endif
254
 
255
  ! Read the constant grid parameters (nx,ny,nz,xmin,xmax,ymin,ymax,pollon,pollat)
256
  ! The negative <-fid> of the file identifier is used as a flag for parameter retrieval
257
  filename = charp//dat(1)
258
  varname  = 'U'
259
  call input_open (fid,filename)
260
  call input_grid (-fid,varname,xmin,xmax,ymin,ymax,dx,dy,nx,ny,tstart,pollon,pollat,rd,rd,nz,rd,rd,rd,timecheck)
261
  call input_close(fid)
262
 
263
  ! Allocate memory for some meteorological arrays
264
  allocate(spt0(nx*ny),stat=stat)
265
  if (stat.ne.0) print*,'*** error allocating array spt0 ***'   ! Surface pressure
266
  allocate(spt1(nx*ny),stat=stat)
267
  if (stat.ne.0) print*,'*** error allocating array spt1 ***'
268
  allocate(p3t0(nx*ny*nz),stat=stat)
269
  if (stat.ne.0) print*,'*** error allocating array p3t0 ***'   ! Pressure
270
  allocate(p3t1(nx*ny*nz),stat=stat)
271
  if (stat.ne.0) print*,'*** error allocating array p3t1 ***'
272
  allocate(f3t0(nx*ny*nz),stat=stat)
273
  if (stat.ne.0) print*,'*** error allocating array p3t0 ***'   ! Tracing field
274
  allocate(f3t1(nx*ny*nz),stat=stat)
275
  if (stat.ne.0) print*,'*** error allocating array p3t1 ***'
276
 
277
  ! Get memory for trajectory arrays
278
  allocate(trainp(ntra,ntim,ncol),stat=stat)
279
  if (stat.ne.0) print*,'*** error allocating array tra      ***'
280
 
281
  ! Bojan
282
  ! allocate memory for clustering mode 
283
  if (intmode .eq. 'clustering') then
284
     allocate(lbl(8),stat=stat)
285
     if (stat.ne.0) print*,'*** error allocating array lbl      ***'
286
     allocate(lblcount(5),stat=stat)
287
     if (stat.ne.0) print*,'*** error allocating array lblcount ***'
288
  endif
289
 
290
  ! allocate memory for circle mode
291
  if ( (intmode.eq.'circle_avg') .or. (intmode.eq.'circle_min') .or. (intmode.eq.'circle_max') ) then
292
     allocate(connect(nx,ny),stat=stat)
293
     if (stat.ne.0) print*,'*** error allocating connect ***'
294
     allocate(stackx(nx*ny),stat=stat)
295
     if (stat.ne.0) print*,'*** error allocating stackx ***'
296
     allocate(stacky(nx*ny),stat=stat)
297
     if (stat.ne.0) print*,'*** error allocating stacky ***'
298
     allocate(circlelon(nx*ny),stat=stat)
299
     if (stat.ne.0) print*,'*** error allocating circlelon ***'
300
     allocate(circlelat(nx*ny),stat=stat)
301
     if (stat.ne.0) print*,'*** error allocating circlelat ***'
302
     allocate(circlef(nx*ny),stat=stat)
303
     if (stat.ne.0) print*,'*** error allocating circlef ***'
304
     allocate(circlearea(nx*ny),stat=stat)
305
     if (stat.ne.0) print*,'*** error allocating circlearea ***'
306
     allocate(longrid(nx),stat=stat)
307
     if (stat.ne.0) print*,'*** error allocating longrid ***'
308
     allocate(latgrid(ny),stat=stat)
309
     if (stat.ne.0) print*,'*** error allocating latgrid ***'
310
     do m=1,nx
311
        longrid(m)=xmin+dx*(m-1)
312
     enddo
313
     do n=1,ny
314
        latgrid(n)=ymin+dy*(n-1)
315
     enddo
316
  endif
317
  ! Bojan
318
 
319
  ! Set the flags for periodic domains
320
  if ( abs(xmax-xmin-360.).lt.eps ) then
321
     per = 1
322
  elseif ( abs(xmax-xmin-360.+dx).lt.eps ) then
323
     per = 2
324
  else
325
     per = 0
326
  endif
327
 
328
  ! Set logical flag for periodic data set (hemispheric or not)
329
  hem = 0
330
  if (per.eq.0.) then
331
     delta=xmax-xmin-360.
332
     if (abs(delta+dx).lt.eps) then               ! Program aborts: arrays must be closed
333
        print*,' ERROR: arrays must be closed... Stop'
334
     else if (abs(delta).lt.eps) then ! Periodic and hemispheric
335
       hem=1
336
       per=360.
337
    endif
338
  else                                            ! Periodic and hemispheric
339
     hem=1
340
  endif
341
 
342
  ! Write some status information
343
  print*,'---- INPUT PARAMETERS -----------------------------------'
344
  print*
345
  print*,'  Input trajectory file  : ',trim(inpfile)
346
  print*,'  Output trajectory file : ',trim(outfile)
347
  print*,'  Format of input file   : ',inpmode
348
  print*,'  Format of output file  : ',outmode
349
  print*,'  Forward/backward       : ',fbflag
350
  print*,'  #tra                   : ',ntra
351
  print*,'  #col                   : ',ncol
352
  print*,'  #tim                   : ',ntim
353
  print*,'  No time check          : ',trim(timecheck)
354
  print*,'  Interpolation mode     : ',trim(intmode)
355
  do i=1,ntrace0
356
     if (compfl(i).eq.0) then
357
        print*,'  Tracing field          : ', trim(tvar(i)), fac(i), ' 0 ', tfil(i)
358
     else
359
        print*,'  Tracing field          : ', trim(tvar(i)), fac(i), '  1 ', tfil(i)
360
     endif
361
  enddo
362
  print*
363
  print*,'---- INPUT DATA FILES -----------------------------------'
364
  print*
365
  call frac2hhmm(tstart,tload)
366
  print*,'  Time of 1st data file  : ',tload
367
  print*,'  #input files           : ',numdat
368
  print*,'  time increment         : ',timeinc
369
  call frac2hhmm(tst,tload)
370
  print*,'  Shift of start         : ',tload
371
  call frac2hhmm(ten,tload)
372
  print*,'  Shift of end           : ',tload
373
  print*,'  First/last input file  : ',trim(dat(1)), ' ... ', trim(dat(numdat))
374
  print*,'  Primary variables      : ',trim(pvars(1))
375
  do i=2,n_pvars
376
     print*,'                         : ',trim(pvars(i))
377
  enddo
378
  if ( n_svars.ge.1 ) then
379
     print*,'  Secondary variables    : ',trim(svars(1))
380
     do i=2,n_svars
381
        print*,'                         : ',trim(svars(i))
382
     enddo
383
  endif
384
  print*
385
  print*,'---- CONSTANT GRID PARAMETERS ---------------------------'
386
  print*
387
  print*,'  xmin,xmax     : ',xmin,xmax
388
  print*,'  ymin,ymax     : ',ymin,ymax
389
  print*,'  dx,dy         : ',dx,dy
390
  print*,'  pollon,pollat : ',pollon,pollat
391
  print*,'  nx,ny,nz      : ',nx,ny,nz
392
  print*,'  per, hem      : ',per,hem
393
  print*
394
 
395
  ! --------------------------------------------------------------------
396
  ! Load the input trajectories
397
  ! --------------------------------------------------------------------
398
 
399
  ! Read the input trajectory file
400
  call ropen_tra(fid,inpfile,ntra,ntim,ncol,reftime,varsinp,inpmode)
401
  call read_tra (fid,trainp,ntra,ntim,ncol,inpmode)
402
  call close_tra(fid,inpmode)
403
 
404
  ! Check that first four columns correspond to time,lon,lat,p
405
  if ( (varsinp(1).ne.'time' ).or. &
406
       (varsinp(2).ne.'xpos' ).and.(varsinp(2).ne.'lon' ).or. &
407
       (varsinp(3).ne.'ypos' ).and.(varsinp(3).ne.'lat' ).or. &
408
       (varsinp(4).ne.'ppos' ).and.(varsinp(4).ne.'p'   ) ) then
409
     print*,' ERROR: problem with input trajectories ...'
410
     stop
411
  endif
412
  varsinp(1) = 'time'
413
  varsinp(2) = 'lon'
414
  varsinp(3) = 'lat'
415
  varsinp(4) = 'p'
416
 
417
  ! Write some status information of the input trajectories
418
  print*,'---- INPUT TRAJECTORIES ---------------------------------'
419
  print*
420
  print*,' Start date             : ',trim(startdate)
421
  print*,' End date               : ',trim(enddate)
422
  print*,' Reference time (year)  : ',reftime(1)
423
  print*,'                (month) : ',reftime(2)
424
  print*,'                (day)   : ',reftime(3)
425
  print*,'                (hour)  : ',reftime(4)
426
  print*,'                (min)   : ',reftime(5)
427
  print*,' Time range (min)       : ',reftime(6)
428
  do i=1,ncol
429
     print*,' Var                    :',i,trim(varsinp(i))
430
  enddo
431
  print*
432
 
433
  ! Check that first time is 0 - otherwise the tracing will produce
434
  ! wrong results because later in the code only absolute times are
435
  ! considered: <itime0   = int(abs(tfrac-tstart)/timeinc) + 1>. This
436
  ! will be changed in a future version.
437
  if ( abs( trainp(1,1,1) ).gt.eps ) then
438
     print*,' ERROR: First time of trajectory must be 0, i.e. '
439
     print*,'     correspond to the reference date. Otherwise'
440
     print*,'     the tracing will give wrong results... STOP'
441
     stop
442
  endif
443
 
444
  ! --------------------------------------------------------------------
445
  ! Check dependencies for trace fields which must be calculated
446
  ! --------------------------------------------------------------------
447
 
448
  ! Set the counter for extra fields
449
  ntrace1 = ntrace0
450
 
451
  ! Loop over all tracing variables
452
  i = 1
453
  do while (i.le.ntrace1)
454
 
455
     ! Skip fields which must be available on the input files
456
     if (i.le.ntrace0) then
457
        if (compfl(i).eq.0) goto 100
458
     endif
459
 
460
     ! Get the dependencies for potential temperature (TH)
461
     if ( tvar(i).eq.'TH' ) then
462
        varname='P'                                   ! P
463
        call add2list(varname,tvar,ntrace1)
464
        varname='T'                                   ! T
465
        call add2list(varname,tvar,ntrace1)
466
 
467
     ! Get the dependencies for potential temperature (TH)
468
     elseif ( tvar(i).eq.'RHO' ) then
469
        varname='P'                                   ! P
470
        call add2list(varname,tvar,ntrace1)
471
        varname='T'                                   ! T
472
        call add2list(varname,tvar,ntrace1)
473
 
474
     ! Get the dependencies for relative humidity (RH)
475
     elseif ( tvar(i).eq.'RH' ) then
476
        varname='P'                                   ! P
477
        call add2list(varname,tvar,ntrace1)
478
        varname='T'                                   ! T
479
        call add2list(varname,tvar,ntrace1)
480
        varname='Q'                                   ! Q
481
        call add2list(varname,tvar,ntrace1)
482
 
483
     ! Get the dependencies for equivalent potential temperature (THE)
484
     elseif ( tvar(i).eq.'THE' ) then
485
        varname='P'                                   ! P
486
        call add2list(varname,tvar,ntrace1)
487
        varname='T'                                   ! T
488
        call add2list(varname,tvar,ntrace1)
489
        varname='Q'                                   ! Q
490
        call add2list(varname,tvar,ntrace1)
491
 
492
     ! Get the dependencies for latent heating rate (LHR)
493
     elseif ( tvar(i).eq.'LHR' ) then
494
        varname='P'                                   ! P
495
        call add2list(varname,tvar,ntrace1)
496
        varname='T'                                   ! T
497
        call add2list(varname,tvar,ntrace1)
498
        varname='Q'                                   ! Q
499
        call add2list(varname,tvar,ntrace1)
500
        varname='OMEGA'                               ! OMEGA
501
        call add2list(varname,tvar,ntrace1)
502
        varname='RH'                                  ! RH
503
        call add2list(varname,tvar,ntrace1)
504
 
505
     ! Get the dependencies for wind speed (VEL)
506
     elseif ( tvar(i).eq.'VEL' ) then
507
        varname='U'                                   ! U
508
        call add2list(varname,tvar,ntrace1)
509
        varname='V'                                   ! V
510
        call add2list(varname,tvar,ntrace1)
511
 
512
     ! Get the dependencies for wind direction (DIR)
513
     elseif ( tvar(i).eq.'DIR' ) then
514
        varname='U'                                   ! U
515
        call add2list(varname,tvar,ntrace1)
516
        varname='V'                                   ! V
517
        call add2list(varname,tvar,ntrace1)
518
 
519
     ! Get the dependencies for du/dx (DUDX)
520
     elseif ( tvar(i).eq.'DUDX' ) then
521
        varname='U:+1DLON'                            ! U:+1DLON
522
        call add2list(varname,tvar,ntrace1)
523
        varname='U:-1DLON'                            ! U:-1DLON
524
        call add2list(varname,tvar,ntrace1)
525
 
526
     ! Get the dependencies for dv(dx (DVDX)
527
     elseif ( tvar(i).eq.'DVDX' ) then
528
        varname='V:+1DLON'                            ! V:+1DLON
529
        call add2list(varname,tvar,ntrace1)
530
        varname='V:-1DLON'                            ! V:-1DLON
531
        call add2list(varname,tvar,ntrace1)
532
 
533
     ! Get the dependencies for du/dy (DUDY)
534
     elseif ( tvar(i).eq.'DUDY' ) then
535
        varname='U:+1DLAT'                            ! U:+1DLAT
536
        call add2list(varname,tvar,ntrace1)
537
        varname='U:-1DLAT'                            ! U:-1DLAT
538
        call add2list(varname,tvar,ntrace1)
539
 
540
     ! Get the dependencies for dv/dy (DVDY)
541
     elseif ( tvar(i).eq.'DVDY' ) then
542
        varname='V:+1DLAT'                            ! V:+1DLAT
543
        call add2list(varname,tvar,ntrace1)
544
        varname='V:-1DLAT'                            ! V:-1DLAT
545
        call add2list(varname,tvar,ntrace1)
546
 
547
     ! Get the dependencies for du/dp (DUDP)
548
     elseif ( tvar(i).eq.'DUDP' ) then
549
        varname='U:+1DP'                              ! U:+1DP
550
        call add2list(varname,tvar,ntrace1)
551
        varname='U:-1DP'                              ! U:-1DP
552
        call add2list(varname,tvar,ntrace1)
553
        varname='P:+1DP'                              ! P:+1DP
554
        call add2list(varname,tvar,ntrace1)
555
        varname='P:-1DP'                              ! P:-1DP
556
        call add2list(varname,tvar,ntrace1)
557
 
558
     ! Get the dependencies for dv/dp (DVDP)
559
     elseif ( tvar(i).eq.'DVDP' ) then
560
        varname='V:+1DP'                              ! V:+1DP
561
        call add2list(varname,tvar,ntrace1)
562
        varname='V:-1DP'                              ! V:-1DP
563
        call add2list(varname,tvar,ntrace1)
564
        varname='P:+1DP'                              ! P:+1DP
565
        call add2list(varname,tvar,ntrace1)
566
        varname='P:-1DP'                              ! P:-1DP
567
        call add2list(varname,tvar,ntrace1)
568
 
569
     ! Get the dependencies for dt/dx (DTDX)
570
     elseif ( tvar(i).eq.'DTDX' ) then
571
        varname='T:+1DLON'                            ! T:+1DLON
572
        call add2list(varname,tvar,ntrace1)
573
        varname='T:-1DLON'                            ! T:-1DLON
574
        call add2list(varname,tvar,ntrace1)
575
 
576
     ! Get the dependencies for dth/dy (DTHDY)
577
     elseif ( tvar(i).eq.'DTHDY' ) then
578
        varname='T:+1DLAT'                            ! T:+1DLON
579
        call add2list(varname,tvar,ntrace1)
580
        varname='T:-1DLAT'                            ! T:-1DLON
581
        call add2list(varname,tvar,ntrace1)
582
        varname='P'                                   ! P
583
        call add2list(varname,tvar,ntrace1)
584
 
585
     ! Get the dependencies for dth/dx (DTHDX)
586
     elseif ( tvar(i).eq.'DTHDX' ) then
587
        varname='T:+1DLON'                            ! T:+1DLON
588
        call add2list(varname,tvar,ntrace1)
589
        varname='T:-1DLON'                            ! T:-1DLON
590
        call add2list(varname,tvar,ntrace1)
591
        varname='P'                                   ! P
592
        call add2list(varname,tvar,ntrace1)
593
 
594
     ! Get the dependencies for dt/dy (DTDY)
595
     elseif ( tvar(i).eq.'DTDY' ) then
596
        varname='T:+1DLAT'                            ! T:+1DLON
597
        call add2list(varname,tvar,ntrace1)
598
        varname='T:-1DLAT'                            ! T:-1DLON
599
        call add2list(varname,tvar,ntrace1)
600
 
601
     ! Get the dependencies for dt/dp (DTDP)
602
     elseif ( tvar(i).eq.'DTDP' ) then
603
        varname='T:+1DP'                              ! T:+1DP
604
        call add2list(varname,tvar,ntrace1)
605
        varname='T:-1DP'                              ! T:-1DP
606
        call add2list(varname,tvar,ntrace1)
607
        varname='P:+1DP'                              ! P:+1DP
608
        call add2list(varname,tvar,ntrace1)
609
        varname='P:-1DP'                              ! P:-1DP
610
        call add2list(varname,tvar,ntrace1)
611
 
612
     ! Get the dependencies for dth/dp (DTHDP)
613
     elseif ( tvar(i).eq.'DTHDP' ) then
614
        varname='T:+1DP'                              ! T:+1DP
615
        call add2list(varname,tvar,ntrace1)
616
        varname='T:-1DP'                              ! T:-1DP
617
        call add2list(varname,tvar,ntrace1)
618
        varname='T'                                   ! T
619
        call add2list(varname,tvar,ntrace1)
620
        varname='P:+1DP'                              ! P:+1DP
621
        call add2list(varname,tvar,ntrace1)
622
        varname='P:-1DP'                              ! P:-1DP
623
        call add2list(varname,tvar,ntrace1)
624
        varname='P'                                   ! P
625
        call add2list(varname,tvar,ntrace1)
626
 
627
     ! Get the dependencies for squared Brunt Vaiäläa frequency (NSQ)
628
     elseif ( tvar(i).eq.'NSQ' ) then
629
        varname='DTHDP'                                ! DTHDP
630
        call add2list(varname,tvar,ntrace1)
631
        varname='TH'                                   ! TH
632
        call add2list(varname,tvar,ntrace1)
633
        varname='RHO'                                  ! RHO
634
        call add2list(varname,tvar,ntrace1)
635
 
636
     ! Get the dependencies for relative vorticity (RELVORT)
637
     elseif ( tvar(i).eq.'RELVORT' ) then
638
        varname='U'                                    ! U
639
        call add2list(varname,tvar,ntrace1)
640
        varname='DUDY'                                 ! DUDY
641
        call add2list(varname,tvar,ntrace1)
642
        varname='DVDX'                                 ! DVDX
643
        call add2list(varname,tvar,ntrace1)
644
 
645
     ! Get the dependencies for relative vorticity (ABSVORT)
646
     elseif ( tvar(i).eq.'ABSVORT' ) then
647
        varname='U'                                    ! U
648
        call add2list(varname,tvar,ntrace1)
649
        varname='DUDY'                                 ! DUDY
650
        call add2list(varname,tvar,ntrace1)
651
        varname='DVDX'                                 ! DVDX
652
        call add2list(varname,tvar,ntrace1)
653
 
654
     ! Get the dependencies for divergence (DIV)
655
     elseif ( tvar(i).eq.'DIV' ) then
656
        varname='V'                                    ! U
657
        call add2list(varname,tvar,ntrace1)
658
        varname='DUDX'                                 ! DUDX
659
        call add2list(varname,tvar,ntrace1)
660
        varname='DVDY'                                 ! DVDY
661
        call add2list(varname,tvar,ntrace1)
662
 
663
     ! Get the dependencies for deformation (DEF)
664
     elseif ( tvar(i).eq.'DEF' ) then
665
        call add2list(varname,tvar,ntrace1)
666
        varname='DUDX'                                 ! DUDX
667
        call add2list(varname,tvar,ntrace1)
668
        varname='DVDY'                                 ! DVDY
669
        call add2list(varname,tvar,ntrace1)
670
        varname='DUDY'                                 ! DUDY
671
        call add2list(varname,tvar,ntrace1)
672
        varname='DVDX'                                 ! DVDX
673
        call add2list(varname,tvar,ntrace1)
674
 
675
     ! Get the dependencies for potential vorticity (PV)
676
     elseif ( tvar(i).eq.'PV' ) then
677
        varname='ABSVORT'                              ! ABSVORT
678
        call add2list(varname,tvar,ntrace1)
679
        varname='DTHDP'                                ! DTHDP
680
        call add2list(varname,tvar,ntrace1)
681
        varname='DUDP'                                 ! DUDP
682
        call add2list(varname,tvar,ntrace1)
683
        varname='DVDP'                                 ! DVDP
684
        call add2list(varname,tvar,ntrace1)
685
        varname='DTHDX'                                ! DTHDX
686
        call add2list(varname,tvar,ntrace1)
687
        varname='DTHDY'                                ! DTHDY
688
        call add2list(varname,tvar,ntrace1)
689
 
690
     ! Get the dependencies for Richardson number (RI)
691
     elseif ( tvar(i).eq.'RI' ) then
692
        varname='DUDP'                                 ! DUDP
693
        call add2list(varname,tvar,ntrace1)
694
        varname='DVDP'                                 ! DVDP
695
        call add2list(varname,tvar,ntrace1)
696
        varname='NSQ'                                  ! NSQ
697
        call add2list(varname,tvar,ntrace1)
698
        varname='RHO'                                  ! RHO
699
        call add2list(varname,tvar,ntrace1)
700
 
701
     ! Get the dependencies for Ellrod&Knapp's turbulence index (TI)
702
     elseif ( tvar(i).eq.'TI' ) then
703
        varname='DEF'                                  ! DEF
704
        call add2list(varname,tvar,ntrace1)
705
        varname='DUDP'                                 ! DUDP
706
        call add2list(varname,tvar,ntrace1)
707
        varname='DVDP'                                 ! DVDP
708
        call add2list(varname,tvar,ntrace1)
709
        varname='RHO'                                  ! RHO
710
        call add2list(varname,tvar,ntrace1)
711
 
712
     endif
713
 
714
     ! Exit point for handling additional fields
715
 100   continue
716
     i = i + 1
717
 
718
  enddo
719
 
720
  ! Save the full variable name (including shift specification)
721
  do i=1,ncol
722
     varsint(i)      = varsinp(i)
723
  enddo
724
  do i=1,ntrace1
725
     varsint(i+ncol) = tvar(i)
726
  enddo
727
 
728
  ! Bojan: check that PV and TH are on trajectory
729
  if (intmode .eq. 'clustering') then
730
     pvpos=-1
731
     thpos=-1
732
     do i=1,ncol+ntrace1
733
        if (varsint(i) .eq. 'TH') then
734
        thpos=i
735
        print*,'Clustering: Found TH at position:',thpos
736
        endif
737
        if (varsint(i) .eq. 'PV') then
738
        pvpos=i
739
        print*,'Clustering: Found PV at position:',pvpos
740
        endif
741
     enddo
742
     if (thpos .eq. -1) then
743
        print*,'WARNING (clustering): Did not find TH'
744
        stop
745
     endif
746
     if (pvpos .eq. -1) then
747
        print*,'WARNING (clustering): Did not find PV'
748
        stop
749
     endif
750
  endif
751
  ! Bojan
752
 
753
  ! Split the variable name and set flags
754
  do i=1,ntrace1
755
 
756
     ! Set the scaling factor
757
     if ( i.gt.ntrace0 ) fac(i) = 1.
758
 
759
     ! Set the base variable name, the shift and the direction
760
     call splitvar(tvar(i),shift_val(i),shift_dir(i) )
761
 
762
     ! Set the prefix of the file name
763
     if ( ( compfl(i).eq.0 ).or.(i.gt.ntrace0) ) then
764
        tfil(i)=' '
765
        do j=1,n_pvars
766
           if ( tvar(i).eq.pvars(j) ) tfil(i)=charp
767
        enddo
768
        do j=1,n_svars
769
           if ( tvar(i).eq.svars(j) ) tfil(i)=chars
770
        enddo
771
     else
772
        tfil(i) = '*'
773
     endif
774
 
775
     ! Set the computational flag
776
     if ( (tvar(i).eq.'P'   ).or. &
777
          (tvar(i).eq.'PLAY').or. &
778
          (tvar(i).eq.'PLEV') ) then
779
        compfl(i) = 0
780
        tfil(i)   = charp
781
     elseif ( ( tfil(i).eq.charp ).or.( tfil(i).eq.chars ) ) then
782
        compfl(i) = 0
783
     else
784
        compfl(i) = 1
785
     endif
786
 
787
  enddo
788
 
789
  ! Check whether the shift modes are supported
790
  do i=1,ntrace1
791
     if ( ( shift_dir(i).ne.'nil'     ).and. &
792
          ( shift_dir(i).ne.'DLON'    ).and. &
793
          ( shift_dir(i).ne.'DLAT'    ).and. &
794
          ( shift_dir(i).ne.'DP'      ).and. &
795
          ( shift_dir(i).ne.'HPA'     ).and. &
796
          ( shift_dir(i).ne.'KM(LON)' ).and. &
797
          ( shift_dir(i).ne.'KM(LAT)' ).and. &
798
          ( shift_dir(i).ne.'H'       ).and. &
799
          ( shift_dir(i).ne.'MIN'     ).and. &
800
          ( shift_dir(i).ne.'INDP'    ) ) then
801
        print*,' ERROR: shift mode ',trim(shift_dir(i)), ' not supported'
802
        stop
803
     endif
804
  enddo
805
 
806
  ! Write status information
807
  print*
808
  print*,'---- COMPLETE TABLE FOR TRACING -------------------------'
809
  print*
810
  do i=1,ntrace1
811
     if ( ( shift_dir(i).ne.'nil' ) ) then
812
        write(*,'(i4,a4,a8,f10.2,a8,3x,a1,i5)') i,' : ',trim(tvar(i)), &
813
             shift_val(i),trim(shift_dir(i)),tfil(i),compfl(i)
814
     else
815
        write(*,'(i4,a4,a8,10x,8x,3x,a1,i5)') &
816
             i,' : ',trim(tvar(i)),tfil(i),compfl(i)
817
     endif
818
  enddo
819
 
820
  ! --------------------------------------------------------------------
821
  ! Prepare the internal and output trajectories
822
  ! --------------------------------------------------------------------
823
 
824
  ! Allocate memory for internal trajectories
825
  allocate(traint(ntra,ntim,ncol+ntrace1),stat=stat)
826
  if (stat.ne.0) print*,'*** error allocating array traint   ***'
827
 
828
  ! Copy input to output trajectory
829
  do i=1,ntra
830
     do j=1,ntim
831
        do k=1,ncol
832
           traint(i,j,k)=trainp(i,j,k)
833
        enddo
834
     enddo
835
  enddo
836
 
837
  ! Set the flags for ready fields/colums - at begin only read-in fields are ready
838
  do i=1,ncol
839
     fok(i) = 1
840
  enddo
841
  do i=ncol+1,ntrace1
842
     fok(i) = 0
843
  enddo
844
 
845
  ! --------------------------------------------------------------------
846
  ! Trace the fields (fields available on input files)
847
  ! --------------------------------------------------------------------
848
 
849
  print*
850
  print*,'---- TRACING FROM PRIMARY AND SECONDARY DATA FILES ------'
851
 
852
  ! Loop over all tracing fields
853
  do i=1,ntrace1
854
 
855
      ! Skip fields which must be computed (compfl=1), will be handled later
856
      if (compfl(i).ne.0)  goto 110
857
 
858
      ! Write some status information
859
      print*
860
      print*,' Now tracing             : ', trim(tvar(i)),shift_val(i),trim(shift_dir(i)),compfl(i),' ',trim(tfil(i))
861
 
862
      ! Set the flag for ready field/column
863
      fok(ncol+i) = 1
864
 
865
      ! Reset flags for load manager
866
      iloaded0 = -1
867
      iloaded1 = -1
868
 
869
      ! Reset the counter for fields outside domain
870
      noutside = 0
871
 
872
      ! Loop over all times
873
      do j=1,ntim
874
 
875
         ! Convert trajectory time from hh.mm to fractional time
876
         call hhmm2frac(trainp(1,j,1),tfrac)
877
 
878
         ! Shift time if requested
879
         if ( shift_dir(i).eq.'H' ) then
880
            tfrac = tfrac + shift_val(i)
881
         elseif ( shift_dir(i).eq.'MIN' ) then
882
            tfrac = tfrac + shift_val(i)/60.
883
         endif
884
 
885
         ! Get the times which are needed
886
         itime0   = int(abs(tfrac-tstart)/timeinc) + 1
887
         time0    = tstart + fbflag * real(itime0-1) * timeinc
888
         itime1   = itime0 + 1
889
         time1    = time0 + fbflag * timeinc
890
         if ( itime1.gt.numdat ) then
891
            itime1 = itime0
892
            time1  = time0
893
         endif
894
 
895
         ! Load manager: Check whether itime0 can be copied from itime1
896
         if ( itime0.eq.iloaded1 ) then
897
            f3t0     = f3t1
898
            p3t0     = p3t1
899
            spt0     = spt1
900
            iloaded0 = itime0
901
         endif
902
 
903
         ! Load manager: Check whether itime1 can be copied from itime0
904
         if ( itime1.eq.iloaded0 ) then
905
            f3t1     = f3t0
906
            p3t1     = p3t0
907
            spt1     = spt0
908
            iloaded1 = itime1
909
         endif
910
 
911
         ! Load manager:  Load first time (tracing variable and grid)
912
         if ( itime0.ne.iloaded0 ) then
913
 
914
            filename = tfil(i)//dat(itime0)
915
            call frac2hhmm(time0,tload)
916
            varname  = tvar(i)
917
            write(*,'(a23,a20,a3,a5,f7.2)') '    ->  loading          : ', trim(filename),'  ',trim(varname),tload
918
            call input_open (fid,filename)
919
            call input_wind &
920
                 (fid,varname,f3t0,tload,stagz,mdv, &
921
                 xmin,xmax,ymin,ymax,dx,dy,nx,ny,nz,timecheck)
922
            call input_grid &
923
                 (fid,varname,xmin,xmax,ymin,ymax,dx,dy,nx,ny, &
924
                 tload,pollon,pollat,p3t0,spt0,nz,ak,bk,stagz, &
925
                 timecheck)
926
            call input_close(fid)
927
 
928
            iloaded0 = itime0
929
 
930
         endif
931
 
932
         ! Load manager: Load second time (tracing variable and grid)
933
         if ( itime1.ne.iloaded1 ) then
934
 
935
            filename = tfil(i)//dat(itime1)
936
            call frac2hhmm(time1,tload)
937
            varname  = tvar(i)
938
            write(*,'(a23,a20,a3,a5,f7.2)') '    ->  loading          : ', trim(filename),'  ',trim(varname),tload
939
            call input_open (fid,filename)
940
            call input_wind &
941
                 (fid,varname,f3t1,tload,stagz,mdv, &
942
                 xmin,xmax,ymin,ymax,dx,dy,nx,ny,nz,timecheck)
943
            call input_grid &
944
                 (fid,varname,xmin,xmax,ymin,ymax,dx,dy,nx,ny, &
945
                 tload,pollon,pollat,p3t1,spt1,nz,ak,bk,stagz, &
946
                 timecheck)
947
            call input_close(fid)
948
 
949
            iloaded1 = itime1
950
 
951
         endif
952
 
953
         ! Loop over all trajectories
954
         do k=1,ntra
955
 
956
            ! Set the horizontal position where to interpolate to
957
            x0       = traint(k,j,2)                          ! Longitude
958
            y0       = traint(k,j,3)                          ! Latitude
959
 
960
            ! Set the vertical position where to interpolate to
961
            if ( nz.gt.1 ) then
962
               p0 = traint(k,j,4)                             ! Pressure (3D tracing)
963
            else
964
               p0 = 1050.                                     ! Lowest level (2D tracing)
965
            endif
966
 
967
            ! Set negative pressures to mdv
968
            if (p0.lt.0.) traint(k,j,4) = mdv
969
 
970
            ! Set the relative time
971
            call hhmm2frac(traint(k,j,1),tfrac)
972
            reltpos0 = fbflag * (tfrac-time0)/timeinc
973
 
974
            ! Make adjustments depending on the shift flag
975
            if ( shift_dir(i).eq.'DLON' ) then                         ! DLON
976
               x0 = x0 + shift_val(i)
977
 
978
            elseif  ( shift_dir(i).eq.'DLAT' ) then                    ! DLAT
979
               y0 = y0 + shift_val(i)
980
 
981
            elseif ( shift_dir(i).eq.'KM(LON)' ) then                  ! KM(LON)
982
               x0 = x0 + shift_val(i)/deg2km * 1./cos(y0*pi180)
983
 
984
            elseif ( shift_dir(i).eq.'KM(LAT)' ) then                  ! KM(LAT)
985
               y0 = y0 + shift_val(i)/deg2km
986
 
987
            elseif ( shift_dir(i).eq.'HPA' ) then                      ! HPA
988
               p0 = p0 + shift_val(i)
989
 
990
            elseif ( shift_dir(i).eq.'DP' ) then                       ! DP
991
               call get_index4 (xind,yind,pind,x0,y0,p0,reltpos0, &
992
                    p3t0,p3t1,spt0,spt1,3,nx,ny,nz,xmin,ymin,dx,dy,mdv)
993
               pind = pind - shift_val(i)
994
               p0   = int_index4(p3t0,p3t1,nx,ny,nz,xind,yind,pind,reltpos0,mdv)
995
 
996
            elseif ( shift_dir(i).eq.'INDP' ) then
997
               p0   = int_index4(p3t0,p3t1,nx,ny,nz,xind,yind,shift_val(i),reltpos0,mdv)
998
 
999
            endif
1000
 
1001
            ! Handle periodic boundaries in zonal direction
1002
            if ( (x0.gt.xmax).and.(per.ne.0) ) x0 = x0 - 360.
1003
            if ( (x0.lt.xmin).and.(per.ne.0) ) x0 = x0 + 360.
1004
 
1005
            ! Handle pole problems for hemispheric data (taken from caltra.f)
1006
            if ((hem.eq.1).and.(y0.gt.90.)) then
1007
               print*,'WARNING: y0>90 ',y0,' => setting to 180-y0 ',180.-y0
1008
               y0=180.-y0
1009
               x0=x0+per/2.
1010
            endif
1011
            if ((hem.eq.1).and.(y0.lt.-90.)) then
1012
               print*,'WARNING: y0<90 ',y0,' => setting to -180-y0 ',-180.-y0
1013
               y0=-180.-y0
1014
               x0=x0+per/2.
1015
            endif
1016
 
1017
            ! Get the index where to interpolate (x0,y0,p0)
1018
            if ( (abs(x0-mdv).gt.eps).and. (abs(y0-mdv).gt.eps) ) then
1019
               call get_index4 (xind,yind,pind,x0,y0,p0,reltpos0, &
1020
                    p3t0,p3t1,spt0,spt1,3,nx,ny,nz,xmin,ymin,dx,dy,mdv)
1021
            else
1022
               xind = mdv
1023
               yind = mdv
1024
               pind = mdv
1025
            endif
1026
 
1027
            ! Check if point is within grid (keep indices if ok)
1028
            if ( (xind.ge.1.).and.(xind.le.real(nx)).and. &
1029
                 (yind.ge.1.).and.(yind.le.real(ny)).and. &
1030
                 (pind.ge.1.).and.(pind.le.real(nz)) ) then
1031
		 xind = xind
1032
		 yind = yind
1033
		 pind = pind
1034
 
1035
            ! Check if pressure is outside, but rest okay => adjust to lowest or highest level
1036
            elseif ( (xind.ge.1.).and.(xind.le.real(nx)).and. (yind.ge.1.).and.(yind.le.real(ny)) ) then ! only vertical problem
1037
               if ( pind.gt.nz ) then ! pressure too low, index too high
1038
                 print('Af5.3A'),' WARNING: pressure too low (pind = ',pind,') => adjusted to highest level (pind=nz.)'
1039
                 print*,'(x0,y0,p0)=',x0,y0,p0
1040
                 pind = real(nz)
1041
               elseif (pind.lt.1.) then ! pressure too high, index too low
1042
                 print('Af5.3A'),' WARNING: pressure too high (pind = ',pind,') => adjusted to lowest level, (pind=1.)'
1043
                 print*,'(x0,y0,p0)=',x0,y0,p0
1044
                 pind = 1.
1045
              endif
1046
 
1047
            else
1048
               print*,'ERROR: point is outside grid (horizontally)'
1049
               print*,'Grid (nx,ny): ',nx,ny,' and (xind,yind): ',xind,yind
1050
               stop
1051
            endif
1052
 
1053
            ! ------------------------ NEAREST mode ------------------------------- 
1054
 
1055
            if ( intmode.eq.'nearest') then
1056
 
1057
               xind = real( nint(xind) )
1058
               yind = real( nint(yind) )
1059
               pind = real( nint(pind) )
1060
 
1061
               if ( xind.lt.1.  ) xind = 1.
1062
               if ( xind.gt.nx  ) xind = real(nx)
1063
               if ( yind.lt.1.  ) yind = 1.
1064
               if ( yind.gt.ny  ) yind = real(ny)
1065
 
1066
               if ( pind.lt.1.  ) pind = 1.
1067
               if ( pind.gt.nz  ) pind = real(nz)
1068
 
1069
               if ( abs(reltpos0).ge.eps ) then
1070
                  print*,'ERROR (nearest): reltpos != 0',reltpos0
1071
                  stop
1072
               endif
1073
 
1074
               ! interpolate
1075
               f0 = int_index4(f3t0,f3t1,nx,ny,nz,xind,yind,pind,reltpos0,mdv)
1076
 
1077
            ! ------------------------ CLUSTERING mode ------------------------------- Bojan
1078
 
1079
            elseif (intmode.eq.'clustering') then
1080
 
1081
            ! Clustering mode only works with LABEL
1082
            if (varname.ne.'LABEL' ) then  
1083
               print*,'ERROR (clustering): varname is not LABEL'
1084
               stop
1085
            endif
1086
 
1087
            ! Get indices of box around the point
1088
            xindb = floor(xind)
1089
            xindf = ceiling(xind)
1090
            yindb = floor(yind)
1091
            yindf = ceiling(yind)
1092
            pindb = floor(pind)
1093
            pindf = ceiling(pind)
1094
 
1095
            ! Make sure all points are within grid
1096
            if ( xindb.lt.1  ) xindb = 1
1097
            if ( xindf.lt.1  ) xindf = 1
1098
            if ( xindb.gt.nx ) xindb = nx
1099
            if ( xindf.gt.nx ) xindf = nx
1100
            if ( yindb.lt.1  ) yindb = 1
1101
            if ( yindf.lt.1  ) yindf = 1
1102
            if ( yindb.gt.ny ) yindb = ny
1103
            if ( yindf.gt.ny ) yindf = ny
1104
            if ( pindb.lt.1  ) pindb = 1
1105
            if ( pindf.lt.1  ) pindf = 1
1106
            if ( pindb.gt.nz ) pindb = nz
1107
            if ( pindf.gt.nz ) pindf = nz
1108
 
1109
            ! Shift one point if they are equal
1110
            if ( xindb.eq.xindf ) then
1111
               if ( xindf.eq.nx ) then
1112
                  xindb=nx-1
1113
               else
1114
                  xindf=xindb+1
1115
               endif
1116
            endif
1117
            if ( yindb.eq.yindf ) then
1118
               if ( yindf.eq.ny ) then
1119
                  yindb=ny-1
1120
               else
1121
                  yindf=yindb+1
1122
               endif
1123
            endif
1124
            if ( pindb.eq.pindf ) then
1125
               if ( pindf.eq.nz ) then
1126
                  pindb=nz-1
1127
               else
1128
                  pindf=pindb+1
1129
               endif
1130
            endif
1131
 
1132
            ! Give warnings and stop if problems occur
1133
            if ( xindb.eq.xindf ) then
1134
               print*,'ERROR (clustering): xindb=xindf'
1135
               print*,xind,xindb,xindf
1136
               stop
1137
            endif
1138
            if ( yindb.eq.yindf ) then
1139
               print*,'ERROR (clustering): yindb=yindf'
1140
               print*,yind,yindb,yindf
1141
               stop
1142
            endif
1143
            if ( pindb.eq.pindf ) then
1144
               print*,'ERROR (clustering): pindb=pindf'
1145
               print*,pind,pindb,pindf
1146
               stop
1147
            endif
1148
            if ( ( xindb.lt.1 ).or.( xindf.gt.nx ) ) then
1149
               print*,'ERROR (clustering): xindb/f outside'
1150
               print*,xind,xindb,xindf
1151
               stop
1152
            endif
1153
            if ( ( yindb.lt.1 ).or.( yindf.gt.ny ) ) then
1154
               print*,'ERROR (clustering): yindb/f outside'
1155
               print*,yind,yindb,yindf
1156
               stop
1157
            endif
1158
            if ( ( pindb.lt.1 ).or.( pindf.gt.nz ) ) then
1159
               print*,'ERROR (clustering): pindb/f outside'
1160
               print*,pind,pindb,pindf
1161
               stop
1162
            endif
1163
            if ( abs(reltpos0).ge.eps ) then
1164
               print*,'ERROR (clustering): reltpos != 0',reltpos0
1165
               stop
1166
            endif
1167
 
1168
            ! Get Value in Box
1169
            lblcount=(/0,0,0,0,0/)
1170
 
1171
            lbl(1) = f3t0( xindb + nx*(yindb-1) + nx*ny*(pindb-1) )
1172
            lbl(2) = f3t0( xindf + nx*(yindb-1) + nx*ny*(pindb-1) )
1173
            lbl(3) = f3t0( xindb + nx*(yindf-1) + nx*ny*(pindb-1) )
1174
            lbl(4) = f3t0( xindf + nx*(yindf-1) + nx*ny*(pindb-1) )
1175
            lbl(5) = f3t0( xindb + nx*(yindb-1) + nx*ny*(pindf-1) )
1176
            lbl(6) = f3t0( xindf + nx*(yindb-1) + nx*ny*(pindf-1) )
1177
            lbl(7) = f3t0( xindb + nx*(yindf-1) + nx*ny*(pindf-1) )
1178
            lbl(8) = f3t0( xindf + nx*(yindf-1) + nx*ny*(pindf-1) )
1179
 
1180
            ! Count the number of times every label appears
1181
            do lci=1,5
1182
               do lcj=1,8
1183
                  if ( abs(lbl(lcj)-lci).lt.eps ) then
1184
                     lblcount(lci)=lblcount(lci)+1
1185
                  endif
1186
               enddo
1187
            enddo
1188
 
1189
            ! Set to -9 to detect if no label was assigned in the end
1190
            f0=-9
1191
 
1192
            ! Stratosphere (PV)
1193
            if ( abs(traint(k,j,pvpos)) .ge. 2.0 ) then
1194
               if ( (lblcount(2).ge.lblcount(3)).and. (lblcount(2).ge.lblcount(5)) ) then
1195
                  f0=2
1196
               elseif ( lblcount(3).ge.lblcount(5) ) then
1197
                  f0=3
1198
               elseif ( lblcount(5).gt.lblcount(3) ) then
1199
                  f0=5
1200
               endif
1201
            endif
1202
 
1203
            ! Troposphere (PV)
1204
            if ( abs(traint(k,j,pvpos)) .lt. 2.0 ) then
1205
               if ( lblcount(1).ge.lblcount(4) ) then
1206
               f0=1
1207
               elseif ( lblcount(4).gt.lblcount(1) ) then
1208
               f0=4
1209
               endif
1210
            endif
1211
 
1212
            ! Stratosphere (TH)
1213
            if ( traint(k,j,thpos) .ge. 380.0 ) then
1214
               f0=2
1215
            endif
1216
 
1217
            if (f0.eq.-9) then
1218
               print*,'ERROR (Clustering): No label assigned!'
1219
               stop
1220
            endif
1221
 
1222
            ! ------------------------ CIRCLE modes ------------------------------- Bojan
1223
 
1224
            elseif ( (intmode.eq.'circle_avg') .or. (intmode.eq.'circle_min') .or. (intmode.eq.'circle_max') ) then
1225
 
1226
            ! reset arrays for this point
1227
            connect    = 0
1228
            stackx     = 0
1229
            stacky     = 0
1230
            circlelon  = 0
1231
            circlelat  = 0
1232
            circlef    = 0
1233
            circlearea = 0
1234
 
1235
            ! Get indices of one coarse grid point within search radius (nint=round to next integer)
1236
            if ( sdis(x0,y0,longrid(nint(xind)),latgrid(nint(yind))) .gt. radius) then
1237
               print*,'ERROR (circle): Search radius is too small... (1). r =',radius
1238
               print*,'Distance to nint grid point (minimum search radius)=',sdis(x0,y0,longrid(nint(xind)),latgrid(nint(yind)))
1239
               stop
1240
            endif
1241
 
1242
            ! Initialize stack with nint(xind),nint(yind)
1243
            kst       = 0            ! counts the number of points in circle
1244
            stackx(1) = nint(xind)
1245
            stacky(1) = nint(yind)
1246
            sp        = 1            ! stack counter
1247
 
1248
            ! Repeat as long as the stack is not empty
1249
            do while (sp.ne.0)
1250
 
1251
            ! Get an element from stack
1252
             ist=stackx(sp)
1253
             jst=stacky(sp)
1254
             sp=sp-1
1255
 
1256
            ! Get distance from reference point
1257
             dist=sdis(x0,y0,longrid(ist),latgrid(jst))
1258
 
1259
            ! Check whether distance is smaller than search radius: connected
1260
             if (dist.lt.radius) then
1261
 
1262
            ! Increase total stack index
1263
              kst=kst+1
1264
              circlelon(kst)=longrid(ist)
1265
              circlelat(kst)=latgrid(jst)
1266
 
1267
            ! Interpolate field to position of point (interpolation in time!) 
1268
              circlef(kst) = int_index4(f3t0,f3t1,nx,ny,nz,real(ist),real(jst),pind,reltpos0,mdv)
1269
 
1270
            ! Calculate area of point (for circle_avg mode only)
1271
              if ( intmode .eq. 'circle_avg' ) then
1272
                 circlearea(kst) = pir/(nx-1)*(sin(pi180*abs(circlelat(kst)))-sin(pi180*(abs(circlelat(kst))-dy)))
1273
              endif
1274
 
1275
            ! Mark this point as visited
1276
              connect(ist,jst)=1
1277
 
1278
            ! Get coordinates of neighbouring points and implement periodicity
1279
              mr=ist+1
1280
              if (mr.gt.nx) mr=1
1281
              ml=ist-1
1282
              if (ml.lt.1) ml=nx
1283
              nu=jst+1
1284
              if (nu.gt.ny) nu=ny
1285
              nd=jst-1
1286
              if (nd.lt.1) nd=1
1287
 
1288
            ! Update stack with neighbouring points
1289
              if (connect(mr,jst).ne. 1) then
1290
                 connect(mr,jst)=1
1291
                 sp=sp+1
1292
                 stackx(sp)=mr
1293
                 stacky(sp)=jst
1294
              endif
1295
              if (connect(ml,jst).ne. 1) then
1296
                 connect(ml,jst)=1
1297
                 sp=sp+1
1298
                 stackx(sp)=ml
1299
                 stacky(sp)=jst
1300
              endif
1301
              if (connect(ist,nd).ne. 1) then
1302
                 connect(ist,nd)=1
1303
                 sp=sp+1
1304
                 stackx(sp)=ist
1305
                 stacky(sp)=nd
1306
              endif
1307
              if (connect(ist,nu).ne. 1) then
1308
                 connect(ist,nu)=1
1309
                 sp=sp+1
1310
                 stackx(sp)=ist
1311
                 stacky(sp)=nu
1312
              endif
1313
 
1314
             endif ! endif radius is smaller => end of updating stack
1315
 
1316
            end do ! end working on stack 
1317
 
1318
	    ! Choose output depending on intmode	
1319
            if (kst.ge.1) then
1320
 
1321
               ! calculate area-weighted average of f in circle	
1322
               if ( intmode .eq. 'circle_avg' ) then
1323
                  circlesum=0.
1324
                  do l=1,kst
1325
                     circlesum=circlesum+circlef(l)*circlearea(l)
1326
                  enddo
1327
                  circleavg=circlesum/sum(circlearea(1:kst))
1328
                  f0=circleavg
1329
 
1330
               ! calculate minimum in circle
1331
               elseif ( intmode .eq. 'circle_min' ) then
1332
                  circlemin=circlef(1)
1333
                  do l=1,kst
1334
                     if (circlef(l) .lt. circlemin) then
1335
                        circlemin=circlef(l)
1336
                     endif
1337
                  enddo
1338
                  f0=circlemin
1339
 
1340
               ! calculate maximum in circle
1341
               elseif ( intmode .eq. 'circle_max' ) then             
1342
                  circlemax=circlef(1)
1343
                  do l=1,kst
1344
                     if (circlef(l) .gt. circlemax) then
1345
                        circlemax=circlef(l)
1346
                     endif
1347
                  enddo
1348
                  f0=circlemax
1349
 
1350
               else 
1351
                  print*,'ERROR (circle): intmode not valid!'
1352
                  stop
1353
               endif
1354
 
1355
            else
1356
               print*,'ERROR (circle): Search radius is too small... (2). r =',radius
1357
               stop
1358
            endif
1359
 
1360
 
1361
            ! ------------------------ NORMAL mode -------------------------------
1362
            else 
1363
 
1364
               f0 = int_index4(f3t0,f3t1,nx,ny,nz,xind,yind,pind,reltpos0,mdv)
1365
 
1366
            endif
1367
 
1368
            ! Save the new field
1369
            if ( abs(f0-mdv).gt.eps) then
1370
               traint(k,j,ncol+i) = f0
1371
            else
1372
               traint(k,j,ncol+i) = mdv
1373
            endif
1374
 
1375
         enddo ! end loop over all trajectories
1376
 
1377
      enddo ! end loop over all times
1378
 
1379
      ! Exit point for loop over all tracing variables
1380
 110   continue
1381
 
1382
   enddo ! end loop over all variables
1383
 
1384
  ! --------------------------------------------------------------------
1385
  ! Calculate additional fields along the trajectories
1386
  ! --------------------------------------------------------------------
1387
 
1388
  print*
1389
  print*,'---- CALCULATE ADDITIONAL FIELDS FROM TRAJECTORY TABLE --'
1390
 
1391
  ! Loop over all tracing fields
1392
  do i=ntrace1,1,-1
1393
 
1394
      ! Skip fields which must not be computed (compfl=0)
1395
      if (compfl(i).eq.0) goto 120
1396
 
1397
      ! Write some status information
1398
      print*
1399
      write(*,'(a10,f10.2,a5,i3,3x,a2)') &
1400
           trim(tvar(i)),shift_val(i),trim(shift_dir(i)),compfl(i),trim(tfil(i))
1401
 
1402
      ! Loop over trajectories and times
1403
      do j=1,ntra
1404
      do k=1,ntim
1405
 
1406
         ! Potential temperature (TH)
1407
         if  ( varsint(i+ncol).eq.'TH' ) then
1408
 
1409
            varname='T'
1410
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1411
            varname='p'
1412
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1413
 
1414
            call calc_TH  (traint(j,k,ncol+i), traint(j,k,ind1), &
1415
                 traint(j,k,ind2) )
1416
 
1417
         ! Density (RHO)
1418
         elseif  ( varsint(i+ncol).eq.'RHO' ) then
1419
 
1420
            varname='T'
1421
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1422
            varname='p'
1423
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1424
 
1425
            call calc_RHO (traint(j,k,ncol+i), traint(j,k,ind1), &
1426
                 traint(j,k,ind2) )
1427
 
1428
         ! Relative humidity (RH)
1429
         elseif  ( varsint(i+ncol).eq.'RH' ) then
1430
 
1431
            varname='T'
1432
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1433
            varname='p'
1434
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1435
            varname='Q'
1436
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1437
 
1438
            call calc_RH (traint(j,k,ncol+i), traint(j,k,ind1), &
1439
                 traint(j,k,ind2),traint(j,k,ind3) )
1440
 
1441
         ! Equivalent potential temperature (THE)
1442
         elseif  ( varsint(i+ncol).eq.'THE' ) then
1443
 
1444
            varname='T'
1445
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1446
            varname='p'
1447
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1448
            varname='Q'
1449
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1450
 
1451
            call calc_THE (traint(j,k,ncol+i), traint(j,k,ind1), &
1452
                 traint(j,k,ind2),traint(j,k,ind3) )
1453
 
1454
         ! Latent heating rate (LHR)
1455
         elseif  ( varsint(i+ncol).eq.'LHR' ) then
1456
 
1457
            varname='T'
1458
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1459
            varname='p'
1460
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1461
            varname='Q'
1462
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1463
            varname='OMEGA'
1464
            call list2ind (ind4,varname,varsint,fok,ncol+ntrace1)
1465
            varname='RH'
1466
            call list2ind (ind5,varname,varsint,fok,ncol+ntrace1)
1467
 
1468
            call calc_LHR (traint(j,k,ncol+i), traint(j,k,ind1), &
1469
                 traint(j,k,ind2),traint(j,k,ind3),traint(j,k,ind4),traint(j,k,ind5) )
1470
 
1471
         ! Wind speed (VEL)
1472
         elseif  ( varsint(i+ncol).eq.'VEL' ) then
1473
 
1474
            varname='U'
1475
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1476
            varname='V'
1477
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1478
 
1479
            call calc_VEL (traint(j,k,ncol+i), traint(j,k,ind1), &
1480
                 traint(j,k,ind2) )
1481
 
1482
         ! Wind direction (DIR)
1483
         elseif  ( varsint(i+ncol).eq.'DIR' ) then
1484
 
1485
            varname='U'
1486
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1487
            varname='V'
1488
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1489
 
1490
            call calc_DIR (traint(j,k,ncol+i), traint(j,k,ind1), &
1491
                 traint(j,k,ind2) )
1492
 
1493
         ! Zonal gradient of U (DUDX)
1494
         elseif  ( varsint(i+ncol).eq.'DUDX' ) then
1495
 
1496
            varname='U:+1DLON'
1497
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1498
            varname='U:-1DLON'
1499
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1500
            varname='lat'
1501
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1502
 
1503
            call calc_DUDX (traint(j,k,ncol+i), traint(j,k,ind1), &
1504
                 traint(j,k,ind2),traint(j,k,ind3) )
1505
 
1506
         ! Zonal gradient of V (DVDX)
1507
         elseif  ( varsint(i+ncol).eq.'DVDX' ) then
1508
 
1509
            varname='V:+1DLON'
1510
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1511
            varname='V:-1DLON'
1512
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1513
            varname='lat'
1514
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1515
 
1516
            call calc_DVDX (traint(j,k,ncol+i), traint(j,k,ind1), &
1517
                 traint(j,k,ind2),traint(j,k,ind3) )
1518
 
1519
         ! Zonal gradient of T (DTDX)
1520
         elseif  ( varsint(i+ncol).eq.'DVDX' ) then
1521
 
1522
            varname='T:+1DLON'
1523
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1524
            varname='T:-1DLON'
1525
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1526
            varname='lat'
1527
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1528
 
1529
            call calc_DTDX (traint(j,k,ncol+i), traint(j,k,ind1), &
1530
                 traint(j,k,ind2),traint(j,k,ind3) )
1531
 
1532
         ! Zonal gradient of TH (DTHDX)
1533
         elseif  ( varsint(i+ncol).eq.'DTHDX' ) then
1534
 
1535
            varname='T:+1DLON'
1536
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1537
            varname='T:-1DLON'
1538
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1539
            varname='P'
1540
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1541
            varname='lat'
1542
            call list2ind (ind4,varname,varsint,fok,ncol+ntrace1)
1543
 
1544
            call calc_DTHDX (traint(j,k,ncol+i), traint(j,k,ind1), &
1545
                 traint(j,k,ind2),traint(j,k,ind3),traint(j,k,ind4) )
1546
 
1547
         ! Meridional gradient of U (DUDY)
1548
         elseif  ( varsint(i+ncol).eq.'DUDY' ) then
1549
 
1550
            varname='U:+1DLAT'
1551
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1552
            varname='U:-1DLAT'
1553
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1554
 
1555
            call calc_DUDY (traint(j,k,ncol+i), traint(j,k,ind1), &
1556
                 traint(j,k,ind2) )
1557
 
1558
         ! Meridional gradient of V (DVDY)
1559
         elseif  ( varsint(i+ncol).eq.'DVDY' ) then
1560
 
1561
            varname='V:+1DLAT'
1562
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1563
            varname='V:-1DLAT'
1564
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1565
 
1566
            call calc_DVDY (traint(j,k,ncol+i), traint(j,k,ind1), &
1567
                 traint(j,k,ind2) )
1568
 
1569
         ! Meridional gradient of T (DTDY)
1570
         elseif  ( varsint(i+ncol).eq.'DTDY' ) then
1571
 
1572
            varname='T:+1DLAT'
1573
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1574
            varname='T:-1DLAT'
1575
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1576
 
1577
            call calc_DTDY (traint(j,k,ncol+i), traint(j,k,ind1), &
1578
                 traint(j,k,ind2) )
1579
 
1580
         ! Meridional gradient of TH (DTHDY)
1581
         elseif  ( varsint(i+ncol).eq.'DTHDY' ) then
1582
 
1583
            varname='T:+1DLAT'
1584
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1585
            varname='T:-1DLAT'
1586
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1587
            varname='P'
1588
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1589
 
1590
            call calc_DTDY (traint(j,k,ncol+i), traint(j,k,ind1), &
1591
                 traint(j,k,ind2),traint(j,k,ind3) )
1592
 
1593
 
1594
         ! Vertical wind shear DU/DP (DUDP)
1595
         elseif  ( varsint(i+ncol).eq.'DUDP' ) then
1596
 
1597
            varname='U:+1DP'
1598
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1599
            varname='U:-1DP'
1600
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1601
            varname='P:+1DP'
1602
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1603
            varname='P:-1DP'
1604
            call list2ind (ind4,varname,varsint,fok,ncol+ntrace1)
1605
 
1606
            call calc_DUDP (traint(j,k,ncol+i), traint(j,k,ind1), &
1607
                 traint(j,k,ind2),traint(j,k,ind3),traint(j,k,ind4) )
1608
 
1609
         ! Vertical wind shear DV/DP (DVDP)
1610
         elseif  ( varsint(i+ncol).eq.'DVDP' ) then
1611
 
1612
            varname='V:+1DP'
1613
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1614
            varname='V:-1DP'
1615
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1616
            varname='P:+1DP'
1617
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1618
            varname='P:-1DP'
1619
            call list2ind (ind4,varname,varsint,fok,ncol+ntrace1)
1620
 
1621
            call calc_DVDP (traint(j,k,ncol+i), traint(j,k,ind1), &
1622
                 traint(j,k,ind2),traint(j,k,ind3),traint(j,k,ind4) )
1623
 
1624
         ! Vertical derivative of T (DTDP)
1625
         elseif  ( varsint(i+ncol).eq.'DTDP' ) then
1626
 
1627
            varname='T:+1DP'
1628
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1629
            varname='T:-1DP'
1630
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1631
            varname='P:+1DP'
1632
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1633
            varname='P:-1DP'
1634
            call list2ind (ind4,varname,varsint,fok,ncol+ntrace1)
1635
 
1636
            call calc_DTDP (traint(j,k,ncol+i), traint(j,k,ind1), &
1637
                 traint(j,k,ind2),traint(j,k,ind3),traint(j,k,ind4) )
1638
 
1639
         ! Vertical derivative of TH (DTHDP)
1640
         elseif  ( varsint(i+ncol).eq.'DTHDP' ) then
1641
 
1642
            varname='T:+1DP'
1643
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1644
            varname='T:-1DP'
1645
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1646
            varname='P:+1DP'
1647
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1648
            varname='P:-1DP'
1649
            call list2ind (ind4,varname,varsint,fok,ncol+ntrace1)
1650
            varname='P'
1651
            call list2ind (ind5,varname,varsint,fok,ncol+ntrace1)
1652
            varname='T'
1653
            call list2ind (ind6,varname,varsint,fok,ncol+ntrace1)
1654
 
1655
            call calc_DTHDP (traint(j,k,ncol+i), traint(j,k,ind1), &
1656
                 traint(j,k,ind2),traint(j,k,ind3),traint(j,k,ind4),traint(j,k,ind5),traint(j,k,ind6) )
1657
 
1658
         ! Squared Brunt-Vaisäla frequency (NSQ)
1659
         elseif  ( varsint(i+ncol).eq.'NSQ' ) then
1660
 
1661
            varname='DTHDP'
1662
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1663
            varname='TH'
1664
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1665
            varname='RHO'
1666
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1667
 
1668
            call calc_NSQ (traint(j,k,ncol+i), traint(j,k,ind1), &
1669
                 traint(j,k,ind2),traint(j,k,ind3))
1670
 
1671
         ! Relative vorticity (RELVORT)
1672
         elseif  ( varsint(i+ncol).eq.'RELVORT' ) then
1673
 
1674
            varname='DUDY'
1675
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1676
            varname='DVDX'
1677
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1678
            varname='U'
1679
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1680
            varname='lat'
1681
            call list2ind (ind4,varname,varsint,fok,ncol+ntrace1)
1682
 
1683
            call calc_RELVORT (traint(j,k,ncol+i), traint(j,k,ind1), &
1684
                 traint(j,k,ind2),traint(j,k,ind3),traint(j,k,ind4))
1685
 
1686
         ! Absolute vorticity (ABSVORT)
1687
         elseif  ( varsint(i+ncol).eq.'ABSVORT' ) then
1688
 
1689
            varname='DUDY'
1690
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1691
            varname='DVDX'
1692
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1693
            varname='U'
1694
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1695
            varname='lat'
1696
            call list2ind (ind4,varname,varsint,fok,ncol+ntrace1)
1697
 
1698
            call calc_ABSVORT (traint(j,k,ncol+i), traint(j,k,ind1), &
1699
                 traint(j,k,ind2),traint(j,k,ind3),traint(j,k,ind4))
1700
 
1701
         ! Divergence (DIV)
1702
         elseif  ( varsint(i+ncol).eq.'DIV' ) then
1703
 
1704
            varname='DUDX'
1705
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1706
            varname='DVDY'
1707
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1708
            varname='V'
1709
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1710
            varname='lat'
1711
            call list2ind (ind4,varname,varsint,fok,ncol+ntrace1)
1712
 
1713
            call calc_DIV (traint(j,k,ncol+i), traint(j,k,ind1), &
1714
                 traint(j,k,ind2),traint(j,k,ind3),traint(j,k,ind4))
1715
 
1716
         ! Deformation (DEF)
1717
         elseif  ( varsint(i+ncol).eq.'DEF' ) then
1718
 
1719
            varname='DUDX'
1720
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1721
            varname='DVDX'
1722
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1723
            varname='DUDY'
1724
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1725
            varname='DVDY'
1726
            call list2ind (ind4,varname,varsint,fok,ncol+ntrace1)
1727
 
1728
            call calc_DEF (traint(j,k,ncol+i), traint(j,k,ind1), &
1729
                 traint(j,k,ind2),traint(j,k,ind3),traint(j,k,ind4))
1730
 
1731
         ! Potential Vorticity (PV)
1732
         elseif  ( varsint(i+ncol).eq.'PV' ) then
1733
 
1734
            varname='ABSVORT'
1735
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1736
            varname='DTHDP'
1737
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1738
            varname='DUDP'
1739
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1740
            varname='DVDP'
1741
            call list2ind (ind4,varname,varsint,fok,ncol+ntrace1)
1742
            varname='DTHDX'
1743
            call list2ind (ind5,varname,varsint,fok,ncol+ntrace1)
1744
            varname='DTHDY'
1745
            call list2ind (ind6,varname,varsint,fok,ncol+ntrace1)
1746
 
1747
            call calc_PV (traint(j,k,ncol+i), traint(j,k,ind1), &
1748
                 traint(j,k,ind2),traint(j,k,ind3),traint(j,k,ind4),traint(j,k,ind5),traint(j,k,ind6) )
1749
 
1750
         ! Richardson number (RI)
1751
         elseif  ( varsint(i+ncol).eq.'RI' ) then
1752
 
1753
            varname='DUDP'
1754
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1755
            varname='DVDP'
1756
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1757
            varname='NSQ'
1758
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1759
            varname='RHO'
1760
            call list2ind (ind4,varname,varsint,fok,ncol+ntrace1)
1761
 
1762
            call calc_RI (traint(j,k,ncol+i), traint(j,k,ind1), &
1763
                 traint(j,k,ind2),traint(j,k,ind3),traint(j,k,ind4) )
1764
 
1765
         ! Ellrod and Knapp's turbulence idicator (TI)
1766
         elseif  ( varsint(i+ncol).eq.'TI' ) then
1767
 
1768
            varname='DEF'
1769
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1770
            varname='DUDP'
1771
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1772
            varname='DVDP'
1773
            call list2ind (ind3,varname,varsint,fok,ncol+ntrace1)
1774
            varname='RHO'
1775
            call list2ind (ind4,varname,varsint,fok,ncol+ntrace1)
1776
 
1777
            call calc_TI (traint(j,k,ncol+i), traint(j,k,ind1), &
1778
                 traint(j,k,ind2),traint(j,k,ind3),traint(j,k,ind4) )
1779
 
1780
         ! Spherical distance from starting position (DIST0)
1781
         elseif  ( varsint(i+ncol).eq.'DIST0' ) then
1782
 
1783
            varname='lon'
1784
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1785
            varname='lat'
1786
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1787
 
1788
            call calc_DIST0 (traint(j,k,ncol+i), traint(j,k,ind1), &
1789
                 traint(j,k,ind2),traint(j,1,ind1),traint(j,1,ind2) )
1790
 
1791
         ! Spherical distance length of trajectory (DIST)
1792
         elseif  ( varsint(i+ncol).eq.'DIST' ) then
1793
 
1794
            varname='lon'
1795
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1796
            varname='lat'
1797
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1798
 
1799
            if ( k.eq.1 ) then
1800
               traint(j,k,ncol+i) = 0.
1801
            else
1802
               call calc_DIST0 (delta, traint(j,k  ,ind1), &
1803
                   traint(j,k  ,ind2),traint(j,k-1,ind1),traint(j,k-1,ind2) )
1804
               traint(j,k,ncol+i) = traint(j,k-1,ncol+i) + delta
1805
            endif
1806
 
1807
         ! Heading of the trajectory (HEAD)
1808
         elseif  ( varsint(i+ncol).eq.'HEAD' ) then
1809
 
1810
            varname='lon'
1811
            call list2ind (ind1,varname,varsint,fok,ncol+ntrace1)
1812
            varname='lat'
1813
            call list2ind (ind2,varname,varsint,fok,ncol+ntrace1)
1814
 
1815
            if (k.eq.ntim) then
1816
               traint(j,k,ncol+i) = mdv
1817
            else
1818
               call calc_HEAD (traint(j,k,ncol+i), &
1819
                    traint(j,k  ,ind1),traint(j,k  ,ind2),traint(j,k+1,ind1),traint(j,k+1,ind2) )
1820
            endif
1821
 
1822
 
1823
         ! Invalid tracing variable
1824
         else
1825
 
1826
            print*,' ERROR: invalid tracing variable ', trim(varsint(i+ncol))
1827
            stop
1828
 
1829
 
1830
         endif
1831
 
1832
      ! End loop over all trajectories and times
1833
      enddo
1834
      enddo
1835
 
1836
      ! Set the flag for a ready field/column
1837
      fok(ncol+i) = 1
1838
 
1839
 
1840
      ! Exit point for loop over all tracing fields
1841
 120   continue
1842
 
1843
   enddo
1844
 
1845
  ! --------------------------------------------------------------------
1846
  ! Write output to output trajectory file
1847
  ! --------------------------------------------------------------------
1848
 
1849
  ! Write status information
1850
  print*
1851
  print*,'---- WRITE OUTPUT TRAJECTORIES --------------------------'
1852
  print*
1853
 
1854
  ! Allocate memory for internal trajectories
1855
  allocate(traout(ntra,ntim,ncol+ntrace0),stat=stat)
1856
  if (stat.ne.0) print*,'*** error allocating array traout   ***'
1857
 
1858
  ! Copy input to output trajectory (apply scaling of output)
1859
  do i=1,ntra
1860
     do j=1,ntim
1861
        do k=1,ncol+ntrace0
1862
           if ( k.le.ncol ) then
1863
              traout(i,j,k) = traint(i,j,k)
1864
           elseif ( abs(traint(i,j,k)-mdv).gt.eps ) then
1865
              traout(i,j,k) = fac(k-ncol) * traint(i,j,k)
1866
           else
1867
              traout(i,j,k) = mdv
1868
           endif
1869
        enddo
1870
     enddo
1871
  enddo
1872
 
1873
  ! Set the variable names for output trajectory
1874
  do i=1,ncol+ntrace0
1875
     varsout(i)      = varsint(i)
1876
  enddo
1877
 
1878
  ! Write trajectories
1879
  call wopen_tra(fod,outfile,ntra,ntim,ncol+ntrace0, &
1880
       reftime,varsout,outmode)
1881
  call write_tra(fod,traout ,ntra,ntim,ncol+ntrace0,outmode)
1882
  call close_tra(fod,outmode)
1883
 
1884
  ! Write some status information, and end of program message
1885
  print*
1886
  print*,'---- STATUS INFORMATION --------------------------------'
1887
  print*
1888
  print*,' ok'
1889
  print*
1890
  print*,'              *** END OF PROGRAM TRACE ***'
1891
  print*,'========================================================='
1892
 
1893
 
1894
end program trace_label_circle
1895
 
1896
 
1897
 
1898
! ******************************************************************
1899
! * SUBROUTINE SECTION                                             *
1900
! ******************************************************************
1901
 
1902
! ------------------------------------------------------------------
1903
! Add a variable to the list if not yet included in this list
1904
! ------------------------------------------------------------------
1905
 
1906
subroutine add2list (varname,list,nlist)
1907
 
1908
  implicit none
1909
 
1910
  ! Declaration of subroutine parameters
1911
  character(len=80) :: varname
1912
  character(len=80) :: list(200)
1913
  integer :: nlist
1914
 
1915
  ! Auxiliray variables
1916
  integer :: i,j
1917
  integer :: isok
1918
 
1919
  ! Expand the list, if necessary
1920
  isok = 0
1921
  do i=1,nlist
1922
     if ( list(i).eq.varname ) isok = 1
1923
  enddo
1924
  if ( isok.eq.0 ) then
1925
     nlist       = nlist + 1
1926
     list(nlist) = varname
1927
  endif
1928
 
1929
  ! Check for too large number of fields
1930
  if ( nlist.ge.200) then
1931
     print*,' ERROR: too many additional fields for tracing ...'
1932
     stop
1933
  endif
1934
 
1935
end subroutine add2list
1936
 
1937
 
1938
! ------------------------------------------------------------------
1939
! Get the index of a variable in the list
1940
! ------------------------------------------------------------------
1941
 
1942
subroutine list2ind (ind,varname,list,fok,nlist)
1943
 
1944
  implicit none
1945
 
1946
  ! Declaration of subroutine parameters
1947
  integer :: ind
1948
  character(len=80) :: varname
1949
  character(len=80) :: list(200)
1950
  integer :: fok(200)
1951
  integer :: nlist
1952
 
1953
  ! Auxiliray variables
1954
  integer :: i,j
1955
  integer :: isok
1956
 
1957
  ! Get the index - error message if not found
1958
  ind = 0
1959
  do i=1,nlist
1960
     if ( varname.eq.list(i) ) then
1961
        ind = i
1962
        goto 100
1963
     endif
1964
  enddo
1965
 
1966
  if ( ind.eq.0) then
1967
     print*
1968
     print*,' ERROR: cannot find ',trim(varname),' in list ...'
1969
     do i=1,nlist
1970
        print*,i,trim(list(i))
1971
     enddo
1972
     print*
1973
     stop
1974
  endif
1975
 
1976
  ! Exit point
1977
 100   continue
1978
 
1979
  ! Check whether the field/column is ready
1980
  if ( fok(ind).eq.0 ) then
1981
     print*
1982
     print*,' ERROR: unresolved dependence : ',trim(list(ind))
1983
     print*
1984
     stop
1985
  endif
1986
 
1987
end subroutine list2ind
1988
 
1989
 
1990
! ------------------------------------------------------------------
1991
! Split the variable name into name, shift and direction
1992
! ------------------------------------------------------------------
1993
 
1994
subroutine splitvar (tvar,shift_val,shift_dir)
1995
 
1996
  implicit none
1997
 
1998
  ! Declaration of subroutine parameters
1999
  character(len=80) :: tvar
2000
  real :: shift_val
2001
  character(len=80) :: shift_dir
2002
 
2003
  ! Auxiliary variables
2004
  integer :: i,j
2005
  integer :: icolon,inumber
2006
  character(len=80) :: name
2007
  character :: ch
2008
 
2009
  ! Save variable name
2010
  name = tvar
2011
 
2012
  ! Search for colon
2013
  icolon=0
2014
  do i=1,80
2015
     if ( (name(i:i).eq.':').and.(icolon.ne.0) ) goto 100
2016
     if ( (name(i:i).eq.':').and.(icolon.eq.0) ) icolon=i
2017
  enddo
2018
 
2019
  ! If there is a colon, split the variable name
2020
  if ( icolon.ne.0 ) then
2021
 
2022
     tvar = name(1:(icolon-1))
2023
 
2024
     do i=icolon+1,80
2025
        ch = name(i:i)
2026
        if ( ( ch.ne.'0' ).and. ( ch.ne.'1' ).and.( ch.ne.'2' ).and. &
2027
             ( ch.ne.'3' ).and. ( ch.ne.'4' ).and.( ch.ne.'5' ).and. &
2028
             ( ch.ne.'6' ).and. ( ch.ne.'7' ).and.( ch.ne.'8' ).and. &
2029
             ( ch.ne.'9' ).and. ( ch.ne.'+' ).and.( ch.ne.'-' ).and. &
2030
             ( ch.ne.'.' ).and. ( ch.ne.' ' )  ) then
2031
           inumber = i
2032
           exit
2033
        endif
2034
     enddo
2035
 
2036
     read(name( (icolon+1):(inumber-1) ),*) shift_val
2037
 
2038
     shift_dir = name(inumber:80)
2039
 
2040
  else
2041
 
2042
     shift_dir = 'nil'
2043
     shift_val = 0.
2044
 
2045
  endif
2046
 
2047
  return
2048
 
2049
  ! Error handling
2050
 100   continue
2051
 
2052
  print*,' ERROR: cannot split variable name ',trim(tvar)
2053
  stop
2054
 
2055
end subroutine splitvar