15#define YAC_WEIGHT_FILE_VERSION_1_0_STRING "yac weight file 1.0"
16#define CDO_WEIGHT_FILE_TITLE "CDO remapping"
28static char const *
cmd;
30 "Usage: %s -S src_grid_type -T tgt_grid_type " \
31 "-s src_filename -t tgt_filename -w weight_filename " \
32 "-o vtk_filename\n\n" \
33 " grid_type can have the following values:\n" \
34 " 'c', 'C': cubed sphere grid (instead of a " \
35 "filename provide N, where\n" \
36 " N = sqrt(n/6), with n being the " \
37 "total number of cells\n" \
38 " 'm', 'M': curvilinear grid\n" \
39 " 'i', 'I': unstructured grid\n" \
40 " 'g', 'G': gaussian grid (instead of a filename provide the grid\n" \
41 " configuration \"x1,y1,x2,y2,nx,ny\", where:\n"\
42 " x1,y1: are the coordinates of the first grid corner\n"\
43 " x2,y2: are the coordinates of the last grid corner\n"\
44 " nx,ny: are the number of cells in each direction\n"\
45 " example: 0.0,-90.0,360.0,90.0,360,180)\n"\
46 " 's', 'S': unstructured grid in scrip file format\n" \
47 " (in addition to the grid filename also provide \n" \
48 " the mask filename and the grid name \"g,m,n\", where:\n" \
49 " g: grid filename\n" \
50 " m: mask filename\n" \
52 " - a lower case grid type indicates, that the global ids\n" \
53 " of the respective grid were \"0\"-based in the model\n" \
54 " component that generated the weight file\n" \
55 " - an upper case grid type indicates \"1\"-based global\n" \
60 " source grid type: unstructured\n" \
61 " source grid file: src_grid.nc\n" \
62 " target grid type: cubed sphere\n" \
63 " target grid file: 100 (N instead of filename)\n" \
64 " weight file name: weight_file.nc\n" \
65 " vtk file name: weights.vtk\n" \
67 " %s -S i -T c -s src_grid.nc -t 100 -w weight_file.nc " \
70#define YAC_ASSERT(exp, msg) \
73 fprintf(stderr, "ERROR: %s\n" STR_USAGE, msg, cmd, cmd); \
78#define YAC_ASSERT_F(exp, format, ...) \
81 fprintf(stderr, "ERROR: " format "\n" STR_USAGE, __VA_ARGS__, cmd, cmd); \
88 double norm = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
138 char const ** weight_filename,
139 char const ** vtk_filename);
140static void read_link_data(
char const * weight_filename,
int src_address_offset,
141 int tgt_address_offset,
struct link_data ** links,
142 unsigned * num_links,
enum yac_location ** src_locations,
143 enum yac_location * tgt_location,
unsigned * max_src_idx,
144 unsigned * max_tgt_idx);
154int main(
int argc,
char ** argv) {
158 struct grid_config src_grid_config, tgt_grid_config;
159 char const * weight_filename, * vtk_filename;
162 &weight_filename, &vtk_filename);
175 "File %s does not exist.", weight_filename)
178 unsigned num_links, max_src_idx, max_tgt_idx;
183 &src_locations, &tgt_location, &max_src_idx, &max_tgt_idx);
187 "weight file does not match with source and target grid")
193 vtk_filename, src_grid, tgt_grid, links, num_links,
194 src_locations, tgt_location);
209 int ncid,
char const * att_name,
char const * ref_att_text) {
215 int status = nc_inq_attlen(ncid, NC_GLOBAL, att_name, &att_len);
216 if (status == NC_NOERR) {
218 att_text = malloc(att_len + 1);
219 att_text[att_len] =
'\0';
222 (strlen(ref_att_text) == att_len) &&
223 !strncmp(att_text, ref_att_text, att_len),
224 "NetCDF file contains attribute string \"%s\", "
225 "but its text does not match (\"%s\" != \"%s\")",
226 att_name, att_text, ref_att_text);
229 }
else if (status == NC_ENOTATT) {
252 char const * weight_filename,
int src_address_offset,
253 int tgt_address_offset,
struct link_data ** links,
254 unsigned * num_links,
enum yac_location ** src_locations,
255 enum yac_location * tgt_location,
unsigned * max_src_idx,
256 unsigned * max_tgt_idx) {
258 int ncid, dimid, var_id;
266 "ERROR(read_link_data): unsupported weight file type")
273 YAC_HANDLE_ERROR(nc_inq_attlen(ncid, var_id,
"contains_links", &str_link_len));
274 str_link = malloc(str_link_len + 1);
275 str_link[str_link_len] =
'\0';
276 YAC_HANDLE_ERROR(nc_get_att_text(ncid, var_id,
"contains_links", str_link));
279 (strlen(
"TRUE") == str_link_len) &&
280 !strncmp(
"TRUE", str_link, str_link_len);
283 ((strlen(
"FALSE") == str_link_len) &&
284 !strncmp(
"FALSE", str_link, str_link_len)),
285 "invalid global attribute contains_links")
289 if (!contains_links) {
292 *src_locations = NULL;
303 num_wgts == 1,
"unsupported number of weights per link "
304 "(num_wgts = %zu; has to be 1)", num_wgts)
307 size_t num_links_in_file = 0;
310 YAC_ASSERT(num_links_in_file > 0,
"no links defined")
311 *num_links = num_links_in_file;
312 *links = malloc(num_links_in_file *
sizeof(**links));
314 size_t num_pointsets = 0;
315 unsigned * num_links_per_pointset;
326 YAC_ASSERT(num_pointsets > 0,
"no point sets in file")
329 size_t max_loc_str_len;
334 "wrong max location string length in weight file")
337 *src_locations = malloc(num_pointsets *
sizeof(**src_locations));
340 for (
unsigned i = 0; i < num_pointsets; ++i) {
344 size_t str_start[2] = {i, 0};
348 nc_get_vara_text(ncid, var_id, str_start, str_count, loc_str));
362 num_links_per_pointset =
363 malloc(num_pointsets *
sizeof(*num_links_per_pointset));
373 *src_locations = malloc(num_pointsets *
sizeof(**src_locations));
376 num_links_per_pointset =
377 malloc(num_pointsets *
sizeof(*num_links_per_pointset));
378 num_links_per_pointset[0] = num_links_in_file;
385 for (
unsigned i = 0; i < num_links_per_pointset[
points_idx];
388 free(num_links_per_pointset);
391 int * address = malloc(num_links_in_file *
sizeof(*address));
395 for (
unsigned i = 0; i < num_links_in_file; ++i) {
396 int idx = address[i] + src_address_offset;
398 if ((
unsigned)idx > *max_src_idx) *max_src_idx = (unsigned)idx;
399 (*links)[i].src_idx = (unsigned)idx;
405 for (
unsigned i = 0; i < num_links_in_file; ++i) {
406 int idx = address[i] + tgt_address_offset;
408 if ((
unsigned)idx > *max_tgt_idx) *max_tgt_idx = (unsigned)idx;
409 (*links)[i].tgt_idx = (unsigned)idx;
413 double * weights = malloc(num_links_in_file *
sizeof(*weights));
416 for (
size_t i = 0; i < num_links_in_file; ++i)
417 (*links)[i].weight = weights[i];
435 for (
int i = 0; i < num_cell_corners; ++i)
436 for (
int j = 0; j < 3; ++j)
437 point[j] += vertex_coordinates[cell_to_vertex[i]][j];
447 point[0] = vertex_coordinates[edge_to_vertex[0]][0] +
448 vertex_coordinates[edge_to_vertex[1]][0];
449 point[1] = vertex_coordinates[edge_to_vertex[0]][1] +
450 vertex_coordinates[edge_to_vertex[1]][1];
451 point[2] = vertex_coordinates[edge_to_vertex[0]][2] +
452 vertex_coordinates[edge_to_vertex[1]][2];
464 (location ==
YAC_LOC_EDGE),
"unsupported point location")
486 (location ==
YAC_LOC_EDGE),
"unsupported point location")
501 return (ids != NULL)?((int)ids[point_index]):((int)point_index);
505 struct link_data * links,
unsigned num_links,
510 for (
unsigned i = 0; i < num_links; ++i) {
516 tgt_grid, (
size_t)(links[i].
tgt_idx), tgt_location,
points[2*i+1]);
523 for (
size_t i = 0, k = 0; i < grid->
num_cells; ++i) {
525 size_t * curr_cell_corners =
529 for (
int j = 0; j < num_cell_corners; ++j)
530 cell_data[k++] = curr_cell_corners[j] + offset;
535 unsigned num_links,
unsigned * polygon_data,
unsigned offset) {
537 for (
unsigned i = 0; i < 2 * num_links; ++i)
538 polygon_data[i] = i + offset;
544 struct link_data * links,
unsigned num_links,
552 size_t num_grid_corners[2] =
554 size_t total_num_points =
555 num_grid_corners[0] + num_grid_corners[1] + 2 * (size_t)num_links;
556 size_t num_polygons[3] =
558 size_t total_num_polygons =
559 num_polygons[0] + num_polygons[1] + num_polygons[2];
569 links, num_links, &src_grid, &tgt_grid, src_locations, tgt_location,
570 points + num_grid_corners[0] + num_grid_corners[1]);
572 unsigned * num_points_per_polygon =
573 malloc(total_num_polygons *
sizeof(*num_points_per_polygon));
574 unsigned num_points_per_polygon_sum[3] = {0, 0, 0};
575 for (
size_t i = 0; i < num_polygons[0]; ++i) {
576 num_points_per_polygon_sum[0] +=
577 (num_points_per_polygon[i] =
580 for (
size_t i = 0; i < num_polygons[1]; ++i) {
581 num_points_per_polygon_sum[1] +=
582 (num_points_per_polygon[num_polygons[0] + i] =
585 for (
size_t i = 0; i < num_polygons[2]; ++i)
586 num_points_per_polygon[num_polygons[0] + num_polygons[1] + i] = 2;
587 num_points_per_polygon_sum[2] = 2 * num_polygons[2];
589 unsigned * polygon_data =
590 malloc((num_points_per_polygon_sum[0] + num_points_per_polygon_sum[1] +
591 num_points_per_polygon_sum[2]) *
sizeof(*polygon_data));
594 num_grid_corners[0]);
596 num_links, polygon_data + num_points_per_polygon_sum[0] +
597 num_points_per_polygon_sum[1], num_grid_corners[0] + num_grid_corners[1]);
603 unsigned * polygon_type = malloc(total_num_polygons *
sizeof(*polygon_type));
604 for (
size_t i = 0; i < num_polygons[0]; ++i) polygon_type[i] = 0;
605 for (
size_t i = 0; i < num_polygons[1]; ++i)
606 polygon_type[num_polygons[0] + i] = 1;
607 for (
size_t i = 0; i < num_polygons[2]; ++i)
608 polygon_type[num_polygons[0] + num_polygons[1] + i] = 2;
610 double * weights = NULL;
612 weights = malloc(total_num_polygons *
sizeof(*weights));
613 for (
size_t i = 0; i < num_polygons[0] + num_polygons[1]; ++i)
615 for (
size_t i = 0; i < num_polygons[2]; ++i)
616 weights[i + num_polygons[0] + num_polygons[1]] = links[i].
weight;
619 int * cell_ids = malloc(total_num_polygons *
sizeof(*cell_ids));
621 for (
size_t i = 0; i < num_polygons[0]; ++i)
622 cell_ids[i] = (
int)(src_grid.
cell_ids[i]);
624 for (
size_t i = 0; i < num_polygons[0]; ++i) cell_ids[i] = (
int)i;
627 for (
size_t i = 0; i < num_polygons[1]; ++i)
628 cell_ids[num_polygons[0] + i] = (
int)(tgt_grid.
cell_ids[i]);
630 for (
size_t i = 0; i < num_polygons[1]; ++i)
631 cell_ids[num_polygons[0] + i] = (
int)i;
633 for (
size_t i = 0; i < num_polygons[2]; ++i)
634 cell_ids[num_polygons[0] + num_polygons[1] + i] = (
int)i;
636 int * src_ids = malloc(total_num_polygons *
sizeof(*src_ids));
637 for (
size_t i = 0; i < num_polygons[0] + num_polygons[1]; ++i)
639 for (
size_t i = 0; i < num_polygons[2]; ++i)
640 src_ids[i + num_polygons[0] + num_polygons[1]] =
644 int * tgt_ids = malloc(total_num_polygons *
sizeof(*tgt_ids));
645 for (
size_t i = 0; i < num_polygons[0] + num_polygons[1]; ++i)
647 for (
size_t i = 0; i < num_polygons[2]; ++i)
648 tgt_ids[i + num_polygons[0] + num_polygons[1]] =
650 &tgt_grid, links[i].
tgt_idx, tgt_location);
652 int * vertex_ids = malloc(total_num_points *
sizeof(*vertex_ids));
655 vertex_ids[i] = (
int)(src_grid.
vertex_ids[i]);
658 vertex_ids[i] = (
int)i;
667 for (
size_t i = 0; i < 2 * (size_t)num_links; ++i)
678 file, polygon_data, num_points_per_polygon, total_num_polygons);
680 file, cell_ids, total_num_polygons,
"cell_ids");
682 file, src_ids, total_num_polygons,
"src_ids");
684 file, tgt_ids, total_num_polygons,
"tgt_ids");
686 file, polygon_type, total_num_polygons,
"polygon_type");
689 file, weights, total_num_polygons,
"weights");
691 file, vertex_ids, total_num_points,
"vertex_ids");
705 free(num_points_per_polygon);
712 YAC_ASSERT_F(arg != NULL,
"-%c argument is missing", str[0])
720 "invalid %s grid type\n", str);
728 "invalid N for cubed sphere %s grid\n", str)
739 arg,
"%lf,%lf,%lf,%lf,%zu,%zu",
746 "invalid %s grid configuration (gauss grid)", str);
750 "invalid %s grid configuration "
751 "(gauss grid has invalid number of cells)", str)
754 char * arg_copy = strdup(arg);
766 char const ** weight_filename,
767 char const ** vtk_filename) {
771 *weight_filename = NULL;
772 *vtk_filename = NULL;
774 char * src_arg = NULL;
775 char * tgt_arg = NULL;
778 while ((opt = getopt(argc, argv,
"S:T:s:t:w:o:")) != -1) {
785 (opt ==
'o'),
"invalid command argument")
792 (opt ==
'S')?src_grid_config:tgt_grid_config;
795 strlen(optarg) == 1,
"invalid grid type for argument %c", (
char)opt);
828 *weight_filename = optarg;
831 *vtk_filename = optarg;
835 YAC_ASSERT_F(optind >= argc,
"non-option ARGV-element: \"%s\"", argv[optind])
837 YAC_ASSERT(*weight_filename != NULL,
"weight_filename argument is missing")
838 YAC_ASSERT(*vtk_filename != NULL,
"vtk_filename argument is missing")
846 double * vertices = malloc(count *
sizeof(*vertices));
848 double d = (end - start) / (
double)(count - 1);
850 for (
size_t i = 0; i < count; ++i)
851 vertices[i] = start + d * (
double)i;
852 vertices[count - 1] = end;
858 double * first_corner,
double * last_corner,
size_t *
num_cells) {
861 int cyclic[2] = {0, 0};
862 double * lon_vertices =
864 double * lat_vertices =
void yac_basic_grid_data_free(struct yac_basic_grid_data grid)
struct yac_basic_grid_data yac_generate_basic_grid_data_reg_2d_deg(size_t nbr_vertices[2], int cyclic[2], double *lon_vertices, double *lat_vertices)
struct yac_basic_grid_data yac_generate_cubed_sphere_grid(unsigned n)
void yac_nc_inq_varid(int ncid, char const *name, int *varidp)
void yac_nc_open(const char *path, int omode, int *ncidp)
void yac_nc_inq_dimid(int ncid, char const *name, int *dimidp)
int yac_file_exists(const char *filename)
#define YAC_HANDLE_ERROR(exp)
enum yac_location yac_str2loc(char const *location_str)
#define YAC_MAX_LOC_STR_LEN
struct yac_basic_grid_data yac_read_icon_basic_grid_data(char const *filename)
struct yac_basic_grid_data yac_read_mpiom_basic_grid_data(char const *filename)
struct yac_basic_grid_data yac_read_scrip_basic_grid_data(char const *grid_filename, char const *mask_filename, char const *grid_name, int valid_mask_value, int use_ll_edges)
struct grid_config::@67::@69 unstruct
union grid_config::@67 config
struct grid_config::@67::@69 curve
struct grid_config::@67::@71 scrip
char const * mask_filename
char const * grid_filename
struct grid_config::@67::@70 gauss
struct grid_config::@67::@68 cube
yac_coordinate_pointer vertex_coordinates
yac_size_t_2_pointer edge_to_vertex
size_t * cell_to_vertex_offsets
int * num_vertices_per_cell
void yac_vtk_write_cell_scalars_uint(YAC_VTK_FILE *vtk_file, unsigned *scalars, unsigned num_cells, char *name)
void yac_vtk_write_cell_scalars_double(YAC_VTK_FILE *vtk_file, double *scalars, unsigned num_cells, char *name)
void yac_vtk_write_cell_scalars_int(YAC_VTK_FILE *vtk_file, int *scalars, unsigned num_cells, char *name)
void yac_vtk_write_point_data(YAC_VTK_FILE *vtk_file, double *point_data, unsigned num_points)
void yac_vtk_write_point_scalars_int(YAC_VTK_FILE *vtk_file, int *scalars, unsigned num_points, char *name)
void yac_vtk_close(YAC_VTK_FILE *vtk_file)
void yac_vtk_write_cell_data(YAC_VTK_FILE *vtk_file, unsigned *cell_corners, unsigned *num_points_per_cell, unsigned num_cells)
YAC_VTK_FILE * yac_vtk_open(const char *filename, const char *title)
static void parse_arguments(int argc, char **argv, struct grid_config *src_grid_config, struct grid_config *tgt_grid_config, char const **weight_filename, char const **vtk_filename)
static void get_grid_cell_data(struct yac_basic_grid_data *grid, unsigned *cell_data, unsigned offset)
static void get_link_address_data(unsigned num_links, unsigned *polygon_data, unsigned offset)
static void interpret_grid_arg(struct grid_config *grid_config, char *arg, char *str)
int main(int argc, char **argv)
static struct yac_basic_grid_data create_grid(struct grid_config grid_config)
static enum weight_file_type determine_weight_file_type(int ncid)
static void get_cell_middle_point(struct yac_basic_grid_data *grid, size_t cell_index, double *point)
#define YAC_ASSERT_F(exp, format,...)
static struct yac_basic_grid_data generate_gauss_grid(double *first_corner, double *last_corner, size_t *num_cells)
static void get_link_xyz_coordinates(struct link_data *links, unsigned num_links, struct yac_basic_grid_data *src_grid, struct yac_basic_grid_data *tgt_grid, enum yac_location *src_locations, enum yac_location tgt_location, yac_coordinate_pointer points)
#define YAC_WEIGHT_FILE_VERSION_1_0_STRING
static void read_link_data(char const *weight_filename, int src_address_offset, int tgt_address_offset, struct link_data **links, unsigned *num_links, enum yac_location **src_locations, enum yac_location *tgt_location, unsigned *max_src_idx, unsigned *max_tgt_idx)
static int get_point_id(struct yac_basic_grid_data *grid, size_t point_index, enum yac_location location)
static void get_point_coordinates(struct yac_basic_grid_data *grid, size_t point_index, enum yac_location location, double *point)
static double * generate_vertices(double start, double end, size_t count)
static void normalise_vector(double v[])
#define CDO_WEIGHT_FILE_TITLE
static int check_global_attribute(int ncid, char const *att_name, char const *ref_att_text)
static void write_data_to_file(char const *filename, struct yac_basic_grid_data src_grid, struct yac_basic_grid_data tgt_grid, struct link_data *links, unsigned num_links, enum yac_location *src_locations, enum yac_location tgt_location)
static void get_edge_middle_point(struct yac_basic_grid_data *grid, size_t edge_index, double *point)
#define YAC_ASSERT(exp, msg)
static struct user_input_data_points ** points
#define YAC_ASSERT_F(exp, format,...)
#define YAC_ASSERT(exp, msg)
double(* yac_coordinate_pointer)[3]