YAC 3.12.0
Yet Another Coupler
Loading...
Searching...
No Matches
weights2vtk.c
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <unistd.h>
8#include <string.h>
9#include <math.h>
10
11#include <netcdf.h>
12
13#include "yac_utils.h"
14
15#define YAC_WEIGHT_FILE_VERSION_1_0_STRING "yac weight file 1.0"
16#define CDO_WEIGHT_FILE_TITLE "CDO remapping"
17
18// redefine YAC assert macros
19#undef YAC_ASSERT
20#undef YAC_ASSERT_F
21
27
28static char const * cmd;
29#define STR_USAGE \
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" \
51 " n: grid name)\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" \
56 " ids\n" \
57 "\n" \
58 "Example:\n" \
59 " Configuration:\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" \
66 " Command:\n" \
67 " %s -S i -T c -s src_grid.nc -t 100 -w weight_file.nc " \
68 "-o weights.vtk\n"
69
70#define YAC_ASSERT(exp, msg) \
71 { \
72 if(!((exp))) { \
73 fprintf(stderr, "ERROR: %s\n" STR_USAGE, msg, cmd, cmd); \
74 exit(EXIT_FAILURE); \
75 } \
76 }
77
78#define YAC_ASSERT_F(exp, format, ...) \
79 { \
80 if(!((exp))) { \
81 fprintf(stderr, "ERROR: " format "\n" STR_USAGE, __VA_ARGS__, cmd, cmd); \
82 exit(EXIT_FAILURE); \
83 } \
84 }
85
86static inline void normalise_vector(double v[]) {
87
88 double norm = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
89
90 v[0] *= norm;
91 v[1] *= norm;
92 v[2] *= norm;
93}
94
95struct link_data {
97 double weight;
98};
99
108
110 union {
111 struct {
112 unsigned n;
114 struct {
115 char const * filename;
117 struct {
118 double corners[2][2];
119 size_t num_cells[2];
121 struct {
122 char const * grid_filename;
123 char const * mask_filename;
124 char const * grid_name;
129};
130
131static void parse_arguments(int argc, char ** argv,
132 struct grid_config * src_grid_config,
133 struct grid_config * tgt_grid_config,
134 char const ** weight_filename,
135 char const ** vtk_filename);
136static void read_link_data(char const * weight_filename, int src_address_offset,
137 int tgt_address_offset, struct link_data ** links,
138 unsigned * num_links, enum yac_location ** src_locations,
139 enum yac_location * tgt_location, unsigned * max_src_idx,
140 unsigned * max_tgt_idx);
141static void write_data_to_file(char const * filename,
142 struct yac_basic_grid_data src_grid,
143 struct yac_basic_grid_data tgt_grid,
144 struct link_data * links,
145 unsigned num_links,
146 enum yac_location * src_locations,
147 enum yac_location tgt_location);
149
150int main(int argc, char ** argv) {
151
152 cmd = argv[0];
153
154 struct grid_config src_grid_config, tgt_grid_config;
155 char const * weight_filename, * vtk_filename;
156
157 parse_arguments(argc, argv, &src_grid_config, &tgt_grid_config,
158 &weight_filename, &vtk_filename);
159
160 //-------------------------------------
161 // read/generate source and target grid
162 //-------------------------------------
163 struct yac_basic_grid_data src_grid = create_grid(src_grid_config);
164 struct yac_basic_grid_data tgt_grid = create_grid(tgt_grid_config);
165
166 //-----------------
167 // read weight file
168 //-----------------
170 yac_file_exists(weight_filename),
171 "File %s does not exist.", weight_filename)
172
173 struct link_data * links;
174 unsigned num_links, max_src_idx, max_tgt_idx;
175 enum yac_location * src_locations;
176 enum yac_location tgt_location = YAC_LOC_UNDEFINED;
177 read_link_data(weight_filename, src_grid_config.address_offset,
178 tgt_grid_config.address_offset, &links, &num_links,
179 &src_locations, &tgt_location, &max_src_idx, &max_tgt_idx);
180
182 (max_src_idx < src_grid.num_cells) && (max_tgt_idx < tgt_grid.num_cells),
183 "weight file does not match with source and target grid")
184
185 //---------------
186 // write vtk file
187 //---------------
189 vtk_filename, src_grid, tgt_grid, links, num_links,
190 src_locations, tgt_location);
191
192 //---------
193 // clean up
194 //---------
195
196 free(src_locations);
197 free(links);
198 yac_basic_grid_data_free(tgt_grid);
199 yac_basic_grid_data_free(src_grid);
200
201 return EXIT_SUCCESS;
202}
203
205 int ncid, char const * att_name, char const * ref_att_text) {
206
207 int att_matches = 0;
208
209 // global attributes
210 size_t att_len;
211 int status = nc_inq_attlen(ncid, NC_GLOBAL, att_name, &att_len);
212 if (status == NC_NOERR) {
213 char * att_text;
214 att_text = malloc(att_len + 1);
215 att_text[att_len] = '\0';
216 YAC_HANDLE_ERROR(nc_get_att_text(ncid, NC_GLOBAL, att_name, att_text));
218 (strlen(ref_att_text) == att_len) &&
219 !strncmp(att_text, ref_att_text, att_len),
220 "NetCDF file contains attribute string \"%s\", "
221 "but its text does not match (\"%s\" != \"%s\")",
222 att_name, att_text, ref_att_text);
223 free(att_text);
224 att_matches = 1;
225 } else if (status == NC_ENOTATT) {
226 status = NC_NOERR;
227 }
228 YAC_HANDLE_ERROR(status);
229 return att_matches;
230}
231
233
235
236 // check for YAC weight file
238 ncid, "version", YAC_WEIGHT_FILE_VERSION_1_0_STRING))
240
241 // check for CDO weight file
243 ncid, "title", CDO_WEIGHT_FILE_TITLE))
244 type = WGT_CDO;
245
246 return type;
247}
248
249static void read_link_data(
250 char const * weight_filename, int src_address_offset,
251 int tgt_address_offset, struct link_data ** links,
252 unsigned * num_links, enum yac_location ** src_locations,
253 enum yac_location * tgt_location, unsigned * max_src_idx,
254 unsigned * max_tgt_idx) {
255
256 int ncid, dimid, var_id;
257 yac_nc_open(weight_filename, NC_NOWRITE, &ncid);
258
259 enum weight_file_type wgt_type = determine_weight_file_type(ncid);
260
262 (wgt_type == WGT_YAC_1_0) ||
263 (wgt_type == WGT_CDO),
264 "ERROR(read_link_data): unsupported weight file type")
265
266 if (wgt_type == WGT_YAC_1_0) {
267
268 size_t str_link_len;
269 char * str_link;
270 var_id = NC_GLOBAL;
271 YAC_HANDLE_ERROR(nc_inq_attlen(ncid, var_id, "contains_links", &str_link_len));
272 str_link = malloc(str_link_len + 1);
273 str_link[str_link_len] = '\0';
274 YAC_HANDLE_ERROR(nc_get_att_text(ncid, var_id, "contains_links", str_link));
275
276 int contains_links =
277 (strlen("TRUE") == str_link_len) &&
278 !strncmp("TRUE", str_link, str_link_len);
280 contains_links ||
281 ((strlen("FALSE") == str_link_len) &&
282 !strncmp("FALSE", str_link, str_link_len)),
283 "invalid global attribute contains_links")
284
285 free(str_link);
286
287 if (!contains_links) {
288 *links = NULL;
289 *num_links = 0;
290 *src_locations = NULL;
291 *max_src_idx = 0;
292 *max_tgt_idx = 0;
293 return;
294 }
295 }
296
297 size_t num_wgts = 0;
298 yac_nc_inq_dimid(ncid, "num_wgts", &dimid);
299 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &num_wgts));
301 num_wgts == 1, "unsupported number of weights per link "
302 "(num_wgts = %zu; has to be 1)", num_wgts)
303
304 // get number of links from file
305 size_t num_links_in_file = 0;
306 yac_nc_inq_dimid(ncid, "num_links", &dimid);
307 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &num_links_in_file));
308 YAC_ASSERT(num_links_in_file > 0, "no links defined")
309 *num_links = num_links_in_file;
310 *links = malloc(num_links_in_file * sizeof(**links));
311
312 size_t num_pointsets = 0;
313 unsigned * num_links_per_pointset;
314
315 // read weight file type specific fields
316 switch (wgt_type) {
317 case (WGT_YAC_1_0): {
318
319 // get number of pointsets
320 yac_nc_inq_dimid(ncid, "num_src_fields", &dimid);
321
322 num_pointsets = 0;
323 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &num_pointsets));
324 YAC_ASSERT(num_pointsets > 0, "no point sets in file")
325
326 // get max location string length from file
327 size_t max_loc_str_len;
328 yac_nc_inq_dimid(ncid, "max_loc_str_len", &dimid);
329 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &max_loc_str_len));
331 max_loc_str_len == YAC_MAX_LOC_STR_LEN,
332 "wrong max location string length in weight file")
333
334 // get source locations
335 *src_locations = malloc(num_pointsets * sizeof(**src_locations));
336 yac_nc_inq_varid(ncid, "src_locations", &var_id);
337
338 for (unsigned i = 0; i < num_pointsets; ++i) {
339
340 char loc_str[YAC_MAX_LOC_STR_LEN];
341
342 size_t str_start[2] = {i, 0};
343 size_t str_count[2] = {1, YAC_MAX_LOC_STR_LEN};
344
346 nc_get_vara_text(ncid, var_id, str_start, str_count, loc_str));
347
348 (*src_locations)[i] = yac_str2loc(loc_str);
349 }
350
351 // get target location
352 yac_nc_inq_varid(ncid, "dst_location", &var_id);
353 {
354 char loc_str[YAC_MAX_LOC_STR_LEN];
355 YAC_HANDLE_ERROR(nc_get_var_text(ncid, var_id, loc_str));
356 *tgt_location = yac_str2loc(loc_str);
357 }
358
359 // get number of links per pointset
360 num_links_per_pointset =
361 malloc(num_pointsets * sizeof(*num_links_per_pointset));
362 yac_nc_inq_varid(ncid, "num_links_per_src_field", &var_id);
363 YAC_HANDLE_ERROR(nc_get_var_uint(ncid, var_id, num_links_per_pointset));
364
365 break;
366 }
367 default:
368 case (WGT_CDO): {
369
370 num_pointsets = 1;
371 *src_locations = malloc(num_pointsets * sizeof(**src_locations));
372 (*src_locations)[0] = YAC_LOC_CELL;
373 *tgt_location = YAC_LOC_CELL;
374 num_links_per_pointset =
375 malloc(num_pointsets * sizeof(*num_links_per_pointset));
376 num_links_per_pointset[0] = num_links_in_file;
377 break;
378 }
379 };
380
381 for (unsigned points_idx = 0, link_idx = 0; points_idx < num_pointsets;
382 ++points_idx)
383 for (unsigned i = 0; i < num_links_per_pointset[points_idx];
384 ++i, ++link_idx)
385 (*links)[link_idx].points_idx = points_idx;
386 free(num_links_per_pointset);
387
388 // get links
389 int * address = malloc(num_links_in_file * sizeof(*address));
390 yac_nc_inq_varid(ncid, "src_address", &var_id);
391 YAC_HANDLE_ERROR(nc_get_var_int(ncid, var_id, address));
392 *max_src_idx = 0;
393 for (unsigned i = 0; i < num_links_in_file; ++i) {
394 int idx = address[i] + src_address_offset;
395 YAC_ASSERT_F(idx >= 0, "invalid src index (%d)", idx);
396 if ((unsigned)idx > *max_src_idx) *max_src_idx = (unsigned)idx;
397 (*links)[i].src_idx = (unsigned)idx;
398 }
399
400 yac_nc_inq_varid(ncid, "dst_address", &var_id);
401 YAC_HANDLE_ERROR(nc_get_var_int(ncid, var_id, address));
402 *max_tgt_idx = 0;
403 for (unsigned i = 0; i < num_links_in_file; ++i) {
404 int idx = address[i] + tgt_address_offset;
405 YAC_ASSERT_F(idx >= 0, "invalid tgt index (%d)", idx);
406 if ((unsigned)idx > *max_tgt_idx) *max_tgt_idx = (unsigned)idx;
407 (*links)[i].tgt_idx = (unsigned)idx;
408 }
409 free(address);
410
411 double * weights = malloc(num_links_in_file * sizeof(*weights));
412 yac_nc_inq_varid(ncid, "remap_matrix", &var_id);
413 YAC_HANDLE_ERROR(nc_get_var_double(ncid, var_id, weights));
414 for (size_t i = 0; i < num_links_in_file; ++i)
415 (*links)[i].weight = weights[i];
416 free(weights);
417
418 YAC_HANDLE_ERROR(nc_close(ncid));
419}
420
422 struct yac_basic_grid_data * grid, size_t cell_index, double * point) {
423
424 int num_cell_corners = grid->num_vertices_per_cell[cell_index];
425 size_t * cell_to_vertex = grid->cell_to_vertex +
426 grid->cell_to_vertex_offsets[cell_index];
427 yac_coordinate_pointer vertex_coordinates = grid->vertex_coordinates;
428
429 point[0] = 0;
430 point[1] = 0;
431 point[2] = 0;
432
433 for (int i = 0; i < num_cell_corners; ++i)
434 for (int j = 0; j < 3; ++j)
435 point[j] += vertex_coordinates[cell_to_vertex[i]][j];
436 normalise_vector(point);
437}
438
440 struct yac_basic_grid_data * grid, size_t edge_index, double * point) {
441
442 size_t * edge_to_vertex = grid->edge_to_vertex[edge_index];
443 yac_coordinate_pointer vertex_coordinates = grid->vertex_coordinates;
444
445 point[0] = vertex_coordinates[edge_to_vertex[0]][0] +
446 vertex_coordinates[edge_to_vertex[1]][0];
447 point[1] = vertex_coordinates[edge_to_vertex[0]][1] +
448 vertex_coordinates[edge_to_vertex[1]][1];
449 point[2] = vertex_coordinates[edge_to_vertex[0]][2] +
450 vertex_coordinates[edge_to_vertex[1]][2];
451
452 normalise_vector(point);
453}
454
456 struct yac_basic_grid_data * grid, size_t point_index,
457 enum yac_location location, double * point) {
458
460 (location == YAC_LOC_CELL) ||
462 (location == YAC_LOC_EDGE), "unsupported point location")
463 switch (location) {
464 case(YAC_LOC_CELL):
465 get_cell_middle_point(grid, point_index, point);
466 break;
467 case(YAC_LOC_CORNER):
468 memcpy(point, grid->vertex_coordinates[point_index], 3 * sizeof(*point));
469 break;
470 default:
471 case(YAC_LOC_EDGE):
472 get_edge_middle_point(grid, point_index, point);
473 break;
474 };
475}
476
477static int get_point_id(
478 struct yac_basic_grid_data * grid, size_t point_index,
479 enum yac_location location) {
480
482 (location == YAC_LOC_CELL) ||
484 (location == YAC_LOC_EDGE), "unsupported point location")
485 yac_int * ids;
486 switch (location) {
487 case(YAC_LOC_CELL):
488 ids = grid->cell_ids;
489 break;
490 case(YAC_LOC_CORNER):
491 ids = grid->vertex_ids;
492 break;
493 default:
494 case(YAC_LOC_EDGE):
495 ids = grid->edge_ids;
496 break;
497 };
498
499 return (ids != NULL)?((int)ids[point_index]):((int)point_index);
500}
501
503 struct link_data * links, unsigned num_links,
504 struct yac_basic_grid_data * src_grid, struct yac_basic_grid_data * tgt_grid,
505 enum yac_location * src_locations, enum yac_location tgt_location,
507
508 for (unsigned i = 0; i < num_links; ++i) {
509
511 src_grid, (size_t)(links[i].src_idx), src_locations[links[i].points_idx],
512 points[2*i+0]);
514 tgt_grid, (size_t)(links[i].tgt_idx), tgt_location, points[2*i+1]);
515 }
516}
517
519 struct yac_basic_grid_data * grid, unsigned * cell_data, unsigned offset) {
520
521 for (size_t i = 0, k = 0; i < grid->num_cells; ++i) {
522
523 size_t * curr_cell_corners =
524 grid->cell_to_vertex + grid->cell_to_vertex_offsets[i];
525 int num_cell_corners = grid->num_vertices_per_cell[i];
526
527 for (int j = 0; j < num_cell_corners; ++j)
528 cell_data[k++] = curr_cell_corners[j] + offset;
529 }
530}
531
533 unsigned num_links, unsigned * polygon_data, unsigned offset) {
534
535 for (unsigned i = 0; i < 2 * num_links; ++i)
536 polygon_data[i] = i + offset;
537}
538
539static void write_data_to_file(char const * filename,
540 struct yac_basic_grid_data src_grid,
541 struct yac_basic_grid_data tgt_grid,
542 struct link_data * links, unsigned num_links,
543 enum yac_location * src_locations,
544 enum yac_location tgt_location) {
545
546 //------------------------------------
547 // generate cell data for the vtk file
548 //------------------------------------
549
550 size_t num_grid_corners[2] =
551 {src_grid.num_vertices, tgt_grid.num_vertices};
552 size_t total_num_points =
553 num_grid_corners[0] + num_grid_corners[1] + 2 * (size_t)num_links;
554 size_t num_polygons[3] =
555 {src_grid.num_cells, tgt_grid.num_cells, num_links};
556 size_t total_num_polygons =
557 num_polygons[0] + num_polygons[1] + num_polygons[2];
558
559 yac_coordinate_pointer points = malloc(total_num_points * sizeof(*points));
560
561 // get the point data of the grids
562 memcpy(points, src_grid.vertex_coordinates,
563 src_grid.num_vertices * sizeof(*points));
564 memcpy(points + src_grid.num_vertices, tgt_grid.vertex_coordinates,
565 tgt_grid.num_vertices * sizeof(*points));
567 links, num_links, &src_grid, &tgt_grid, src_locations, tgt_location,
568 points + num_grid_corners[0] + num_grid_corners[1]);
569
570 unsigned * num_points_per_polygon =
571 malloc(total_num_polygons * sizeof(*num_points_per_polygon));
572 unsigned num_points_per_polygon_sum[3] = {0, 0, 0};
573 for (size_t i = 0; i < num_polygons[0]; ++i) {
574 num_points_per_polygon_sum[0] +=
575 (num_points_per_polygon[i] =
576 (unsigned)(src_grid.num_vertices_per_cell[i]));
577 }
578 for (size_t i = 0; i < num_polygons[1]; ++i) {
579 num_points_per_polygon_sum[1] +=
580 (num_points_per_polygon[num_polygons[0] + i] =
581 (unsigned)(tgt_grid.num_vertices_per_cell[i]));
582 }
583 for (size_t i = 0; i < num_polygons[2]; ++i)
584 num_points_per_polygon[num_polygons[0] + num_polygons[1] + i] = 2;
585 num_points_per_polygon_sum[2] = 2 * num_polygons[2];
586
587 unsigned * polygon_data =
588 malloc((num_points_per_polygon_sum[0] + num_points_per_polygon_sum[1] +
589 num_points_per_polygon_sum[2]) * sizeof(*polygon_data));
590 get_grid_cell_data(&src_grid, polygon_data, 0);
591 get_grid_cell_data(&tgt_grid, polygon_data + num_points_per_polygon_sum[0],
592 num_grid_corners[0]);
594 num_links, polygon_data + num_points_per_polygon_sum[0] +
595 num_points_per_polygon_sum[1], num_grid_corners[0] + num_grid_corners[1]);
596
597 //------------------------------------
598 // generate scalar data
599 //------------------------------------
600
601 unsigned * polygon_type = malloc(total_num_polygons * sizeof(*polygon_type));
602 for (size_t i = 0; i < num_polygons[0]; ++i) polygon_type[i] = 0;
603 for (size_t i = 0; i < num_polygons[1]; ++i)
604 polygon_type[num_polygons[0] + i] = 1;
605 for (size_t i = 0; i < num_polygons[2]; ++i)
606 polygon_type[num_polygons[0] + num_polygons[1] + i] = 2;
607
608 double * weights = NULL;
609 if (num_links > 0) {
610 weights = malloc(total_num_polygons * sizeof(*weights));
611 for (size_t i = 0; i < num_polygons[0] + num_polygons[1]; ++i)
612 weights[i] = -1;
613 for (size_t i = 0; i < num_polygons[2]; ++i)
614 weights[i + num_polygons[0] + num_polygons[1]] = links[i].weight;
615 }
616
617 int * cell_ids = malloc(total_num_polygons * sizeof(*cell_ids));
618 if (src_grid.cell_ids != NULL) {
619 for (size_t i = 0; i < num_polygons[0]; ++i)
620 cell_ids[i] = (int)(src_grid.cell_ids[i]);
621 } else {
622 for (size_t i = 0; i < num_polygons[0]; ++i) cell_ids[i] = (int)i;
623 }
624 if (tgt_grid.cell_ids != NULL) {
625 for (size_t i = 0; i < num_polygons[1]; ++i)
626 cell_ids[num_polygons[0] + i] = (int)(tgt_grid.cell_ids[i]);
627 } else {
628 for (size_t i = 0; i < num_polygons[1]; ++i)
629 cell_ids[num_polygons[0] + i] = (int)i;
630 }
631 for (size_t i = 0; i < num_polygons[2]; ++i)
632 cell_ids[num_polygons[0] + num_polygons[1] + i] = (int)i;
633
634 int * src_ids = malloc(total_num_polygons * sizeof(*src_ids));
635 for (size_t i = 0; i < num_polygons[0] + num_polygons[1]; ++i)
636 src_ids[i] = -1;
637 for (size_t i = 0; i < num_polygons[2]; ++i)
638 src_ids[i + num_polygons[0] + num_polygons[1]] =
640 &src_grid, links[i].src_idx, src_locations[links[i].points_idx]);
641
642 int * tgt_ids = malloc(total_num_polygons * sizeof(*tgt_ids));
643 for (size_t i = 0; i < num_polygons[0] + num_polygons[1]; ++i)
644 tgt_ids[i] = -1;
645 for (size_t i = 0; i < num_polygons[2]; ++i)
646 tgt_ids[i + num_polygons[0] + num_polygons[1]] =
648 &tgt_grid, links[i].tgt_idx, tgt_location);
649
650 int * vertex_ids = malloc(total_num_points * sizeof(*vertex_ids));
651 if (src_grid.vertex_ids != NULL) {
652 for (size_t i = 0; i < src_grid.num_vertices; ++i)
653 vertex_ids[i] = (int)(src_grid.vertex_ids[i]);
654 } else {
655 for (size_t i = 0; i < src_grid.num_vertices; ++i)
656 vertex_ids[i] = (int)i;
657 }
658 if (tgt_grid.vertex_ids != NULL) {
659 for (size_t i = 0; i < tgt_grid.num_vertices; ++i)
660 vertex_ids[src_grid.num_vertices + i] = (int)(tgt_grid.vertex_ids[i]);
661 } else {
662 for (size_t i = 0; i < tgt_grid.num_vertices; ++i)
663 vertex_ids[src_grid.num_vertices + i] = (int)i;
664 }
665 for (size_t i = 0; i < 2 * (size_t)num_links; ++i)
666 vertex_ids[src_grid.num_vertices + tgt_grid.num_vertices + i] =
667 (int)(i >> 1);
668
669 //------------------------------------
670 // generate the actual vtk file
671 //------------------------------------
672
673 YAC_VTK_FILE * file = yac_vtk_open(filename, "grid data");
674 yac_vtk_write_point_data(file, &(points[0][0]), total_num_points);
676 file, polygon_data, num_points_per_polygon, total_num_polygons);
678 file, cell_ids, total_num_polygons, "cell_ids");
680 file, src_ids, total_num_polygons, "src_ids");
682 file, tgt_ids, total_num_polygons, "tgt_ids");
684 file, polygon_type, total_num_polygons, "polygon_type");
685 if (num_links > 0)
687 file, weights, total_num_polygons, "weights");
689 file, vertex_ids, total_num_points, "vertex_ids");
690 yac_vtk_close(file);
691
692 //------------------------------------
693 // some final cleanup
694 //------------------------------------
695
696 free(weights);
697 free(polygon_type);
698 free(tgt_ids);
699 free(src_ids);
700 free(cell_ids);
701 free(vertex_ids);
702 free(polygon_data);
703 free(num_points_per_polygon);
704 free(points);
705}
706
708 struct grid_config * grid_config, char * arg, char * str) {
709
710 YAC_ASSERT_F(arg != NULL, "-%c argument is missing", str[0])
711
713 (grid_config->type == CUBE) ||
714 (grid_config->type == CURVE) ||
715 (grid_config->type == UNSTRUCT) ||
716 (grid_config->type == GAUSS) ||
717 (grid_config->type == SCRIP),
718 "invalid %s grid type\n", str);
719
720 switch (grid_config->type) {
721 default:
722 case CUBE:
723 grid_config->config.cube.n = atoi(arg);
726 "invalid N for cubed sphere %s grid\n", str)
727 break;
728 case CURVE:
730 break;
731 case UNSTRUCT:
733 break;
734 case GAUSS:
736 sscanf(
737 arg, "%lf,%lf,%lf,%lf,%zu,%zu",
744 "invalid %s grid configuration (gauss grid)", str);
746 (grid_config->config.gauss.num_cells[0] > 0) &&
748 "invalid %s grid configuration "
749 "(gauss grid has invalid number of cells)", str)
750 break;
751 case SCRIP: {
752 char * arg_copy = strdup(arg);
753 grid_config->config.scrip.grid_filename = strtok(arg_copy, ",");
754 grid_config->config.scrip.mask_filename = strtok(NULL, ",");
755 grid_config->config.scrip.grid_name = strtok(NULL, ",");
756 break;
757 }
758 }
759}
760
761void parse_arguments(int argc, char ** argv,
762 struct grid_config * src_grid_config,
763 struct grid_config * tgt_grid_config,
764 char const ** weight_filename,
765 char const ** vtk_filename) {
766
767 src_grid_config->type = NONE;
768 tgt_grid_config->type = NONE;
769 *weight_filename = NULL;
770 *vtk_filename = NULL;
771
772 char * src_arg = NULL;
773 char * tgt_arg = NULL;
774
775 int opt;
776 while ((opt = getopt(argc, argv, "S:T:s:t:w:o:")) != -1) {
778 (opt == 'S') ||
779 (opt == 'T') ||
780 (opt == 's') ||
781 (opt == 't') ||
782 (opt == 'w') ||
783 (opt == 'o'), "invalid command argument")
784 switch (opt) {
785 default:
786 case 'S':
787 case 'T':
788 {
789 struct grid_config * grid_config =
790 (opt == 'S')?src_grid_config:tgt_grid_config;
791
793 strlen(optarg) == 1, "invalid grid type for argument %c", (char)opt);
794
795 switch (optarg[0]) {
796 case 'c':
797 case 'C':
799 break;
800 case 'm':
801 case 'M':
803 break;
804 case 'i':
805 case 'I':
807 break;
808 case 'g':
809 case 'G':
811 break;
812 case 's':
813 case 'S':
815 };
816 grid_config->address_offset = (optarg[0] < 'a')?-2:-1;
817 break;
818 }
819 case 's':
820 src_arg = optarg;
821 break;
822 case 't':
823 tgt_arg = optarg;
824 break;
825 case 'w':
826 *weight_filename = optarg;
827 break;
828 case 'o':
829 *vtk_filename = optarg;
830 break;
831 }
832 }
833 YAC_ASSERT_F(optind >= argc, "non-option ARGV-element: \"%s\"", argv[optind])
834 YAC_ASSERT(argc != 1, "too few arguments")
835 YAC_ASSERT(*weight_filename != NULL, "weight_filename argument is missing")
836 YAC_ASSERT(*vtk_filename != NULL, "vtk_filename argument is missing")
837
838 interpret_grid_arg(src_grid_config, src_arg, "source");
839 interpret_grid_arg(tgt_grid_config, tgt_arg, "target");
840}
841
842static double * generate_vertices(double start, double end, size_t count) {
843
844 double * vertices = malloc(count * sizeof(*vertices));
845
846 double d = (end - start) / (double)(count - 1);
847
848 for (size_t i = 0; i < count; ++i)
849 vertices[i] = start + d * (double)i;
850 vertices[count - 1] = end;
851
852 return vertices;
853}
854
856 double * first_corner, double * last_corner, size_t * num_cells) {
857
858 size_t num_vertices[2] = {num_cells[0] + 1, num_cells[1] + 1};
859 int cyclic[2] = {0, 0};
860 double * lon_vertices =
861 generate_vertices(first_corner[0], last_corner[0], num_vertices[0]);
862 double * lat_vertices =
863 generate_vertices(first_corner[1], last_corner[1], num_vertices[1]);
864
867 num_vertices, cyclic, lon_vertices, lat_vertices);
868
869 free(lon_vertices);
870 free(lat_vertices);
871
872 return grid_data;
873}
874
876
878 (grid_config.type == CUBE) ||
879 (grid_config.type == CURVE) ||
881 (grid_config.type == GAUSS) ||
882 (grid_config.type == SCRIP), "invalid grid configuration")
883 switch(grid_config.type) {
884 default:
885 case CUBE:
887 case CURVE:
890 "File %s does not exist.", grid_config.config.curve.filename);
891 return
894 case UNSTRUCT:
897 "File %s does not exist.", grid_config.config.unstruct.filename);
898 return
901 case GAUSS:
902 return
907 case SCRIP:
910 "File %s does not exist.", grid_config.config.scrip.grid_filename);
913 "File %s does not exist.", grid_config.config.scrip.mask_filename);
914 return
918 (char*)(grid_config.config.scrip.grid_name), 0, 0);
919 }
920}
921
#define YAC_ASSERT(exp, msg)
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)
Definition grid_reg2d.c:74
struct yac_basic_grid_data yac_generate_cubed_sphere_grid(unsigned n)
enum callback_type type
void yac_nc_inq_varid(int ncid, char const *name, int *varidp)
Definition io_utils.c:411
void yac_nc_open(const char *path, int omode, int *ncidp)
Definition io_utils.c:350
void yac_nc_inq_dimid(int ncid, char const *name, int *dimidp)
Definition io_utils.c:385
int yac_file_exists(const char *filename)
Definition utils_core.c:12
enum yac_location yac_str2loc(char const *location_str)
Definition location.c:21
yac_location
Definition location.h:12
@ YAC_LOC_CORNER
Definition location.h:15
@ YAC_LOC_UNDEFINED
Definition location.h:17
@ YAC_LOC_EDGE
Definition location.h:16
@ YAC_LOC_CELL
Definition location.h:14
#define YAC_MAX_LOC_STR_LEN
Definition location.h:10
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)
unsigned n
struct grid_config::@107::@111 scrip
char const * filename
union grid_config::@107 config
struct grid_config::@107::@110 gauss
double corners[2][2]
struct grid_config::@107::@108 cube
enum grid_type type
struct grid_config::@107::@109 unstruct
char const * mask_filename
char const * grid_name
char const * grid_filename
struct grid_config::@107::@109 curve
size_t num_cells[2]
int * cell_to_vertex
size_t num_cells[2]
unsigned cyclic[2]
int const * location
#define YAC_HANDLE_ERROR(exp)
Definition toy_output.c:13
void yac_vtk_write_cell_scalars_uint(YAC_VTK_FILE *vtk_file, unsigned *scalars, unsigned num_cells, char *name)
Definition vtk_output.c:243
void yac_vtk_write_cell_scalars_double(YAC_VTK_FILE *vtk_file, double *scalars, unsigned num_cells, char *name)
Definition vtk_output.c:264
void yac_vtk_write_cell_scalars_int(YAC_VTK_FILE *vtk_file, int *scalars, unsigned num_cells, char *name)
Definition vtk_output.c:250
void yac_vtk_write_point_data(YAC_VTK_FILE *vtk_file, double *point_data, unsigned num_points)
Definition vtk_output.c:69
void yac_vtk_write_point_scalars_int(YAC_VTK_FILE *vtk_file, int *scalars, unsigned num_points, char *name)
Definition vtk_output.c:278
void yac_vtk_close(YAC_VTK_FILE *vtk_file)
Definition vtk_output.c:403
void yac_vtk_write_cell_data(YAC_VTK_FILE *vtk_file, unsigned *cell_corners, unsigned *num_points_per_cell, unsigned num_cells)
Definition vtk_output.c:88
YAC_VTK_FILE * yac_vtk_open(const char *filename, const char *title)
Definition vtk_output.c:45
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 char const * cmd
Definition weights2vtk.c:28
static void interpret_grid_arg(struct grid_config *grid_config, char *arg, char *str)
static struct yac_basic_grid_data create_grid(struct grid_config grid_config)
weight_file_type
Definition weights2vtk.c:22
@ WGT_CDO
Definition weights2vtk.c:24
@ WGT_YAC_1_0
Definition weights2vtk.c:23
@ WGT_UNKNOWN
Definition weights2vtk.c:25
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,...)
Definition weights2vtk.c:78
@ UNSTRUCT
@ GAUSS
@ CURVE
@ SCRIP
@ NONE
@ CUBE
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
Definition weights2vtk.c:15
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[])
Definition weights2vtk.c:86
#define CDO_WEIGHT_FILE_TITLE
Definition weights2vtk.c:16
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)
Definition weights2vtk.c:70
static struct user_input_data_points ** points
Definition yac.c:158
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:19
YAC_INT yac_int
Definition yac_types.h:15
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:19