Subversion Repositories lagranto.wrf

Rev

Rev 17 | Rev 21 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 michaesp 1
      PROGRAM caltra
2
 
3
C     ********************************************************************
4
C     *                                                                  *
5
C     * Calculates trajectories                                          *
6
C     *                                                                  *
7
C     *	Heini Wernli	   first version:	April 1993                   *
8
C     * Michael Sprenger   major upgrade:       2008-2009                *
9
C     *                                                                  *
10
C     ********************************************************************
11
 
12
      implicit none      
13
 
14
c     --------------------------------------------------------------------
15
c     Declaration of parameters
16
c     --------------------------------------------------------------------
17
 
18
c     Maximum number of levels for input files
19
      integer   nlevmax
20
      parameter	(nlevmax=100)
21
 
22
c     Maximum number of input files (dates, length of trajectories)
23
      integer   ndatmax
24
      parameter	(ndatmax=500)
25
 
26
c     Numerical epsilon (for float comparison)
27
      real      eps
28
      parameter (eps=0.001)
29
 
30
c     Distance in m between 2 lat circles 
31
      real	deltay
32
      parameter	(deltay=1.112E5)
33
 
34
c     Number of iterations for iterative Euler scheme
35
      integer   numit
36
      parameter (numit=3)
37
 
38
c     Input and output format for trajectories (see iotra.f)
39
      integer   inpmode
40
      integer   outmode
41
 
17 michaesp 42
c     Missing data value
43
      real      mdv
44
      parameter (mdv = -999. )
45
 
2 michaesp 46
c     Filename prefix (typically 'P')
47
      character*1 prefix
48
      parameter   (prefix='P')
49
 
50
c     Externals
51
      real       sdis
52
      external   sdis
53
 
54
c     --------------------------------------------------------------------
55
c     Declaration of variables
56
c     --------------------------------------------------------------------
57
 
58
c     Input parameters
59
      integer                                fbflag          ! Flag for forward/backward mode
60
      integer                                numdat          ! Number of input files
61
      character*11                           dat(ndatmax)    ! Dates of input files
62
      real                                   timeinc         ! Time increment between input files
63
      integer                                per             ! Periodicity flag (=0 if none)
64
      integer                                ntra            ! Number of trajectories
65
      character*80                           cdfname         ! Name of output files
66
      real                                   ts              ! Time step
67
      real                                   tst,ten         ! Shift of start and end time relative to first data file
68
      integer                                deltout         ! Output time interval (in minutes)
69
      integer                                jflag           ! Jump flag (if =1 ground-touching trajectories reenter atmosphere)
70
      real                                   wfactor         ! Factor for vertical velocity field
71
      character*80                           strname         ! File with start positions
72
      character*80                           timecheck       ! Either 'yes' or 'no'
73
      character*10		              	     gridflag        ! "ideal" or "real"
74
 
75
c     Trajectories
76
      integer                                ncol            ! Number of columns for insput trajectories
77
      real,allocatable, dimension (:,:,:) :: trainp          ! Input start coordinates (ntra,1,ncol)
78
      real,allocatable, dimension (:,:,:) :: traout          ! Output trajectories (ntra,ntim,4)
79
      integer                                reftime(6)      ! Reference date
80
      character*80                           vars(200)       ! Field names
81
      real,allocatable, dimension (:)     :: xx0,yy0,pp0     ! Position of air parcels
82
      integer,allocatable, dimension (:)  :: leftflag        ! Flag for domain-leaving
83
      real                                   xx1,yy1,pp1     ! Updated position of air parcel
84
      integer                                leftcount       ! Number of domain leaving trajectories
85
      integer                                ntim            ! Number of output time steps
86
 
87
c     Meteorological fields
88
      real,allocatable, dimension (:)     :: spt0,spt1       ! Surface pressure
89
      real,allocatable, dimension (:)     :: uut0,uut1       ! Zonal wind
90
      real,allocatable, dimension (:)     :: vvt0,vvt1       ! Meridional wind
91
      real,allocatable, dimension (:)     :: wwt0,wwt1       ! Vertical wind
92
      real,allocatable, dimension (:)     :: p3t0,p3t1       ! 3d-pressure 
93
 
94
c     Grid description
95
      real                                   pollon,pollat   ! Longitude/latitude of pole
96
      real                                   ak(nlevmax)     ! Vertical layers and levels
97
      real                                   bk(nlevmax) 
98
      real                                   xmin,xmax       ! Zonal grid extension
99
      real                                   ymin,ymax       ! Meridional grid extension
100
      integer                                nx,ny,nz        ! Grid dimensions
101
      real                                   dx,dy           ! Horizontal grid resolution
102
      integer                                hem             ! Flag for hemispheric domain
103
      real,allocatable, dimension (:,:)   :: mpx,mpy         ! Map scale factor in x,y direction
104
      real,allocatable, dimension (:,:)   :: lat,lon         ! Map scale factor in x,y direction
105
 
106
c     Auxiliary variables                 
107
      real                                   delta,rd
108
      integer	                             itm,iloop,i,j,k,filo,lalo
109
      integer                                ierr,stat
110
      integer                                cdfid,fid
111
      real	                                 tstart,time0,time1,time
112
      real                                   reltpos0,reltpos1
113
      real                                   xind,yind,pind,pp,sp,stagz
114
      character*80                           filename,varname
115
      integer                                reftmp(6)
116
      character                              ch
117
      real                                   frac,tload
118
      integer                                itim
119
      integer                                wstep
120
      character*80                           radunit
121
      real                                   lon1,lat1,lon2,lat2
122
      real                                   scale_max,scale_min
123
 
124
c     --------------------------------------------------------------------
125
c     Start of program, Read parameters
126
c     --------------------------------------------------------------------
127
 
128
c     Write start message
129
      print*,'========================================================='
130
      print*,'              *** START OF PROGRAM CALTRA ***'
131
      print*
132
 
133
c     Open the parameter file
134
      open(9,file='caltra.param')
135
 
136
c     Read flag for forward/backward mode (fbflag)
137
      read(9,*) fbflag
138
 
139
c     Read number of input files (numdat)
140
      read(9,*) numdat
141
      if (numdat.gt.ndatmax) then
142
        print*,' ERROR: too many input files ',numdat,ndatmax
143
        goto 993
144
      endif
145
 
146
c     Read list of input dates (dat, sort depending on forward/backward mode)
147
      if (fbflag.eq.1) then
148
        do itm=1,numdat
149
          read(9,'(a11)') dat(itm)
150
        enddo
151
      else
152
        do itm=numdat,1,-1
153
          read(9,'(a11)') dat(itm)
154
        enddo
155
      endif
156
 
157
c     Read time increment between input files (timeinc)
158
      read(9,*) timeinc
159
 
160
C     Read if data domain is periodic and its periodicity
161
      read(9,*) per
162
 
163
 
164
c     Read the number of trajectories and name of position file
165
      read(9,*) strname
166
      read(9,*) ntra
167
      read(9,*) ncol 
168
      if (ntra.eq.0) goto 991
169
 
170
C     Read the name of the output trajectory file and set the constants file
171
      read(9,*) cdfname
172
 
173
C     Read the timestep for trajectory calculation (convert from minutes to hours)
174
      read(9,*) ts
175
      ts=ts/60.    
176
 
177
C     Read shift of start and end time relative to first data file
178
      read(9,*) tst
179
      read(9,*) ten
180
 
181
C     Read output time interval (in minutes)
182
      read(9,*) deltout
183
 
184
C     Read jumpflag (if =1 ground-touching trajectories reenter the atmosphere)
185
      read(9,*) jflag
186
 
187
C     Read factor for vertical velocity field
188
      read(9,*) wfactor
189
 
190
c     Read the reference time and the time range
191
      read(9,*) reftime(1)                  ! year
192
      read(9,*) reftime(2)                  ! month
193
      read(9,*) reftime(3)                  ! day
194
      read(9,*) reftime(4)                  ! hour
195
      read(9,*) reftime(5)                  ! min
196
      read(9,*) reftime(6)                  ! time range (in min)
197
 
198
c     Read flag for 'no time check'
199
      read(9,*) timecheck
200
 
201
c     Close the input file
202
      close(9)
203
 
204
c     Calculate the number of output time steps
205
      ntim = abs(reftime(6)/deltout) + 1
206
 
207
c     Set the formats of the input and output files
208
      call mode_tra(inpmode,strname)
209
      call mode_tra(outmode,cdfname)
210
      if (outmode.eq.-1) outmode=1
211
 
212
c     Write some status information
213
      print*,'---- INPUT PARAMETERS -----------------------------------'
214
      print* 
215
      print*,'  Forward/Backward       : ',fbflag
216
      print*,'  #input files           : ',numdat
217
      print*,'  First/last input file  : ',trim(dat(1)),' ... ',
218
     >                                     trim(dat(numdat))
219
      print*,'  time increment         : ',timeinc
220
      print*,'  Output file            : ',trim(cdfname)
221
      print*,'  Time step (min)        : ',60.*ts
222
      write(*,'(a27,f7.2,f7.2)') '   Time shift (start,end) : ',tst,ten
223
      print*,'  Output time interval   : ',deltout
224
      print*,'  Jump flag              : ',jflag
225
      print*,'  Vertical wind (scale)  : ',wfactor
226
      print*,'  Trajectory pos file    : ',trim(strname)
227
      print*,'  # of trajectories      : ',ntra
228
      print*,'  # of output timesteps  : ',ntim
229
      if ( inpmode.eq.-1) then
230
         print*,'  Input format           : (x,y,z)-list'
231
      else
232
         print*,'  Input format           : ',inpmode
233
      endif
234
      print*,'  Output format          : ',outmode
235
      print*,'  Periodicity            : ',per
236
      print*,'  Time check             : ',trim(timecheck)
237
      print*
238
 
239
      print*,'---- FIXED NUMERICAL PARAMETERS -------------------------'
