Subversion Repositories lagranto.wrf

Rev

Rev 15 | Rev 19 | 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
662
           traout(i,j,2) = ( traout(i,j,2) - xmin ) / dx + 1.
663
           traout(i,j,3) = ( traout(i,j,3) - ymin ) / dy + 1.
664
        enddo
665
      enddo
666
 
667
c     Write trajectory file
668
      vars(1)  ='time'
669
      vars(2)  ='x'
670
      vars(3)  ='y'
671
      vars(4)  ='z'
672
      call wopen_tra(cdfid,cdfname,ntra,ntim,4,reftime,vars,outmode)
673
      call write_tra(cdfid,traout,ntra,ntim,4,outmode)
674
      call close_tra(cdfid,outmode)   
675
 
676
c     Write some status information, and end of program message
677
      print*  
678
      print*,'---- STATUS INFORMATION --------------------------------'
679
      print*
680
      print*,'  #leaving domain    ', leftcount
681
      print*,'  #staying in domain ', ntra-leftcount
682
      print*
683
      print*,'              *** END OF PROGRAM CALTRA ***'
684
      print*,'========================================================='
685
 
686
      stop
687
 
688
c     ------------------------------------------------------------------
689
c     Exception handling
690
c     ------------------------------------------------------------------
691
 
692
 991  write(*,*) '*** ERROR: all start points outside the data domain'
693
      call exit(1)
694
 
695
 992  write(*,*) '*** ERROR: close arrays on files (prog. closear)'
696
      call exit(1)
697
 
698
 993  write(*,*) '*** ERROR: problems with array size'
699
      call exit(1)
700
 
701
      end 
702
 
703
 
704
c     *******************************************************************
705
c     * Time step : either Euler or Runge-Kutta                         *
706
c     *******************************************************************
707
 
