Skip to content

Commit 95c0db6

Browse files
authored
Merge pull request #638 from mgharamti/hydroDART
Recent WRF-Hydro Developments
2 parents cd249bf + 4e7c1fa commit 95c0db6

9 files changed

+1153
-331
lines changed

models/wrf_hydro/create_identity_streamflow_obs.f90

+21-13
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ program create_identity_streamflow_obs
6666
integer, parameter :: NUM_COPIES = 1 ! number of copies in sequence
6767
integer, parameter :: NUM_QC = 1 ! number of QC entries
6868
real(r8), parameter :: MIN_OBS_ERR_STD = 0.1_r8 ! m^3/sec
69-
real(r8), parameter :: MAX_OBS_ERR_STD = 100000.0_r8
69+
real(r8), parameter :: MAX_OBS_ERR_STD = 1000000.0_r8
7070
real(r8), parameter :: NORMAL_FLOW = 10.0_r8
7171
real(r8), parameter :: contract = 0.001_r8
7272

@@ -104,7 +104,7 @@ program create_identity_streamflow_obs
104104
real(r8), allocatable :: discharge(:)
105105

106106
character(len=IDLength), allocatable :: desired_gages(:)
107-
integer :: n_wanted_gages
107+
integer :: n_wanted_gages, n_desired_gages
108108
real(r8) :: oerr, qc
109109
integer :: oday, osec
110110
type(obs_type) :: obs
@@ -127,6 +127,7 @@ program create_identity_streamflow_obs
127127
character(len=256) :: location_file = 'location.nc'
128128
character(len=256) :: gages_list_file = ''
129129
real(r8) :: obs_fraction_for_error = 0.01
130+
logical :: assimilate_all = .false.
130131
integer :: debug = 0
131132

132133
namelist / create_identity_streamflow_obs_nml / &
@@ -135,6 +136,7 @@ program create_identity_streamflow_obs
135136
location_file, &
136137
gages_list_file, &
137138
obs_fraction_for_error, &
139+
assimilate_all, &
138140
debug
139141

140142
!-------------------------------------------------------------------------------
@@ -209,7 +211,12 @@ program create_identity_streamflow_obs
209211
call init_obs(obs, num_copies=NUM_COPIES, num_qc=NUM_QC)
210212
call init_obs(prev_obs, num_copies=NUM_COPIES, num_qc=NUM_QC)
211213

212-
n_wanted_gages = set_desired_gages(gages_list_file)
214+
! Collect all the gauges:
215+
! - desired ones will have the provided obs_err_sd
216+
! - remaining gauges are dummy with very large obs_err_sd
217+
218+
n_desired_gages = set_desired_gages(gages_list_file)
219+
n_wanted_gages = 0 !set_desired_gages(gages_list_file)
213220
call find_textfile_dims(input_files, nfiles)
214221

215222
num_new_obs = estimate_total_obs_count(input_files, nfiles)
@@ -308,7 +315,8 @@ program create_identity_streamflow_obs
308315

309316
OBSLOOP: do n = 1, nobs
310317

311-
if ( discharge(n) < 0.0_r8 ) cycle OBSLOOP
318+
! make sure discharge is physical
319+
if ( discharge(n) < 0.0_r8 .or. discharge(n) /= discharge(n) ) cycle OBSLOOP
312320

313321
! relate the TimeSlice:station to the RouteLink:gage so we can
314322
! determine the location
@@ -318,13 +326,13 @@ program create_identity_streamflow_obs
318326
! relate the physical location to the dart state vector index
319327
dart_index = linkloc_to_dart(lat(indx), lon(indx))
320328

321-
! oerr is the observation error standard deviation in this application.
322-
! The observation error variance encoded in the observation file
323-
! will be oerr*oerr
324-
oerr = max(discharge(n)*obs_fraction_for_error, MIN_OBS_ERR_STD)
325-
326-
! MEG: A fix to not crush the ensemble in a no-flood period (stagnant water).
327-
!if ( discharge(n) < NORMAL_FLOW ) then
329+
! desired gauges get the provided obs_err
330+
! remaining ones are for verification purposes
331+
if (ANY(desired_gages == station_strings(n)) .or. assimilate_all) then
332+
oerr = max(discharge(n)*obs_fraction_for_error, MIN_OBS_ERR_STD)
333+
else
334+
oerr = MAX_OBS_ERR_STD
335+
endif
328336
! don't correct that much, the gauge observations imply that the flow
329337
! in the stream is small. This is not a flood period. Streamflow values
330338
! indicate a more or less lake situation rather than a strongly flowing stream.
@@ -660,9 +668,9 @@ function estimate_total_obs_count(file_list,nfiles) result (num_obs)
660668

661669
! We need to know how many observations there may be.
662670
! Specifying too many is not really a problem.
663-
! I am adding 20%
671+
! I am multiplying by 10.
664672

665-
num_obs = 1.2_r8 * nobs * nfiles
673+
num_obs = 10.0_r8 * nobs * nfiles
666674

667675
end function estimate_total_obs_count
668676

models/wrf_hydro/hydro_dart_py/hydrodartpy/core/create_usgs_daily_obs_seq.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def parallel_process_day(arg_dict):
5050

