Subversion Repositories lagranto.wrf

Rev

Rev 17 | Rev 21 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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