-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathCombineRasters.F90
450 lines (352 loc) · 12.5 KB
/
CombineRasters.F90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
! $Id:
#include "Raster.h"
program mkOverlaySimple
use LogRectRasterizeMod
use MAPL_SortMod
use MAPL_HashMod
! Overlay atmosphere, land, and ocean rasters, creating a .idx file.
! The ocean raster should be defined everywhere, or at least, everywhere
! that the land Raster is non zero. The land raster uses the actual
! continental outlines to define land and has zero else where.
! The land and ocean files produce a surface raster by masking the
! ocean with the land. The resulting Raster is the overlaid with the
! atmosphere producing a unique index for each pair of atmosphere and
! surface rstare values. This pair together with the assigned index
! is written in the .idx file. This file is ascii and is sorted by
! surface types. This puts the ocean points first, since they are given
! negative values.
implicit none
integer, parameter :: RSTUNIT1 = 20
integer, parameter :: RSTUNIT2 = 21
integer, parameter :: TILUNIT1 = 22
integer, parameter :: TILUNIT2 = 23
REAL_, parameter :: PI = RASTER_PI
integer :: IARGC
integer :: nxt, argl, fill
integer :: i, j, k, l, ip
integer :: STATUS, i1, i2, nvars, rvars
integer :: ip1, ip2, nf1, nf2
integer :: nx1, nx2, ny1, ny2, nx, ny
integer :: maxtiles, hash
integer :: count0,count1,count_rate
integer, allocatable :: RST1(:,:)
integer, allocatable :: RST2(: )
integer, allocatable :: iTable(:,:)
REAL_ , allocatable :: Table1(:,:)
REAL_ , allocatable :: Table2(:,:)
REAL_ , allocatable :: rTable(:,:)
REAL_ , allocatable :: cc(:), ss(:)
REAL_ :: dx, dy, area, xc, yc, d2r, vv(4)
REAL_ :: lats, lons, da
logical :: DoZip
logical :: Verb
logical :: found
logical :: Merge
character*4 :: tildir, rstdir
character*1 :: Opt
character*128 :: arg
character*128 :: Overlay=''
character*128 :: GridName1, GridName2
character*128 :: Grid1, Grid2
character*128 :: TilFile, RstFile
character*128 :: &
Usage = "CombineRasters -v -h -z -t MT -g GF -f TYPE BOTTOMRASTER TOPRASTER"
integer :: Pix1, Pix2
! Argument defaults
DoZip = .false. ! No zipping
Verb = .false. ! Run quiet
fill = -1 ! Fill all
tildir='til/' ! Write in current dir
rstdir='rst/' ! Write in current dir
maxtiles=4000000
I = iargc()
if(I < 2 .or. I > 11) then
print *, trim(Usage)
call exit(1)
end if
nxt = 1
call getarg(nxt,arg)
do while(arg(1:1)=='-')
opt=arg(2:2)
argl = len(trim(arg))
if(argl==2) then
if(scan(opt,'zvh')==0) then
nxt = nxt + 1
call getarg(nxt,arg)
end if
else
arg = arg(3:)
end if
select case (opt)
case ('v')
Verb = .true.
case ('z')
DoZip = .true.
case ('h')
tildir = ''
rstdir = ''
case ('f')
read(arg,*) fill
case ('t')
read(arg,*) maxtiles
case ('g')
Overlay = trim(arg)
case default
print *, trim(Usage)
call exit(1)
end select
nxt = nxt + 1
call getarg(nxt,arg)
end do
Grid1 = ARG
nxt = nxt + 1
call getarg(nxt,arg)
Grid2 = ARG
Merge = fill/=-1
if(trim(Overlay)=='') then
if(Merge) then
Overlay = trim(Grid1)//"-"//adjustl(Grid2)
else
Overlay = trim(Grid1)//"_"//adjustl(Grid2)
end if
end if
if(DoZip) then
TilFile = trim(tildir)//trim(Overlay)//'.til.gz'
RstFile = trim(rstdir)//trim(Overlay)//'.rst.gz'
else
TilFile = trim(tildir)//trim(Overlay)//'.til'
RstFile = trim(rstdir)//trim(Overlay)//'.rst'
end if
! Input files:
open (TILUNIT1,file=trim(tildir)//trim(adjustl(Grid1))//'.til', &
form= 'formatted', status='old')
open (TILUNIT2,file=trim(tildir)//trim(adjustl(Grid2))//'.til', &
form= 'formatted', status='old')
open (RSTUNIT1,file=trim(rstdir)//trim(adjustl(Grid1))//'.rst', &
form= 'unformatted', convert='little_endian', status='old')
open (RSTUNIT2,file=trim(rstdir)//trim(adjustl(Grid2))//'.rst', &
form= 'unformatted', convert='little_endian', status='old')
call system_clock(count0,count_rate)
! Read raster sizes info from .til headers
read(TILUNIT1,*) ip1, nf1, nx1, ny1
read(TILUNIT2,*) ip2, nf2, nx, ny
! Both grids must be based on same shape rasters
_ASSERT(NX1==NX,'needs informative message')
_ASSERT(NY1==NY,'needs informative message')
! allocate space
if(Merge) then
rvars = 5
nvars = 3
else
rvars = 6
nvars = 7
endif
allocate(iTable(0:nvars,maxtiles),stat=status)
VERIFY_(STATUS)
allocate(rTable(1:rvars,maxtiles),stat=status)
VERIFY_(STATUS)
allocate(rst1(nx,ny), stat=status)
VERIFY_(STATUS)
allocate(cc(nx),ss(nx), rst2(nx), stat=status)
VERIFY_(STATUS)
allocate(Table1(6,ip1), stat=status)
VERIFY_(STATUS)
allocate(Table2(6,ip2), stat=status)
VERIFY_(STATUS)
! The rasters cover the sphere in lat-lon
dx = 360._8/nx
dy = 180._8/ny
d2r = PI/180._8
! sine and cosine of raster longitudes
do i=1,nx
lons = d2r*(-180._8 + (i-0.5_8)*dx)
cc(i) = cos(lons)
ss(i) = sin(lons)
enddo
! Read input tables
read(TILUNIT1,*) k
read(TILUNIT1,*) Grid1
read(TILUNIT1,*) nx1
read(TILUNIT1,*) ny1
do j=2,k
read(TILUNIT1,*)
read(TILUNIT1,*)
read(TILUNIT1,*)
end do
if(Verb) print *, 'First input grid: ',trim(Grid1), ip1, nx1, ny1
read(TILUNIT2,*) k
read(TILUNIT2,*) Grid2
read(TILUNIT2,*) nx2
read(TILUNIT2,*) ny2
do j=2,k
read(TILUNIT2,*)
read(TILUNIT2,*)
read(TILUNIT2,*)
end do
if(Verb) print *, 'Second input grid: ',trim(Grid2), ip2, nx2, ny2
do k=1,ip1
read(TILUNIT1,*) Table1(1:2,k),lons,lons,Table1(3:6,k)
enddo
do k=1,ip2
read(TILUNIT2,*) Table2(1:2,k),lons,lons,Table2(3:6,k)
enddo
if(Verb) then
call system_clock(count1)
print *, 'Read Tables. Time = ', (count1-count0)/float(count_rate)
count0 = count1
end if
ip = 0
Hash = MAPL_HashCreate(8*1024)
if(Verb) write (6, '(A)', advance='NO') ' Started Overlay'
LATITUDES: do j=1,ny
lats = -90._8 + (j - 0.5_8)*dy
da = (sin(d2r*(lats+0.5*dy)) - &
sin(d2r*(lats-0.5*dy)) )*(dx*d2r)
vv(3) = da*lats
vv(4) = da
read(RSTUNIT1) Rst1(:,j)
read(RSTUNIT2) Rst2
LONGITUDES: do i=1,nx
vv(1) = da*ss(i)
vv(2) = da*cc(i)
Pix1 = Rst1(i,j)
Pix2 = Rst2(i)
! If it is an overlay or we are at the tile type of the first grid
! that is being overlayed during a merge, hash the tile indeces from
! the two grids. If it is a merge and we are at the tile type of the
! first grid that is being retained, hash it into a single pseudo bin
! of the second grid.
if(.not.Merge) then
k = MAPL_HashIncrement(Hash,Pix1,Pix2)
else if (nint(Table2(1,Pix2))==fill ) then
k = MAPL_HashIncrement(Hash,Pix1, 0)
else
k = MAPL_HashIncrement(Hash, 0,Pix2)
end if
found = k<=ip ! The grid indices were in hask
Rst1(i,j) = k
! Table variables
!
! iTable(0) :: Surface type
! iTable(1) :: tile count
! iTable(2) :: I_1 I of first grid
! iTable(3) :: J_1
! iTable(4) :: I_2 I of 2nd grid
! iTable(5) :: J_2
!
! rTable(1) :: sum of lons
! rTable(2) :: sum of lats
! rTable(3) :: area
! rTable(4) :: of first grid box area
! rTable(5) :: of 2nd grid box area
if(found) then ! Bump the counter and the lon, lat, and area sums
iTable( 1,k) = iTable( 1,k) + 1
if(.not.Merge) then
rTable(:4,k) = rTable(:4,k) + vv(:4)
else
rTable(:3,k) = rTable(:3,k) + vv(:3)
end if
else ! We have a new tile in the exchange grid
ip = ip + 1
if(ip>maxtiles) then
print *, "Exceeded maxtiles = ", maxtiles," at j= ", j, &
" ny=", ny, " i=", i, " nx=", nx
print *, "Use -t option to increase."
call exit(1)
end if
iTable(0 ,ip) = nint(Table2(1,Pix2))
iTable(1 ,ip) = 1
if(.not.Merge) then
rTable(:4,ip) = vv(:4)
else
rTable(:3,ip) = vv(:3)
end if
if(.not.Merge) then ! This is a normal overlay of two grids
iTable(2,ip) = nint(Table1(3,Pix1))
iTable(3,ip) = nint(Table1(4,Pix1))
rTable(5,ip) = Table1(2,Pix1)
iTable(4,ip) = nint(Table2(3,Pix2))
iTable(5,ip) = nint(Table2(4,Pix2))
rTable(6,ip) = Table2(2,Pix2)
iTable(6,ip) = nint(Table1(6,Pix1))
iTable(7,ip) = nint(Table2(6,Pix2))
elseif(nint(Table2(1,Pix2))==fill) then ! A use 1st grid area of a merge
iTable(2,ip) = nint(Table1(3,Pix1))
iTable(3,ip) = nint(Table1(4,Pix1))
rTable(4,ip) = Table1(2,Pix1)
rTable(5,ip) = Table1(2,Pix1)
else ! A retain 2nd grid area of a merge
iTable(2,ip) = nint(Table2(3,Pix2))
iTable(3,ip) = nint(Table2(4,Pix2))
rTable(4,ip) = Table2(2,Pix2)
rTable(5,ip) = Table2(2,Pix2)
end if
end if
end do LONGITUDES ! End raster I-loop
if(Verb) then
if(mod(j,200)==0) then
write (6, '(A)', advance='NO') '.'
end if
end if
enddo LATITUDES ! End raster J-loop
if(Verb) then
call system_clock(count1)
print *, "Found ",ip," unique tiles. Time = ", (count1-count0)/float(count_rate)
count0 = count1
end if
! Done with some space and with hash
! deallocate(Table1,Table2,Rst2,ss,cc,stat=STATUS)
VERIFY_(STATUS)
! call MAPL_HashDestroy(Hash)
! Compute proper longitude and latitude in degrees and compress
! the real table for WriteTiling.
if(Verb) print *, "Computing weighted lons and lats..."
do k=1,ip
rTable(1,k) = atan2(rTable(1,k),rTable(2,k))/d2r
if(rTable(4,k) < 1.e-15) then
rTable(2,k) = rTable(3,k)/(rTable(4,k) + 1.e-15)
else
rTable(2,k) = rTable(3,k)/rTable(4,k)
endif
rTable(3,k) = rTable(4,k)
rTable(4,k) = rTable(5,k)
end do
if(rvars==6) then
rTable(5,:ip) = rTable(6,:ip)
end if
! Sort table by the first grid type in descending order.
if(Verb) print *, "Sorting..."
call SortTiling(Rst1,rTable(:,:ip),iTable(:,:ip))
if(Verb) then
call system_clock(count1)
print *, "Done Sorting. Time = ", (count1-count0)/float(count_rate)
count0 = count1
end if
! Write .til and .rst files
if(Verb) print *, 'Writing til file...'
if(.not.Merge) then
call WriteTiling(TilFile,(/Grid1,Grid2/), (/nx1,nx2/),(/ny1,ny2/),(/ip1,ip2/), &
nx, ny, iTable(:,:ip),rTable(:5,:ip),Dozip, Verb)
else
call WriteTiling(TilFile,(/Overlay/),(/nx1/), (/ny1/), (/ip1/), &
nx, ny, iTable(:,:ip),rTable(:4,:ip),Dozip, Verb)
end if
if(Verb) then
call system_clock(count1)
print *, "Done Writing. Time = ", (count1-count0)/float(count_rate)
count0 = count1
end if
if(Verb) print *, 'Writing raster file...'
call WriteRaster(RstFile,Rst1,DoZip)
if(Verb) then
call system_clock(count1)
print *, "Done Wrting. Time = ", (count1-count0)/float(count_rate)
count0 = count1
end if
! Clean up
deallocate(Rst1, iTable, rTable)
! All done
if(Verb) print * , 'Terminated Normally'
call exit(0)
end program mkOverlaySimple
!===================================================================