5151
the_cmd = exe_cmd.format(
5252
**{
53-
'cmd': './' + the_converter.name,
53+
'cmd': './create_identity_streamflow_obs',
5454
'nproc': 1
5555
}
5656
)

models/wrf_hydro/hydro_dart_py/hydrodartpy/core/setup_usgs_daily.py

+22-10
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ def setup_usgs_daily(
2727
input_dir = usgs_daily_config['input_dir']
2828
output_dir = usgs_daily_config['output_dir']
2929
# Output directory: make if DNE
30-
output_dir.mkdir(exist_ok=False, parents=True)
30+
#output_dir.mkdir(exist_ok=False, parents=True)
31+
output_dir.mkdir(exist_ok=True, parents=True)
3132

3233
# converter: identity or regular obs converter?
3334
# Check that the desired obs converter is in the dart build
@@ -75,7 +76,8 @@ def setup_usgs_daily(
7576
run_dir = config['experiment']['run_dir']
7677
m0 = pickle.load(open(run_dir / "member_000/WrfHydroSim.pkl", 'rb'))
7778
route_link_f = run_dir / 'member_000' / m0.base_hydro_namelist['hydro_nlist']['route_link_f']
78-
(output_dir / route_link_f.name).symlink_to(route_link_f)
79+
if not route_link_f.is_file():
80+
(output_dir / route_link_f.name).symlink_to(route_link_f)
7981
input_nml[converter_nml]['location_file'] = route_link_f.name
8082

8183
#input.nml input_files: create a list of files in the start and end range.
@@ -101,27 +103,35 @@ def setup_usgs_daily(
101103
if usgs_daily_config['identity_obs']:
102104

103105
hydro_rst_file = run_dir / 'member_000' / m0.base_hydro_namelist['hydro_nlist']['restart_file']
104-
(output_dir / hydro_rst_file.name).symlink_to(hydro_rst_file)
106+
if not hydro_rst_file.is_file():
107+
(output_dir / hydro_rst_file.name).symlink_to(hydro_rst_file)
105108
input_nml['model_nml']['domain_order'] = 'hydro'
106109
input_nml['model_nml']['domain_shapefiles'] = str(hydro_rst_file.name)
107110

108111
f90nml.Namelist(m0.base_hydro_namelist).write(output_dir / 'hydro.namelist', force=True)
109112
top_level_dir = get_top_level_dir_from_config(config, m0)
110-
(output_dir / top_level_dir).symlink_to(config['wrf_hydro']['domain_src'] / top_level_dir)
113+
nwm_dir = config['wrf_hydro']['domain_src'] / top_level_dir
114+
if not nwm_dir.is_dir():
115+
(output_dir / top_level_dir).symlink_to(config['wrf_hydro']['domain_src'] / top_level_dir)
111116

112117
# Now we are done editing it, write the input.nml back out.
113-
input_nml.write(output_dir / 'input.nml')
118+
out_input = output_dir / 'input.nml'
119+
if not out_input.is_file():
120+
input_nml.write(output_dir / 'input.nml')
114121

115122
# Symlink the config file into the output_dir so the default yaml file name
116123
# can be used by create_usgs_daily_obs_seq.
117124
if config_file is None:
118125
config_file = sorted(exp_dir.glob('original.*.yaml'))[0]
119-
(output_dir / 'config_file.yaml').symlink_to(config_file)
126+
if not config_file.is_file():
127+
(output_dir / 'config_file.yaml').symlink_to(config_file)
120128

121129
# Stage the file that does the batch processing.
122130
this_file = pathlib.Path(__file__)
123131
batcher_base = 'create_usgs_daily_obs_seq.py'
124-
(output_dir / batcher_base).symlink_to(this_file.parent / batcher_base)
132+
pyscript = this_file.parent / batcher_base
133+
if not pyscript.is_file():
134+
(output_dir / batcher_base).symlink_to(this_file.parent / batcher_base)
125135

126136
# Setup the scheduled script.
127137
orig_submit_script = this_file.parent / 'submission_scripts/submit_usgs_daily_obs_converter.sh'
@@ -152,10 +162,11 @@ def setup_usgs_daily(
152162

153163
# Select statement
154164
# Right now, only single node processing
155-
select_stmt = 'select=1:ncpus={ncpus}:mpiprocs={mpiprocs}'.format(
165+
select_stmt = 'select=1:ncpus={ncpus}:mpiprocs={mpiprocs}:mem={reqmem}GB'.format(
156166
**{
157167
'ncpus': usgs_sched['ncpus'],
158-
'mpiprocs': usgs_sched['mpiprocs']
168+
'mpiprocs': usgs_sched['mpiprocs'],
169+
'reqmem': usgs_sched['reqmem']
159170
}
160171
)
161172
replace_in_file(this_submit_script, 'PBS_SELECT_TEMPLATE', select_stmt)
@@ -191,6 +202,7 @@ def setup_usgs_daily(
191202
all_obs_dir = pathlib.PosixPath(config['observation_preparation']['all_obs_dir'])
192203
all_obs_seq = output_dir.glob('obs_seq.*')
193204
for oo in all_obs_seq:
194-
(all_obs_dir / oo.name).symlink_to(oo)
205+
if not oo.is_file():
206+
(all_obs_dir / oo.name).symlink_to(oo)
195207

196208
return 0

0 commit comments

Comments
 (0)