Skip to content

Commit

Permalink
Merge pull request #1719 from dtcenter/bugfix_1715_pb2nc_seg_fault_wi…
Browse files Browse the repository at this point in the history
…th_pbl

Bugfix 1715 pb2nc seg fault with pbl
  • Loading branch information
hsoh-u authored Mar 18, 2021
2 parents 92f0ff0 + b7fb7c1 commit 7998d89
Show file tree
Hide file tree
Showing 3 changed files with 242 additions and 28 deletions.
89 changes: 61 additions & 28 deletions met/src/tools/other/pb2nc/pb2nc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2428,7 +2428,7 @@ void write_netcdf_hdr_data() {

// Check for no messages retained
if(dim_count <= 0) {
mlog << Error << method_name << " -> "
mlog << Error << "\n" << method_name << " -> "
<< "No PrepBufr messages retained. Nothing to write.\n\n";
// Delete the NetCDF file
remove_temp_file(ncfile);
Expand Down Expand Up @@ -2920,39 +2920,64 @@ int combine_tqz_and_uv(map<float, float*> pqtzuv_map_tq,
float *pqtzuv_tq, *pqtzuv_uv;
float *pqtzuv_merged = (float *) 0;
float *next_pqtzuv, *prev_pqtzuv;
float tq_pres_max, tq_pres_min, uv_pres_max, uv_pres_min;
std::map<float,float*>::iterator it, it_tq, it_uv;

// Gets pressure levels for TQZ records
for (it=pqtzuv_map_tq.begin(); it!=pqtzuv_map_tq.end(); ++it) {
tq_levels.add(int(it->first));
it = pqtzuv_map_tq.begin();
tq_pres_min = tq_pres_max = it->first;
for (; it!=pqtzuv_map_tq.end(); ++it) {
float pres_v = it->first;
if (tq_pres_min > pres_v) tq_pres_min = pres_v;
if (tq_pres_max < pres_v) tq_pres_max = pres_v;
tq_levels.add(nint(pres_v));
}
// Gets pressure levels for common records
for (it=pqtzuv_map_uv.begin(); it!=pqtzuv_map_uv.end(); ++it) {
if (tq_levels.has(int(it->first))) {
common_levels.add(int(it->first));
it = pqtzuv_map_uv.begin();
uv_pres_min = uv_pres_max = it->first;
for (; it!=pqtzuv_map_uv.end(); ++it) {
float pres_v = it->first;
if (uv_pres_min > pres_v) uv_pres_min = pres_v;
if (uv_pres_max < pres_v) uv_pres_max = pres_v;
if (tq_levels.has(nint(pres_v))) {
common_levels.add(nint(pres_v));
}
}

if(mlog.verbosity_level() >= PBL_DEBUG_LEVEL) {
log_tqz_and_uv(pqtzuv_map_tq, pqtzuv_map_uv, method_name);
}

bool no_overlap = (tq_pres_max < uv_pres_min) || (tq_pres_min > uv_pres_max);
mlog << Debug(6) << method_name << "TQZ pressures: " << tq_pres_max
<< " to " << tq_pres_min << " UV pressures: " << uv_pres_max
<< " to " << uv_pres_min << (no_overlap ? " no overlap!" : " overlapping") << "\n";
if( no_overlap ) {
mlog << Warning << "\n" << method_name
<< "Can not combine TQ and UV records because of no overlapping."
<< " TQZ count: " << tq_count << ", UV count: " << uv_count
<< " common_levels: " << common_levels.n() << "\n\n";
return pqtzuv_map_merged.size();
}

// Select first record by 1) merging two records with the same pressure
// level or 2) interpolate
int tq_pres, uv_pres;
next_pqtzuv = (float *)0;
it_tq = pqtzuv_map_tq.begin();
it_uv = pqtzuv_map_uv.begin();
pqtzuv_tq = (float *)it_tq->second;
pqtzuv_uv = (float *)it_uv->second;;
pqtzuv_merged = new float[mxr8vt];
if (common_levels.has(int(it_tq->first))
|| common_levels.has(int(it_uv->first))) {
tq_pres = nint(it_tq->first);
uv_pres = nint(it_uv->first);
if (common_levels.has(tq_pres) || common_levels.has(uv_pres)) {
// Found the records with the same precsure level
if (it_tq->first != it_uv->first) {
if (common_levels.has(int(it_uv->first))) {
if (tq_pres != uv_pres) {
if (common_levels.has(uv_pres)) {
pqtzuv_uv = pqtzuv_map_uv[it_uv->first];
}
else if (common_levels.has(int(it_tq->first))) {
else if (common_levels.has(tq_pres)) {
pqtzuv_tq = pqtzuv_map_tq[it_tq->first];
}
}
Expand All @@ -2968,7 +2993,7 @@ int combine_tqz_and_uv(map<float, float*> pqtzuv_map_tq,
prev_pqtzuv = (float *)it_uv->second;
++it_uv;
}
next_pqtzuv = it_uv->second;
next_pqtzuv = (float *)it_uv->second;
}
else {
//Interpolate TQZ into UV
Expand All @@ -2978,7 +3003,7 @@ int combine_tqz_and_uv(map<float, float*> pqtzuv_map_tq,
prev_pqtzuv = (float *)it_tq->second;
++it_tq;
}
next_pqtzuv = it_tq->second;
next_pqtzuv = (float *)it_tq->second;
}
interpolate_pqtzuv(prev_pqtzuv, pqtzuv_merged, next_pqtzuv);
}
Expand All @@ -2996,6 +3021,7 @@ int combine_tqz_and_uv(map<float, float*> pqtzuv_map_tq,
if(mlog.verbosity_level() >= PBL_DEBUG_LEVEL) {
log_merged_tqz_uv(pqtzuv_map_tq, pqtzuv_map_uv, pqtzuv_map_merged, method_name);
}
delete [] pqtzuv_merged;
}

return pqtzuv_map_merged.size();
Expand Down Expand Up @@ -3034,7 +3060,7 @@ float compute_pbl(map<float, float*> pqtzuv_map_tq,
hgt_cnt = spfh_cnt = 0;
for (it=pqtzuv_map_merged.begin(); it!=pqtzuv_map_merged.end(); ++it) {
if (index < 0) {
mlog << Error << method_name << "negative index: " << index << "\n";
mlog << Error << "\n" << method_name << "negative index: " << index << "\n\n";
break;
}

Expand All @@ -3048,13 +3074,13 @@ float compute_pbl(map<float, float*> pqtzuv_map_tq,
pbl_data_vgrd[index] = pqtzuv[5];
if (!is_eq(pbl_data_spfh[index], bad_data_float)) spfh_cnt++;
if (!is_eq(pbl_data_hgt[index], bad_data_float)) hgt_cnt++;
selected_levels.add(int(it->first));
selected_levels.add(nint(it->first));
}

index--;
}
if (index != -1) {
mlog << Error << method_name << "Missing some levels (" << index << ")\n";
mlog << Error << "\n" << method_name << "Missing some levels (" << index << ")\n";
}

if (pbl_level > MAX_PBL_LEVEL) {
Expand All @@ -3070,7 +3096,7 @@ float compute_pbl(map<float, float*> pqtzuv_map_tq,
if (!is_eq(highest_pressure, bad_data_float)) {
index = MAX_PBL_LEVEL - 1;
for (; it!=pqtzuv_map_tq.end(); ++it) {
int pres_level = int(it->first);
int pres_level = nint(it->first);
if (selected_levels.has(pres_level)) break;

float *pqtzuv = pqtzuv_map_merged[it->first];
Expand Down Expand Up @@ -3139,10 +3165,10 @@ void insert_pbl(float *obs_arr, const float pbl_value, const int pbl_code,
hdr_info << unix_to_yyyymmdd_hhmmss(hdr_vld_ut)
<< " " << hdr_typ << " " << hdr_sid;
if (is_eq(pbl_value, bad_data_float)) {
mlog << Warning << "Failed to compute PBL " << hdr_info << "\n\n";
mlog << Warning << "\nFailed to compute PBL " << hdr_info << "\n\n";
}
else if (pbl_value < hdr_elv) {
mlog << Warning << "Not saved because the computed PBL (" << pbl_value
mlog << Warning << "\nNot saved because the computed PBL (" << pbl_value
<< ") is less than the station elevation (" << hdr_elv
<< "). " << hdr_info << "\n\n";
obs_arr[4] = 0;
Expand All @@ -3156,7 +3182,7 @@ void insert_pbl(float *obs_arr, const float pbl_value, const int pbl_code,
<< " lat: " << hdr_lat << ", lon: " << hdr_lon
<< ", elv: " << hdr_elv << " " << hdr_info << "\n\n";
if (obs_arr[4] > MAX_PBL) {
mlog << Warning << " Computed PBL (" << obs_arr[4] << " from "
mlog << Warning << "\nComputed PBL (" << obs_arr[4] << " from "
<< pbl_value << ") is too high, Reset to " << MAX_PBL
<< " " << hdr_info<< "\n\n";
obs_arr[4] = MAX_PBL;
Expand Down Expand Up @@ -3192,9 +3218,14 @@ int interpolate_by_pressure(int length, float *pres_data, float *var_data) {
<< var_data[idx_start] << " and " << var_data[idx_end] << "\n";
float data_diff = var_data[idx_end] - var_data[idx_start];
for (idx2 = idx_start+1; idx2<idx_end; idx2++) {
float pres_ratio = (pres_data[idx2] - pres_data[idx_start])
/ (pres_data[idx_end] - pres_data[idx_start]);
var_data[idx2] = var_data[idx_start] + (data_diff * pres_ratio);
if (!is_eq(pres_data[idx_end], pres_data[idx_start])) {
float pres_ratio = (pres_data[idx2] - pres_data[idx_start])
/ (pres_data[idx_end] - pres_data[idx_start]);
var_data[idx2] = var_data[idx_start] + (data_diff * pres_ratio);
}
else {
var_data[idx2] = var_data[idx_start];
}
mlog << Debug(7) << method_name << " interpolated value["
<< idx2 << "] = " << var_data[idx2] << "\n";
count_interpolated++;
Expand All @@ -3219,11 +3250,13 @@ int interpolate_by_pressure(int length, float *pres_data, float *var_data) {
void interpolate_pqtzuv(float *prev_pqtzuv, float *cur_pqtzuv, float *next_pqtzuv) {
static const char *method_name = "interpolate_pqtzuv() ";

if ((prev_pqtzuv[0] == cur_pqtzuv[0]) || (next_pqtzuv[0] == cur_pqtzuv[0])) {
mlog << Error << method_name
if ((nint(prev_pqtzuv[0]) == nint(cur_pqtzuv[0]))
|| (nint(next_pqtzuv[0]) == nint(cur_pqtzuv[0]))
|| (nint(prev_pqtzuv[0]) == nint(next_pqtzuv[0]))) {
mlog << Error << "\n" << method_name
<< " Can't interpolate because of same pressure levels. prev: "
<< prev_pqtzuv[0] << ", cur: " << cur_pqtzuv[0]
<< ", next: " << prev_pqtzuv[0] << "\n";
<< ", next: " << prev_pqtzuv[0] << "\n\n";
}
else {
float p_ratio = (cur_pqtzuv[0] - prev_pqtzuv[0]) / (next_pqtzuv[0] - prev_pqtzuv[0]);
Expand Down Expand Up @@ -3272,8 +3305,8 @@ void merge_records(float *first_pqtzuv, map<float, float*> pqtzuv_map_pivot,
if (first_pres < it_pivot->first) break;
}
mlog << Debug(8) << method_name << "pivot->first: " << it_pivot->first
<< " aux->first " << it_aux->first << " first_pres: " << first_pres
<< " prev_pqtzuv[0]" << prev_pqtzuv[0] << "\n";
<< " aux->first: " << it_aux->first << " first_pres: " << first_pres
<< " prev_pqtzuv[0]: " << prev_pqtzuv[0] << "\n";
// Find next UV level
for (; it_aux!=pqtzuv_map_aux.end(); ++it_aux) {
// Skip the records below the first mathcing/interpolated level
Expand Down
162 changes: 162 additions & 0 deletions test/config/PB2NCConfig_pbl
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
////////////////////////////////////////////////////////////////////////////////
//
// PB2NC configuration file.
//
// For additional information, see the MET_BASE/config/README file.
//
////////////////////////////////////////////////////////////////////////////////

//
// PrepBufr message type
//
message_type = ["ONLYSF", "ADPUPA"];

//
// Mapping of message type group name to comma-separated list of values
// Derive PRMSL only for SURFACE message types
//
message_type_group_map = [
{ key = "SURFACE"; val = "ADPSFC,SFCSHP,MSONET"; },
{ key = "ANYAIR"; val = "AIRCAR,AIRCFT"; },
{ key = "ANYSFC"; val = "ADPSFC,SFCSHP,ADPUPA,PROFLR,MSONET"; },
{ key = "ONLYSF"; val = "ADPSFC,SFCSHP"; }
];

//
// Mapping of input PrepBufr message types to output message types
//
message_type_map = [];

//
// PrepBufr station ID
//
station_id = [];

////////////////////////////////////////////////////////////////////////////////

//
// Observation time window
//
obs_window = {
beg = -2700;
end = 2700;
}

////////////////////////////////////////////////////////////////////////////////

//
// Observation retention regions
//
mask = {
grid = "";
poly = "";
}

////////////////////////////////////////////////////////////////////////////////

//
// Observing location elevation
//
elevation_range = {
beg = -1000;
end = 100000;
}

////////////////////////////////////////////////////////////////////////////////

//
// Observation types
//
pb_report_type = [];

in_report_type = [];

instrument_type = [];

////////////////////////////////////////////////////////////////////////////////

//
// Vertical levels to retain
//
level_range = {
beg = 1;
end = 511;
}

level_category = [0, 1, 4, 5, 6];

///////////////////////////////////////////////////////////////////////////////

//
// BUFR variable names to retain or derive.
// Use obs_bufr_map to rename variables in the output.
// If empty, process all available variables.
//
obs_bufr_var = ["D_CAPE", "D_PBL"];
////////////////////////////////////////////////////////////////////////////////

//
// Mapping of input BUFR variable names to output variables names.
// The default PREPBUFR map, obs_prepbufr_map, is appended to this map.
//
obs_bufr_map = [];

//
// Default mapping for PREPBUFR. Replace input BUFR variable names with GRIB
// abbreviations in the output. This default map is appended to obs_bufr_map.
// This should not typically be overridden.
//
obs_prefbufr_map = [
{ key = "POB"; val = "PRES"; },
{ key = "QOB"; val = "SPFH"; },
{ key = "TOB"; val = "TMP"; },
{ key = "UOB"; val = "UGRD"; },
{ key = "VOB"; val = "VGRD"; },
{ key = "D_DPT"; val = "DPT"; },
{ key = "D_WDIR"; val = "WDIR"; },
{ key = "D_WIND"; val = "WIND"; },
{ key = "D_RH"; val = "RH"; },
{ key = "D_MIXR"; val = "MIXR"; },
{ key = "D_PBL"; val = "HPBL"; },
{ key = "D_PRMSL"; val = "PRMSL"; },
{ key = "D_CAPE"; val = "CAPE"; },
{ key = "TDO"; val = "DPT"; },
{ key = "PMO"; val = "PRMSL"; },
{ key = "TOCC"; val = "TCDC"; },
{ key = "HOVI"; val = "VIS"; },
{ key = "CEILING"; val = "HGT"; },
{ key = "MXGS"; val = "GUST"; }
];

////////////////////////////////////////////////////////////////////////////////

quality_mark_thresh = 9;
event_stack_flag = TOP;

////////////////////////////////////////////////////////////////////////////////

//
// Time periods for the summarization
// obs_var (string array) is added and works like grib_code (int array)
// when use_var_id is enabled and variable names are saved.
//
time_summary = {
flag = FALSE;
raw_data = FALSE;
beg = "000000";
end = "235959";
step = 300;
width = 600;
grib_code = [];
obs_var = [ "TMP", "WDIR", "RH" ];
type = [ "min", "max", "range", "mean", "stdev", "median", "p80" ];
vld_freq = 0;
vld_thresh = 0.0;
}

////////////////////////////////////////////////////////////////////////////////

tmp_dir = "/tmp";
version = "V10.0";

////////////////////////////////////////////////////////////////////////////////
Loading

0 comments on commit 7998d89

Please sign in to comment.