708
C     Time-step from (x0,y0,p0) to (x1,y1,p1)
709
C
710
C     (x0,y0,p0) input	coordinates (long,lat,p) for starting point
711
C     (x1,y1,p1) output	coordinates (long,lat,p) for end point
712
C     deltat	 input	timestep in seconds
713
C     numit	 input	number of iterations
714
C     jump	 input  flag (=1 trajectories don't enter the ground)
715
C     left	 output	flag (=1 if trajectory leaves data domain)
716
 
717
c     -------------------------------------------------------------------
718
c     Iterative Euler time step
719
c     -------------------------------------------------------------------
720
 
721
      subroutine euler(x1,y1,p1,left,x0,y0,p0,reltpos0,reltpos1,
722
     >                 deltat,numit,jump,mdv,wfactor,fbflag,
723
     >		           spt0,spt1,p3d0,p3d1,uut0,uut1,vvt0,vvt1,wwt0,wwt1,
724
     >                 xmin,ymin,dx,dy,per,hem,nx,ny,nz,mpx,mpy)
725
 
726
      implicit none
727
 
11 michaesp 728
c     Flag for test mode
729
      integer      test
730
      parameter    (test=0)
731
 
2 michaesp 732
c     Declaration of subroutine parameters
733
      integer      nx,ny,nz
734
      real         x1,y1,p1
735
      integer      left
736
      real	       x0,y0,p0
737
      real         reltpos0,reltpos1
738
      real   	   deltat
739
      integer      numit
740
      integer      jump
741
      real         wfactor
742
      integer      fbflag
743
      real     	   spt0(nx*ny)   ,spt1(nx*ny)
744
      real         uut0(nx*ny*nz),uut1(nx*ny*nz)
745
      real 	       vvt0(nx*ny*nz),vvt1(nx*ny*nz)
746
      real         wwt0(nx*ny*nz),wwt1(nx*ny*nz)
747
      real         p3d0(nx*ny*nz),p3d1(nx*ny*nz)
748
      real         xmin,ymin,dx,dy
749
      integer      per
750
      integer      hem
751
      real         mdv
752
      real         mpx(nx*ny),mpy(nx*ny)
753
 
754
c     Auxiliary variables
755
      real         xmax,ymax
756
      real	       xind,yind,pind
757
 
758
      real	       u0,v0,w0,u1,v1,w1,u,v,w,sp
759
      integer	   icount
760
      character    ch
761
      real         mpsc_x,mpsc_y
762
 
763
c     Externals    
764
      real         int_index4
765
      external     int_index4
766
 
767
c     Reset the flag for domain-leaving
768
      left=0
769
 
770
c     Set the esat-north boundary of the domain
771
      xmax = xmin+real(nx-1)*dx
772
      ymax = ymin+real(ny-1)*dy
773
 
774
C     Interpolate wind fields to starting position (x0,y0,p0)
775
      call get_index4 (xind,yind,pind,x0,y0,p0,reltpos0,
776
     >                 p3d0,p3d1,spt0,spt1,3,
777
     >                 nx,ny,nz,xmin,ymin,dx,dy,mdv)
778
 
779
      u0 = int_index4(uut0,uut1,nx,ny,nz,xind,yind,pind,reltpos0,mdv)
780
      v0 = int_index4(vvt0,vvt1,nx,ny,nz,xind,yind,pind,reltpos0,mdv)
781
      w0 = int_index4(wwt0,wwt1,nx,ny,nz,xind,yind,pind,reltpos0,mdv)
782
 
783
c     Force the near-surface wind to zero
784
      if (pind.lt.1.) w0=w0*pind
785
 
786
C     For first iteration take ending position equal to starting position
787
      x1=x0
788
      y1=y0
789
      p1=p0
790
 
791
C     Iterative calculation of new position
792
      do icount=1,numit
793
 
794
C        Calculate new winds for advection
795
         call get_index4 (xind,yind,pind,x1,y1,p1,reltpos1,
796
     >                    p3d0,p3d1,spt0,spt1,3,
797
     >                    nx,ny,nz,xmin,ymin,dx,dy,mdv)
798
         u1 = int_index4(uut0,uut1,nx,ny,nz,xind,yind,pind,reltpos1,mdv)
799
         v1 = int_index4(vvt0,vvt1,nx,ny,nz,xind,yind,pind,reltpos1,mdv)
800
         w1 = int_index4(wwt0,wwt1,nx,ny,nz,xind,yind,pind,reltpos1,mdv)
801
 
802
c        Force the near-surface wind to zero
803
         if (pind.lt.1.) w1=w1*pind
804
 
805
c        Get the new velocity in between
806
         u=(u0+u1)/2.
807
         v=(v0+v1)/2.
808
         w=(w0+w1)/2.
809
 
810
c        Get the mapping scale factors for this position
811
         mpsc_x = int_index4 (mpx,mpx,nx,ny,1,xind,yind,1.,reltpos1,mdv)
812
         mpsc_y = int_index4 (mpy,mpy,nx,ny,1,xind,yind,1.,reltpos1,mdv)
813
 
814
C        Calculate new positions (adapted for cartesian grid)
815
         x1 = x0 + fbflag * deltat * u * dx/mpsc_x
816
         y1 = y0 + fbflag * deltat * v * dy/mpsc_y
817
         p1 = p0 + fbflag * deltat * w * wfactor
818
 
11 michaesp 819
c        Write the update positions for tests
820
         if ( (icount.eq.3).and.(test.eq.1) ) then
821
            write(*,'(10f10.2)') x0,u,x1-x0,p0,w,p1-p0
822
         endif
823
 
2 michaesp 824
C       Interpolate surface geop.height to actual position
825
        call get_index4 (xind,yind,pind,x1,y1,0.,reltpos1,
826
     >                   p3d0,p3d1,spt0,spt1,3,
827
     >                   nx,ny,nz,xmin,ymin,dx,dy,mdv)
828
        sp = int_index4 (spt0,spt1,nx,ny,1,xind,yind,1.,reltpos1,mdv)
829
 
830
c       Handle trajectories which cross the lower boundary (jump flag)
831
        if ((jump.eq.1).and.(p1.lt.sp)) p1=sp+10.
832
 
833
c       Handle periodioc boundaries for 'ideal' mode
834
        if ( per.eq.1 ) then
835
	        if ( x1.gt.xmax ) x1=x1-xmax
836
	        if ( x1.lt.xmin ) x1=x1+xmax
837
        endif
838
 
839
C       Check if trajectory leaves data domain
840
        if ( (x1.lt.xmin).or.(x1.gt.xmax).or.
841
     >       (y1.lt.ymin).or.(y1.gt.ymax).or.(p1.lt.sp) )   ! geopot : .lt. ; pressure: .gt.
842
     >  then
843
          left=1
844
          print*,x1,y1,p1
845
          print*,xmin,ymin
846
	      print*,xmax,ymax
847
	      print*,sp
848
          goto 100
849
        endif
850
 
851
      enddo
852
 
853
c     Exit point for subroutine
854
 100  continue
855
 
856
      return
857
 
858
      end
859
 
860
 
861
c     ----------------------------------------------------------------------
862
c     Get spherical distance between lat/lon points
863
c     ----------------------------------------------------------------------
864
 
865
      real function sdis(xp,yp,xq,yq,unit)
866
 
867
c     Calculates spherical distance (in km) between two points given
868
c     by their spherical coordinates (xp,yp) and (xq,yq), respectively.
869
 
870
      real,parameter ::       re=6371.229
871
      real,parameter ::       rad2deg=180./3.14159265
872
      real,parameter ::       deg2rad=3.141592654/180.
873
 
874
      real         xp,yp,xq,yq,arg
875
      character*80 unit
876
      real         dlon,dlat,alpha,rlat1,ralt2
877
 
878
      if ( unit.eq.'km' ) then
879
 
15 michaesp 880
         arg=sin(yp*deg2rad)*sin(yq*deg2rad)+
881
     >              cos(yp*deg2rad)*cos(yq*deg2rad)*cos((xp-xq)*deg2rad)
2 michaesp 882
         if (arg.lt.-1.) arg=-1.
883
         if (arg.gt.1.) arg=1.
884
         sdis=re*acos(arg)
885
 
886
      elseif ( unit.eq.'deg' ) then
887
 
888
         dlon = xp-xq
889
         if ( dlon.gt. 180. ) dlon = dlon - 360.
890
         if ( dlon.lt.-180. ) dlon = dlon + 360.
891
         sdis = sqrt( dlon**2 + (yp-yq)**2 )
892
 
893
      elseif ( unit.eq.'km.haversine' ) then
894
 
895
        dlat   =  (yp - yq)*deg2rad
896
        dlon   =  (xp - xq)*deg2rad
897
        rlat1   =  yp*deg2rad
898
        rlat2   =  yq*deg2rad
899
 
900
        alpha  = ( sin(0.5*dlat)**2 ) +
901
     >           ( sin(0.5*dlon)**2 )*cos(rlat1)*cos(rlat2)
902
 
903
        sdis = 4. * re * atan2( sqrt(alpha),1. + sqrt( 1. - alpha ) )
904
 
905
      endif
906
 
907
      end