Skip to content

Commit 5ee48c8

Browse files
authored
Merge pull request #671 from mandli/add-scaling-storm
Add Scaling Parameters to Data-Driven Storms
2 parents 921c376 + 50215f8 commit 5ee48c8

File tree

4 files changed

+133
-224
lines changed

4 files changed

+133
-224
lines changed

src/2d/shallow/surge/data_storm_module.f90

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
!
77
! ==============================================================================
88
! Copyright (C) Clawpack Developers 2017
9-
! Distributed under the terms of the Berkeley Software Distribution (BSD)
9+
! Distributed under the terms of the Berkeley Software Distribution (BSD)
1010
! license
1111
! http://www.opensource.org/licenses/
1212
! ==============================================================================
1313
module data_storm_module
14-
14+
1515
implicit none
1616
save
1717

@@ -45,6 +45,9 @@ module data_storm_module
4545

4646
integer, private :: last_storm_index
4747

48+
! Run-time storm modification settings
49+
real(kind=8) :: wind_scaling, pressure_scaling
50+
4851
! Ramping settings
4952
integer :: window_type
5053
real(kind=8) :: window(4), ramp_width
@@ -63,7 +66,7 @@ module data_storm_module
6366
! Initializes the storm type for an HWRF type data derived storm that is
6467
! saved as a netcdf format
6568
subroutine set_storm(storm_data_path, storm, storm_spec_type, log_unit)
66-
69+
6770
#ifdef NETCDF
6871
use netcdf
6972
#endif
@@ -86,7 +89,7 @@ subroutine set_storm(storm_data_path, storm, storm_spec_type, log_unit)
8689

8790
! ASCII
8891
real(kind=8) :: sw_lon, sw_lat, dx, dy
89-
92+
9093
! NetCDF
9194
integer :: nc_fid, num_dims, num_vars, var_id
9295
character(len=16) :: name, dim_names(3), var_names(3)
@@ -105,12 +108,14 @@ subroutine set_storm(storm_data_path, storm, storm_spec_type, log_unit)
105108
read(data_unit, "(a)") storm%time_offset
106109
read(data_unit, "(i2)") file_format
107110
read(data_unit, "(i2)") num_data_files
111+
read(data_unit, *) wind_scaling, pressure_scaling
108112
read(data_unit, "(i2)") window_type
109113
read(data_unit, *) ramp_width
110114

111115
write(log_unit, "('time_offset = ',a)") storm%time_offset
112-
write(log_unit, "('Format = ',i2)") file_format
113-
write(log_unit, "('Num files = ',i2)") num_data_files
116+
write(log_unit, "('format = ',i2)") file_format
117+
write(log_unit, "('num files = ',i2)") num_data_files
118+
write(log_unit, "('scaling = ',2d16.8)") wind_scaling, pressure_scaling
114119
write(log_unit, "('window_type = ',i2)") window_type
115120
write(log_unit, "('ramp_width = ',d16.8)") ramp_width
116121

@@ -121,7 +126,7 @@ subroutine set_storm(storm_data_path, storm, storm_spec_type, log_unit)
121126
read(data_unit, *)
122127
end if
123128
read(data_unit, *)
124-
129+
125130
if (DEBUG) then
126131
print "('time_offset = ',a)", storm%time_offset
127132
print "('Format = ',i2)", file_format
@@ -201,13 +206,13 @@ subroutine set_storm(storm_data_path, storm, storm_spec_type, log_unit)
201206
storm, seconds_from_epoch(time(:, 1)))
202207

