diff --git a/dartwrf/dart_nml.py b/dartwrf/dart_nml.py index c11c9a99181f5bbb64881e1ffc24d90525a1ecff..e2b490023f4097663771853945e63b15dc04aee2 100644 --- a/dartwrf/dart_nml.py +++ b/dartwrf/dart_nml.py @@ -5,6 +5,7 @@ from config.cluster import cluster earth_radius_km = 6370 + def read_namelist(filepath): """Read the DART namelist file into a dictionary. @@ -64,7 +65,7 @@ def read_namelist(filepath): param_data.append(val) - print('this iteration var, val ...', {param: param_data}) + # print('this iteration var, val ...', {param: param_data}) # add variable to dictionary d[section][param] = param_data @@ -86,7 +87,7 @@ def write_namelist_from_dict(d, filepath): try: parameters = d[section].keys() - print(parameters, [len(p) for p in parameters]) + # print(parameters, [len(p) for p in parameters]) max_width_of_parameter_name = max([len(p) for p in parameters]) width = max_width_of_parameter_name + 1 except: @@ -107,9 +108,9 @@ def write_namelist_from_dict(d, filepath): if i == 0: - f.write(' '+parameter.ljust(width)+' = '+line+'\n') + f.write(' '+parameter.ljust(width)+' = '+line+',\n') else: - f.write(' '+' '*width+' = '+line+'\n') + f.write(' '+' '*width+' '+line+',\n') f.write(' /\n\n') @@ -191,7 +192,8 @@ def _get_list_of_localizations(): def _to_fortran_list(l): - """Ensure formatting as "arg1", "arg2", """ + """Ensure formatting with quotation mark, e.g. parameter = "arg1", "arg2", + """ assert isinstance(l, list) if len(l) > 1: # multiple entries @@ -243,7 +245,6 @@ def write_namelist(just_prior_values=False): nml['&location_nml']['special_vert_normalization_heights'] = [_to_fortran_list(list_loc_vert_km)] nml['&location_nml']['special_vert_normalization_scale_heights'] = [_to_fortran_list(list_loc_vert_scaleheight)] - print(nml['&location_nml']['special_vert_normalization_obs_types']) # overwrite namelist with experiment configuration for section, sdata in exp.dart_nml.items(): diff --git a/tests/input.nml.desired_output b/tests/input.nml.desired_output new file mode 100644 index 0000000000000000000000000000000000000000..64635bd3a885d1243c24f5553df7343b47d1c613 --- /dev/null +++ b/tests/input.nml.desired_output @@ -0,0 +1,579 @@ +&perfect_model_obs_nml + read_input_state_from_file = .true. + single_file_in = .false. + input_state_files = 'wrfinput_d01' + init_time_days = -1 + init_time_seconds = -1 + + write_output_state_to_file = .false. + single_file_out = .false. + output_state_files = 'perfect_output_d01.nc' + output_interval = 1 + + obs_seq_in_file_name = "obs_seq.in" + obs_seq_out_file_name = "obs_seq.out" + first_obs_days = -1 + first_obs_seconds = -1 + last_obs_days = -1 + last_obs_seconds = -1 + + async = 0 + adv_ens_command = "../shell_scripts/advance_model.csh" + + trace_execution = .true. + output_timestamps = .false. + print_every_nth_obs = -1 + output_forward_op_errors = .true. + silence = .false. + / + +&filter_nml + async = 0, + adv_ens_command = "../shell_scripts/advance_model.csh", + ens_size = 999, + obs_sequence_in_name = "obs_seq.out", + obs_sequence_out_name = "obs_seq.final", + input_state_file_list = "input_list.txt" + output_state_file_list = "output_list.txt" + init_time_days = -1, + init_time_seconds = -1, + first_obs_days = -1, + first_obs_seconds = -1, + last_obs_days = -1, + last_obs_seconds = -1, + num_output_state_members = 999, + num_output_obs_members = 999, + output_interval = 1, + num_groups = 1, + distributed_state = .true. + compute_posterior = .true. + output_forward_op_errors = .false., + output_timestamps = .false., + trace_execution = .false., + + stages_to_write = 'preassim', 'output' + output_members = .false. + output_mean = .true. + output_sd = .false. + write_all_stages_at_end = .false. + + inf_flavor = 2, 0, + inf_initial_from_restart = .true., .false., + inf_sd_initial_from_restart = .true., .false., + inf_initial = 1.0, 1.00, + inf_lower_bound = 1.0, 1.0, + inf_upper_bound = 1000000.0, 1000000.0, + inf_damping = 0.9, 1.0, + inf_sd_initial = 0.6, 0.0, + inf_sd_lower_bound = 0.6, 0.0, + inf_sd_max_change = 1.05, 1.05, + / + +&quality_control_nml + input_qc_threshold = 3.0, + outlier_threshold = 3.0, + enable_special_outlier_code = .false. + / + +&fill_inflation_restart_nml + write_prior_inf = .true. + prior_inf_mean = 1.00 + prior_inf_sd = 0.6 + + write_post_inf = .false. + post_inf_mean = 1.00 + post_inf_sd = 0.6 + + input_state_files = 'wrfinput_d01', 'wrfinput_d02' + single_file = .false. + verbose = .false. + / + +&smoother_nml + num_lags = 0, + start_from_restart = .false., + output_restart = .false., + restart_in_file_name = 'smoother_ics', + restart_out_file_name = 'smoother_restart', + / + +# cutoff is in radians; for the earth, 0.05 is about 300 km. +# cutoff is defined to be the half-width of the localization radius, +# so 0.05 radians for cutoff is about an 600 km effective +# localization radius, where the influence of an obs decreases +# to ~half at 300 km, and ~0 at the edges of the area. +&assim_tools_nml + filter_kind = 1, + cutoff = 0.05, + sort_obs_inc = .false., + spread_restoration = .false., + sampling_error_correction = .true., + adaptive_localization_threshold = -1, + output_localization_diagnostics = .false., + localization_diagnostics_file = 'localization_diagnostics', + convert_all_state_verticals_first = .true. + convert_all_obs_verticals_first = .true. + print_every_nth_obs = 0, + / + +&cov_cutoff_nml + select_localization = 1, + / + +&obs_sequence_nml + write_binary_obs_sequence = .false., + / + +&preprocess_nml + overwrite_output = .true. + input_obs_qty_mod_file = '../../../assimilation_code/modules/observations/DEFAULT_obs_kind_mod.F90' + output_obs_qty_mod_file = '../../../assimilation_code/modules/observations/obs_kind_mod.f90' + input_obs_def_mod_file = '../../../observations/forward_operators/DEFAULT_obs_def_mod.F90' + output_obs_def_mod_file = '../../../observations/forward_operators/obs_def_mod.f90' + quantity_files = '../../../assimilation_code/modules/observations/atmosphere_quantities_mod.f90' + obs_type_files = '../../../observations/forward_operators/obs_def_reanalysis_bufr_mod.f90', + '../../../observations/forward_operators/obs_def_radar_mod.f90', + '../../../observations/forward_operators/obs_def_metar_mod.f90', + '../../../observations/forward_operators/obs_def_dew_point_mod.f90', + '../../../observations/forward_operators/obs_def_rel_humidity_mod.f90', + '../../../observations/forward_operators/obs_def_altimeter_mod.f90', + '../../../observations/forward_operators/obs_def_gps_mod.f90', + '../../../observations/forward_operators/obs_def_vortex_mod.f90', + '../../../observations/forward_operators/obs_def_gts_mod.f90', + '../../../observations/forward_operators/obs_def_rttov_mod.f90' + / + +&obs_kind_nml + assimilate_these_obs_types = 'RADIOSONDE_TEMPERATURE', + 'RADIOSONDE_U_WIND_COMPONENT', + 'RADIOSONDE_V_WIND_COMPONENT', + 'SAT_U_WIND_COMPONENT', + 'SAT_V_WIND_COMPONENT', + 'AIRCRAFT_U_WIND_COMPONENT', + 'AIRCRAFT_V_WIND_COMPONENT', + 'AIRCRAFT_TEMPERATURE', + 'ACARS_U_WIND_COMPONENT', + 'ACARS_V_WIND_COMPONENT', + 'ACARS_TEMPERATURE', + 'GPSRO_REFRACTIVITY', + 'DOPPLER_RADIAL_VELOCITY', + 'RADAR_REFLECTIVITY', + 'MSG_4_SEVIRI_RADIANCE', + 'MSG_4_SEVIRI_TB', + 'MSG_4_SEVIRI_BDRF', + 'LAND_SFC_PRESSURE', + 'SYNOP_SURFACE_PRESSURE', + 'SYNOP_TEMPERATURE', + 'SYNOP_SPECIFIC_HUMIDITY', + 'GPS_PRECIPITABLE_WATER' + evaluate_these_obs_types = 'RADIOSONDE_SPECIFIC_HUMIDITY', + / + +# Notes for obs_def_radar_mod_nml: +# (1) Reflectivity limit can be applied to observations and/or forward operator. +# (2) The default constants below match the WRF defaults. They will need to +# be changed for other cases, depending on which microphysics scheme is used. +# + +&obs_def_radar_mod_nml + apply_ref_limit_to_obs = .false., + reflectivity_limit_obs = -10.0, + lowest_reflectivity_obs = -10.0, + apply_ref_limit_to_fwd_op = .false., + reflectivity_limit_fwd_op = -10.0, + lowest_reflectivity_fwd_op = -10.0, + max_radial_vel_obs = 1000000, + allow_wet_graupel = .false., + microphysics_type = 2 , + allow_dbztowt_conv = .false., + dielectric_factor = 0.224, + n0_rain = 8.0e6, + n0_graupel = 4.0e6, + n0_snow = 3.0e6, + rho_rain = 1000.0, + rho_graupel = 400.0, + rho_snow = 100.0, + / + + +# Notes for model_nml: +# (1) vert_localization_coord must be one of: +# 1 = model level +# 2 = pressure +# 3 = height +# 4 = scale height + +# set default_state_variables to .false. to use the explicit list. +# otherwise it uses a hardcoded default list: U, V, W, PH, T, MU, QV only. +# see ../wrf_state_variables_table for a full list of what wrf fields are +# supported in the DART state vector, and what settings should be used here. +# 'UPDATE' and 'NO_COPY_BACK' are supported in the 4th column; 'NO_UPDATE' is +# not yet supported. + +&model_nml + default_state_variables = .false., + wrf_state_variables = 'U', 'QTY_U_WIND_COMPONENT', 'TYPE_U', 'UPDATE','999', + 'V', 'QTY_V_WIND_COMPONENT', 'TYPE_V', 'UPDATE','999', + 'W', 'QTY_VERTICAL_VELOCITY', 'TYPE_W', 'UPDATE','999', + 'PH', 'QTY_GEOPOTENTIAL_HEIGHT', 'TYPE_GZ', 'UPDATE','999', + 'T', 'QTY_POTENTIAL_TEMPERATURE','TYPE_T', 'UPDATE','999', + 'MU', 'QTY_PRESSURE', 'TYPE_MU', 'UPDATE','999', + 'QVAPOR','QTY_VAPOR_MIXING_RATIO', 'TYPE_QV', 'UPDATE','999', + 'QICE', 'QTY_ICE_MIXING_RATIO', 'TYPE_QI', 'UPDATE','999', + 'QCLOUD','QTY_CLOUDWATER_MIXING_RATIO','TYPE_QC', 'UPDATE','999', + 'CLDFRA','QTY_CLOUD_FRACTION', 'TYPE_CFRAC','UPDATE','999', + 'PSFC', 'QTY_SURFACE_PRESSURE', 'TYPE_PSFC', 'UPDATE','999', + 'T2', 'QTY_2M_TEMPERATURE', 'TYPE_T', 'UPDATE','999', + 'TSK', 'QTY_SKIN_TEMPERATURE', 'TYPE_T', 'UPDATE','999', + 'REFL_10CM','QTY_RADAR_REFLECTIVITY','TYPE_REFL', 'UPDATE','999', + wrf_state_bounds = 'QVAPOR','0.0','NULL','CLAMP', + 'QRAIN', '0.0','NULL','CLAMP', + 'QCLOUD','0.0','NULL','CLAMP', + 'QICE','0.0','NULL','CLAMP', + 'CLDFRA','0.0','1.0','CLAMP', + num_domains = 1, + calendar_type = 3, + assimilation_period_seconds = 21600, + vert_localization_coord = 3, + center_search_half_length = 500000., + center_spline_grid_scale = 10, + sfc_elev_max_diff = -1.0, + circulation_pres_level = 80000.0, + circulation_radius = 108000.0, + allow_obs_below_vol = .false. + / + +# vert_normalization_X is amount of X equiv to 1 radian in horiz. +# vert localization is 'cutoff' times the pressure/height/levels, +# only if horiz_dist_only is set to .false. in the namelist below. +# the default nlon/nlat should be good for most experiments. it sets +# an internal structure that speeds up searches. don't change it +# based on your grid size. nlon must be an odd number. +&location_nml + horiz_dist_only = .false., + vert_normalization_pressure = 6666666.7, + vert_normalization_height = 5000000.0, + vert_normalization_level = 2666.7, + vert_normalization_scale_height = 10.0, + approximate_distance = .false., + nlon = 71, + nlat = 36, + output_box_info = .false., + / + +&utilities_nml + TERMLEVEL = 1, + module_details = .false., + logfilename = 'dart_log.out', + nmlfilename = 'dart_log.nml', + write_nml = 'file', + / + +&mpi_utilities_nml + / + +®_factor_nml + select_regression = 1, + input_reg_file = "time_mean_reg", + save_reg_diagnostics = .false., + reg_diagnostics_file = "reg_diagnostics", + / + +# layout = 2 spreads the IO tasks across the nodes. +# This can greatly improve the performance in IO if +# tasks_per_node is set to match your hardware +&ensemble_manager_nml + layout = 2, + tasks_per_node = 16 + / + +&obs_def_gps_nml + max_gpsro_obs = 100000, + / + +&obs_def_tpw_nml + / + +# The times in the namelist for the obs_diag program are vectors +# that follow the following sequence: +# year month day hour minute second +# max_num_bins can be used to specify a fixed number of bins, +# in which case last_bin_center should be safely in the future. +# +# Acceptable latitudes range from [-90, 90] +# Acceptable longitudes range from [ 0, Inf] + +&obs_diag_nml + obs_sequence_name = 'obs_seq.final', + obs_sequence_list = '', + first_bin_center = 2003, 1, 1, 0, 0, 0 , + last_bin_center = 2003, 1, 2, 0, 0, 0 , + bin_separation = 0, 0, 0,12, 0, 0 , + bin_width = 0, 0, 0, 6, 0, 0 , + time_to_skip = 0, 0, 0, 0, 0, 0 , + max_num_bins = 1000, + trusted_obs = 'null', + Nregions = 4, + lonlim1 = 0.0, 0.0, 0.0, 235.0, + lonlim2 = 360.0, 360.0, 360.0, 295.0, + latlim1 = 20.0, -80.0, -20.0, 25.0, + latlim2 = 80.0, -20.0, 20.0, 55.0, + reg_names = 'Northern Hemisphere', 'Southern Hemisphere', 'Tropics', 'North America', + print_mismatched_locs = .false., + create_rank_histogram = .true., + outliers_in_histogram = .true., + use_zero_error_obs = .false., + verbose = .false. + / + +&schedule_nml + calendar = 'Gregorian', + first_bin_start = 1601, 1, 1, 0, 0, 0, + first_bin_end = 2999, 1, 1, 0, 0, 0, + last_bin_end = 2999, 1, 1, 0, 0, 0, + bin_interval_days = 1000000, + bin_interval_seconds = 0, + max_num_bins = 1000, + print_table = .true., + / + +&obs_seq_to_netcdf_nml + obs_sequence_name = 'obs_seq.final', + obs_sequence_list = '', + append_to_netcdf = .false., + lonlim1 = 0.0, + lonlim2 = 360.0, + latlim1 = -90.0, + latlim2 = 90.0, + verbose = .false., + / + +# There is one GIGANTIC difference between the obsdef_mask.txt and .nc +# The netCDF file intentionally ignores the effect of nTmin/nTmax. +# The netCDF file has ALL matching stations, regardless of temporal coverage. + +&obs_seq_coverage_nml + obs_sequences = '' + obs_sequence_list = 'obs_coverage_list.txt' + obs_of_interest = 'METAR_U_10_METER_WIND' + textfile_out = 'METAR_U_10_METER_WIND_obsdef_mask.txt' + netcdf_out = 'METAR_U_10_METER_WIND_obsdef_mask.nc' + first_analysis = 2003, 1, 1, 0, 0, 0 + last_analysis = 2003, 1, 2, 0, 0, 0 + forecast_length_days = 1 + forecast_length_seconds = 0 + verification_interval_seconds = 21600 + temporal_coverage_percent = 100.0 + lonlim1 = 0.0 + lonlim2 = 360.0 + latlim1 = -90.0 + latlim2 = 90.0 + verbose = .true. + / + +# selections_file is a list of obs_defs output +# from the obs_seq_coverage utility. + +&obs_selection_nml + filename_seq = 'obs_seq.out', + filename_seq_list = '', + filename_out = 'obs_seq.processed', + selections_file = 'obsdef_mask.txt', + selections_is_obs_seq = .false., + print_only = .false., + calendar = 'gregorian', + / + +&obs_seq_verify_nml + obs_sequences = '' + obs_sequence_list = 'obs_verify_list.txt' + input_template = 'obsdef_mask.nc' + netcdf_out = 'forecast.nc' + obtype_string = 'METAR_U_10_METER_WIND' + print_every = 10000 + verbose = .true. + debug = .false. + / + +&obs_sequence_tool_nml + num_input_files = 1, + filename_seq = 'obs_seq.out', + filename_out = 'obs_seq.processed', + first_obs_days = -1, + first_obs_seconds = -1, + last_obs_days = -1, + last_obs_seconds = -1, + obs_types = '', + keep_types = .false., + print_only = .false., + min_lat = -90.0, + max_lat = 90.0, + min_lon = 0.0, + max_lon = 360.0, + / + +&replace_wrf_fields_nml + debug = .false., + fail_on_missing_field = .false., + fieldnames = "SNOWC", + "ALBBCK", + "TMN", + "TSK", + "SH2O", + "SMOIS", + "SEAICE", + "HGT_d01", + "TSLB", + "SST", + "SNOWH", + "SNOW", + fieldlist_file = '', + / + +&obs_common_subset_nml + num_to_compare_at_once = 2, + filename_seq = 'obs_seq1.final', 'obs_seq2.final', + filename_seq_list = '', + filename_out_suffix = '.common' , + calendar = 'Gregorian', + print_every = 1000, + dart_qc_threshold = 3, + print_only = .false., + / + +&wrf_dart_to_fields_nml + include_slp = .true., + include_wind_components = .true., + include_height_on_pres = .true., + include_temperature = .true., + include_rel_humidity = .true., + include_surface_fields = .false., + include_sat_ir_temp = .false., + pres_levels = 70000., + / + +&ncepobs_nml + year = 2010, + month = 06, + day = 00, + tot_days = 1, + max_num = 1000000, + ObsBase = 'temp_obs.', + select_obs = 0, + ADPUPA = .false., + AIRCAR = .false., + AIRCFT = .false., + SATEMP = .false., + SFCSHP = .false., + ADPSFC = .false., + SATWND = .true., + obs_U = .false., + obs_V = .false., + obs_T = .false., + obs_PS = .false., + obs_QV = .false., + daily_file = .true., + obs_time = .false., + lat1 = 10.00, + lat2 = 60.00, + lon1 = 210.0, + lon2 = 300.0 + / + +&prep_bufr_nml + obs_window_upa = 1.0, + obs_window_air = 1.0, + obs_window_cw = 1.0, + otype_use = 242.0, 243.0, 245.0, 246.0, 251.0, 252.0, 253.0, 257.0, 259.0 + qctype_use = 0, 1, 2, 3, 4, 9, 15 + / + +&convert_cosmic_gps_nml + gpsro_netcdf_file = '', + gpsro_netcdf_filelist = 'flist', + gpsro_out_file = 'obs_seq.gpsro', + local_operator = .true., + obs_levels = 0.22, 0.55, 1.1, 1.8, 2.7, 3.7, 4.9, + 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + ray_ds = 5000.0, + ray_htop = 13000.1, + / + +&wrf_obs_preproc_nml + + file_name_input = 'obs_seq20110901' + file_name_output = 'obs_seq.europe.prev' + + overwrite_obs_time = .false. + + obs_boundary = 0.0 + increase_bdy_error = .false. + maxobsfac = 2.5 + obsdistbdy = 1.0 + + sfc_elevation_check = .false. + sfc_elevation_tol = 3000.0 + obs_pressure_top = 0.0 + obs_height_top = 2.0e10 + + include_sig_data = .true. + tc_sonde_radii = -1.0 + + superob_aircraft = .true. + aircraft_horiz_int = 800.0 + aircraft_pres_int = 25000.0 + + superob_sat_winds = .true. + sat_wind_horiz_int = 800.0 + sat_wind_pres_int = 25000.0 + + overwrite_ncep_satwnd_qc = .false. + overwrite_ncep_sfc_qc = .false. + / + +! sonde_extra = 'obs_seq.rawin' +! land_sfc_extra = 'obs_seq.land_sfc' +! metar_extra = 'obs_seq.metar' +! marine_sfc_extra = 'obs_seq.marine' +! sat_wind_extra = 'obs_seq.satwnd' +! profiler_extra = 'obs_seq.profiler' +! gpsro_extra = 'obs_seq.gpsro' +! acars_extra = 'obs_seq.acars' +! trop_cyclone_extra = 'obs_seq.tc' + +&state_vector_io_nml + single_precision_output = .true., + / + +&compare_states_nml + / + +&closest_member_tool_nml + input_restart_file_list = 'input_file_list_d01.txt', + output_file_name = 'closest_results.txt' + ens_size = 3, + single_restart_file_in = .false., + difference_method = 4, + use_only_qtys = 'QTY_U_WIND_COMPONENT' + / + +# To test both domains, you must change 'model_nml:num_domains = 2' + +&model_mod_check_nml + input_state_files = 'wrfinput_d01', 'wrfinput_d02' + output_state_files = 'mmc_output1.nc', 'mmc_output2.nc' + test1thru = 0 + run_tests = 1,2,3,4,5 + x_ind = 87370 + loc_of_interest = 231.0, 40.0, 10.0 + quantity_of_interest = 'QTY_U_WIND_COMPONENT' + interp_test_dlon = 0.1 + interp_test_dlat = 0.1 + interp_test_dvert = 1000.0 + interp_test_lonrange = 250.0, 260.0 + interp_test_latrange = 30.0, 45.0 + interp_test_vertrange = 2000.0, 4000.0 + interp_test_vertcoord = 'VERTISHEIGHT' + verbose = .false. + / + diff --git a/tests/input.nml.original b/tests/input.nml.original new file mode 100644 index 0000000000000000000000000000000000000000..c7f6fee6762770e30b4f649e406e91b38e984c71 --- /dev/null +++ b/tests/input.nml.original @@ -0,0 +1,579 @@ +&perfect_model_obs_nml + read_input_state_from_file = .true. + single_file_in = .false. + input_state_files = 'wrfinput_d01' + init_time_days = -1 + init_time_seconds = -1 + + write_output_state_to_file = .false. + single_file_out = .false. + output_state_files = 'perfect_output_d01.nc' + output_interval = 1 + + obs_seq_in_file_name = "obs_seq.in" + obs_seq_out_file_name = "obs_seq.out" + first_obs_days = -1 + first_obs_seconds = -1 + last_obs_days = -1 + last_obs_seconds = -1 + + async = 0 + adv_ens_command = "../shell_scripts/advance_model.csh" + + trace_execution = .true. + output_timestamps = .false. + print_every_nth_obs = -1 + output_forward_op_errors = .true. + silence = .false. + / + +&filter_nml + async = 0, + adv_ens_command = "../shell_scripts/advance_model.csh", + ens_size = 3, + obs_sequence_in_name = "obs_seq.out", + obs_sequence_out_name = "obs_seq.final", + input_state_file_list = "input_list.txt" + output_state_file_list = "output_list.txt" + init_time_days = -1, + init_time_seconds = -1, + first_obs_days = -1, + first_obs_seconds = -1, + last_obs_days = -1, + last_obs_seconds = -1, + num_output_state_members = 0, + num_output_obs_members = 32, + output_interval = 1, + num_groups = 1, + distributed_state = .true. + compute_posterior = .true. + output_forward_op_errors = .false., + output_timestamps = .false., + trace_execution = .false., + + stages_to_write = 'preassim', 'output' + output_members = .false. + output_mean = .true. + output_sd = .false. + write_all_stages_at_end = .false. + + inf_flavor = 2, 0, + inf_initial_from_restart = .true., .false., + inf_sd_initial_from_restart = .true., .false., + inf_initial = 1.0, 1.00, + inf_lower_bound = 1.0, 1.0, + inf_upper_bound = 1000000.0, 1000000.0, + inf_damping = 0.9, 1.0, + inf_sd_initial = 0.6, 0.0, + inf_sd_lower_bound = 0.6, 0.0, + inf_sd_max_change = 1.05, 1.05, + / + +&quality_control_nml + input_qc_threshold = 3.0, + outlier_threshold = 3.0, + enable_special_outlier_code = .false. + / + +&fill_inflation_restart_nml + write_prior_inf = .true. + prior_inf_mean = 1.00 + prior_inf_sd = 0.6 + + write_post_inf = .false. + post_inf_mean = 1.00 + post_inf_sd = 0.6 + + input_state_files = 'wrfinput_d01', 'wrfinput_d02' + single_file = .false. + verbose = .false. + / + +&smoother_nml + num_lags = 0, + start_from_restart = .false., + output_restart = .false., + restart_in_file_name = 'smoother_ics', + restart_out_file_name = 'smoother_restart', + / + +# cutoff is in radians; for the earth, 0.05 is about 300 km. +# cutoff is defined to be the half-width of the localization radius, +# so 0.05 radians for cutoff is about an 600 km effective +# localization radius, where the influence of an obs decreases +# to ~half at 300 km, and ~0 at the edges of the area. +&assim_tools_nml + filter_kind = 1, + cutoff = 0.05, + sort_obs_inc = .false., + spread_restoration = .false., + sampling_error_correction = .true., + adaptive_localization_threshold = -1, + output_localization_diagnostics = .false., + localization_diagnostics_file = 'localization_diagnostics', + convert_all_state_verticals_first = .true. + convert_all_obs_verticals_first = .true. + print_every_nth_obs = 0, + / + +&cov_cutoff_nml + select_localization = 1, + / + +&obs_sequence_nml + write_binary_obs_sequence = .false., + / + +&preprocess_nml + overwrite_output = .true. + input_obs_qty_mod_file = '../../../assimilation_code/modules/observations/DEFAULT_obs_kind_mod.F90' + output_obs_qty_mod_file = '../../../assimilation_code/modules/observations/obs_kind_mod.f90' + input_obs_def_mod_file = '../../../observations/forward_operators/DEFAULT_obs_def_mod.F90' + output_obs_def_mod_file = '../../../observations/forward_operators/obs_def_mod.f90' + quantity_files = '../../../assimilation_code/modules/observations/atmosphere_quantities_mod.f90' + obs_type_files = '../../../observations/forward_operators/obs_def_reanalysis_bufr_mod.f90', + '../../../observations/forward_operators/obs_def_radar_mod.f90', + '../../../observations/forward_operators/obs_def_metar_mod.f90', + '../../../observations/forward_operators/obs_def_dew_point_mod.f90', + '../../../observations/forward_operators/obs_def_rel_humidity_mod.f90', + '../../../observations/forward_operators/obs_def_altimeter_mod.f90', + '../../../observations/forward_operators/obs_def_gps_mod.f90', + '../../../observations/forward_operators/obs_def_vortex_mod.f90', + '../../../observations/forward_operators/obs_def_gts_mod.f90', + '../../../observations/forward_operators/obs_def_rttov_mod.f90' + / + +&obs_kind_nml + assimilate_these_obs_types = 'RADIOSONDE_TEMPERATURE', + 'RADIOSONDE_U_WIND_COMPONENT', + 'RADIOSONDE_V_WIND_COMPONENT', + 'SAT_U_WIND_COMPONENT', + 'SAT_V_WIND_COMPONENT', + 'AIRCRAFT_U_WIND_COMPONENT', + 'AIRCRAFT_V_WIND_COMPONENT', + 'AIRCRAFT_TEMPERATURE', + 'ACARS_U_WIND_COMPONENT', + 'ACARS_V_WIND_COMPONENT', + 'ACARS_TEMPERATURE', + 'GPSRO_REFRACTIVITY', + 'DOPPLER_RADIAL_VELOCITY', + 'RADAR_REFLECTIVITY', + 'MSG_4_SEVIRI_RADIANCE', + 'MSG_4_SEVIRI_TB', + 'MSG_4_SEVIRI_BDRF', + 'LAND_SFC_PRESSURE', + 'SYNOP_SURFACE_PRESSURE', + 'SYNOP_TEMPERATURE', + 'SYNOP_SPECIFIC_HUMIDITY', + 'GPS_PRECIPITABLE_WATER' + evaluate_these_obs_types = 'RADIOSONDE_SPECIFIC_HUMIDITY', + / + +# Notes for obs_def_radar_mod_nml: +# (1) Reflectivity limit can be applied to observations and/or forward operator. +# (2) The default constants below match the WRF defaults. They will need to +# be changed for other cases, depending on which microphysics scheme is used. +# + +&obs_def_radar_mod_nml + apply_ref_limit_to_obs = .false., + reflectivity_limit_obs = -10.0, + lowest_reflectivity_obs = -10.0, + apply_ref_limit_to_fwd_op = .false., + reflectivity_limit_fwd_op = -10.0, + lowest_reflectivity_fwd_op = -10.0, + max_radial_vel_obs = 1000000, + allow_wet_graupel = .false., + microphysics_type = 2 , + allow_dbztowt_conv = .false., + dielectric_factor = 0.224, + n0_rain = 8.0e6, + n0_graupel = 4.0e6, + n0_snow = 3.0e6, + rho_rain = 1000.0, + rho_graupel = 400.0, + rho_snow = 100.0, + / + + +# Notes for model_nml: +# (1) vert_localization_coord must be one of: +# 1 = model level +# 2 = pressure +# 3 = height +# 4 = scale height + +# set default_state_variables to .false. to use the explicit list. +# otherwise it uses a hardcoded default list: U, V, W, PH, T, MU, QV only. +# see ../wrf_state_variables_table for a full list of what wrf fields are +# supported in the DART state vector, and what settings should be used here. +# 'UPDATE' and 'NO_COPY_BACK' are supported in the 4th column; 'NO_UPDATE' is +# not yet supported. + +&model_nml + default_state_variables = .false., + wrf_state_variables = 'U', 'QTY_U_WIND_COMPONENT', 'TYPE_U', 'UPDATE','999', + 'V', 'QTY_V_WIND_COMPONENT', 'TYPE_V', 'UPDATE','999', + 'W', 'QTY_VERTICAL_VELOCITY', 'TYPE_W', 'UPDATE','999', + 'PH', 'QTY_GEOPOTENTIAL_HEIGHT', 'TYPE_GZ', 'UPDATE','999', + 'T', 'QTY_POTENTIAL_TEMPERATURE','TYPE_T', 'UPDATE','999', + 'MU', 'QTY_PRESSURE', 'TYPE_MU', 'UPDATE','999', + 'QVAPOR','QTY_VAPOR_MIXING_RATIO', 'TYPE_QV', 'UPDATE','999', + 'QICE', 'QTY_ICE_MIXING_RATIO', 'TYPE_QI', 'UPDATE','999', + 'QCLOUD','QTY_CLOUDWATER_MIXING_RATIO','TYPE_QC', 'UPDATE','999', + 'CLDFRA','QTY_CLOUD_FRACTION', 'TYPE_CFRAC','UPDATE','999', + 'PSFC', 'QTY_SURFACE_PRESSURE', 'TYPE_PSFC', 'UPDATE','999', + 'T2', 'QTY_2M_TEMPERATURE', 'TYPE_T', 'UPDATE','999', + 'TSK', 'QTY_SKIN_TEMPERATURE', 'TYPE_T', 'UPDATE','999', + 'REFL_10CM','QTY_RADAR_REFLECTIVITY','TYPE_REFL', 'UPDATE','999', + wrf_state_bounds = 'QVAPOR','0.0','NULL','CLAMP', + 'QRAIN', '0.0','NULL','CLAMP', + 'QCLOUD','0.0','NULL','CLAMP', + 'QICE','0.0','NULL','CLAMP', + 'CLDFRA','0.0','1.0','CLAMP', + num_domains = 1, + calendar_type = 3, + assimilation_period_seconds = 21600, + vert_localization_coord = 3, + center_search_half_length = 500000., + center_spline_grid_scale = 10, + sfc_elev_max_diff = -1.0, + circulation_pres_level = 80000.0, + circulation_radius = 108000.0, + allow_obs_below_vol = .false. + / + +# vert_normalization_X is amount of X equiv to 1 radian in horiz. +# vert localization is 'cutoff' times the pressure/height/levels, +# only if horiz_dist_only is set to .false. in the namelist below. +# the default nlon/nlat should be good for most experiments. it sets +# an internal structure that speeds up searches. don't change it +# based on your grid size. nlon must be an odd number. +&location_nml + horiz_dist_only = .false., + vert_normalization_pressure = 6666666.7, + vert_normalization_height = 5000000.0, + vert_normalization_level = 2666.7, + vert_normalization_scale_height = 10.0, + approximate_distance = .false., + nlon = 71, + nlat = 36, + output_box_info = .false., + / + +&utilities_nml + TERMLEVEL = 1, + module_details = .false., + logfilename = 'dart_log.out', + nmlfilename = 'dart_log.nml', + write_nml = 'file', + / + +&mpi_utilities_nml + / + +®_factor_nml + select_regression = 1, + input_reg_file = "time_mean_reg", + save_reg_diagnostics = .false., + reg_diagnostics_file = "reg_diagnostics", + / + +# layout = 2 spreads the IO tasks across the nodes. +# This can greatly improve the performance in IO if +# tasks_per_node is set to match your hardware +&ensemble_manager_nml + layout = 2, + tasks_per_node = 16 + / + +&obs_def_gps_nml + max_gpsro_obs = 100000, + / + +&obs_def_tpw_nml + / + +# The times in the namelist for the obs_diag program are vectors +# that follow the following sequence: +# year month day hour minute second +# max_num_bins can be used to specify a fixed number of bins, +# in which case last_bin_center should be safely in the future. +# +# Acceptable latitudes range from [-90, 90] +# Acceptable longitudes range from [ 0, Inf] + +&obs_diag_nml + obs_sequence_name = 'obs_seq.final', + obs_sequence_list = '', + first_bin_center = 2003, 1, 1, 0, 0, 0 , + last_bin_center = 2003, 1, 2, 0, 0, 0 , + bin_separation = 0, 0, 0,12, 0, 0 , + bin_width = 0, 0, 0, 6, 0, 0 , + time_to_skip = 0, 0, 0, 0, 0, 0 , + max_num_bins = 1000, + trusted_obs = 'null', + Nregions = 4, + lonlim1 = 0.0, 0.0, 0.0, 235.0, + lonlim2 = 360.0, 360.0, 360.0, 295.0, + latlim1 = 20.0, -80.0, -20.0, 25.0, + latlim2 = 80.0, -20.0, 20.0, 55.0, + reg_names = 'Northern Hemisphere', 'Southern Hemisphere', 'Tropics', 'North America', + print_mismatched_locs = .false., + create_rank_histogram = .true., + outliers_in_histogram = .true., + use_zero_error_obs = .false., + verbose = .false. + / + +&schedule_nml + calendar = 'Gregorian', + first_bin_start = 1601, 1, 1, 0, 0, 0, + first_bin_end = 2999, 1, 1, 0, 0, 0, + last_bin_end = 2999, 1, 1, 0, 0, 0, + bin_interval_days = 1000000, + bin_interval_seconds = 0, + max_num_bins = 1000, + print_table = .true., + / + +&obs_seq_to_netcdf_nml + obs_sequence_name = 'obs_seq.final', + obs_sequence_list = '', + append_to_netcdf = .false., + lonlim1 = 0.0, + lonlim2 = 360.0, + latlim1 = -90.0, + latlim2 = 90.0, + verbose = .false., + / + +# There is one GIGANTIC difference between the obsdef_mask.txt and .nc +# The netCDF file intentionally ignores the effect of nTmin/nTmax. +# The netCDF file has ALL matching stations, regardless of temporal coverage. + +&obs_seq_coverage_nml + obs_sequences = '' + obs_sequence_list = 'obs_coverage_list.txt' + obs_of_interest = 'METAR_U_10_METER_WIND' + textfile_out = 'METAR_U_10_METER_WIND_obsdef_mask.txt' + netcdf_out = 'METAR_U_10_METER_WIND_obsdef_mask.nc' + first_analysis = 2003, 1, 1, 0, 0, 0 + last_analysis = 2003, 1, 2, 0, 0, 0 + forecast_length_days = 1 + forecast_length_seconds = 0 + verification_interval_seconds = 21600 + temporal_coverage_percent = 100.0 + lonlim1 = 0.0 + lonlim2 = 360.0 + latlim1 = -90.0 + latlim2 = 90.0 + verbose = .true. + / + +# selections_file is a list of obs_defs output +# from the obs_seq_coverage utility. + +&obs_selection_nml + filename_seq = 'obs_seq.out', + filename_seq_list = '', + filename_out = 'obs_seq.processed', + selections_file = 'obsdef_mask.txt', + selections_is_obs_seq = .false., + print_only = .false., + calendar = 'gregorian', + / + +&obs_seq_verify_nml + obs_sequences = '' + obs_sequence_list = 'obs_verify_list.txt' + input_template = 'obsdef_mask.nc' + netcdf_out = 'forecast.nc' + obtype_string = 'METAR_U_10_METER_WIND' + print_every = 10000 + verbose = .true. + debug = .false. + / + +&obs_sequence_tool_nml + num_input_files = 1, + filename_seq = 'obs_seq.out', + filename_out = 'obs_seq.processed', + first_obs_days = -1, + first_obs_seconds = -1, + last_obs_days = -1, + last_obs_seconds = -1, + obs_types = '', + keep_types = .false., + print_only = .false., + min_lat = -90.0, + max_lat = 90.0, + min_lon = 0.0, + max_lon = 360.0, + / + +&replace_wrf_fields_nml + debug = .false., + fail_on_missing_field = .false., + fieldnames = "SNOWC", + "ALBBCK", + "TMN", + "TSK", + "SH2O", + "SMOIS", + "SEAICE", + "HGT_d01", + "TSLB", + "SST", + "SNOWH", + "SNOW", + fieldlist_file = '', + / + +&obs_common_subset_nml + num_to_compare_at_once = 2, + filename_seq = 'obs_seq1.final', 'obs_seq2.final', + filename_seq_list = '', + filename_out_suffix = '.common' , + calendar = 'Gregorian', + print_every = 1000, + dart_qc_threshold = 3, + print_only = .false., + / + +&wrf_dart_to_fields_nml + include_slp = .true., + include_wind_components = .true., + include_height_on_pres = .true., + include_temperature = .true., + include_rel_humidity = .true., + include_surface_fields = .false., + include_sat_ir_temp = .false., + pres_levels = 70000., + / + +&ncepobs_nml + year = 2010, + month = 06, + day = 00, + tot_days = 1, + max_num = 1000000, + ObsBase = 'temp_obs.', + select_obs = 0, + ADPUPA = .false., + AIRCAR = .false., + AIRCFT = .false., + SATEMP = .false., + SFCSHP = .false., + ADPSFC = .false., + SATWND = .true., + obs_U = .false., + obs_V = .false., + obs_T = .false., + obs_PS = .false., + obs_QV = .false., + daily_file = .true., + obs_time = .false., + lat1 = 10.00, + lat2 = 60.00, + lon1 = 210.0, + lon2 = 300.0 + / + +&prep_bufr_nml + obs_window_upa = 1.0, + obs_window_air = 1.0, + obs_window_cw = 1.0, + otype_use = 242.0, 243.0, 245.0, 246.0, 251.0, 252.0, 253.0, 257.0, 259.0 + qctype_use = 0, 1, 2, 3, 4, 9, 15 + / + +&convert_cosmic_gps_nml + gpsro_netcdf_file = '', + gpsro_netcdf_filelist = 'flist', + gpsro_out_file = 'obs_seq.gpsro', + local_operator = .true., + obs_levels = 0.22, 0.55, 1.1, 1.8, 2.7, 3.7, 4.9, + 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, + ray_ds = 5000.0, + ray_htop = 13000.1, + / + +&wrf_obs_preproc_nml + + file_name_input = 'obs_seq20110901' + file_name_output = 'obs_seq.europe.prev' + + overwrite_obs_time = .false. + + obs_boundary = 0.0 + increase_bdy_error = .false. + maxobsfac = 2.5 + obsdistbdy = 1.0 + + sfc_elevation_check = .false. + sfc_elevation_tol = 3000.0 + obs_pressure_top = 0.0 + obs_height_top = 2.0e10 + + include_sig_data = .true. + tc_sonde_radii = -1.0 + + superob_aircraft = .true. + aircraft_horiz_int = 800.0 + aircraft_pres_int = 25000.0 + + superob_sat_winds = .true. + sat_wind_horiz_int = 800.0 + sat_wind_pres_int = 25000.0 + + overwrite_ncep_satwnd_qc = .false. + overwrite_ncep_sfc_qc = .false. + / + +! sonde_extra = 'obs_seq.rawin' +! land_sfc_extra = 'obs_seq.land_sfc' +! metar_extra = 'obs_seq.metar' +! marine_sfc_extra = 'obs_seq.marine' +! sat_wind_extra = 'obs_seq.satwnd' +! profiler_extra = 'obs_seq.profiler' +! gpsro_extra = 'obs_seq.gpsro' +! acars_extra = 'obs_seq.acars' +! trop_cyclone_extra = 'obs_seq.tc' + +&state_vector_io_nml + single_precision_output = .true., + / + +&compare_states_nml + / + +&closest_member_tool_nml + input_restart_file_list = 'input_file_list_d01.txt', + output_file_name = 'closest_results.txt' + ens_size = 3, + single_restart_file_in = .false., + difference_method = 4, + use_only_qtys = 'QTY_U_WIND_COMPONENT' + / + +# To test both domains, you must change 'model_nml:num_domains = 2' + +&model_mod_check_nml + input_state_files = 'wrfinput_d01', 'wrfinput_d02' + output_state_files = 'mmc_output1.nc', 'mmc_output2.nc' + test1thru = 0 + run_tests = 1,2,3,4,5 + x_ind = 87370 + loc_of_interest = 231.0, 40.0, 10.0 + quantity_of_interest = 'QTY_U_WIND_COMPONENT' + interp_test_dlon = 0.1 + interp_test_dlat = 0.1 + interp_test_dvert = 1000.0 + interp_test_lonrange = 250.0, 260.0 + interp_test_latrange = 30.0, 45.0 + interp_test_vertrange = 2000.0, 4000.0 + interp_test_vertcoord = 'VERTISHEIGHT' + verbose = .false. + / + diff --git a/tests/test_inputnml.py b/tests/test_inputnml.py new file mode 100644 index 0000000000000000000000000000000000000000..26466033dd02a2a1fca25dbf326359e26307fbc4 --- /dev/null +++ b/tests/test_inputnml.py @@ -0,0 +1,47 @@ +import os, shutil +import datetime as dt + +from dartwrf import dart_nml + + + +def test_input_nml(): + test_input = './input.nml.original' + test_output = './input.nml.output' + desired_output = './input.nml.desired_output' + + # read an existing input.nml + nml = dart_nml.read_namelist(test_input) + + # modify one parameter + nml['&filter_nml']['ens_size'] = [[str(999)]] + nml['&filter_nml']['num_output_state_members'] = [[str(999)]] + nml['&filter_nml']['num_output_obs_members'] = [[str(999)]] + + # save the configuration as input.nml + dart_nml.write_namelist_from_dict(nml, test_output) + + # compare the saved input.nml to the true input.nml + # by reading both and comparing the dictionaries + nml_desired = dart_nml.read_namelist(desired_output) + nml_test = dart_nml.read_namelist(test_output) + + for section, _ in nml_desired.items(): + + for param, value in nml_desired[section].items(): + + should_have = nml_desired[section][param] + should_have = [v.strip() for line in should_have for v in line] + + have = nml_test[section][param] + have = [v.strip() for line in have for v in line] + + if should_have != have: + + raise ValueError(section, param, 'should be', should_have, 'but is', have) + + + os.remove(test_output) + +if __name__ == '__main__': + test_input_nml()