240
      print*
241
      print*,'  Number of iterations   : ',numit
242
      print*,'  Filename prefix        : ',prefix
243
      print*,'  Missing data value     : ',mdv
244
      print*
245
 
246
c     --------------------------------------------------------------------
247
c     Read grid parameters, checks and allocate memory
248
c     --------------------------------------------------------------------
249
 
250
c     Read the constant grid parameters (nx,ny,nz,xmin,xmax,ymin,ymax,pollon,pollat)
251
c     The negative <-fid> of the file identifier is used as a flag for parameter retrieval  
252
      filename = prefix//dat(1)
253
      varname  = 'U'
254
      nx       = 1
255
      ny       = 1
256
      nz       = 1
257
      tload    = -tst
258
      call input_open (fid,filename)
259
	  call input_grid_wrf(fid,xmin,xmax,ymin,ymax,dx,dy,nx,ny,nz)
260
      call input_close(fid)
261
 
262
C     Check if the number of levels is too large
263
      if (nz.gt.nlevmax) goto 993
264
 
265
C     Set logical flag for hemispheric mode (not yet supported)
266
      hem = 0
267
 
268
C     Allocate memory for some meteorological arrays
269
      allocate(spt0(nx*ny),stat=stat)
270
      if (stat.ne.0) print*,'*** error allocating array spt0 ***'   ! Surface geopotential height
271
      allocate(spt1(nx*ny),stat=stat)
272
      if (stat.ne.0) print*,'*** error allocating array spt1 ***'
273
      allocate(uut0(nx*ny*nz),stat=stat)
274
      if (stat.ne.0) print*,'*** error allocating array uut0 ***'   ! Zonal wind
275
      allocate(uut1(nx*ny*nz),stat=stat)
276
      if (stat.ne.0) print*,'*** error allocating array uut1 ***'
277
      allocate(vvt0(nx*ny*nz),stat=stat)
278
      if (stat.ne.0) print*,'*** error allocating array vvt0 ***'   ! Meridional wind
279
      allocate(vvt1(nx*ny*nz),stat=stat)
280
      if (stat.ne.0) print*,'*** error allocating array vvt1 ***'
281
      allocate(wwt0(nx*ny*nz),stat=stat)
282
      if (stat.ne.0) print*,'*** error allocating array wwt0 ***'   ! Vertical wind
283
      allocate(wwt1(nx*ny*nz),stat=stat)
284
      if (stat.ne.0) print*,'*** error allocating array wwt1 ***'
285
      allocate(p3t0(nx*ny*nz),stat=stat)
286
      if (stat.ne.0) print*,'*** error allocating array p3t0 ***'   ! geopotential height
287
      allocate(p3t1(nx*ny*nz),stat=stat)
288
      if (stat.ne.0) print*,'*** error allocating array p3t1 ***'
289
      allocate(mpx(nx,ny),stat=stat)
290
      if (stat.ne.0) print*,'*** error allocating array mpx * **'   ! Map scale factor in x
291
      allocate(mpy(nx,ny),stat=stat)
292
      if (stat.ne.0) print*,'*** error allocating array mpy ***'    ! Map scale factor in y
293
      allocate(lon(nx,ny),stat=stat)
294
      if (stat.ne.0) print*,'*** error allocating array lon ***'    ! Grid -> lon
295
      allocate(lat(nx,ny),stat=stat)
296
      if (stat.ne.0) print*,'*** error allocating array lat ***'    ! Gridy -> lat
297
 
298
C     Get memory for trajectory arrays
299
      allocate(trainp(ntra,1,ncol),stat=stat)
300
      if (stat.ne.0) print*,'*** error allocating array trainp   ***' ! Input start coordinates
301
      allocate(traout(ntra,ntim,4),stat=stat)
302
      if (stat.ne.0) print*,'*** error allocating array traout   ***' ! Output trajectories
303
      allocate(xx0(ntra),stat=stat)
304
      if (stat.ne.0) print*,'*** error allocating array xx0      ***' ! X position (longitude)
305
      allocate(yy0(ntra),stat=stat)
306
      if (stat.ne.0) print*,'*** error allocating array yy0      ***' ! Y position (latitude)
307
      allocate(pp0(ntra),stat=stat)
308
      if (stat.ne.0) print*,'*** error allocating array pp0      ***' ! Pressure
309
      allocate(leftflag(ntra),stat=stat)
310
      if (stat.ne.0) print*,'*** error allocating array leftflag ***' ! Leaving-domain flag
311
 
312
c     Write some status information
313
      print*,'---- CONSTANT GRID PARAMETERS ---------------------------'
314
      print*
315
      print*,'  xmin,xmax     : ',xmin,xmax
316
      print*,'  ymin,ymax     : ',ymin,ymax
317
      print*,'  dx,dy         : ',dx,dy
318
      print*,'  nx,ny,nz      : ',nx,ny,nz
319
      print*,'  per, hem      : ',per,hem
320
      print*
321
 
