forked from lmadaus/cm1_dart
-
Notifications
You must be signed in to change notification settings - Fork 1
/
make_osse_obs.py
executable file
·227 lines (191 loc) · 8.66 KB
/
make_osse_obs.py
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
#!/usr/bin/env python
from __future__ import division, print_function
import os, sys
import re
from datetime import datetime, timedelta
from netCDF4 import Dataset
sys.path.append('/home/disk/pvort/nobackup/lmadaus/cm1/DOMAINS/kdvn_ensemble')
from ens_dart_param import *
"""
Script to operate on output from a "truth" run, found in the members directory,
to extract an observation sequence at the specified time.
"""
GENERATE_IDEAL_OBS = True
error_var = {'TEMPERATURE_2M' : 1.0,
'U_WIND_10M' : 1.0,
'V_WIND_10M' : 1.0,
'SURFACE_PRESSURE' : 100.0,
'SPECIFIC_HUMIDITY_2M' : 0.001}
heights = {'TEMPERATURE_2M' : 0.0,
'U_WIND_10M' : 10.0,
'V_WIND_10M' : 10.0,
'SURFACE_PRESSURE' : 0.0,
'SPECIFIC_HUMIDITY_2M' : 2.0,
}
curdir = os.getcwd()
def main():
#build_obs_structure(0)
if GENERATE_IDEAL_OBS:
for t in range(60,660,60):
generate_ideal_obs(intime=t)
def build_obs_structure(intime, rst_file, gridspace=4):
""" Function to specify what variables we want and how dense they should be """
#from make_namelist_dart import set_namelist_sectors, write_namelist
#from write_cm1_namelist import set_namelist_defaults
from namelist_utils import read_namelist, write_dart_namelist
# Generate the DART namelist structure so we
# can query (and modify) it
dartnml = read_namelist('input.nml')
cm1nml = read_namelist('namelist.input')
# Build the epoch from the cm1 namelist
param11 = cm1nml['param11']
startdate = datetime(param11['year'], param11['month'],\
param11['day'], param11['hour'],\
param11['minute'], param11['second'])
# Parse out the observations to assimilate
use_obs = dartnml['obs_kind_nml']['assimilate_these_obs_types']
# I'm just testing this for now
#use_obs = use_obs[0:2]
#use_obs = ['LAND_SFC_U_WIND_COMPONENT', 'LAND_SFC_V_WIND_COMPONENT', 'LAND_SFC_TEMPERATURE',
# 'LAND_SFC_SPECIFIC_HUMIDITY']
use_obs = ['TEMPERATURE_2M','SURFACE_PRESSURE','SPECIFIC_HUMIDITY_2M','V_WIND_10M','U_WIND_10M']
print(use_obs)
# Put time as datetime
intime = startdate + timedelta(seconds=intime)
epoch = datetime(1601,1,1,0)
print("Indate:", intime)
# Figure out the grid structure
dx = cm1nml['param1']['dx']
dy = cm1nml['param1']['dy']
nx = cm1nml['param0']['nx']
ny = cm1nml['param0']['ny']
# Now figure out how many obs we'll need
gridspace *= 1000
obx = range(int(dx/2.),int(nx*dx),gridspace)
oby = range(int(dy/2.),int(ny*dx),gridspace)
#obx = [16000]
#oby = [16000]
total_obs = len(obx)*len(oby)*len(use_obs)
print("Total number of obs:", total_obs)
# Write a new dart namelist for the current time
delt = intime - epoch
#dartnml['perfect_model_obs_nml']['first_obs_days'] = str(delt.days)
#dartnml['perfect_model_obs_nml']['first_obs_seconds'] = str(delt.seconds)
#dartnml['perfect_model_obs_nml']['last_obs_days'] = str(delt.days)
#dartnml['perfect_model_obs_nml']['last_obs_seconds'] = str(delt.seconds)
#dartnml['perfect_model_obs_nml']['init_time_days'] = str(delt.days)
#dartnml['perfect_model_obs_nml']['init_time_seconds'] = str(delt.seconds)
dartnml['perfect_model_obs_nml']['obs_seq_in_file_name'] = 'obs_seq.in'
dartnml['perfect_model_obs_nml']['restart_in_file_name'] = rst_file
# Make sure we have the right io pattern
dartnml['io_filenames_nml']['restart_in_stub'] = 'notinuse'
dartnml['io_filenames_nml']['overwrite_input'] = False
dartnml['io_filenames_nml']['rpointer'] = True
dartnml['io_filenames_nml']['rpointer_file'] = 'input_filelist.txt'
# Write the pointer file
with open('input_filelist.txt', 'w') as pointerfile:
pointerfile.write(rst_file)
os.system('mv input_filelist.txt {:s}/'.format(dir_obs))
# Write the modified namelist
write_dart_namelist(dartnml)
# Set up the input file
with open('obs_seq_input.txt','w') as infile:
infile.write(str(total_obs)+'\n') # Total num obs
infile.write('0\n') # 0 copies
infile.write('0\n') # 0 QC values
for obtype in use_obs:
for x in obx:
for y in oby:
infile.write('0\n')
infile.write(obtype+'\n') # Identify ob type
infile.write('0\n') # Specify location
infile.write(str(x)+'\n') # X coordinate
infile.write(str(y)+'\n') # Y coordinate
infile.write(str(heights[obtype]) + '\n') # Z coordinate
infile.write('{:d} {:d} {:d} {:d} {:d} {:d}\n'.format(\
intime.year, intime.month,\
intime.day, intime.hour,\
intime.minute, intime.second))
infile.write(str(error_var[obtype])+'\n') # Error variance
infile.write('obs_seq.in\n')
# Move these files to the obs dir
if os.path.exists(os.path.join(dir_obs, 'input.nml')):
os.system('rm -f {:s}'.format(os.path.join(dir_obs, 'input.nml')))
if os.path.exists(os.path.join(dir_obs, 'obs_seq_input.txt')):
os.system('rm -f {:s}'.format(os.path.join(dir_obs, 'obs_seq_input.txt')))
os.system('mv obs_seq_input.txt {:s}'.format(dir_obs))
os.system('cp input.nml {:s}'.format(dir_obs))
return None
def generate_ideal_obs(intime):
"""
Run the DART sequence to generate "truth" observations from a
run within the truth directory
"""
# Multiply intime by 60 for seconds
intime *= 60
intime = int(intime)
# Check to see that the truth run is where it's supposed to be
truthdir = os.path.join(dir_members, 'truth')
if not os.path.exists(truthdir):
raise ProceduralError('Unable to find directory{:s}/truth'.format(dir_members),\
'generate_ideal_obs')
# Search the restart files for the appropriate time
rst_filenames = [f for f in os.listdir(truthdir) if 'rst' in f and f.endswith('.nc')]
if len(rst_filenames) < 1:
raise ProceduralError('Unable to find any rst files in {:s}'.format(truthdir),\
'generate_ideal_obs')
# Match these files to the intime
rst_files = [Dataset(os.path.join(truthdir,f),'r') for f in rst_filenames]
file_times = [int(r.variables['time'][0]) for r in rst_files]
for f in rst_files:
f.close()
if intime not in file_times:
raise ProceduralError('Could not find time {:d} in any rst files in {:s}'.format(intime,truthdir),\
'generate_ideal_obs')
# Get this file
rst_file = rst_filenames[file_times.index(intime)]
os.system('rm -f {:s}/cm1out_rst*.nc'.format(dir_obs))
os.system('ln -sf {:s}/{:s} {:s}/{:s}'.format(truthdir, rst_file, dir_obs, rst_file))
print("Found restart file at time {:d}: {:s}".format(intime, rst_file))
# Build the obs structure file based on this
build_obs_structure(intime, rst_file)
#os.system('./write_namelist_dart.py -d {:d}'.format(intime/60))
#os.system('cp input.nml {:s}/'.format(dir_obs))
# Go into the obs directory
os.chdir(dir_obs)
# Cleanup
os.system('rm -f True_State.nc obs_seq.in obs_seq.out')
if not os.path.exists('cm1out_rst_000001.nc'):
os.system('ln -sf {:s} .'.format(os.path.join(truthdir, 'cm1out_rst_000001.nc')))
if not os.path.exists('namelist.input'):
os.system('cp {:s}/namelist.input .'.format(dir_dom))
# Link in the executables we may need and run in order
exe_sequence = ['create_obs_sequence','perfect_model_obs']
for exe in exe_sequence:
if not os.path.exists(exe):
os.system('ln -sf {:s} .'.format(os.path.join(dir_src_dart,exe)))
# Special instructions for each here
if exe == 'create_obs_sequence':
# Here goes the code that tells
# which obs to generate
os.system('./{:s} < obs_seq_input.txt'.format(exe))
else:
os.system('./{:s}'.format(exe))
# Check to be sure it worked
if not os.path.exists('obs_seq.out'):
raise ProceduralError("perfect_model_obs sequence failed! No obs_seq.out file.",'')
else:
print("Success! Made obs_seq.out file.")
os.system('mv obs_seq.out {:d}_obs_seq.prior'.format(intime))
os.chdir(curdir)
class ProceduralError(Exception):
"""
A simple class to throw a text exception
"""
def __init__(self, text, function):
self.text = text
self.function = function
def __str__(self):
return repr(self.text)
if __name__ == '__main__':
main()