203208
case(2)
204-
#ifdef NETCDF
209+
#ifdef NETCDF
205210
! Open file and get file ID
206211
! :TODO: Only read in times that are between t0 and tfinal
207212
print *, "Reading storm NetCDF file ", storm%paths(1)
208213
call check_netcdf_error(nf90_open(storm%paths(1), nf90_nowrite, nc_fid))
209214
! Check dim/var number
210-
call check_netcdf_error(nf90_inquire(nc_fid, num_dims, num_vars))
215+
call check_netcdf_error(nf90_inquire(nc_fid, num_dims, num_vars))
211216
if (num_dims /= 3 .and. num_vars /= 3) then
212217
print *, "Invalid number of dimensions/variables."
213218
print *, " num_dims = ", num_dims
@@ -230,7 +235,7 @@ subroutine set_storm(storm_data_path, storm, storm_spec_type, log_unit)
230235
allocate(storm%longitude(mx))
231236
allocate(storm%latitude(my))
232237
allocate(storm%time(mt))
233-
238+
234239
write(log_unit, *) "Storm header info:"
235240
write(log_unit, "(' mx,mx,mt = ', 3i4)") mx, my, mt
236241

@@ -300,7 +305,7 @@ end subroutine set_storm
300305
! data structure
301306
subroutine read_OWI_ASCII_header(pressure_file, mx, my, mt, swlon, swlat, &
302307
dy, dx)
303-
308+
304309
use utility_module, only: seconds_from_epoch
305310