322
c     --------------------------------------------------------------------
323
c     Calculate the map scale factors
324
c     --------------------------------------------------------------------
325
 
326
c     Read lon/lat on the model grid from first data file
327
      filename = prefix//dat(1)
328
      call input_open (fid,filename)
329
      varname='XLONG'
330
      call input_var_wrf(fid,varname,lon,nx,ny,1)
331
      varname='XLAT'
332
      call input_var_wrf(fid,varname,lat,nx,ny,1)
333
      call input_close(fid)
334
 
335
c     Get map scale for interior points
336
      do i=2,nx-1
337
         do j=2,ny-1
338
 
339
c           Map scale in x direction
340
            lon1     = lon(i-1,j)
341
            lat1     = lat(i-1,j)
342
            lon2     = lon(i+1,j)
343
            lat2     = lat(i+1,j)
344
            radunit  = 'km.haversine'
345
            mpx(i,j) = 0.5 * 1000. * sdis(lon1,lat1,lon2,lat2,radunit)
346
 
347
c           Map scale in y direction
348
            lon1     = lon(i,j-1)
349
            lat1     = lat(i,j-1)
350
            lon2     = lon(i,j+1)
351
            lat2     = lat(i,j+1)
352
            radunit  = 'km.haversine'
353
            mpy(i,j) = 0.5 * 1000. * sdis(lon1,lat1,lon2,lat2,radunit)
354
 
355
         enddo
356
      enddo
357
 
358
c     Copy map scale for boundary points
359
      do i=2,nx-1
360
        mpx(i, 1) = mpx(i,   2)
361
        mpx(i,ny) = mpx(i,ny-1)
362
        mpy(i, 1) = mpy(i,   2)
363
        mpy(i,ny) = mpy(i,ny-1)
364
      enddo
365
      do j=2,ny-1
366
        mpx(1, j) = mpx(2,   j)
367
        mpx(nx,j) = mpx(nx-1,j)
368
        mpy(1, j) = mpy(2,   j)
369
        mpy(nx,j) = mpy(nx-1,j)
370
      enddo
371
      mpx(1,1)   = mpx(2,2)
372
      mpy(1,1)   = mpy(2,2)
373
      mpx(nx,1)  = mpx(nx-1,2)
374
      mpy(nx,1)  = mpy(nx-1,2)
375
      mpx(nx,ny) = mpx(nx-1,ny-1)
376
      mpy(nx,ny) = mpy(nx-1,ny-1)
377
      mpx(1,ny)  = mpx(2,ny-1)
378
      mpy(1,ny)  = mpy(2,ny-1)
379
 
380
c	  Write some status information
15 michaesp 381
      print*,'---- MAPPING SCALE FACTORS -----------------------------'
2 michaesp 382
      print*
383
 
384
      scale_max = mpx(1,1)
385
      scale_min = mpx(1,1)
386
      do i=1,nx
387
      	do j=1,ny
388
      	   if ( mpx(i,j).gt.scale_max ) scale_max = mpx(i,j)
389
      	   if ( mpx(i,j).lt.scale_min ) scale_min = mpx(i,j)
390
      	 enddo
391
      enddo
392
      print*,'  map scale x (min,max) : ',scale_min,scale_max
393
      scale_max = mpy(1,1)
394
      scale_min = mpy(1,1)
395
      do i=1,nx
396
      	do j=1,ny
397
      	   if ( mpy(i,j).gt.scale_max ) scale_max = mpy(i,j)
398
      	   if ( mpy(i,j).lt.scale_min ) scale_min = mpy(i,j)
399
      	 enddo
400
      enddo
401
      print*,'  map scale y (min,max) : ',scale_min,scale_max
402
      print*
403
 
404
c     --------------------------------------------------------------------
405
c     Initialize the trajectory calculation
406
c     --------------------------------------------------------------------
407
 
408
c     Read start coordinates from file - Format (x,y,lev)
409
      if (inpmode.eq.-1) then
410
         open(fid,file=strname)
411
          do i=1,ntra
412
             read(fid,*) xx0(i),yy0(i),pp0(i)
413
          enddo
414
         close(fid)
415
 
416
c     Read start coordinates from trajectory file - check consistency of ref time
417
      else
418
         call ropen_tra(cdfid,strname,ntra,1,ncol,reftmp,vars,inpmode)
419
         call read_tra (cdfid,trainp,ntra,1,ncol,inpmode)
420
         do i=1,ntra
421
            time   = trainp(i,1,1)
422
            xx0(i) = trainp(i,1,2) 
423
            yy0(i) = trainp(i,1,3) 
424
            pp0(i) = trainp(i,1,4) 
425
         enddo
426
         call close_tra(cdfid,inpmode)
427
 
428
         if ( ( vars(2).ne.'x').and.(vars(3).ne.'y') ) then
429
            print*,' ERROR: starting positions must be in x/y/z format'
430
            stop
431
         endif
432
 
