3 |
michaesp |
1 |
program contrack
|
|
|
2 |
|
|
|
3 |
! ----------------------------------------------------------------------
|
|
|
4 |
!
|
|
|
5 |
! Date: 1st January 2011
|
|
|
6 |
!
|
|
|
7 |
!
|
|
|
8 |
! ------->> Purpose: Spatial and temporal contour tracking programm
|
|
|
9 |
!
|
|
|
10 |
! This programm is a completely re-written new version of the tracking
|
|
|
11 |
! programm used for the studies in e.g. Schwierz et al. (2005),
|
|
|
12 |
! Croci-Maspoli et al. (2007a,b), Croci-Maspoli et al. (2009).
|
|
|
13 |
!
|
|
|
14 |
! ------->> What is necessary to compile contrack?
|
|
|
15 |
|
|
|
16 |
! - contrack has been compiled with gfortran
|
|
|
17 |
! (included in the GCC family, http://gcc.gnu.org/ ). Feel free
|
|
|
18 |
! to test other fortran compilers.
|
|
|
19 |
! - contrack requires the netcdf-4.0.1 library (also compiled with gfortran).
|
|
|
20 |
! - contrack comes with a simple make-file (you have to adjust this file
|
|
|
21 |
! before compiling).
|
|
|
22 |
!
|
|
|
23 |
! ------->> What netCDF-file is necessary as input?
|
|
|
24 |
!
|
|
|
25 |
! - a single CF-netCDF-file (http://cf-pcmdi.llnl.gov/) including all required
|
|
|
26 |
! time steps.
|
|
|
27 |
! - a longitude, latitude and time dimension.
|
|
|
28 |
! - contrack does not calculate a climatological anomaly field. This needs to
|
|
|
29 |
! be calculated before running contrack.
|
|
|
30 |
!
|
|
|
31 |
! ------->> How does the output file look like?
|
|
|
32 |
!
|
|
|
33 |
! - the output CF-netCDF file has the same dimensions as the input netCDF file
|
|
|
34 |
! - the output has a binary format (0 and 1), whereas 1 captures regions of
|
|
|
35 |
! the blocks.
|
|
|
36 |
!
|
|
|
37 |
! ------->> Known issues or features not implemented yet in contrack 0.8:
|
|
|
38 |
!
|
|
|
39 |
! 1) The calculation and saving of common statistical blocking features
|
|
|
40 |
! (e.g. blocking size, blocking length, blocking path, ...) is not
|
|
|
41 |
! implemented yet. My intention is to save these information directly
|
|
|
42 |
! on the netCDF file.
|
|
|
43 |
! 2) Only two-dimensional netCDF-files can be used as input file (longitude,
|
|
|
44 |
! latitude and time). The code can not handle a third dimension (e.g.
|
|
|
45 |
! vertical) on the same netCDF-file yet.
|
|
|
46 |
! 3) The asymmetry of the blocking features is not implemented yet.
|
|
|
47 |
! 3) ... more to come!
|
|
|
48 |
!
|
|
|
49 |
! ------->> Version control
|
|
|
50 |
|
|
|
51 |
! Version 0.1-0.8: May 2010 - fortran 90 compatible
|
|
|
52 |
! - CF-netCDF compatible (instead of IVE-netCDF)
|
|
|
53 |
! - new tracking algorithm
|
|
|
54 |
! Oct 2011 - started with handling also different vertical
|
|
|
55 |
! levels but not finished yet.
|
|
|
56 |
! Jan 2011 - added these explanations
|
|
|
57 |
!
|
|
|
58 |
! If you have any comments please send them to mischa.croci-maspoli@alumni.ethz.ch.
|
|
|
59 |
!
|
|
|
60 |
! This programm code comes with no guarantee and is currently still
|
|
|
61 |
! under construction. Be aware that no extensive testing and comparison to the
|
|
|
62 |
! old code has been performed yet.
|
|
|
63 |
!
|
|
|
64 |
! Copyright: mischa.croci-maspoli@alumni.ethz.ch
|
|
|
65 |
!
|
|
|
66 |
! Modifications SP: omit first and last n time steps in output,
|
|
|
67 |
! where n=persistence;
|
|
|
68 |
! comment out allocation etc. related to vertical dimension
|
|
|
69 |
!
|
|
|
70 |
! ----------------------------------------------------------------------
|
|
|
71 |
|
|
|
72 |
USE netcdf
|
|
|
73 |
|
|
|
74 |
implicit none
|
|
|
75 |
|
|
|
76 |
integer, external :: iargc
|
|
|
77 |
|
|
|
78 |
integer :: i,j,t,k,ii,jj,tt,counter
|
|
|
79 |
integer :: persistence, verbose, calcmeranom, cont
|
|
|
80 |
integer :: titleLength, commentLength, sourceLength, institLength
|
|
|
81 |
integer :: errmsg, outarr
|
|
|
82 |
integer :: nrcontours
|
|
|
83 |
integer :: ttbegin, ttend
|
|
|
84 |
real :: fraction, areacon, areaover, overlap, threshold
|
|
|
85 |
|
|
|
86 |
character*(100) infilename,outfilename,arg
|
|
|
87 |
character*(100) outvarname,outstandvarname, outvarunit
|
|
|
88 |
character*(100) invarname, inlat, inlon, intime, inver
|
|
|
89 |
character*(100) contrackversion
|
|
|
90 |
character*(5) gorl
|
|
|
91 |
|
|
|
92 |
character*(1000) cfcomment, cftitle, cfsource, cfinstit
|
|
|
93 |
character*(1000) cfoutcomment, cfouttitle, cfoutsource, cfoutinstit
|
|
|
94 |
integer :: ncid, status, nDims, nVars, nGlobalAtts, unlimDimID
|
|
|
95 |
integer :: label, nrsmooth, nrg, nrgc
|
|
|
96 |
|
|
|
97 |
integer :: LatDimID,LonDimID, TimeDimID,timeVarID,lonVarID,latVarID,vorpotVarID
|
|
|
98 |
integer :: VerDimID
|
|
|
99 |
integer :: varLatID,varLonID,varPVID,varTimeID
|
|
|
100 |
integer :: nLats,nLong,nTimes,nVert
|
|
|
101 |
|
|
|
102 |
integer, dimension(:), allocatable :: times, latitude, longitude, longi
|
|
|
103 |
integer, dimension(:), allocatable :: vertical
|
|
|
104 |
integer, dimension(:), allocatable :: iiv, jjv, ttv
|
|
|
105 |
integer, dimension(:), allocatable :: time_array
|
|
|
106 |
real, dimension(:,:,:), allocatable :: inarr, arr, arr1, arr2
|
|
|
107 |
real, dimension(:,:), allocatable :: latmean
|
|
|
108 |
|
|
|
109 |
|
|
|
110 |
! --------------------------------------------------------------
|
|
|
111 |
! input handling
|
|
|
112 |
! --------------------------------------------------------------
|
|
|
113 |
|
|
|
114 |
contrackversion = 'version 0.8'
|
|
|
115 |
status = 0
|
|
|
116 |
|
|
|
117 |
print*, '-------------------------------------------------------'
|
|
|
118 |
print*, 'contrack ', trim(contrackversion)
|
|
|
119 |
print*, '-------------------------------------------------------'
|
|
|
120 |
|
|
|
121 |
999 continue
|
|
|
122 |
|
|
|
123 |
if ( (iargc().ne.1).or.(status.gt.0) ) then
|
|
|
124 |
print*, '-------------------------------------------------------'
|
|
|
125 |
print*, 'contrack ', trim(contrackversion)
|
|
|
126 |
print*, '-------------------------------------------------------'
|
|
|
127 |
print*, 'Usage: contrack inputfile'
|
|
|
128 |
print*, '-------------------------------------------------------'
|
|
|
129 |
print*, 'The inputfile needs the following structure:'
|
|
|
130 |
print*, ''
|
|
|
131 |
print*, 'infilename -> name of the input CF-netCDF file'
|
|
|
132 |
print*, 'invarname -> name of the netCDF variable name'
|
|
|
133 |
print*, 'inlat -> name of the netCDF latitude variable'
|
|
|
134 |
print*, 'inlon -> name of the netCDF longitude variable'
|
|
|
135 |
print*, 'intime -> name of the netCDF time variable'
|
|
|
136 |
print*, 'threshold -> threshold value to detect contours'
|
|
|
137 |
print*, 'gorl -> find contours that are greater or '
|
|
|
138 |
print*, ' lower threshold value [ge,le,gt,lt]'
|
|
|
139 |
print*, 'persistence -> temporal persistence (in time steps)'
|
|
|
140 |
print*, ' of the contour life time'
|
|
|
141 |
print*, 'overlap -> overlapping fraction of two contours'
|
|
|
142 |
print*, ' between two time steps [0-1]'
|
|
|
143 |
print*, 'nrsmooth -> temporal smoothing of the infilename'
|
|
|
144 |
print*, ' (in time steps)'
|
|
|
145 |
print*, 'outarr -> values of the contours in the output array'
|
|
|
146 |
print*, ' 0: contours are numbered by each contour'
|
|
|
147 |
print*, ' 1: contours are labeled 0 and 1'
|
|
|
148 |
print*, 'outfilename -> name of the output CF-netCDF file'
|
|
|
149 |
print*, 'outvarname -> name of the output netCDF variable name'
|
|
|
150 |
print*, 'outstvarname -> name of the output netCDF standard'
|
|
|
151 |
print*, ' variable name'
|
|
|
152 |
print*, 'outvarunit -> name of the outuput netCDF unit'
|
|
|
153 |
print*, 'verbose -> [0 or 1]'
|
|
|
154 |
print*, 'calcmeranom -> flag whether to calc meriodonal anomalies'
|
|
|
155 |
print*, ' or not [0 or 1]'
|
|
|
156 |
print*, '-------------------------------------------------------'
|
|
|
157 |
print*, 'Please send any comments / bugs to:'
|
|
|
158 |
print*, 'mischa.croci-maspoli@alumni.ethz.ch'
|
|
|
159 |
print*, '-------------------------------------------------------'
|
|
|
160 |
print*, ''
|
|
|
161 |
print*, '-->> contrack not executed, an error occured!'
|
|
|
162 |
print*, ''
|
|
|
163 |
call exit(1)
|
|
|
164 |
endif
|
|
|
165 |
|
|
|
166 |
! Read inputfile
|
|
|
167 |
! --------------
|
|
|
168 |
call getarg(1,arg)
|
|
|
169 |
infilename=trim(arg)
|
|
|
170 |
|
|
|
171 |
|
|
|
172 |
! Open inputfile and read variables
|
|
|
173 |
! ---------------------------------
|
|
|
174 |
open(2,file=infilename,status='old',iostat=status)
|
|
|
175 |
if ( status.gt.0 ) then
|
|
|
176 |
print*, ''
|
|
|
177 |
print*, '-> Problem in contrack: Your ASCII input file "', trim(infilename), &
|
|
|
178 |
'" can not be found'
|
|
|
179 |
print*, '-> For further information use ./contrack only'
|
|
|
180 |
print*, ''
|
|
|
181 |
stop
|
|
|
182 |
endif
|
|
|
183 |
|
|
|
184 |
read(2,*,iostat=status) infilename
|
|
|
185 |
if ( status.gt.0 ) goto 999
|
|
|
186 |
read(2,*,iostat=status) invarname
|
|
|
187 |
if ( status.gt.0 ) goto 999
|
|
|
188 |
read(2,*,iostat=status) inlat
|
|
|
189 |
if ( status.gt.0 ) goto 999
|
|
|
190 |
read(2,*,iostat=status) inlon
|
|
|
191 |
if ( status.gt.0 ) goto 999
|
|
|
192 |
read(2,*,iostat=status) intime
|
|
|
193 |
if ( status.gt.0 ) goto 999
|
|
|
194 |
read(2,*,iostat=status) threshold
|
|
|
195 |
if ( status.gt.0 ) goto 999
|
|
|
196 |
read(2,*,iostat=status) gorl
|
|
|
197 |
if ( status.gt.0 ) goto 999
|
|
|
198 |
read(2,*,iostat=status) persistence
|
|
|
199 |
if ( status.gt.0 ) goto 999
|
|
|
200 |
read(2,*,iostat=status) overlap
|
|
|
201 |
if ( status.gt.0 ) goto 999
|
|
|
202 |
read(2,*,iostat=status) nrsmooth
|
|
|
203 |
if ( status.gt.0 ) goto 999
|
|
|
204 |
read(2,*,iostat=status) outarr
|
|
|
205 |
if ( status.gt.0 ) goto 999
|
|
|
206 |
read(2,*,iostat=status) outfilename
|
|
|
207 |
if ( status.gt.0 ) goto 999
|
|
|
208 |
read(2,*,iostat=status) outvarname
|
|
|
209 |
if ( status.gt.0 ) goto 999
|
|
|
210 |
read(2,*,iostat=status) outstandvarname
|
|
|
211 |
if ( status.gt.0 ) goto 999
|
|
|
212 |
read(2,*,iostat=status) outvarunit
|
|
|
213 |
if ( status.gt.0 ) goto 999
|
|
|
214 |
read(2,*,iostat=status) verbose
|
|
|
215 |
if ( status.gt.0 ) goto 999
|
|
|
216 |
read(2,*,iostat=status) calcmeranom
|
|
|
217 |
if ( status.gt.0 ) goto 999
|
|
|
218 |
close(2)
|
|
|
219 |
|
|
|
220 |
|
|
|
221 |
! --------------------------------------------------------------
|
|
|
222 |
! read CF-netCDF file
|
|
|
223 |
! --------------------------------------------------------------
|
|
|
224 |
|
|
|
225 |
allocate(time_array(8))
|
|
|
226 |
call date_and_time (values=time_array)
|
|
|
227 |
write(*,100), "-> Read ", trim(infilename), time_array(5), ':', time_array(6), ':', time_array(7)
|
|
|
228 |
100 format(A,A,I5,A,I2,A,I2)
|
|
|
229 |
|
|
|
230 |
! Initially set error to indicate no errors.
|
|
|
231 |
status = 0
|
|
|
232 |
|
|
|
233 |
! open netCDF file
|
|
|
234 |
status = nf90_open(infilename, nf90_nowrite, ncid)
|
|
|
235 |
|
|
|
236 |
! get dimensions
|
|
|
237 |
status = nf90_inq_dimid(ncid, inlat, LatDimID)
|
|
|
238 |
status = nf90_inquire_dimension(ncid, LatDimID, len = nLats)
|
|
|
239 |
|
|
|
240 |
status = nf90_inq_dimid(ncid, inlon, LonDimID)
|
|
|
241 |
status = nf90_inquire_dimension(ncid, LonDimID, len = nLong)
|
|
|
242 |
|
|
|
243 |
!status = nf90_inq_dimid(ncid, inver, VerDimID)
|
|
|
244 |
!status = nf90_inquire_dimension(ncid, VerDimID, len = nVert)
|
|
|
245 |
|
|
|
246 |
status = nf90_inq_dimid(ncid, intime, TimeDimID)
|
|
|
247 |
status = nf90_inquire_dimension(ncid, TimeDimID, len = nTimes)
|
|
|
248 |
|
|
|
249 |
! allocate arrays
|
|
|
250 |
allocate(times(nTimes))
|
|
|
251 |
allocate(latitude(nLats))
|
|
|
252 |
allocate(longitude(nLong))
|
|
|
253 |
!allocate(vertical(nVert))
|
|
|
254 |
allocate(inarr(nLong,nLats,nTimes))
|
|
|
255 |
allocate(arr(nLong,nLats,nTimes))
|
|
|
256 |
allocate(arr1(nLong,nLats,nTimes))
|
|
|
257 |
allocate(arr2(nLong,nLats,nTimes))
|
|
|
258 |
allocate(latmean(nLats,nTimes))
|
|
|
259 |
allocate(iiv(nLats*nLong*nTimes))
|
|
|
260 |
allocate(jjv(nLats*nLong*nTimes))
|
|
|
261 |
allocate(ttv(nLats*nLong*nTimes))
|
|
|
262 |
|
|
|
263 |
! get variables
|
|
|
264 |
status = nf90_inq_varid(ncid, intime, timeVarID)
|
|
|
265 |
status = nf90_get_var(ncid, timeVarID, times)
|
|
|
266 |
|
|
|
267 |
status = nf90_inq_varid(ncid, inlon, lonVarID)
|
|
|
268 |
status = nf90_get_var(ncid, lonVarID, longitude)
|
|
|
269 |
|
|
|
270 |
status = nf90_inq_varid(ncid, inlat, latVarID)
|
|
|
271 |
status = nf90_get_var(ncid, latVarID, latitude)
|
|
|
272 |
|
|
|
273 |
status = nf90_inq_varid(ncid, invarname, vorpotVarID)
|
|
|
274 |
status = nf90_get_var(ncid, vorpotVarID, inarr)
|
|
|
275 |
|
|
|
276 |
status = nf90_inquire_attribute(ncid, nf90_global, "comment", len = commentLength)
|
|
|
277 |
status = nf90_get_att(ncid, NF90_GLOBAL, 'comment', cfcomment)
|
|
|
278 |
status = nf90_inquire_attribute(ncid, nf90_global, "title", len = titleLength)
|
|
|
279 |
status = nf90_get_att(ncid, NF90_GLOBAL, 'title', cftitle)
|
|
|
280 |
status = nf90_inquire_attribute(ncid, nf90_global, "source", len = sourceLength)
|
|
|
281 |
status = nf90_get_att(ncid, NF90_GLOBAL, 'source', cfsource)
|
|
|
282 |
status = nf90_inquire_attribute(ncid, nf90_global, "institution", len = institLength)
|
|
|
283 |
status = nf90_get_att(ncid, NF90_GLOBAL, 'institution', cfinstit)
|
|
|
284 |
|
|
|
285 |
status = nf90_close(ncid)
|
|
|
286 |
|
|
|
287 |
|
|
|
288 |
! --------------------------------------------------------------
|
|
|
289 |
! Calculate meridional anomaly
|
|
|
290 |
! --------------------------------------------------------------
|
|
|
291 |
|
|
|
292 |
if ( calcmeranom.eq.1 ) then
|
|
|
293 |
|
|
|
294 |
print*, '-->> calculate meridional mean anomaly'
|
|
|
295 |
|
|
|
296 |
! Calculate latitudinal mean
|
|
|
297 |
! --------------------------------------------------------------
|
|
|
298 |
do t = 1,nTimes
|
|
|
299 |
do j = 1,nLats
|
|
|
300 |
do i = 1,nLong
|
|
|
301 |
latmean(j,t) = latmean(j,t) + inarr(i,j,t)
|
|
|
302 |
enddo
|
|
|
303 |
enddo
|
|
|
304 |
enddo
|
|
|
305 |
|
|
|
306 |
! Subtract latitudinal mean
|
|
|
307 |
! --------------------------------------------------------------
|
|
|
308 |
do t = 1,nTimes
|
|
|
309 |
do j = 1,nLats
|
|
|
310 |
do i = 1,nLong
|
|
|
311 |
arr(i,j,t) = inarr(i,j,t) - latmean(j,t)/nLong
|
|
|
312 |
enddo
|
|
|
313 |
enddo
|
|
|
314 |
enddo
|
|
|
315 |
|
|
|
316 |
|
|
|
317 |
! Calculate running means (centered at the first file)
|
|
|
318 |
! --------------------------------------------------------------
|
|
|
319 |
do t = 1,nTimes
|
|
|
320 |
do j = 1,nLats
|
|
|
321 |
do i = 1,nLong
|
|
|
322 |
do k = 0,nrsmooth
|
|
|
323 |
arr1(i,j,t) = arr1(i,j,t) + arr(i,j,t+k)
|
|
|
324 |
enddo
|
|
|
325 |
enddo
|
|
|
326 |
enddo
|
|
|
327 |
enddo
|
|
|
328 |
|
|
|
329 |
arr = arr1/nrsmooth
|
|
|
330 |
|
|
|
331 |
else
|
|
|
332 |
print*, '-->> no anomaly calculated'
|
|
|
333 |
arr(:,:,:) = inarr(:,:,:)
|
|
|
334 |
endif
|
|
|
335 |
|
|
|
336 |
|
|
|
337 |
! Define closed contours by a threshold value
|
|
|
338 |
! --------------------------------------------------------------
|
|
|
339 |
|
|
|
340 |
print*, '-->> define contours with threshold value'
|
|
|
341 |
|
|
|
342 |
do t = 1,nTimes
|
|
|
343 |
do j = 1,nLats
|
|
|
344 |
do i = 1,nLong
|
|
|
345 |
|
|
|
346 |
if ( trim(gorl).eq.'ge' ) then
|
|
|
347 |
if ( arr(i,j,t).ge.threshold) then
|
|
|
348 |
arr(i,j,t) = 1
|
|
|
349 |
else
|
|
|
350 |
arr(i,j,t) = 0
|
|
|
351 |
endif
|
|
|
352 |
endif
|
|
|
353 |
if ( trim(gorl).eq.'le' ) then
|
|
|
354 |
if ( arr(i,j,t).le.threshold) then
|
|
|
355 |
arr(i,j,t) = 1
|
|
|
356 |
else
|
|
|
357 |
arr(i,j,t) = 0
|
|
|
358 |
endif
|
|
|
359 |
endif
|
|
|
360 |
if ( trim(gorl).eq.'gt' ) then
|
|
|
361 |
if ( arr(i,j,t).gt.threshold) then
|
|
|
362 |
arr(i,j,t) = 1
|
|
|
363 |
else
|
|
|
364 |
arr(i,j,t) = 0
|
|
|
365 |
endif
|
|
|
366 |
endif
|
|
|
367 |
if ( trim(gorl).eq.'lt' ) then
|
|
|
368 |
if ( arr(i,j,t).lt.threshold) then
|
|
|
369 |
arr(i,j,t) = 1
|
|
|
370 |
else
|
|
|
371 |
arr(i,j,t) = 0
|
|
|
372 |
endif
|
|
|
373 |
endif
|
|
|
374 |
|
|
|
375 |
|
|
|
376 |
|
|
|
377 |
|
|
|
378 |
enddo
|
|
|
379 |
enddo
|
|
|
380 |
enddo
|
|
|
381 |
|
|
|
382 |
|
|
|
383 |
! Identify individual contour areas on a 2D-space (only x-y, no time)
|
|
|
384 |
! -------------------------------------------------------------------
|
|
|
385 |
|
|
|
386 |
print*, '-->> identify individual contours'
|
|
|
387 |
|
|
|
388 |
arr2(:,:,:) = 0 ! set arr2 to zero
|
|
|
389 |
|
|
|
390 |
do t = 1,nTimes
|
|
|
391 |
label = 1 ! begin labeling with 1
|
|
|
392 |
do j = 1,nLats
|
|
|
393 |
do i = 1,nLong
|
|
|
394 |
|
|
|
395 |
if ( (arr(i,j,t).eq.1).and.(arr2(i,j,t).lt.1) ) then
|
|
|
396 |
|
|
|
397 |
arr2(i,j,t) = label ! first identified grid point in countour
|
|
|
398 |
nrg = 1 ! number of grid points
|
|
|
399 |
nrgc = 1 ! number of grid points counter
|
|
|
400 |
iiv(nrgc) = i ! x-dir coordinates within contour
|
|
|
401 |
jjv(nrgc) = j ! y-dir coordinates within contour
|
|
|
402 |
|
|
|
403 |
do while ( nrgc.le.nrg )
|
|
|
404 |
|
|
|
405 |
do ii=-1,1
|
|
|
406 |
do jj=-1,1
|
|
|
407 |
|
|
|
408 |
if ( (arr(iiv(nrgc)+ii,jjv(nrgc)+jj,t).eq.1).and. &
|
|
|
409 |
(arr2(iiv(nrgc)+ii,jjv(nrgc)+jj,t).ne.label) ) then
|
|
|
410 |
|
|
|
411 |
arr2(iiv(nrgc)+ii,jjv(nrgc)+jj,t) = label
|
|
|
412 |
nrg = nrg + 1
|
|
|
413 |
iiv(nrg) = iiv(nrgc)+ii
|
|
|
414 |
jjv(nrg) = jjv(nrgc)+jj
|
|
|
415 |
|
|
|
416 |
endif
|
|
|
417 |
|
|
|
418 |
enddo
|
|
|
419 |
enddo
|
|
|
420 |
|
|
|
421 |
nrgc = nrgc + 1
|
|
|
422 |
|
|
|
423 |
enddo
|
|
|
424 |
|
|
|
425 |
|
|
|
426 |
label = label + 1
|
|
|
427 |
|
|
|
428 |
endif
|
|
|
429 |
|
|
|
430 |
enddo
|
|
|
431 |
enddo
|
|
|
432 |
enddo
|
|
|
433 |
|
|
|
434 |
|
|
|
435 |
! Define temporal overlapping
|
|
|
436 |
! --------------------------------------------------------------
|
|
|
437 |
|
|
|
438 |
print*, '-->> overlapping'
|
|
|
439 |
|
|
|
440 |
do t = 1,nTimes
|
|
|
441 |
do ii = 1,int(maxval(arr2(:,:,t))) ! loop over the number of individual contours
|
|
|
442 |
|
|
|
443 |
areacon = 0.
|
|
|
444 |
areaover = 0.
|
|
|
445 |
fraction = 0.
|
|
|
446 |
|
|
|
447 |
do i = 1,nLong
|
|
|
448 |
do j = 1,nLats
|
|
|
449 |
|
|
|
450 |
if ( ( arr2(i,j,t).eq.ii) ) then
|
|
|
451 |
areacon = areacon+(111*(111*cos(2*3.14159/360*j)))
|
|
|
452 |
endif
|
|
|
453 |
|
|
|
454 |
if ( ( arr2(i,j,t).eq.ii).and.(arr2(i,j,t+1).ge.1) ) then
|
|
|
455 |
areaover = areaover+(111*(111*cos(2*3.14159/360*j)))
|
|
|
456 |
endif
|
|
|
457 |
|
|
|
458 |
enddo
|
|
|
459 |
enddo
|
|
|
460 |
|
|
|
461 |
fraction = 1 / areacon * areaover
|
|
|
462 |
!print*, ii, int(maxval(arr2(:,:,t))), fraction
|
|
|
463 |
|
|
|
464 |
do i = 1,nLong
|
|
|
465 |
do j = 1,nLats
|
|
|
466 |
if ( (fraction.lt.overlap).and.(arr2(i,j,t).eq.ii) ) then
|
|
|
467 |
arr2(i,j,t) = 0.
|
|
|
468 |
endif
|
|
|
469 |
enddo
|
|
|
470 |
enddo
|
|
|
471 |
|
|
|
472 |
enddo
|
|
|
473 |
enddo
|
|
|
474 |
|
|
|
475 |
|
|
|
476 |
! Identify individual contour areas (3D including time)
|
|
|
477 |
! --------------------------------------------------------------
|
|
|
478 |
|
|
|
479 |
print*, '-->> identify 3D contours'
|
|
|
480 |
|
|
|
481 |
arr(:,:,:) = arr2(:,:,:)
|
|
|
482 |
|
|
|
483 |
do t = 1,nTimes
|
|
|
484 |
do j = 1,nLats
|
|
|
485 |
do i = 1,nLong
|
|
|
486 |
|
|
|
487 |
if ( arr(i,j,t).ge.1 ) then
|
|
|
488 |
arr(i,j,t) = 1
|
|
|
489 |
endif
|
|
|
490 |
|
|
|
491 |
enddo
|
|
|
492 |
enddo
|
|
|
493 |
enddo
|
|
|
494 |
|
|
|
495 |
arr2(:,:,:) = 0 ! set arr2 to zero
|
|
|
496 |
label = 1 ! begin labeling with 1
|
|
|
497 |
|
|
|
498 |
do t = 1,nTimes
|
|
|
499 |
do j = 1,nLats
|
|
|
500 |
do i = 1,nLong
|
|
|
501 |
|
|
|
502 |
if ( (arr(i,j,t).eq.1).and.(arr2(i,j,t).lt.1) ) then
|
|
|
503 |
|
|
|
504 |
arr2(i,j,t) = label ! first identified grid point in countour
|
|
|
505 |
nrg = 1 ! number of grid points
|
|
|
506 |
nrgc = 1 ! number of grid points counter
|
|
|
507 |
iiv(nrgc) = i ! x-dir coordinates within contour
|
|
|
508 |
jjv(nrgc) = j ! y-dir coordinates within contour
|
|
|
509 |
ttv(nrgc) = t ! t-dir coordinates within contour
|
|
|
510 |
ttbegin = t ! genesis time
|
|
|
511 |
|
|
|
512 |
! print*, i,j,t,label
|
|
|
513 |
|
|
|
514 |
do while ( nrgc.le.nrg )
|
|
|
515 |
|
|
|
516 |
do ii=-1,1
|
|
|
517 |
do jj=-1,1
|
|
|
518 |
do tt=-1,1
|
|
|
519 |
|
|
|
520 |
if ( (arr(iiv(nrgc)+ii,jjv(nrgc)+jj,ttv(nrgc)+tt).eq.1).and. &
|
|
|
521 |
(arr2(iiv(nrgc)+ii,jjv(nrgc)+jj,ttv(nrgc)+tt).ne.label) ) then
|
|
|
522 |
|
|
|
523 |
arr2(iiv(nrgc)+ii,jjv(nrgc)+jj,ttv(nrgc)+tt) = label
|
|
|
524 |
nrg = nrg + 1
|
|
|
525 |
iiv(nrg) = iiv(nrgc)+ii
|
|
|
526 |
jjv(nrg) = jjv(nrgc)+jj
|
|
|
527 |
ttv(nrg) = ttv(nrgc)+tt
|
|
|
528 |
|
|
|
529 |
! get time of lysis
|
|
|
530 |
if (ttv(nrg).gt.ttend) then
|
|
|
531 |
ttend = ttend + 1
|
|
|
532 |
endif
|
|
|
533 |
|
|
|
534 |
endif
|
|
|
535 |
|
|
|
536 |
enddo
|
|
|
537 |
enddo
|
|
|
538 |
enddo
|
|
|
539 |
|
|
|
540 |
! print*, iiv(nrg),jjv(nrg),ttv(nrg), label
|
|
|
541 |
! print*, nrg, nrgc, ttv(nrgc)
|
|
|
542 |
! if (nrgc.gt.20) stop
|
|
|
543 |
|
|
|
544 |
nrgc = nrgc + 1
|
|
|
545 |
|
|
|
546 |
enddo
|
|
|
547 |
|
|
|
548 |
print*, label, ttbegin, ttend,ttend-ttbegin
|
|
|
549 |
label = label + 1
|
|
|
550 |
|
|
|
551 |
|
|
|
552 |
endif
|
|
|
553 |
|
|
|
554 |
enddo
|
|
|
555 |
enddo
|
|
|
556 |
enddo
|
|
|
557 |
|
|
|
558 |
|
|
|
559 |
if ( verbose.eq.1 ) print*, ' -> number of individual contours: ', label-1
|
|
|
560 |
|
|
|
561 |
! Temporal persistence
|
|
|
562 |
! --------------------------------------------------------------
|
|
|
563 |
|
|
|
564 |
print*, '-->> temporal persistence'
|
|
|
565 |
|
|
|
566 |
do ii = 1,label
|
|
|
567 |
counter = 0
|
|
|
568 |
do t = 1,nTimes
|
|
|
569 |
do j = 1,nLats
|
|
|
570 |
do i = 1,nLong
|
|
|
571 |
|
|
|
572 |
if ( arr2(i,j,t).eq.ii) then
|
|
|
573 |
counter = counter + 1
|
|
|
574 |
goto 234
|
|
|
575 |
endif
|
|
|
576 |
|
|
|
577 |
enddo
|
|
|
578 |
enddo
|
|
|
579 |
234 continue
|
|
|
580 |
enddo
|
|
|
581 |
|
|
|
582 |
do t = 1,nTimes
|
|
|
583 |
do j = 1,nLats
|
|
|
584 |
do i = 1,nLong
|
|
|
585 |
|
|
|
586 |
if ( (counter.lt.persistence ).and.(arr2(i,j,t).eq.ii) ) then
|
|
|
587 |
arr2(i,j,t) = 0.
|
|
|
588 |
endif
|
|
|
589 |
|
|
|
590 |
enddo
|
|
|
591 |
enddo
|
|
|
592 |
enddo
|
|
|
593 |
|
|
|
594 |
enddo
|
|
|
595 |
|
|
|
596 |
! get contour information
|
|
|
597 |
! --------------------------------------------------------------
|
|
|
598 |
|
|
|
599 |
print*, '-->> get contour information'
|
|
|
600 |
|
|
|
601 |
! number of individual contours
|
|
|
602 |
! length of individual contours
|
|
|
603 |
! mean area size of individual contours
|
|
|
604 |
! genesis/lysis date
|
|
|
605 |
! genesis/lysis area at specific date
|
|
|
606 |
|
|
|
607 |
nrcontours = 0
|
|
|
608 |
do t = 1,nTimes
|
|
|
609 |
do j = 1,nLats
|
|
|
610 |
do i = 1,nLong
|
|
|
611 |
|
|
|
612 |
if ( arr2(i,j,t).gt.nrcontours ) then
|
|
|
613 |
nrcontours = nrcontours + 1
|
|
|
614 |
endif
|
|
|
615 |
|
|
|
616 |
enddo
|
|
|
617 |
enddo
|
|
|
618 |
enddo
|
|
|
619 |
|
|
|
620 |
print*, ' -> number of tracked contours: ', nrcontours
|
|
|
621 |
|
|
|
622 |
|
|
|
623 |
|
|
|
624 |
! change output array to a 0/1 array
|
|
|
625 |
! --------------------------------------------------------------
|
|
|
626 |
|
|
|
627 |
if ( outarr.eq.1 ) then
|
|
|
628 |
do t = 1,nTimes
|
|
|
629 |
do j = 1,nLats
|
|
|
630 |
do i = 1,nLong
|
|
|
631 |
|
|
|
632 |
if ( arr2(i,j,t).gt.0 ) then
|
|
|
633 |
arr2(i,j,t) = 1.
|
|
|
634 |
endif
|
|
|
635 |
enddo
|
|
|
636 |
enddo
|
|
|
637 |
enddo
|
|
|
638 |
endif
|
|
|
639 |
|
|
|
640 |
|
|
|
641 |
arr = arr2
|
|
|
642 |
|
|
|
643 |
11 continue
|
|
|
644 |
|
|
|
645 |
|
|
|
646 |
! --------------------------------------------------------------
|
|
|
647 |
! write CF-netCDF file
|
|
|
648 |
! --------------------------------------------------------------
|
|
|
649 |
|
|
|
650 |
call date_and_time (values=time_array)
|
|
|
651 |
write(*,100), "-> Write ", trim(outfilename), time_array(5), ':', time_array(6), ':', time_array(7)
|
|
|
652 |
|
|
|
653 |
! definitions
|
|
|
654 |
! --------------------------------------------------------------
|
|
|
655 |
|
|
|
656 |
cfoutinstit = cfinstit
|
|
|
657 |
cfouttitle = 'contrack '//trim(contrackversion)
|
|
|
658 |
cfoutsource = cfsource
|
|
|
659 |
write(cfoutcomment, 101) 'contrack is based upon the following input file attributes: ', &
|
|
|
660 |
trim(cfcomment), &
|
|
|
661 |
' -->> Contrack specifications:: ',&
|
|
|
662 |
'contours identified that are -', trim(gorl), '- threshold value, ', &
|
|
|
663 |
'threshold value for contour:', threshold, &
|
|
|
664 |
', overlapping fraction:', overlap, &
|
|
|
665 |
', persistence time steps:', persistence, &
|
|
|
666 |
', anomalies calculated by subtracting meridional mean [1] or ', &
|
|
|
667 |
'from the input file directly [0]: ', calcmeranom
|
|
|
668 |
|
|
|
669 |
101 format(A,A,A,A,A,A,A,F8.3,A,F7.3,A,I5,A,A,I3)
|
|
|
670 |
|
|
|
671 |
! start writing
|
|
|
672 |
! ----------------------------------------------------------------
|
|
|
673 |
|
|
|
674 |
! Initially set error to indicate no errors.
|
|
|
675 |
status = 0
|
|
|
676 |
|
|
|
677 |
! create the netCDF file
|
|
|
678 |
status = nf90_create(trim(outfilename), NF90_CLOBBER, ncID)
|
|
|
679 |
! IF (ierr.NE.0) GOTO 920
|
|
|
680 |
|
|
|
681 |
! Dimensions -----------------------------------------------------
|
|
|
682 |
status=nf90_def_dim(ncID,'longitude',nLong,LonDimID)
|
|
|
683 |
status=nf90_def_dim(ncID,'latitude',nLats,LatDimID)
|
|
|
684 |
status=nf90_def_dim(ncID,'time',nf90_unlimited, TimeDimID)
|
|
|
685 |
|
|
|
686 |
! Variables ------------------------------------------------------
|
|
|
687 |
status = nf90_def_var(ncID,'longitude',NF90_FLOAT,(/ LonDimID /),varLonID)
|
|
|
688 |
status = nf90_put_att(ncID, varLonID, "standard_name", "longitude")
|
|
|
689 |
status = nf90_put_att(ncID, varLonID, "units", "degree_east")
|
|
|
690 |
|
|
|
691 |
status = nf90_def_var(ncID,'latitude',NF90_FLOAT,(/ LatDimID /),varLatID)
|
|
|
692 |
status = nf90_put_att(ncID, varLatID, "standard_name", "latitude")
|
|
|
693 |
status = nf90_put_att(ncID, varLatID, "units", "degree_north")
|
|
|
694 |
|
|
|
695 |
status = nf90_def_var(ncID,'time',NF90_FLOAT, (/ TimeDimID /), varTimeID)
|
|
|
696 |
status = nf90_put_att(ncID, varTimeID, "axis", "T")
|
|
|
697 |
status = nf90_put_att(ncID, varTimeID, "calendar", "standard")
|
|
|
698 |
status = nf90_put_att(ncID, varTimeID, "long_name", "time")
|
|
|
699 |
status = nf90_put_att(ncID, varTimeID, "units", "hours since &
|
|
|
700 |
1950-01-01 00:OO UTC")
|
|
|
701 |
|
|
|
702 |
! Global Attributes -----------------------------------------------
|
|
|
703 |
status = nf90_put_att(ncID, NF90_GLOBAL, 'Conventions', 'CF-1.0')
|
|
|
704 |
status = nf90_put_att(ncID, NF90_GLOBAL, 'title', cfouttitle)
|
|
|
705 |
status = nf90_put_att(ncID, NF90_GLOBAL, 'source', cfoutsource)
|
|
|
706 |
status = nf90_put_att(ncID, NF90_GLOBAL, 'institution', cfoutinstit)
|
|
|
707 |
status = nf90_put_att(ncID, NF90_GLOBAL, 'comment', cfoutcomment)
|
|
|
708 |
|
|
|
709 |
|
|
|
710 |
! Specific variable -----------------------------------------------
|
|
|
711 |
status = nf90_def_var(ncID,trim(outvarname),NF90_FLOAT,&
|
|
|
712 |
(/ LonDimID, LatDimID, varTimeID /),varPVID)
|
|
|
713 |
!status = nf90_def_var(ncID,trim(outvarname),NF90_FLOAT,&
|
|
|
714 |
! (/ LatDimID, varTimeID /),varPVID)
|
|
|
715 |
status = nf90_put_att(ncID, varPVID, "standard_name",trim(outstandvarname))
|
|
|
716 |
status = nf90_put_att(ncID, varPVID, "units", trim(outvarunit))
|
|
|
717 |
status = nf90_put_att(ncID, varPVID, '_FillValue', -999.99)
|
|
|
718 |
|
|
|
719 |
! END variable definitions.
|
|
|
720 |
|
|
|
721 |
status = nf90_enddef(ncID)
|
|
|
722 |
IF (status.GT.0) THEN
|
|
|
723 |
print*, 'An error occurred while attempting to ', &
|
|
|
724 |
'finish definition mode.'
|
|
|
725 |
!GOTO 920
|
|
|
726 |
ENDIF
|
|
|
727 |
|
|
|
728 |
! write DATA
|
|
|
729 |
! -------------------------------------------------------------------
|
|
|
730 |
status = nf90_put_var(ncID,varLonID,longitude)
|
|
|
731 |
status = nf90_put_var(ncID,varLatID,latitude)
|
|
|
732 |
!status = nf90_put_var(ncID,varTimeID, times)
|
|
|
733 |
status = nf90_put_var(ncID,varTimeID, &
|
|
|
734 |
times((persistence+1):(nTimes-persistence)))
|
|
|
735 |
|
|
|
736 |
|
|
|
737 |
! Write block
|
|
|
738 |
!status = nf90_put_var(ncID,varPVID, arr(:,:,:))
|
|
|
739 |
status = nf90_put_var(ncID,varPVID, &
|
|
|
740 |
arr(:,:,(persistence+1):(nTimes-persistence)))
|
|
|
741 |
|
|
|
742 |
status = nf90_close(ncID)
|
|
|
743 |
IF (status.NE.0) THEN
|
|
|
744 |
WRITE(0,*) trim(nf90_strerror(status))
|
|
|
745 |
WRITE(0,*) 'An error occurred while attempting to ', &
|
|
|
746 |
'close the netcdf file.'
|
|
|
747 |
WRITE(0,*) 'in clscdf_CF'
|
|
|
748 |
ENDIF
|
|
|
749 |
|
|
|
750 |
close(ncID)
|
|
|
751 |
|
|
|
752 |
|
|
|
753 |
END
|
|
|
754 |
|
|
|
755 |
|