306311
implicit none
@@ -321,20 +326,20 @@ subroutine read_OWI_ASCII_header(pressure_file, mx, my, mt, swlon, swlat, &
321326
"i4,i2,i2,i2,i2)"
322327
character(len=*), parameter :: time_info_format = &
323328
"(t69,i4,i2,i2,i2,i2)"
324-
329+
325330
! Local
326331
integer, parameter :: OWI_unit = 156
327332
integer :: i, time(5, 2), total_time, dt
328333

329334

330335
! Read in start and end dates of file from first header line
331336
open(OWI_unit, file=pressure_file, status='old', action='read')
332-
337+
333338
! Total number of time in seconds of the dataset
334-
read(OWI_unit, header_format) time(1:4, 1), time(1:4, 2)
339+
read(OWI_unit, header_format) time(1:4, 1), time(1:4, 2)
335340
total_time = seconds_from_epoch(time(1:4, 2)) &
336341
- seconds_from_epoch(time(1:4, 1))
337-
342+
338343
! Read second header from file to obtain array sizes and first timestep
339344
read(OWI_unit, full_info_format) my, mx, dx, dy, swlat, swlon, time(:, 1)
340345

@@ -343,32 +348,32 @@ subroutine read_OWI_ASCII_header(pressure_file, mx, my, mt, swlon, swlat, &
343348
read(OWI_unit, *)
344349
end do
345350
read(OWI_unit, time_info_format) time(:, 2)
346-
351+
347352
close(OWI_unit)
348353

349354
dt = seconds_from_epoch(time(:, 2)) - seconds_from_epoch(time(:, 1))
350355
mt = (total_time / dt) + 1
351356

352-
end subroutine read_OWI_ASCII_header
353-
357+
end subroutine read_OWI_ASCII_header
358+
354359

355360
! === read_OWI_ASCII =======================================================
356361
! reads the data files and fills out the storm object and it's dataarrays
357362
subroutine read_OWI_ASCII(wind_file, pressure_file, mx, my, mt, &
358363
swlat, swlon, &
359364
dx, dy, storm, &
360365
seconds_from_offset)
361-
366+
362367
use utility_module, only: seconds_from_epoch
363-
368+
364369
implicit none
365-
370+
366371
! Input arguments
367372
type(data_storm_type) :: storm
368373
character(len=*), intent(in) :: wind_file, pressure_file
369-
integer, intent(in) :: my, mx, mt, seconds_from_offset
374+
integer, intent(in) :: my, mx, mt, seconds_from_offset
370375
real(kind=8), intent(in) :: swlat, swlon, dx, dy
371-
376+
372377
! Local storage
373378
integer, parameter :: wind_unit = 700, pressure_unit = 800
374379
integer :: i, j, n, time(5)
@@ -380,17 +385,17 @@ subroutine read_OWI_ASCII(wind_file, pressure_file, mx, my, mt, &
380385
! Skip file headers
381386
read(wind_unit, *)
382387
read(pressure_unit, *)
383-
! Loop over all timesteps
388+
! Loop over all timesteps
384389
do n = 1, mt
385390
! Read each time from the next array
386391
read(wind_unit, '(t69, i4,i2,i2,i2, i2)') time
387392
storm%time(n) = seconds_from_epoch(time) - seconds_from_offset
388393

389394
read(wind_unit, '(8f10.0)') ((storm%wind_u(i,j, n),i=1,mx),j=1,my)
390395
read(wind_unit, '(8f10.0)') ((storm%wind_v(i,j, n),i=1,mx),j=1,my)
391-
396+
392397
read(pressure_unit, *) ! Skip header line since we have it from above
393-
read(pressure_unit, '(8f10.0)') ((storm%pressure(i,j, n),i=1,mx),j=1,my)
398+
read(pressure_unit, '(8f10.0)') ((storm%pressure(i,j, n),i=1,mx),j=1,my)
394399
! Convert from Pa to hPa
395400
storm%pressure(:,:,n) = storm%pressure(:,:,n) * 100.0
396401
end do
@@ -405,7 +410,7 @@ subroutine read_OWI_ASCII(wind_file, pressure_file, mx, my, mt, &
405410
do j = 1, mx
406411
storm%longitude(j) = swlon + j * dx
407412
end do
408-
413+
409414
end subroutine read_OWI_ASCII
410415

411416

@@ -575,9 +580,11 @@ subroutine set_data_fields(maux, mbc, mx, my, xlower, ylower, &
575580
ramp = 0.d0
576581
end if
577582
aux(pressure_index,i,j) = &
578-
Pa + (aux(pressure_index,i,j) - Pa) * ramp
583+
Pa + (aux(pressure_index,i,j) - Pa) &
584+
* ramp * pressure_scaling
579585
aux(wind_index:wind_index+1,i,j) = &
580-
aux(wind_index:wind_index+1,i,j) * ramp
586+
aux(wind_index:wind_index+1,i,j) &
587+
* ramp * wind_scaling
581588

582589
else
583590
aux(wind_index:wind_index + 1, i, j) = 0.d0
@@ -630,7 +637,7 @@ end subroutine set_netcdf_fields
630637
! === interp_time ==========================================================
631638
! Interpolate storm arrays to get current time
632639
subroutine interp_time(storm, t, wind_u, wind_v, pressure)
633-
640+
634641
implicit none
635642
! Subroutine IO
636643
type(data_storm_type), intent(in) :: storm
@@ -688,9 +695,9 @@ end subroutine interp_time
688695
! === spatial_intrp ========================================================
689696
! Spatially interpolate interp_array onto (x,y) point
690697
pure real(kind=8) function spatial_interp(storm, x, y, interp_array) result(value)
691-
698+
692699
implicit none
693-
700+
694701
! Subroutine I/O
695702
type(data_storm_type), intent(in) :: storm
696703
real(kind=8), intent(in) :: x, y, interp_array(size(storm%longitude), &
@@ -731,7 +738,7 @@ pure real(kind=8) function spatial_interp(storm, x, y, interp_array) result(valu
731738
endif
732739

733740
value = interp_array(xidx_low, yidx_low)
734-
741+
735742
else
736743
call find_nearest(storm, x - storm_dx, y - storm_dy, llon, llat, xidx_low, yidx_low)
737744
call find_nearest(storm, x + storm_dx, y + storm_dy, ulon, ulat, xidx_high, yidx_high)
@@ -740,15 +747,15 @@ pure real(kind=8) function spatial_interp(storm, x, y, interp_array) result(valu
740747
q12 = interp_array(xidx_low, yidx_high)
741748
q21 = interp_array(xidx_high, yidx_low)
742749
q22 = interp_array(xidx_high, yidx_high)
743-
750+
744751
! Calculate the value at the center of the box using bilinear interpolation
745752
value = (q11 * (ulon - x) * (ulat - y) + &
746753
q21 * (x - llon) * (ulat - y) + &
747754
q12 * (ulon - x) * (y - llat) + &
748755
q22 * (x - llon) * (y - llat)) / ((ulon - llon) * (ulat - llat) + 0.00)
749-
756+
750757
end if
751-
758+
752759
end function spatial_interp
753760

754761
! === find_nearest =========================================================
@@ -768,4 +775,4 @@ pure subroutine find_nearest(storm, x, y, lon, lat, xidx, yidx)
768775
lat = storm%latitude(yidx)
769776
end subroutine find_nearest
770777

771-
end module data_storm_module
778+
end module data_storm_module

src/python/geoclaw/data.py

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"""
3030

3131
import os
32+
from pathlib import Path
3233
import numpy as np
3334
import warnings
3435

@@ -575,6 +576,43 @@ def __init__(self):
575576
self.add_attribute('storm_specification_type', 0) # Type of parameterized storm
576577
self.add_attribute("storm_file", None) # File containing data
577578

579+
def read(self, path: Path=Path("surge.data"), force: bool=False):
580+
"""Read surge data file"""
581+
582+
with Path(path).open() as data_file:
583+
# Header
584+
data_file.readline()
585+
data_file.readline()
586+
data_file.readline()
587+
data_file.readline()
588+
data_file.readline()
589+
data_file.readline()
590+
591+
self.wind_forcing = bool(data_file.readline())
592+
self.drag_law = int(data_file.readline().split("=:")[0])
593+
self.pressure_forcing = bool(data_file.readline().split("=:")[0])
594+
self.rotation_override = data_file.readline().split("=:")[0]
595+
data_file.readline()
596+
597+
self.wind_index = int(data_file.readline().split("=:")[0]) - 1
598+
self.pressure_index = int(data_file.readline().split("=:")[0]) - 1
599+
self.display_landfall_time = bool(data_file.readline().split("=:")[0])
600+
data_file.readline()
601+
602+
# AMR parameters
603+
self.wind_refine = self._parse_value(data_file.readline())
604+
self.R_refine = self._parse_value(data_file.readline())
605+
data_file.readline()
606+
607+
# Storm specification
608+
self.storm_specification_type = int(data_file.readline().split("=:")[0])
609+
line = data_file.readline().split("=:")[0]
610+
if line[0] == "'":
611+
self.storm_file = line.strip()[1:-1]
612+
else:
613+
raise IOError("Error reading storm file name.")
614+
615+
578616
def write(self, out_file='surge.data', data_source="setrun.py"):
579617
"""Write out the data file to the path given"""
580618

@@ -697,21 +735,14 @@ def read(self, path="friction.data", force=False):
697735
# Regions
698736
self.friction_regions = []
699737
for n in range(num_regions):
700-
lower = self._convert_line(data_file.readline())
701-
upper = self._convert_line(data_file.readline())
702-
depths = self._convert_line(data_file.readline())
703-
coeff = self._convert_line(data_file.readline())
738+
lower = self._parse_value(data_file.readline())
739+
upper = self._parse_value(data_file.readline())
740+
depths = self._parse_value(data_file.readline())
741+
coeff = self._parse_value(data_file.readline())
704742
self.friction_regions.append([lower, upper, depths, coeff])
705743
data_file.readline()
706744
self.friction_files = [] # Is not supported
707745

708-
def _convert_line(self, line):
709-
values = []
710-
for value in line.split("=:")[0].split(" "):
711-
if len(value) > 1:
712-
values.append(float(value))
713-
return values
714-
715746

716747
def write(self, out_file='friction.data', data_source='setrun.py'):
717748

@@ -911,4 +942,3 @@ def write(self,out_file='bouss.data',data_source='setrun.py'):
911942
self.data_write('bouss_min_depth')
912943

913944
self.close_data_file()
914-

0 commit comments

Comments
 (0)