433
         if ( ( reftime(1).ne.reftmp(1) ).or.
434
     >        ( reftime(2).ne.reftmp(2) ).or.
435
     >        ( reftime(3).ne.reftmp(3) ).or.
436
     >        ( reftime(4).ne.reftmp(4) ).or.
437
     >        ( reftime(5).ne.reftmp(5) ) )
438
     >   then
439
            print*,' WARNING: Inconsistent reference times'
440
            write(*,'(5i8)') (reftime(i),i=1,5)
441
            write(*,'(5i8)') (reftmp (i),i=1,5)
442
            print*,'Enter a key to proceed...'
443
            stop
444
         endif
445
      endif
446
 
447
c     Transform start coordinates from index space to WRF grid
448
      do i=1,ntra
449
         xx0(i) = xmin + ( xx0(i) - 1. ) * dx
450
         yy0(i) = ymin + ( yy0(i) - 1. ) * dy
451
      enddo
452
 
453
c     Set sign of time range
454
      reftime(6) = fbflag * reftime(6)
455
 
456
c     Write some status information
457
      print*,'---- REFERENCE DATE---------- ---------------------------'
458
      print*
459
      print*,' Reference time (year)  :',reftime(1)
460
      print*,'                (month) :',reftime(2)
461
      print*,'                (day)   :',reftime(3)
462
      print*,'                (hour)  :',reftime(4)
463
      print*,'                (min)   :',reftime(5)
464
      print*,' Time range             :',reftime(6),' min'
465
      print*
466
 
467
C     Save starting positions 
468
      itim = 1
469
      do i=1,ntra
470
         traout(i,itim,1) = 0.
471
         traout(i,itim,2) = xx0(i)
472
         traout(i,itim,3) = yy0(i)
473
         traout(i,itim,4) = pp0(i)
474
      enddo
475
 
476
c     Init the flag and the counter for trajectories leaving the domain
477
      leftcount=0
478
      do i=1,ntra
479
         leftflag(i)=0
480
      enddo
481
 
482
C     Convert time shifts <tst,ten> from <hh.mm> into fractional time
483
      call hhmm2frac(tst,frac)
484
      tst = frac
485
      call hhmm2frac(ten,frac)
486
      ten = frac
487
 
488
c     -----------------------------------------------------------------------
489
c     Loop to calculate trajectories
490
c     -----------------------------------------------------------------------
491
 
492
c     Write some status information
493
      print*,'---- TRAJECTORIES ----------- ---------------------------'
494
      print*    
495
 
496
C     Set the time for the first data file (depending on forward/backward mode)
497
      if (fbflag.eq.1) then
498
        tstart = -tst
499
      else
500
        tstart = tst
501
      endif
502
 
503
c     Set the minute counter for output
504
      wstep = 0
505
 
506
c     Read wind fields and vertical grid from first file
507
      filename = prefix//dat(1)
508
 
509
      call frac2hhmm(tstart,tload)
510
 
511
      write(*,'(a16,a20,f7.2)') '  (file,time) : ',
512
     >                       trim(filename),tload
513
 
514
      call input_open (fid,filename)
515
 
516
      varname='U'					! U
517
 	  call input_var_wrf(fid,varname,uut1,nx,ny,nz)
518
 
519
	  varname='V'					! V
520
	  call input_var_wrf(fid,varname,vvt1,nx,ny,nz)
521
 
522
	  varname='W'					! W
523
	  call input_var_wrf(fid,varname,wwt1,nx,ny,nz)
524
 
525
	  varname='geopot'				! geopot.height
526
	  call input_var_wrf(fid,varname,p3t1,nx,ny,nz)
527
 
528
	  varname='geopots'				! geopot.height at surface
529
	  call input_var_wrf(fid,varname,spt1,nx,ny,1)
530
 
531
      call input_close(fid)
532
 
533
c     Loop over all input files (time step is <timeinc>)
534
      do itm=1,numdat-1
535
 
536
c       Calculate actual and next time
537
        time0 = tstart+real(itm-1)*timeinc*fbflag
538
        time1 = time0+timeinc*fbflag
539
 
540
 
541
c       Copy old velocities and pressure fields to new ones       
542
        do i=1,nx*ny*nz
543
           uut0(i)=uut1(i)
544
           vvt0(i)=vvt1(i)
545
           wwt0(i)=wwt1(i)
546
           p3t0(i)=p3t1(i)
547
        enddo
548
        do i=1,nx*ny
549
           spt0(i)=spt1(i)
550
        enddo
551
 
552
c       Read wind fields and surface pressure at next time
553
        filename = prefix//dat(itm+1)
554
 
555
        call frac2hhmm(time1,tload)
556
        write(*,'(a16,a20,f7.2)') '  (file,time) : ',
557
     >                          trim(filename),tload
558
 
559
        call input_open (fid,filename)
560
 
561
  	    varname='U'					! U
562
	    call input_var_wrf(fid,varname,uut1,nx,ny,nz)
563
 
564
	    varname='V'					! V
565
	    call input_var_wrf(fid,varname,vvt1,nx,ny,nz)
566
 
567
	    varname='W'					! W
