Skip to content
Snippets Groups Projects
Commit 0da787c8 authored by lkugler's avatar lkugler
Browse files

bugfix

parent 66349851
No related branches found
No related tags found
No related merge requests found
...@@ -74,6 +74,7 @@ def replace_errors_obsseqout(f, new_errors): ...@@ -74,6 +74,7 @@ def replace_errors_obsseqout(f, new_errors):
new_errors (np.array) : standard deviation, new_errors (np.array) : standard deviation,
shape must match the number of observations shape must match the number of observations
""" """
debug = True
obsseq = open(f, 'r').readlines() obsseq = open(f, 'r').readlines()
# find number of lines between two ' OBS ' lines: # find number of lines between two ' OBS ' lines:
...@@ -96,7 +97,7 @@ def replace_errors_obsseqout(f, new_errors): ...@@ -96,7 +97,7 @@ def replace_errors_obsseqout(f, new_errors):
previous_err_var = obsseq[line_error_obs_i] previous_err_var = obsseq[line_error_obs_i]
new_err_obs_i = new_errors[i_obs]**2 # variance in obs_seq.out new_err_obs_i = new_errors[i_obs]**2 # variance in obs_seq.out
#print('previous err var ', previous_err_var, 'new error', new_err_obs_i) if debug: print('previous err var ', previous_err_var, 'new error', new_err_obs_i)
obsseq[line_error_obs_i] = ' '+str(new_err_obs_i)+' \n' obsseq[line_error_obs_i] = ' '+str(new_err_obs_i)+' \n'
i_obs += 1 # next iteration i_obs += 1 # next iteration
...@@ -189,9 +190,10 @@ def obs_operator_ensemble(istage): ...@@ -189,9 +190,10 @@ def obs_operator_ensemble(istage):
# DART may need a wrfinput file as well, which serves as a template for dimension sizes # DART may need a wrfinput file as well, which serves as a template for dimension sizes
symlink(cluster.dartrundir+'/wrfout_d01', cluster.dartrundir+'/wrfinput_d01') symlink(cluster.dartrundir+'/wrfout_d01', cluster.dartrundir+'/wrfinput_d01')
# I dont think this is necessary, we do this already in pre_assim.py
# add geodata, if istage>0, wrfout is DART output (has coords) # add geodata, if istage>0, wrfout is DART output (has coords)
if istage == 0: #if istage == 0:
wrfout_add_geo.run(cluster.dartrundir+'/geo_em.d01.nc', cluster.dartrundir+'/wrfout_d01') # wrfout_add_geo.run(cluster.dartrundir+'/geo_em.d01.nc', cluster.dartrundir+'/wrfout_d01')
# run perfect_model obs (forward operator) # run perfect_model obs (forward operator)
os.system('mpirun -np 12 ./perfect_model_obs > /dev/null') os.system('mpirun -np 12 ./perfect_model_obs > /dev/null')
...@@ -221,6 +223,7 @@ def link_nature_to_dart_truth(time): ...@@ -221,6 +223,7 @@ def link_nature_to_dart_truth(time):
cluster.dartrundir+'/wrfout_d01') cluster.dartrundir+'/wrfout_d01')
# DART may need a wrfinput file as well, which serves as a template for dimension sizes # DART may need a wrfinput file as well, which serves as a template for dimension sizes
symlink(cluster.dartrundir+'/wrfout_d01', cluster.dartrundir+'/wrfinput_d01') symlink(cluster.dartrundir+'/wrfout_d01', cluster.dartrundir+'/wrfinput_d01')
print('linked', time.strftime(cluster.nature_wrfout), 'to', cluster.dartrundir+'/wrfout_d01')
def prepare_nature_dart(time): def prepare_nature_dart(time):
...@@ -254,7 +257,7 @@ def run_perfect_model_obs(): ...@@ -254,7 +257,7 @@ def run_perfect_model_obs():
os.system('mpirun -np 12 ./perfect_model_obs > log.perfect_model_obs') os.system('mpirun -np 12 ./perfect_model_obs > log.perfect_model_obs')
if not os.path.exists(cluster.dartrundir+'/obs_seq.out'): if not os.path.exists(cluster.dartrundir+'/obs_seq.out'):
raise RuntimeError('obs_seq.out does not exist in '+cluster.dartrundir, raise RuntimeError('obs_seq.out does not exist in '+cluster.dartrundir,
'\n look for '+cluster.dartrundir+'log.perfect_model_obs') '\n look for '+cluster.dartrundir+'/log.perfect_model_obs')
def assimilate(nproc=96): def assimilate(nproc=96):
print('time now', dt.datetime.now()) print('time now', dt.datetime.now())
...@@ -279,6 +282,8 @@ def archive_diagnostics(archive_dir, time): ...@@ -279,6 +282,8 @@ def archive_diagnostics(archive_dir, time):
# warnings.warn(str(e)) # warnings.warn(str(e))
def recycle_output(): def recycle_output():
"""Use output of assimilation (./filter) as input for another assimilation (with ./filter)
Specifically, this copies the state fields from filter_restart_d01.000x to the wrfout files in advance_temp folders"""
update_vars = ['U', 'V', 'T', 'PH', 'MU', 'QVAPOR', 'QCLOUD', 'QICE', 'QRAIN', 'U10', 'V10', 'T2', 'Q2', 'TSK', 'PSFC', 'CLDFRA'] update_vars = ['U', 'V', 'T', 'PH', 'MU', 'QVAPOR', 'QCLOUD', 'QICE', 'QRAIN', 'U10', 'V10', 'T2', 'Q2', 'TSK', 'PSFC', 'CLDFRA']
updates = ','.join(update_vars) updates = ','.join(update_vars)
...@@ -344,6 +349,9 @@ if __name__ == "__main__": ...@@ -344,6 +349,9 @@ if __name__ == "__main__":
Assumptions: Assumptions:
- x_ensemble is already linked for DART to advance_temp<iens>/wrfout_d01 - x_ensemble is already linked for DART to advance_temp<iens>/wrfout_d01
Example call:
python assim.py 2008-08-07_12:00
""" """
time = dt.datetime.strptime(sys.argv[1], '%Y-%m-%d_%H:%M') time = dt.datetime.strptime(sys.argv[1], '%Y-%m-%d_%H:%M')
...@@ -360,20 +368,21 @@ if __name__ == "__main__": ...@@ -360,20 +368,21 @@ if __name__ == "__main__":
################################################ ################################################
print(' 1) get the assimilation errors in a single vector ') print(' 1) get the assimilation errors in a single vector ')
error_assimilate = [] error_generate = []
for i, obscfg in enumerate(exp.observations): for i, obscfg in enumerate(exp.observations):
n_obs = obscfg['n_obs'] n_obs = obscfg['n_obs']
n_obs_z = obscfg.get('heights', 1) n_obs_z = len(obscfg.get('heights', [1,]))
n_obs_3d = n_obs * n_obs_z n_obs_3d = n_obs * n_obs_z
parametrized = obscfg.get('sat_channel') == 6 parametrized = obscfg.get('sat_channel') == 6
if not parametrized: if not parametrized:
err_this_type = np.zeros(n_obs_3d) + obscfg['error_generate'] err_this_type = np.zeros(n_obs_3d) + obscfg['error_generate']
else: # error parametrization for WV73 else: # error parametrization for WV73
# get observations for sat 6 # get observations for sat 6
osq.create_obsseqin_alltypes(time, [obscfg,], obs_errors='error_generate') osq.create_obsseqin_alltypes(time, [obscfg,], np.zeros(n_obs_3d))
run_perfect_model_obs() run_perfect_model_obs()
# depends on obs_seq.out produced before by run_perfect_model_obs() # depends on obs_seq.out produced before by run_perfect_model_obs()
...@@ -382,11 +391,11 @@ if __name__ == "__main__": ...@@ -382,11 +391,11 @@ if __name__ == "__main__":
Hx_prior = obs_operator_ensemble(istage) # files are already linked to DART directory Hx_prior = obs_operator_ensemble(istage) # files are already linked to DART directory
err_this_type = calc_obserr_WV73(Hx_nat, Hx_prior) err_this_type = calc_obserr_WV73(Hx_nat, Hx_prior)
error_assimilate.extend(err_this_type) error_generate.extend(err_this_type) # the obs-error we assume for generating observations
################################################ ################################################
print(' 2) generate observations ') print(' 2) generate observations ')
osq.create_obsseqin_alltypes(time, exp.observations, obs_errors='error_generate', osq.create_obsseqin_alltypes(time, exp.observations, obs_errors=error_generate,
archive_obs_coords=archive_stage+'/obs_coords.pkl') archive_obs_coords=archive_stage+'/obs_coords.pkl')
first_obstype = exp.observations[0] first_obstype = exp.observations[0]
...@@ -397,58 +406,60 @@ if __name__ == "__main__": ...@@ -397,58 +406,60 @@ if __name__ == "__main__":
################################################ ################################################
print(' 3) assimilate with adapted observation-errors ') print(' 3) assimilate with adapted observation-errors ')
error_assimilate = np.zeros(n_obs_3d) + obscfg['error_assimilate'] # the obs-error we assume for assimilation
replace_errors_obsseqout(cluster.dartrundir+'/obs_seq.out', error_assimilate) replace_errors_obsseqout(cluster.dartrundir+'/obs_seq.out', error_assimilate)
t = time.time() t = time_module.time()
assimilate() assimilate()
print('filter took', time_module.time()-t, 'seconds')
dir_obsseq = cluster.archivedir+'/obs_seq_final/assim_stage'+str(istage) dir_obsseq = cluster.archivedir+'/obs_seq_final/assim_stage'+str(istage)
archive_diagnostics(dir_obsseq, time) archive_diagnostics(dir_obsseq, time)
archive_output(archive_stage) archive_output(archive_stage)
sys.exit() # below is the code for separate assimilation of different obs types #sys.exit() # below is the code for separate assimilation of different obs types
for istage, obscfg in enumerate(exp.observations): #for istage, obscfg in enumerate(exp.observations):
print('running observation stage', istage, obscfg) # print('running observation stage', istage, obscfg)
archive_stage = archive_time + '/assim_stage'+str(istage)+'/' # archive_stage = archive_time + '/assim_stage'+str(istage)+'/'
n_obs = obscfg['n_obs'] # n_obs = obscfg['n_obs']
n_obs_3d = n_obs * len(obscfg['heights']) # n_obs_3d = n_obs * len(obscfg['heights'])
sat_channel = obscfg.get('sat_channel', False) # sat_channel = obscfg.get('sat_channel', False)
# debug option: overwrite time in prior files # # debug option: overwrite time in prior files
# for iens in range(1,41): # # for iens in range(1,41):
# os.system('ncks -A -v Times '+cluster.dartrundir+'/wrfout_d01 '+cluster.dartrundir+'/advance_temp'+str(iens)+'/wrfout_d01') # # os.system('ncks -A -v Times '+cluster.dartrundir+'/wrfout_d01 '+cluster.dartrundir+'/advance_temp'+str(iens)+'/wrfout_d01')
if error_assimilate == False: # if error_assimilate == False:
# use error parametrization for assimilation-obs.errors # # use error parametrization for assimilation-obs.errors
if sat_channel != 6: # if sat_channel != 6:
raise NotImplementedError('sat channel '+str(sat_channel)) # raise NotImplementedError('sat channel '+str(sat_channel))
# depends on obs_seq.out produced before by run_perfect_model_obs() # # depends on obs_seq.out produced before by run_perfect_model_obs()
Hx_nat, _ = read_truth_obs_obsseq(cluster.dartrundir+'/obs_seq.out') # Hx_nat, _ = read_truth_obs_obsseq(cluster.dartrundir+'/obs_seq.out')
Hx_prior = obs_operator_ensemble(istage) # files are already linked to DART directory # Hx_prior = obs_operator_ensemble(istage) # files are already linked to DART directory
error_assimilate = calc_obserr_WV73(Hx_nat, Hx_prior) # error_assimilate = calc_obserr_WV73(Hx_nat, Hx_prior)
else: # else:
# overwrite error values in obs_seq.out # # overwrite error values in obs_seq.out
error_assimilate = np.zeros(n_obs_3d) + error_assimilate # ensure shape # error_assimilate = np.zeros(n_obs_3d) + error_assimilate # ensure shape
replace_errors_obsseqout(cluster.dartrundir+'/obs_seq.out', error_assimilate) # replace_errors_obsseqout(cluster.dartrundir+'/obs_seq.out', error_assimilate)
assimilate() # assimilate()
dir_obsseq = cluster.archivedir+'/obs_seq_final/assim_stage'+str(istage) # dir_obsseq = cluster.archivedir+'/obs_seq_final/assim_stage'+str(istage)
archive_diagnostics(dir_obsseq, time) # archive_diagnostics(dir_obsseq, time)
if istage < n_stages-1: # if istage < n_stages-1:
# recirculation: filter output -> input # # recirculation: filter output -> input
archive_output(archive_stage) # archive_output(archive_stage)
recycle_output() # recycle_output()
elif istage == n_stages-1: # elif istage == n_stages-1:
# last assimilation, continue integration now # # last assimilation, continue integration now
archive_output(archive_stage) # archive_output(archive_stage)
else: # else:
RuntimeError('this should never occur?!') # RuntimeError('this should never occur?!')
...@@ -143,7 +143,7 @@ def calc_obs_locations(n_obs, coords_from_domaincenter=True, ...@@ -143,7 +143,7 @@ def calc_obs_locations(n_obs, coords_from_domaincenter=True,
omit_covloc_radius_on_boundary = True omit_covloc_radius_on_boundary = True
if omit_covloc_radius_on_boundary: # in order to avoid an increment step on the boundary if omit_covloc_radius_on_boundary: # in order to avoid an increment step on the boundary
skip_km = cov_loc_radius_km*1.5 skip_km = 50 # cov_loc_radius_km*1.5
skip_gridpoints = int(skip_km/model_dx_km) # skip this many gridpoints on each side skip_gridpoints = int(skip_km/model_dx_km) # skip this many gridpoints on each side
gridpoints_left = nx - 2*skip_gridpoints gridpoints_left = nx - 2*skip_gridpoints
...@@ -376,13 +376,14 @@ def create_obsseq_in_separate_obs(time_dt, obscfg, obs_errors=False, ...@@ -376,13 +376,14 @@ def create_obsseq_in_separate_obs(time_dt, obscfg, obs_errors=False,
write_file(txt, output_path=cluster.dartrundir+'/obs_seq.in') write_file(txt, output_path=cluster.dartrundir+'/obs_seq.in')
def create_obsseqin_alltypes(time_dt, list_obscfg, obs_errors='error_assimilate', archive_obs_coords=False): def create_obsseqin_alltypes(time_dt, list_obscfg, obs_errors, archive_obs_coords=False):
"""Create obs_seq.in with multiple obs types in one file """Create obs_seq.in with multiple obs types in one file
Args: Args:
time_dt (dt.datetime): time of observation time_dt (dt.datetime): time of observation
list_obscfg (list of dict) list_obscfg (list of dict)
obs_errors (False or str): Key to obsdict, which field contains the error values obs_errors (list of float, False): contains observation errors, one for each observation
if False: use zero error
archive_obs_coords (bool, str): False or str (filepath where `obs_seq.in` will be saved) archive_obs_coords (bool, str): False or str (filepath where `obs_seq.in` will be saved)
""" """
print('creating obs_seq.in:') print('creating obs_seq.in:')
...@@ -411,9 +412,12 @@ def create_obsseqin_alltypes(time_dt, list_obscfg, obs_errors='error_assimilate' ...@@ -411,9 +412,12 @@ def create_obsseqin_alltypes(time_dt, list_obscfg, obs_errors='error_assimilate'
n_obs_3d_thistype = len(coords) n_obs_3d_thistype = len(coords)
# define obs error # define obs error
obserr_std = np.zeros(n_obs_3d_thistype) if obs_errors == False:
if obs_errors: obs_errors = np.zeros(n_obs_3d_thistype)
obserr_std += obscfg[obs_errors] assert len(obs_errors) == n_obs_3d_thistype, 'len(obs_errors) == n_obs_3d_thistype'
obserr_std = obs_errors #np.zeros(n_obs_3d_thistype)
#if obs_errors:
# obserr_std += obscfg[obs_errors]
sat_info = write_sat_angle_appendix(sat_channel, lat0, lon0, time_dt) sat_info = write_sat_angle_appendix(sat_channel, lat0, lon0, time_dt)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment