Skip to content
Snippets Groups Projects
Commit 1b40bce3 authored by Moritz Hanke's avatar Moritz Hanke
Browse files

adds support for CDO-generated weight files to weights2vtk

parent b04e684a
No related branches found
No related tags found
No related merge requests found
......@@ -13,11 +13,18 @@
#include "yac_utils.h"
#define YAC_WEIGHT_FILE_VERSION_1_0_STRING "yac weight file 1.0"
#define CDO_WEIGHT_FILE_TITLE "CDO remapping"
// redefine YAC assert macros
#undef YAC_ASSERT
#undef YAC_ASSERT_F
enum weight_file_type {
WGT_YAC_1_0,
WGT_CDO,
WGT_UNKNOWN,
};
static char const * cmd;
#define STR_USAGE \
"Usage: %s -S src_grid_type -T tgt_grid_type " \
......@@ -198,6 +205,49 @@ int main(int argc, char ** argv) {
return EXIT_SUCCESS;
}
static int check_global_attribute(
int ncid, char const * att_name, char const * ref_att_text) {
int att_matches = 0;
// global attributes
size_t att_len;
int status = nc_inq_attlen(ncid, NC_GLOBAL, att_name, &att_len);
if (status == NC_NOERR) {
char * att_text;
att_text = malloc(att_len + 1);
att_text[att_len] = '\0';
YAC_HANDLE_ERROR(nc_get_att_text(ncid, NC_GLOBAL, att_name, att_text));
YAC_ASSERT_F(
(strlen(ref_att_text) == att_len) &&
!strncmp(att_text, ref_att_text, att_len),
"NetCDF file contains attribute string \"%s\", "
"but its text does not match (\"%s\" != \"%s\")",
att_name, att_text, ref_att_text);
free(att_text);
att_matches = 1;
} else if (status == NC_ENOTATT) {
status = NC_NOERR;
}
YAC_HANDLE_ERROR(status);
return att_matches;
}
static enum weight_file_type determine_weight_file_type(int ncid) {
// check for YAC weight file
if (check_global_attribute(
ncid, "version", YAC_WEIGHT_FILE_VERSION_1_0_STRING))
return WGT_YAC_1_0;
// check for CDO weight file
if (check_global_attribute(
ncid, "title", CDO_WEIGHT_FILE_TITLE))
return WGT_CDO;
return WGT_UNKNOWN;
}
static void read_link_data(
char const * weight_filename, int src_address_offset,
int tgt_address_offset, struct link_data ** links,
......@@ -208,51 +258,50 @@ static void read_link_data(
int ncid, dimid, var_id;
yac_nc_open(weight_filename, NC_NOWRITE, &ncid);
// global attributes
size_t version_len;
char * version;
YAC_HANDLE_ERROR(nc_inq_attlen(ncid, NC_GLOBAL, "version", &version_len));
version = malloc(version_len + 1);
version[version_len] = '\0';
YAC_HANDLE_ERROR(nc_get_att_text(ncid, NC_GLOBAL, "version", version));
YAC_ASSERT(
(strlen(YAC_WEIGHT_FILE_VERSION_1_0_STRING) == version_len) &&
!strncmp(version, YAC_WEIGHT_FILE_VERSION_1_0_STRING, version_len),
"version string from weight file is not \""
YAC_WEIGHT_FILE_VERSION_1_0_STRING "\"");
free(version);
size_t str_link_len;
char * str_link;
var_id = NC_GLOBAL;
YAC_HANDLE_ERROR(nc_inq_attlen(ncid, var_id, "contains_links", &str_link_len));
str_link = malloc(str_link_len + 1);
str_link[str_link_len] = '\0';
YAC_HANDLE_ERROR(nc_get_att_text(ncid, var_id, "contains_links", str_link));
int contains_links =
(strlen("TRUE") == str_link_len) &&
!strncmp("TRUE", str_link, str_link_len);
enum weight_file_type wgt_type = determine_weight_file_type(ncid);
YAC_ASSERT(
contains_links ||
((strlen("FALSE") == str_link_len) &&
!strncmp("FALSE", str_link, str_link_len)),
"invalid global attribute contains_links")
if (!contains_links) {
*links = NULL;
*num_links = 0;
*src_locations = NULL;
*max_src_idx = 0;
*max_tgt_idx = 0;
return;
(wgt_type == WGT_YAC_1_0) ||
(wgt_type == WGT_CDO),
"ERROR(read_link_data): unsupported weight file type")
if (wgt_type == WGT_YAC_1_0) {
size_t str_link_len;
char * str_link;
var_id = NC_GLOBAL;
YAC_HANDLE_ERROR(nc_inq_attlen(ncid, var_id, "contains_links", &str_link_len));
str_link = malloc(str_link_len + 1);
str_link[str_link_len] = '\0';
YAC_HANDLE_ERROR(nc_get_att_text(ncid, var_id, "contains_links", str_link));
int contains_links =
(strlen("TRUE") == str_link_len) &&
!strncmp("TRUE", str_link, str_link_len);
YAC_ASSERT(
contains_links ||
((strlen("FALSE") == str_link_len) &&
!strncmp("FALSE", str_link, str_link_len)),
"invalid global attribute contains_links")
free(str_link);
if (!contains_links) {
*links = NULL;
*num_links = 0;
*src_locations = NULL;
*max_src_idx = 0;
*max_tgt_idx = 0;
return;
}
}
size_t num_wgts = 0;
yac_nc_inq_dimid(ncid, "num_wgts", &dimid);
YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &num_wgts));
YAC_ASSERT(
num_wgts == 1, "YAC only supports num_wgts == 1")
YAC_ASSERT_F(
num_wgts == 1, "unsupported number of weights per link "
"(num_wgts = %zu; has to be 1)", num_wgts)
// get number of links from file
size_t num_links_in_file = 0;
......@@ -262,54 +311,79 @@ static void read_link_data(
*num_links = num_links_in_file;
*links = malloc(num_links_in_file * sizeof(**links));
// get number of pointsets
size_t num_pointsets = 0;
yac_nc_inq_dimid(ncid, "num_src_fields", &dimid);
YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &num_pointsets));
YAC_ASSERT(num_pointsets > 0, "no point sets in file")
// get max location string length from file
size_t max_loc_str_len;
yac_nc_inq_dimid(ncid, "max_loc_str_len", &dimid);
YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &max_loc_str_len));
YAC_ASSERT(
max_loc_str_len == YAC_MAX_LOC_STR_LEN,
"wrong max location string length in weight file")
unsigned * num_links_per_pointset;
// get source locations
*src_locations = malloc(num_pointsets * sizeof(**src_locations));
yac_nc_inq_varid(ncid, "src_locations", &var_id);
// read weight file type specific fields
switch (wgt_type) {
case (WGT_YAC_1_0): {
for (unsigned i = 0; i < num_pointsets; ++i) {
// get number of pointsets
yac_nc_inq_dimid(ncid, "num_src_fields", &dimid);
char loc_str[YAC_MAX_LOC_STR_LEN];
num_pointsets = 0;
YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &num_pointsets));
YAC_ASSERT(num_pointsets > 0, "no point sets in file")
size_t str_start[2] = {i, 0};
size_t str_count[2] = {1, YAC_MAX_LOC_STR_LEN};
// get max location string length from file
size_t max_loc_str_len;
yac_nc_inq_dimid(ncid, "max_loc_str_len", &dimid);
YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &max_loc_str_len));
YAC_ASSERT(
max_loc_str_len == YAC_MAX_LOC_STR_LEN,
"wrong max location string length in weight file")
YAC_HANDLE_ERROR(nc_get_vara_text(ncid, var_id, str_start, str_count, loc_str));
// get source locations
*src_locations = malloc(num_pointsets * sizeof(**src_locations));
yac_nc_inq_varid(ncid, "src_locations", &var_id);
(*src_locations)[i] = yac_str2loc(loc_str);
}
for (unsigned i = 0; i < num_pointsets; ++i) {
// get target location
yac_nc_inq_varid(ncid, "dst_location", &var_id);
{
char loc_str[YAC_MAX_LOC_STR_LEN];
YAC_HANDLE_ERROR(nc_get_var_text(ncid, var_id, loc_str));
*tgt_location = yac_str2loc(loc_str);
}
char loc_str[YAC_MAX_LOC_STR_LEN];
size_t str_start[2] = {i, 0};
size_t str_count[2] = {1, YAC_MAX_LOC_STR_LEN};
YAC_HANDLE_ERROR(
nc_get_vara_text(ncid, var_id, str_start, str_count, loc_str));
(*src_locations)[i] = yac_str2loc(loc_str);
}
// get target location
yac_nc_inq_varid(ncid, "dst_location", &var_id);
{
char loc_str[YAC_MAX_LOC_STR_LEN];
YAC_HANDLE_ERROR(nc_get_var_text(ncid, var_id, loc_str));
*tgt_location = yac_str2loc(loc_str);
}
// get number of links per pointset
num_links_per_pointset =
malloc(num_pointsets * sizeof(*num_links_per_pointset));
yac_nc_inq_varid(ncid, "num_links_per_src_field", &var_id);
YAC_HANDLE_ERROR(nc_get_var_uint(ncid, var_id, num_links_per_pointset));
// get number of links per pointset
unsigned * num_links_per_pointset =
malloc(num_pointsets * sizeof(*num_links_per_pointset));
yac_nc_inq_varid(ncid, "num_links_per_src_field", &var_id);
YAC_HANDLE_ERROR(nc_get_var_uint(ncid, var_id, num_links_per_pointset));
break;
}
default:
case (WGT_CDO): {
num_pointsets = 1;
*src_locations = malloc(num_pointsets * sizeof(**src_locations));
(*src_locations)[0] = YAC_LOC_CELL;
*tgt_location = YAC_LOC_CELL;
num_links_per_pointset =
malloc(num_pointsets * sizeof(*num_links_per_pointset));
num_links_per_pointset[0] = num_links_in_file;
break;
}
};
for (unsigned points_idx = 0, link_idx = 0; points_idx < num_pointsets;
++points_idx)
++points_idx)
for (unsigned i = 0; i < num_links_per_pointset[points_idx];
++i, ++link_idx)
++i, ++link_idx)
(*links)[link_idx].points_idx = points_idx;
free(num_links_per_pointset);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment