Subversion Repositories lagranto.icon

Rev

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

Rev Author Line No. Line
3 michaesp 1
      PROGRAM timeresolution
2
 
3
c     ***********************************************************************
4
c     * Change time resolution of of a trajectory file                      *
5
c     * Michael Sprenger / Winter 2010                                      *
6
c     ***********************************************************************
7
 
8
      implicit none
9
 
10
c     ----------------------------------------------------------------------
11
c     Declaration of variables
12
c     ----------------------------------------------------------------------
13
 
14
c     Parameters
15
      character*80                           inpfile     
16
      character*80                           outfile     
17
      integer                                ntra,otim,ncol
18
      real                                   timeres
19
      character*80                           unit
20
      character*80                           mode
21
 
22
c     Trajectories
23
      character*80                           vars(100)   
24
      integer                                refdate(6)  
25
      integer                                ntim       
26
      real,allocatable, dimension (:,:,:) :: trainp        
27
      real,allocatable, dimension (:,:,:) :: traout        
28
      real,allocatable, dimension (:)     :: timold,timnew
29
      real,allocatable, dimension (:)     :: fldold,fldnew
30
 
31
c     Numerical constants
32
      real                                   eps
33
      parameter                              (eps=0.001)
34
 
35
c     Auxiliary variables
36
      integer                                inpmode
37
      integer                                outmode
38
      integer                                stat
39
      integer                                fid
40
      integer                                i,j,k
41
      real                                   hhmm,tfrac
42
      real                                   range
43
      integer                                date0(5),date1(5)
44
      character*20                           ch
45
      real                                   t1,t2,t3
46
 
47
c     ----------------------------------------------------------------------
48
c     Parameter handling
49
c     ----------------------------------------------------------------------
50
 
51
c     Read parameters
52
      open(10,file='timeres.param')
53
       read(10,*) inpfile
54
       read(10,*) outfile
55
       read(10,*) ntra,otim,ncol
56
       read(10,*) timeres
57
       read(10,*) unit
58
       read(10,*) mode
59
      close(10)
60
 
61
c     Change unit to minutes
62
      if ( unit.eq.'min') then
63
         timeres = 1./60. * timeres
64
         unit    = 'h'
65
      endif
66
 
67
c     Determine the formats
68
      call mode_tra(inpmode,inpfile)
69
      if (inpmode.eq.-1) inpmode=1
70
      call mode_tra(outmode,outfile)
71
      if (outmode.eq.-1) outmode=1
72
 
73
c     ----------------------------------------------------------------------
74
c     Read input trajectory and allocate memory
75
c     ----------------------------------------------------------------------
76
 
77
c     Allocate memory for input trajectories
78
      allocate(trainp(ntra,otim,ncol),stat=stat)
79
      if (stat.ne.0) print*,'*** error allocating array trainp   ***' 
80
      allocate(timold(otim),stat=stat)
81
      if (stat.ne.0) print*,'*** error allocating array timold   ***' 
82
      allocate(fldold(otim),stat=stat)
83
      if (stat.ne.0) print*,'*** error allocating array fldold   ***' 
84
 
85
c     Read inpufile
86
      call ropen_tra(fid,inpfile,ntra,otim,ncol,refdate,vars,inpmode)
87
      call read_tra (fid,trainp,ntra,otim,ncol,inpmode)
88
      call close_tra(fid,inpmode)
89
 
90
c     Check that first four columns correspond to time,lon,lat,p
91
      if ( (vars(1).ne.'time' ).or.
92
     >     (vars(2).ne.'xpos' ).and.(vars(2).ne.'lon' ).or.
93
     >     (vars(3).ne.'ypos' ).and.(vars(3).ne.'lat' ).or.
94
     >     (vars(4).ne.'ppos' ).and.(vars(4).ne.'z'   ) )
95
     >then
96
         print*,' ERROR: problem with input trajectories ...'
97
         stop
98
      endif
99
 
100
c     Convert all times from hhmm to fractional time
101
      do i=1,ntra
102
         do j=1,otim
103
            hhmm = trainp(i,j,1)
104
            call hhmm2frac(hhmm,tfrac)
105
            trainp(i,j,1) = tfrac
106
         enddo
107
      enddo
108
 