568
	    call input_var_wrf(fid,varname,wwt1,nx,ny,nz)
569
 
570
	    varname='geopot'				! geopot.height
571
	    call input_var_wrf(fid,varname,p3t1,nx,ny,nz)
572
 
573
	    varname='geopots'				! geopot.height
574
	    call input_var_wrf(fid,varname,spt1,nx,ny,1)
575
 
576
        call input_close(fid)
577
 
578
C       Determine the first and last loop indices
579
        if (numdat.eq.2) then
580
          filo = nint(tst/ts)+1
581
          lalo = nint((timeinc-ten)/ts) 
582
        elseif ( itm.eq.1 ) then
583
          filo = nint(tst/ts)+1
584
          lalo = nint(timeinc/ts)
585
        else if (itm.eq.numdat-1) then
586
          filo = 1
587
          lalo = nint((timeinc-ten)/ts)
588
        else
589
          filo = 1
590
          lalo = nint(timeinc/ts)
591
        endif
592
 
593
c       Split the interval <timeinc> into computational time steps <ts>
594
        do iloop=filo,lalo
595
 
596
C         Calculate relative time position in the interval timeinc (0=beginning, 1=end)
597
          reltpos0 = ((real(iloop)-1.)*ts)/timeinc
598
          reltpos1 = real(iloop)*ts/timeinc
599
 
600
C         Initialize counter for domain leaving trajectories
601
          leftcount=0
602
 
603
c         Timestep for all trajectories
604
          do i=1,ntra
605
 
606
C           Check if trajectory has already left the data domain
607
            if (leftflag(i).ne.1) then	
608
 
609
c             Iterative Euler timestep (x0,y0,p0 -> x1,y1,p1)
610
              call euler(
611
     >               xx1,yy1,pp1,leftflag(i),
612
     >               xx0(i),yy0(i),pp0(i),reltpos0,reltpos1,
613
     >               ts*3600,numit,jflag,mdv,wfactor,fbflag,
614
     >               spt0,spt1,p3t0,p3t1,uut0,uut1,vvt0,vvt1,wwt0,wwt1,
615
     >               xmin,ymin,dx,dy,per,hem,nx,ny,nz,mpx,mpy)
616
 
617
c             Update trajectory position, or increase number of trajectories leaving domain
618
              if (leftflag(i).eq.1) then
619
                leftcount=leftcount+1
620
                if ( leftcount.lt.10 ) then
621
                   print*,'     -> Trajectory ',i,' leaves domain'
622
                elseif ( leftcount.eq.10 ) then
623
                   print*,'     -> N>=10 trajectories leave domain'
624
                endif
625
              else
626
                xx0(i)=xx1      
627
                yy0(i)=yy1
628
                pp0(i)=pp1
629
              endif
630
 
631
c          Trajectory has already left data domain (mark as <mdv>)
632
           else
633
              xx0(i)=mdv
634
              yy0(i)=mdv
635
              pp0(i)=mdv
636
 
637
           endif
638
 
639
          enddo
640
 
641
C         Save positions only every deltout minutes
642
          delta = aint(iloop*60*ts/deltout)-iloop*60*ts/deltout
643
          if (abs(delta).lt.eps) then
644
            time = time0+reltpos1*timeinc*fbflag
645
            itim = itim + 1
646
            do i=1,ntra
647
               call frac2hhmm(time,tload)
648
               traout(i,itim,1) = tload
649
               traout(i,itim,2) = xx0(i)
650
               traout(i,itim,3) = yy0(i) 
651
               traout(i,itim,4) = pp0(i)
652
            enddo
653
          endif
654
 
655
        enddo
656
 
657
      enddo
658
 
659
c     Transform trajectory position from WRF grid do grid index
660
      do i=1,ntra
661
        do j=1,ntim
19 michaesp 662
           if ( abs(traout(i,j,2)-mdv).gt.eps ) then
663
              traout(i,j,2) = ( traout(i,j,2) - xmin ) / dx + 1.
664
           else
665
              traout(i,j,2) = mdv
666
           endif
667
           if ( abs(traout(i,j,3)-mdv).gt.eps ) then
668
              traout(i,j,3) = ( traout(i,j,3) - ymin ) / dy + 1.
669
           else
670
              traout(i,j,3) = mdv
671
           endif
2 michaesp 672
        enddo
673
      enddo
674
 
675
c     Write trajectory file
676
      vars(1)  ='time'
677
      vars(2)  ='x'
678
      vars(3)  ='y'
679
      vars(4)  ='z'
680
      call wopen_tra(cdfid,cdfname,ntra,ntim,4,reftime,vars,outmode)
681
      call write_tra(cdfid,traout,ntra,ntim,4,outmode)
682
      call close_tra(cdfid,outmode)   
683
 
684
c     Write some status information, and end of program message
685
      print*  
686
      print*,'---- STATUS INFORMATION --------------------------------'
687
      print*
688
      print*,'  #leaving domain    ', leftcount
689
      print*,'  #staying in domain ', ntra-leftcount
690
      print*
