Subversion Repositories lagranto.20cr

Rev

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

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