109
c     Get the time range in minutes
110
      range = ( trainp(1,otim,1) - trainp(1,1,1) ) 
111
 
112
c     Determine the new number of times
113
      if ( mode.eq.'shift0' ) then
114
        ntim = otim
115
      else
116
        ntim = nint( abs( range ) / timeres ) + 1
117
      endif
118
 
119
c     Allocate memory for output trajectories
120
      allocate(traout(ntra,ntim,ncol),stat=stat)
121
      if (stat.ne.0) print*,'*** error allocating array trainp   ***' 
122
      allocate(timnew(ntim),stat=stat)
123
      if (stat.ne.0) print*,'*** error allocating array timnew   ***' 
124
      allocate(fldnew(ntim),stat=stat)
125
      if (stat.ne.0) print*,'*** error allocating array fldnew   ***' 
126
 
127
c     ----------------------------------------------------------------------
128
c     Change time resolution
129
c     ----------------------------------------------------------------------
130
 
131
      if ( (mode.eq.'linear').or.(mode.eq.'cubic') ) then
132
 
133
c     Check that the time range and new time resolution are consistent
134
      if ( abs( real(ntim-1) * timeres -range ).gt.eps ) then
135
         print*
136
         print*,'------------------------------------------------------'
137
         print*,' WARNING: time range and resolution are not compatible'
138
         print*,'   range              = ',range
139
         print*,'   (ntim-1) * timeres = ',real(ntim-1) * timeres
140
         print*
141
         print*,'------------------------------------------------------'
142
         stop
143
      endif
144
 
145
c     Define the old and new times
146
      do i=1,otim
147
         timold(i) = trainp(1,i,1)
148
      enddo
149
      do i=1,ntim
150
         timnew(i) = timold(1) + real(i-1) * timeres
151
      enddo
152
 
153
      print*,timnew(1)
154
      print*,timnew(2)
155
      print*,timnew(3)
156
 
157
c     Loop over all trajectories
158
      do i=1,ntra
159
      do k=2,ncol
160
 
161
c        Copy old field
162
         do j=1,otim
163
            fldold(j) = trainp(i,j,k)
164
         enddo
165
 
166
c        Exception: Handle date line problem for longitude
167
         if ( k.eq.2 ) then 
168
            do j=2,otim
169
               if ( (fldold(j-1)-fldold(j)).gt.180. ) then
170
                  fldold(j) = fldold(j) + 360.
171
               else if ( (fldold(j-1)-fldold(j)).lt.-180. ) then
172
                  fldold(j) = fldold(j) - 360.
173
               endif
174
            enddo
175
         endif
176
 
177
c        Cubic spline fitting
178
         if ( mode.eq.'cubic' ) then
179
            call cubicfit (timold,fldold,otim,timnew,fldnew,ntim)
180
         else if (mode.eq.'linear' ) then
181
            call linearfit(timold,fldold,otim,timnew,fldnew,ntim)
182
         endif
183
 
184
c        Exception: Reverse date line handling for longitude
185
         if ( k.eq.2 ) then
186
            do j=1,ntim
187
               if ( fldnew(j).gt.180. ) then
188
                  fldnew(j) = fldnew(j) -360.
189
               else if ( fldnew(j).lt.-180. ) then
190
                  fldnew(j) = fldnew(j) +360.
191
               endif
192
            enddo
193
         endif
194
 
195
c        Save the new field in the output trajectory
196
         do j=1,ntim
197
            traout(i,j,1) = timnew(j)
198
            traout(i,j,k) = fldnew(j)
199
         enddo
200
 
201
      enddo
202
      enddo
203
 
204
      endif
205
 
206
c     ----------------------------------------------------------------------
207
c     Shift the times, first trajectory time is 0
208
c     ----------------------------------------------------------------------
209
 
210
      if ( mode.eq.'shift0' ) then
211
 
212
c        Copy old to new trajectory, change trajectory time
213
         do i=1,ntra
214
            do j=1,ntim
215
             traout(i,j,1) = trainp(i,j,1) - trainp(i,1,1)
216
             do k=2,ncol
217
                traout(i,j,k) = trainp(i,j,k)
218
             enddo
219
           enddo
220
         enddo
221
 
222
c        Change the reference date
223
         date0(1) = refdate(1)
224
         date0(2) = refdate(2)