691
      print*,'              *** END OF PROGRAM CALTRA ***'
692
      print*,'========================================================='
693
 
694
      stop
695
 
696
c     ------------------------------------------------------------------
697
c     Exception handling
698
c     ------------------------------------------------------------------
699
 
700
 991  write(*,*) '*** ERROR: all start points outside the data domain'
701
      call exit(1)
702
 
703
 992  write(*,*) '*** ERROR: close arrays on files (prog. closear)'
704
      call exit(1)
705
 
706
 993  write(*,*) '*** ERROR: problems with array size'
707
      call exit(1)
708
 
709
      end 
710
 
711
 
712
c     *******************************************************************
713
c     * Time step : either Euler or Runge-Kutta                         *
714
c     *******************************************************************
715
 
716
C     Time-step from (x0,y0,p0) to (x1,y1,p1)
717
C
718
C     (x0,y0,p0) input	coordinates (long,lat,p) for starting point
719
C     (x1,y1,p1) output	coordinates (long,lat,p) for end point
720
C     deltat	 input	timestep in seconds
721
C     numit	 input	number of iterations
722
C     jump	 input  flag (=1 trajectories don't enter the ground)
723
C     left	 output	flag (=1 if trajectory leaves data domain)
724
 
725
c     -------------------------------------------------------------------
726
c     Iterative Euler time step
727
c     -------------------------------------------------------------------
728
 
729
      subroutine euler(x1,y1,p1,left,x0,y0,p0,reltpos0,reltpos1,
730
     >                 deltat,numit,jump,mdv,wfactor,fbflag,
731
     >		           spt0,spt1,p3d0,p3d1,uut0,uut1,vvt0,vvt1,wwt0,wwt1,
732
     >                 xmin,ymin,dx,dy,per,hem,nx,ny,nz,mpx,mpy)
733
 
734
      implicit none
735
 
11 michaesp 736
c     Flag for test mode
737
      integer      test
738
      parameter    (test=0)
739
 
2 michaesp 740
c     Declaration of subroutine parameters
741
      integer      nx,ny,nz
742
      real         x1,y1,p1
743
      integer      left
744
      real	       x0,y0,p0
745
      real         reltpos0,reltpos1
746
      real   	   deltat
747
      integer      numit
748
      integer      jump
749
      real         wfactor
750
      integer      fbflag
751
      real     	   spt0(nx*ny)   ,spt1(nx*ny)
752
      real         uut0(nx*ny*nz),uut1(nx*ny*nz)
753
      real 	       vvt0(nx*ny*nz),vvt1(nx*ny*nz)
754
      real         wwt0(nx*ny*nz),wwt1(nx*ny*nz)
755
      real         p3d0(nx*ny*nz),p3d1(nx*ny*nz)
756
      real         xmin,ymin,dx,dy
757
      integer      per
758
      integer      hem
759
      real         mdv
760
      real         mpx(nx*ny),mpy(nx*ny)
761
 
762
c     Auxiliary variables
763
      real         xmax,ymax
764
      real	       xind,yind,pind
765
 
766
      real	       u0,v0,w0,u1,v1,w1,u,v,w,sp
767
      integer	   icount
768
      character    ch
769
      real         mpsc_x,mpsc_y
770
 
771
c     Externals    
772
      real         int_index4
773
      external     int_index4
774
 
775
c     Reset the flag for domain-leaving
776
      left=0
777
 
778
c     Set the esat-north boundary of the domain
779
      xmax = xmin+real(nx-1)*dx
780
      ymax = ymin+real(ny-1)*dy
781
 
782
C     Interpolate wind fields to starting position (x0,y0,p0)
783
      call get_index4 (xind,yind,pind,x0,y0,p0,reltpos0,
784
     >                 p3d0,p3d1,spt0,spt1,3,
785
     >                 nx,ny,nz,xmin,ymin,dx,dy,mdv)
786
 
787
      u0 = int_index4(uut0,uut1,nx,ny,nz,xind,yind,pind,reltpos0,mdv)
788
      v0 = int_index4(vvt0,vvt1,nx,ny,nz,xind,yind,pind,reltpos0,mdv)
789
      w0 = int_index4(wwt0,wwt1,nx,ny,nz,xind,yind,pind,reltpos0,mdv)
790
 
791
c     Force the near-surface wind to zero
792
      if (pind.lt.1.) w0=w0*pind
793
 
794
C     For first iteration take ending position equal to starting position
795
      x1=x0
796
      y1=y0
797
      p1=p0
798
 
799
C     Iterative calculation of new position
800
      do icount=1,numit
801
 
802
C        Calculate new winds for advection
803
         call get_index4 (xind,yind,pind,x1,y1,p1,reltpos1,
804
     >                    p3d0,p3d1,spt0,spt1,3,
805
     >                    nx,ny,nz,xmin,ymin,dx,dy,mdv)
806
         u1 = int_index4(uut0,uut1,nx,ny,nz,xind,yind,pind,reltpos1,mdv)
807
         v1 = int_index4(vvt0,vvt1,nx,ny,nz,xind,yind,pind,reltpos1,mdv)
808
         w1 = int_index4(wwt0,wwt1,nx,ny,nz,xind,yind,pind,reltpos1,mdv)
809
 
810
c        Force the near-surface wind to zero
811
         if (pind.lt.1.) w1=w1*pind
812
 
813
c        Get the new velocity in between
814
         u=(u0+u1)/2.
815
         v=(v0+v1)/2.
816
         w=(w0+w1)/2.
817
 
818
c        Get the mapping scale factors for this position
819
         mpsc_x = int_index4 (mpx,mpx,nx,ny,1,xind,yind,1.,reltpos1,mdv)
820
         mpsc_y = int_index4 (mpy,mpy,nx,ny,1,xind,yind,1.,reltpos1,mdv)
821
 
822
C        Calculate new positions (adapted for cartesian grid)
823
         x1 = x0 + fbflag * deltat * u * dx/mpsc_x
824
         y1 = y0 + fbflag * deltat * v * dy/mpsc_y
825
         p1 = p0 + fbflag * deltat * w * wfactor
826
 
11 michaesp 827
c        Write the update positions for tests
828
         if ( (icount.eq.3).and.(test.eq.1) ) then
829
            write(*,'(10f10.2)') x0,u,x1-x0,p0,w,p1-p0
830
         endif
831
 
2 michaesp 832
C       Interpolate surface geop.height to actual position
833
        call get_index4 (xind,yind,pind,x1,y1,0.,reltpos1,
834
     >                   p3d0,p3d1,spt0,spt1,3,
835
     >                   nx,ny,nz,xmin,ymin,dx,dy,mdv)
836
        sp = int_index4 (spt0,spt1,nx,ny,1,xind,yind,1.,reltpos1,mdv)
837
 
838
c       Handle trajectories which cross the lower boundary (jump flag)
839
        if ((jump.eq.1).and.(p1.lt.sp)) p1=sp+10.
840
 
841
c       Handle periodioc boundaries for 'ideal' mode
842
        if ( per.eq.1 ) then
843
	        if ( x1.gt.xmax ) x1=x1-xmax
844
	        if ( x1.lt.xmin ) x1=x1+xmax
845
        endif
846
 
847
C       Check if trajectory leaves data domain
848
        if ( (x1.lt.xmin).or.(x1.gt.xmax).or.
849
     >       (y1.lt.ymin).or.(y1.gt.ymax).or.(p1.lt.sp) )   ! geopot : .lt. ; pressure: .gt.
850
     >  then
851
          left=1
852
          print*,x1,y1,p1
853
          print*,xmin,ymin
854
	      print*,xmax,ymax
855
	      print*,sp
856
          goto 100
857
        endif
858
 
859
      enddo
860
 
861
c     Exit point for subroutine
862
 100  continue
863
 
864
      return
865
 
866
      end
867
 
868
 
869
c     ----------------------------------------------------------------------
870
c     Get spherical distance between lat/lon points
871
c     ----------------------------------------------------------------------
872
 
873
      real function sdis(xp,yp,xq,yq,unit)
874
 
875
c     Calculates spherical distance (in km) between two points given
876
c     by their spherical coordinates (xp,yp) and (xq,yq), respectively.
877
 
878
      real,parameter ::       re=6371.229
879
      real,parameter ::       rad2deg=180./3.14159265
880
      real,parameter ::       deg2rad=3.141592654/180.
881
 
882
      real         xp,yp,xq,yq,arg
883
      character*80 unit
884
      real         dlon,dlat,alpha,rlat1,ralt2
885
 
886
      if ( unit.eq.'km' ) then
887
 
15 michaesp 888
         arg=sin(yp*deg2rad)*sin(yq*deg2rad)+
889
     >              cos(yp*deg2rad)*cos(yq*deg2rad)*cos((xp-xq)*deg2rad)
2 michaesp 890
         if (arg.lt.-1.) arg=-1.
891
         if (arg.gt.1.) arg=1.
892
         sdis=re*acos(arg)
893
 
894
      elseif ( unit.eq.'deg' ) then
895
 
896
         dlon = xp-xq
897
         if ( dlon.gt. 180. ) dlon = dlon - 360.
898
         if ( dlon.lt.-180. ) dlon = dlon + 360.
899
         sdis = sqrt( dlon**2 + (yp-yq)**2 )
900
 
901
      elseif ( unit.eq.'km.haversine' ) then
902
 
903
        dlat   =  (yp - yq)*deg2rad
904
        dlon   =  (xp - xq)*deg2rad
905
        rlat1   =  yp*deg2rad
906
        rlat2   =  yq*deg2rad
907
 
908
        alpha  = ( sin(0.5*dlat)**2 ) +
909
     >           ( sin(0.5*dlon)**2 )*cos(rlat1)*cos(rlat2)
910
 
911
        sdis = 4. * re * atan2( sqrt(alpha),1. + sqrt( 1. - alpha ) )
912
 
913
      endif
914
 
915
      end