225
         date0(3) = refdate(3)
226
         date0(4) = refdate(4)
227
         date0(5) = refdate(5)
228
         call newdate(date0,trainp(1,1,1),date1)
229
         refdate(1) = date1(1)
230
         refdate(2) = date1(2)
231
         refdate(3) = date1(3)
232
         refdate(4) = date1(4)
233
         refdate(5) = date1(5)
234
 
235
      endif
236
 
237
c     ----------------------------------------------------------------------
238
c     Write output trajectory
239
c     ----------------------------------------------------------------------
240
 
241
      print*
242
      print*,timnew(1)
243
      print*,timnew(2)
244
      print*,timnew(3)
245
 
246
c     Convert all times from fractional to hhmm time
247
      do i=1,ntra
248
         do j=1,ntim
249
            tfrac = traout(i,j,1)
250
            call frac2hhmm(tfrac,hhmm)
251
            traout(i,j,1) = hhmm
252
         enddo
253
      enddo
254
 
255
c     Write output file
256
      call wopen_tra(fid,outfile,ntra,ntim,ncol,refdate,vars,outmode)
257
      call write_tra(fid,traout,ntra,ntim,ncol,outmode)
258
      call close_tra(fid,outmode)
259
 
260
      end
261
 
262
 
263
c     ********************************************************************
264
c     * REPARAMETERIZATION SUBROUTINES                                   *
265
c     ********************************************************************
266
 
267
c     -------------------------------------------------------------
268
c     Interpolation of the trajectory with linear interpolation
269
c     -------------------------------------------------------------
270
 
271
      SUBROUTINE linearfit (time,lon,n,sptime,splon,spn)
272
 
273
c     Given the curve <time,lon> with <n> data points, fit a
274
c     linear fit to this curve. The new curve is returned in 
275
c     <sptime,splon,spn> with <spn> data points. The parameter
276
c     <spn> specifies on entry the number of interpolated points
277
c     along the curve.
278
 
279
      implicit none
280
 
281
c     Declaration of subroutine parameters
282
      integer n
283
      real    time(n),lon(n)
284
      integer spn
285
      real    sptime(spn),splon(spn)
286
 
287
c     Auxiliary variables
288
      real    dt
289
      real    s
290
      integer i,j,iold
291
      real    order
292
 
293
c     Determine whether the input array is ascending or descending
294
      if (time(1).gt.time(n)) then
295
         order=-1.
296
      else
297
         order= 1.
298
      endif
299
 
300
c     Bring the time array into ascending order
301
      do i=1,n
302
         time(i)=order*time(i)
303
      enddo
304
 
305
c     Prepare the linear interpolation: define the new times
306
      dt=(time(n)-time(1))/real(spn-1)
307
      do i=1,spn
308
         sptime(i)=time(1)+real(i-1)*dt
309
      enddo
310
 
311
c     Do the interpolation
312
      iold = 1
313
      do i=1,spn
314
 
315
c        Decide which interval of the old time series must be taken
316
         do j=iold,n-1
317
            if ( ( sptime(i).ge.time(j  ) ).and.
318
     >           ( sptime(i).lt.time(j+1) ) ) 
319
     >      then
320
               iold = j
321
               exit
322
            endif
323
         enddo
324
 
325
c        Do the linear interpolation
326
         splon(i) = lon(iold) + ( lon(iold+1) - lon(iold) ) * 
327
     >       ( sptime(i) - time(iold) ) / ( time(iold+1) - time(iold) ) 
328
 
329
      enddo
330
 
331
c     Change the time arrays back: original order
332
      do i=1,spn
333
         sptime(i)=order*sptime(i)
334
      enddo
335
      do i=1,n
336
         time(i)=order*time(i)
337
      enddo
338
 
339
      return
340
      end
341
 
342
 
343
c     -------------------------------------------------------------
344
c     Interpolation of the trajectory with a natural cubic spline
345
c     -------------------------------------------------------------
346
 
347
      SUBROUTINE cubicfit (time,lon,n,sptime,splon,spn)
348
 
349
c     Given the curve <time,lon> with <n> data points, fit a
350
c     cubic spline to this curve. The new curve is returned in 
351
c     <sptime,splon,spn> with <spn> data points. The parameter
352
c     <spn> specifies on entry the number of spline interpolated points
353
c     along the curve.
354
 
355
      implicit none
356
 
357
c     Declaration of subroutine parameters
358
      integer n
359
      real    time(n),lon(n)
360
      integer spn
361
      real    sptime(spn),splon(spn)
362
 
363
c     Auxiliary variables
364
      real    y2ax(n)
365
      real    dt
366
      real    s
367
      integer i
368
      real    order
369
 
370
c     Determine whether the input array is ascending or descending
371
      if (time(1).gt.time(n)) then
372
         order=-1.
373
      else
374
         order= 1.
375
      endif
376
 
377
c     Bring the time array into ascending order
378
      do i=1,n
379
         time(i)=order*time(i)
380
      enddo
381
 
382
c     Prepare the (natural) cubic spline interpolation
383
      call spline (time,lon,n,1.e30,1.e30,y2ax)
384
      dt=(time(n)-time(1))/real(spn-1)
385
      do i=1,spn
386
         sptime(i)=time(1)+real(i-1)*dt
387
      enddo
388
 
389
c     Do the spline interpolation
390
      do i=1,spn
391
         call splint(time,lon,y2ax,n,sptime(i),s)
392
         splon(i)=s
393
      enddo
394
 
395
c     Change the time arrays back
396
      do i=1,spn
397
         sptime(i)=order*sptime(i)
398
      enddo
399
      do i=1,n
400
         time(i)=order*time(i)
401
      enddo
402
 
403
      return
404
      end
405
 
406
c     -------------------------------------------------------------
407
c     Basic routines for spline interpolation (Numerical Recipes)
408
c     -------------------------------------------------------------
409
 
410
      SUBROUTINE spline(x,y,n,yp1,ypn,y2)
411
      INTEGER n,NMAX
412
      REAL yp1,ypn,x(n),y(n),y2(n)
413
      PARAMETER (NMAX=500)
414
      INTEGER i,k
415
      REAL p,qn,sig,un,u(NMAX)
416
      if (yp1.gt..99e30) then
417
        y2(1)=0.
418
        u(1)=0.
419
      else
420
        y2(1)=-0.5
421
        u(1)=(3./(x(2)-x(1)))*((y(2)-y(1))/(x(2)-x(1))-yp1)
422
      endif
423
      do 11 i=2,n-1
424
        sig=(x(i)-x(i-1))/(x(i+1)-x(i-1))
425
        p=sig*y2(i-1)+2.
426
        y2(i)=(sig-1.)/p
427
        u(i)=(6.*((y(i+1)-y(i))/(x(i+
428
     *1)-x(i))-(y(i)-y(i-1))/(x(i)-x(i-1)))/(x(i+1)-x(i-1))-sig*
429
     *u(i-1))/p
430
11    continue
431
      if (ypn.gt..99e30) then
432
        qn=0.
433
        un=0.
434
      else
435
        qn=0.5
436
        un=(3./(x(n)-x(n-1)))*(ypn-(y(n)-y(n-1))/(x(n)-x(n-1)))
437
      endif
438
      y2(n)=(un-qn*u(n-1))/(qn*y2(n-1)+1.)
439
      do 12 k=n-1,1,-1
440
        y2(k)=y2(k)*y2(k+1)+u(k)
441
12    continue
442
      return
443
      END
444
 
445
      SUBROUTINE splint(xa,ya,y2a,n,x,y)
446
      INTEGER n
447
      REAL x,y,xa(n),y2a(n),ya(n)
448
      INTEGER k,khi,klo
449
      REAL a,b,h
450
      klo=1
451
      khi=n
452
1     if (khi-klo.gt.1) then
453
        k=(khi+klo)/2
454
        if(xa(k).gt.x)then
455
          khi=k
456
        else
457
          klo=k
458
        endif
459
      goto 1
460
      endif
461
      h=xa(khi)-xa(klo)
462
      if (h.eq.0.) pause 'bad xa input in splint'
463
      a=(xa(khi)-x)/h
464
      b=(x-xa(klo))/h
465
      y=a*ya(klo)+b*ya(khi)+((a**3-a)*y2a(klo)+(b**3-b)*y2a(khi))*(h**
466
     *2)/6.
467
      return
468
      END
469
 
470
 
471