YetAnotherCoupler 3.5.2
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
99struct link_data {
101 double weight;
102};
103
112
114 union {
115 struct {
116 unsigned n;
118 struct {
119 char const * filename;
121 struct {
122 double corners[2][2];
123 size_t num_cells[2];
125 struct {
126 char const * grid_filename;
127 char const * mask_filename;
128 char const * grid_name;
133};
134
135static void parse_arguments(int argc, char ** argv,
136 struct grid_config * src_grid_config,
137 struct grid_config * tgt_grid_config,
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);
145static void write_data_to_file(char const * filename,
146 struct yac_basic_grid_data src_grid,
147 struct yac_basic_grid_data tgt_grid,
148 struct link_data * links,
149 unsigned num_links,
150 enum yac_location * src_locations,
151 enum yac_location tgt_location);
153
154int main(int argc, char ** argv) {
155
156 cmd = argv[0];
157
158 struct grid_config src_grid_config, tgt_grid_config;
159 char const * weight_filename, * vtk_filename;
160
161 parse_arguments(argc, argv, &src_grid_config, &tgt_grid_config,
162 &weight_filename, &vtk_filename);
163
164 //-------------------------------------
165 // read/generate source and target grid
166 //-------------------------------------
167 struct yac_basic_grid_data src_grid = create_grid(src_grid_config);
168 struct yac_basic_grid_data tgt_grid = create_grid(tgt_grid_config);
169
170 //-----------------
171 // read weight file
172 //-----------------
174 yac_file_exists(weight_filename),
175 "File %s does not exist.", weight_filename)
176
177 struct link_data * links;
178 unsigned num_links, max_src_idx, max_tgt_idx;
179 enum yac_location * src_locations;
180 enum yac_location tgt_location = YAC_LOC_UNDEFINED;
181 read_link_data(weight_filename, src_grid_config.address_offset,
182 tgt_grid_config.address_offset, &links, &num_links,
183 &src_locations, &tgt_location, &max_src_idx, &max_tgt_idx);
184
186 (max_src_idx < src_grid.num_cells) && (max_tgt_idx < tgt_grid.num_cells),
187 "weight file does not match with source and target grid")
188
189 //---------------
190 // write vtk file
191 //---------------
193 vtk_filename, src_grid, tgt_grid, links, num_links,
194 src_locations, tgt_location);
195
196 //---------
197 // clean up
198 //---------
199
200 free(src_locations);
201 free(links);
202 yac_basic_grid_data_free(tgt_grid);
203 yac_basic_grid_data_free(src_grid);
204
205 return EXIT_SUCCESS;
206}
207
209 int ncid, char const * att_name, char const * ref_att_text) {
210
211 int att_matches = 0;
212
213 // global attributes
214 size_t att_len;
215 int status = nc_inq_attlen(ncid, NC_GLOBAL, att_name, &att_len);
216 if (status == NC_NOERR) {
217 char * att_text;
218 att_text = malloc(att_len + 1);
219 att_text[att_len] = '\0';
220 YAC_HANDLE_ERROR(nc_get_att_text(ncid, NC_GLOBAL, att_name, att_text));
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);
227 free(att_text);
228 att_matches = 1;
229 } else if (status == NC_ENOTATT) {
230 status = NC_NOERR;
231 }
232 YAC_HANDLE_ERROR(status);
233 return att_matches;
234}
235
237
238 // check for YAC weight file
240 ncid, "version", YAC_WEIGHT_FILE_VERSION_1_0_STRING))
241 return WGT_YAC_1_0;
242
243 // check for CDO weight file
245 ncid, "title", CDO_WEIGHT_FILE_TITLE))
246 return WGT_CDO;
247
248 return WGT_UNKNOWN;
249}
250
251static void read_link_data(
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) {
257
258 int ncid, dimid, var_id;
259 yac_nc_open(weight_filename, NC_NOWRITE, &ncid);
260
261 enum weight_file_type wgt_type = determine_weight_file_type(ncid);
262
264 (wgt_type == WGT_YAC_1_0) ||
265 (wgt_type == WGT_CDO),
266 "ERROR(read_link_data): unsupported weight file type")
267
268 if (wgt_type == WGT_YAC_1_0) {
269
270 size_t str_link_len;
271 char * str_link;
272 var_id = NC_GLOBAL;
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));
277
278 int contains_links =
279 (strlen("TRUE") == str_link_len) &&
280 !strncmp("TRUE", str_link, str_link_len);
282 contains_links ||
283 ((strlen("FALSE") == str_link_len) &&
284 !strncmp("FALSE", str_link, str_link_len)),
285 "invalid global attribute contains_links")
286
287 free(str_link);
288
289 if (!contains_links) {
290 *links = NULL;
291 *num_links = 0;
292 *src_locations = NULL;
293 *max_src_idx = 0;
294 *max_tgt_idx = 0;
295 return;
296 }
297 }
298
299 size_t num_wgts = 0;
300 yac_nc_inq_dimid(ncid, "num_wgts", &dimid);
301 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &num_wgts));
303 num_wgts == 1, "unsupported number of weights per link "
304 "(num_wgts = %zu; has to be 1)", num_wgts)
305
306 // get number of links from file
307 size_t num_links_in_file = 0;
308 yac_nc_inq_dimid(ncid, "num_links", &dimid);
309 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &num_links_in_file));
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));
313
314 size_t num_pointsets = 0;
315 unsigned * num_links_per_pointset;
316
317 // read weight file type specific fields
318 switch (wgt_type) {
319 case (WGT_YAC_1_0): {
320
321 // get number of pointsets
322 yac_nc_inq_dimid(ncid, "num_src_fields", &dimid);
323
324 num_pointsets = 0;
325 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &num_pointsets));
326 YAC_ASSERT(num_pointsets > 0, "no point sets in file")
327
328 // get max location string length from file
329 size_t max_loc_str_len;
330 yac_nc_inq_dimid(ncid, "max_loc_str_len", &dimid);
331 YAC_HANDLE_ERROR(nc_inq_dimlen(ncid, dimid, &max_loc_str_len));
333 max_loc_str_len == YAC_MAX_LOC_STR_LEN,
334 "wrong max location string length in weight file")
335
336 // get source locations
337 *src_locations = malloc(num_pointsets * sizeof(**src_locations));
338 yac_nc_inq_varid(ncid, "src_locations", &var_id);
339
340 for (unsigned i = 0; i < num_pointsets; ++i) {
341
342 char loc_str[YAC_MAX_LOC_STR_LEN];
343
344 size_t str_start[2] = {i, 0};
345 size_t str_count[2] = {1, YAC_MAX_LOC_STR_LEN};
346
348 nc_get_vara_text(ncid, var_id, str_start, str_count, loc_str));
349
350 (*src_locations)[i] = yac_str2loc(loc_str);
351 }
352
353 // get target location
354 yac_nc_inq_varid(ncid, "dst_location", &var_id);
355 {
356 char loc_str[YAC_MAX_LOC_STR_LEN];
357 YAC_HANDLE_ERROR(nc_get_var_text(ncid, var_id, loc_str));
358 *tgt_location = yac_str2loc(loc_str);
359 }
360
361 // get number of links per pointset
362 num_links_per_pointset =
363 malloc(num_pointsets * sizeof(*num_links_per_pointset));
364 yac_nc_inq_varid(ncid, "num_links_per_src_field", &var_id);
365 YAC_HANDLE_ERROR(nc_get_var_uint(ncid, var_id, num_links_per_pointset));
366
367 break;
368 }
369 default:
370 case (WGT_CDO): {
371
372 num_pointsets = 1;
373 *src_locations = malloc(num_pointsets * sizeof(**src_locations));
374 (*src_locations)[0] = YAC_LOC_CELL;
375 *tgt_location = YAC_LOC_CELL;
376 num_links_per_pointset =
377 malloc(num_pointsets * sizeof(*num_links_per_pointset));
378 num_links_per_pointset[0] = num_links_in_file;
379 break;
380 }
381 };
382
383 for (unsigned points_idx = 0, link_idx = 0; points_idx < num_pointsets;
384 ++points_idx)
385 for (unsigned i = 0; i < num_links_per_pointset[points_idx];
386 ++i, ++link_idx)
387 (*links)[link_idx].points_idx = points_idx;
388 free(num_links_per_pointset);
389
390 // get links
391 int * address = malloc(num_links_in_file * sizeof(*address));
392 yac_nc_inq_varid(ncid, "src_address", &var_id);
393 YAC_HANDLE_ERROR(nc_get_var_int(ncid, var_id, address));
394 *max_src_idx = 0;
395 for (unsigned i = 0; i < num_links_in_file; ++i) {
396 int idx = address[i] + src_address_offset;
397 YAC_ASSERT_F(idx >= 0, "invalid src index (%d)", idx);
398 if ((unsigned)idx > *max_src_idx) *max_src_idx = (unsigned)idx;
399 (*links)[i].src_idx = (unsigned)idx;
400 }
401
402 yac_nc_inq_varid(ncid, "dst_address", &var_id);
403 YAC_HANDLE_ERROR(nc_get_var_int(ncid, var_id, address));
404 *max_tgt_idx = 0;
405 for (unsigned i = 0; i < num_links_in_file; ++i) {
406 int idx = address[i] + tgt_address_offset;
407 YAC_ASSERT_F(idx >= 0, "invalid tgt index (%d)", idx);
408 if ((unsigned)idx > *max_tgt_idx) *max_tgt_idx = (unsigned)idx;
409 (*links)[i].tgt_idx = (unsigned)idx;
410 }
411 free(address);
412
413 double * weights = malloc(num_links_in_file * sizeof(*weights));
414 yac_nc_inq_varid(ncid, "remap_matrix", &var_id);
415 YAC_HANDLE_ERROR(nc_get_var_double(ncid, var_id, weights));
416 for (size_t i = 0; i < num_links_in_file; ++i)
417 (*links)[i].weight = weights[i];
418 free(weights);
419
420 YAC_HANDLE_ERROR(nc_close(ncid));
421}
422
424 struct yac_basic_grid_data * grid, size_t cell_index, double * point) {
425
426 int num_cell_corners = grid->num_vertices_per_cell[cell_index];
427 size_t * cell_to_vertex = grid->cell_to_vertex +
428 grid->cell_to_vertex_offsets[cell_index];
429 yac_coordinate_pointer vertex_coordinates = grid->vertex_coordinates;
430
431 point[0] = 0;
432 point[1] = 0;
433 point[2] = 0;
434
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];
438 normalise_vector(point);
439}
440
442 struct yac_basic_grid_data * grid, size_t edge_index, double * point) {
443
444 size_t * edge_to_vertex = grid->edge_to_vertex[edge_index];
445 yac_coordinate_pointer vertex_coordinates = grid->vertex_coordinates;
446
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];
453
454 normalise_vector(point);
455}
456
458 struct yac_basic_grid_data * grid, size_t point_index,
459 enum yac_location location, double * point) {
460
462 (location == YAC_LOC_CELL) ||
463 (location == YAC_LOC_CORNER) ||
464 (location == YAC_LOC_EDGE), "unsupported point location")
465 switch (location) {
466 case(YAC_LOC_CELL):
467 get_cell_middle_point(grid, point_index, point);
468 break;
469 case(YAC_LOC_CORNER):
470 memcpy(point, grid->vertex_coordinates[point_index], 3 * sizeof(*point));
471 break;
472 default:
473 case(YAC_LOC_EDGE):
474 get_edge_middle_point(grid, point_index, point);
475 break;
476 };
477}
478
479static int get_point_id(
480 struct yac_basic_grid_data * grid, size_t point_index,
481 enum yac_location location) {
482
484 (location == YAC_LOC_CELL) ||
485 (location == YAC_LOC_CORNER) ||
486 (location == YAC_LOC_EDGE), "unsupported point location")
487 yac_int * ids;
488 switch (location) {
489 case(YAC_LOC_CELL):
490 ids = grid->cell_ids;
491 break;
492 case(YAC_LOC_CORNER):
493 ids = grid->vertex_ids;
494 break;
495 default:
496 case(YAC_LOC_EDGE):
497 ids = grid->edge_ids;
498 break;
499 };
500
501 return (ids != NULL)?((int)ids[point_index]):((int)point_index);
502}
503
505 struct link_data * links, unsigned num_links,
506 struct yac_basic_grid_data * src_grid, struct yac_basic_grid_data * tgt_grid,
507 enum yac_location * src_locations, enum yac_location tgt_location,
509
510 for (unsigned i = 0; i < num_links; ++i) {
511
513 src_grid, (size_t)(links[i].src_idx), src_locations[links[i].points_idx],
514 points[2*i+0]);
516 tgt_grid, (size_t)(links[i].tgt_idx), tgt_location, points[2*i+1]);
517 }
518}
519
521 struct yac_basic_grid_data * grid, unsigned * cell_data, unsigned offset) {
522
523 for (size_t i = 0, k = 0; i < grid->num_cells; ++i) {
524
525 size_t * curr_cell_corners =
526 grid->cell_to_vertex + grid->cell_to_vertex_offsets[i];
527 int num_cell_corners = grid->num_vertices_per_cell[i];
528
529 for (int j = 0; j < num_cell_corners; ++j)
530 cell_data[k++] = curr_cell_corners[j] + offset;
531 }
532}
533
535 unsigned num_links, unsigned * polygon_data, unsigned offset) {
536
537 for (unsigned i = 0; i < 2 * num_links; ++i)
538 polygon_data[i] = i + offset;
539}
540
541static void write_data_to_file(char const * filename,
542 struct yac_basic_grid_data src_grid,
543 struct yac_basic_grid_data tgt_grid,
544 struct link_data * links, unsigned num_links,
545 enum yac_location * src_locations,
546 enum yac_location tgt_location) {
547
548 //------------------------------------
549 // generate cell data for the vtk file
550 //------------------------------------
551
552 size_t num_grid_corners[2] =
553 {src_grid.num_vertices, tgt_grid.num_vertices};
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] =
557 {src_grid.num_cells, tgt_grid.num_cells, num_links};
558 size_t total_num_polygons =
559 num_polygons[0] + num_polygons[1] + num_polygons[2];
560
561 yac_coordinate_pointer points = malloc(total_num_points * sizeof(*points));
562
563 // get the point data of the grids
564 memcpy(points, src_grid.vertex_coordinates,
565 src_grid.num_vertices * sizeof(*points));
566 memcpy(points + src_grid.num_vertices, tgt_grid.vertex_coordinates,
567 tgt_grid.num_vertices * sizeof(*points));
569 links, num_links, &src_grid, &tgt_grid, src_locations, tgt_location,
570 points + num_grid_corners[0] + num_grid_corners[1]);
571
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] =
578 (unsigned)(src_grid.num_vertices_per_cell[i]));
579 }
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] =
583 (unsigned)(tgt_grid.num_vertices_per_cell[i]));
584 }
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];
588
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));
592 get_grid_cell_data(&src_grid, polygon_data, 0);
593 get_grid_cell_data(&tgt_grid, polygon_data + num_points_per_polygon_sum[0],
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]);
598
599 //------------------------------------
600 // generate scalar data
601 //------------------------------------
602
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;
609
610 double * weights = NULL;
611 if (num_links > 0) {
612 weights = malloc(total_num_polygons * sizeof(*weights));
613 for (size_t i = 0; i < num_polygons[0] + num_polygons[1]; ++i)
614 weights[i] = -1;
615 for (size_t i = 0; i < num_polygons[2]; ++i)
616 weights[i + num_polygons[0] + num_polygons[1]] = links[i].weight;
617 }
618
619 int * cell_ids = malloc(total_num_polygons * sizeof(*cell_ids));
620 if (src_grid.cell_ids != NULL) {
621 for (size_t i = 0; i < num_polygons[0]; ++i)
622 cell_ids[i] = (int)(src_grid.cell_ids[i]);
623 } else {
624 for (size_t i = 0; i < num_polygons[0]; ++i) cell_ids[i] = (int)i;
625 }
626 if (tgt_grid.cell_ids != NULL) {
627 for (size_t i = 0; i < num_polygons[1]; ++i)
628 cell_ids[num_polygons[0] + i] = (int)(tgt_grid.cell_ids[i]);
629 } else {
630 for (size_t i = 0; i < num_polygons[1]; ++i)
631 cell_ids[num_polygons[0] + i] = (int)i;
632 }
633 for (size_t i = 0; i < num_polygons[2]; ++i)
634 cell_ids[num_polygons[0] + num_polygons[1] + i] = (int)i;
635
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)
638 src_ids[i] = -1;
639 for (size_t i = 0; i < num_polygons[2]; ++i)
640 src_ids[i + num_polygons[0] + num_polygons[1]] =
642 &src_grid, links[i].src_idx, src_locations[links[i].points_idx]);
643
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)
646 tgt_ids[i] = -1;
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);
651
652 int * vertex_ids = malloc(total_num_points * sizeof(*vertex_ids));
653 if (src_grid.vertex_ids != NULL) {
654 for (size_t i = 0; i < src_grid.num_vertices; ++i)
655 vertex_ids[i] = (int)(src_grid.vertex_ids[i]);
656 } else {
657 for (size_t i = 0; i < src_grid.num_vertices; ++i)
658 vertex_ids[i] = (int)i;
659 }
660 if (tgt_grid.vertex_ids != NULL) {
661 for (size_t i = 0; i < tgt_grid.num_vertices; ++i)
662 vertex_ids[src_grid.num_vertices + i] = (int)(tgt_grid.vertex_ids[i]);
663 } else {
664 for (size_t i = 0; i < tgt_grid.num_vertices; ++i)
665 vertex_ids[src_grid.num_vertices + i] = (int)i;
666 }
667 for (size_t i = 0; i < 2 * (size_t)num_links; ++i)
668 vertex_ids[src_grid.num_vertices + tgt_grid.num_vertices + i] =
669 (int)(i >> 1);
670
671 //------------------------------------
672 // generate the actual vtk file
673 //------------------------------------
674
675 YAC_VTK_FILE * file = yac_vtk_open(filename, "grid data");
676 yac_vtk_write_point_data(file, &(points[0][0]), total_num_points);
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");
687 if (num_links > 0)
689 file, weights, total_num_polygons, "weights");
691 file, vertex_ids, total_num_points, "vertex_ids");
692 yac_vtk_close(file);
693
694 //------------------------------------
695 // some final cleanup
696 //------------------------------------
697
698 free(weights);
699 free(polygon_type);
700 free(tgt_ids);
701 free(src_ids);
702 free(cell_ids);
703 free(vertex_ids);
704 free(polygon_data);
705 free(num_points_per_polygon);
706 free(points);
707}
708
710 struct grid_config * grid_config, char * arg, char * str) {
711
712 YAC_ASSERT_F(arg != NULL, "-%c argument is missing", str[0])
713
715 (grid_config->type == CUBE) ||
716 (grid_config->type == CURVE) ||
717 (grid_config->type == UNSTRUCT) ||
718 (grid_config->type == GAUSS) ||
719 (grid_config->type == SCRIP),
720 "invalid %s grid type\n", str);
721
722 switch (grid_config->type) {
723 default:
724 case CUBE:
725 grid_config->config.cube.n = atoi(arg);
728 "invalid N for cubed sphere %s grid\n", str)
729 break;
730 case CURVE:
732 break;
733 case UNSTRUCT:
735 break;
736 case GAUSS:
738 sscanf(
739 arg, "%lf,%lf,%lf,%lf,%zu,%zu",
746 "invalid %s grid configuration (gauss grid)", str);
748 (grid_config->config.gauss.num_cells[0] > 0) &&
750 "invalid %s grid configuration "
751 "(gauss grid has invalid number of cells)", str)
752 break;
753 case SCRIP: {
754 char * arg_copy = strdup(arg);
755 grid_config->config.scrip.grid_filename = strtok(arg_copy, ",");
756 grid_config->config.scrip.mask_filename = strtok(NULL, ",");
757 grid_config->config.scrip.grid_name = strtok(NULL, ",");
758 break;
759 }
760 }
761}
762
763void parse_arguments(int argc, char ** argv,
764 struct grid_config * src_grid_config,
765 struct grid_config * tgt_grid_config,
766 char const ** weight_filename,
767 char const ** vtk_filename) {
768
769 src_grid_config->type = NONE;
770 tgt_grid_config->type = NONE;
771 *weight_filename = NULL;
772 *vtk_filename = NULL;
773
774 char * src_arg = NULL;
775 char * tgt_arg = NULL;
776
777 int opt;
778 while ((opt = getopt(argc, argv, "S:T:s:t:w:o:")) != -1) {
780 (opt == 'S') ||
781 (opt == 'T') ||
782 (opt == 's') ||
783 (opt == 't') ||
784 (opt == 'w') ||
785 (opt == 'o'), "invalid command argument")
786 switch (opt) {
787 default:
788 case 'S':
789 case 'T':
790 {
791 struct grid_config * grid_config =
792 (opt == 'S')?src_grid_config:tgt_grid_config;
793
795 strlen(optarg) == 1, "invalid grid type for argument %c", (char)opt);
796
797 switch (optarg[0]) {
798 case 'c':
799 case 'C':
801 break;
802 case 'm':
803 case 'M':
805 break;
806 case 'i':
807 case 'I':
809 break;
810 case 'g':
811 case 'G':
813 break;
814 case 's':
815 case 'S':
817 };
818 grid_config->address_offset = (optarg[0] < 'a')?-2:-1;
819 break;
820 }
821 case 's':
822 src_arg = optarg;
823 break;
824 case 't':
825 tgt_arg = optarg;
826 break;
827 case 'w':
828 *weight_filename = optarg;
829 break;
830 case 'o':
831 *vtk_filename = optarg;
832 break;
833 }
834 }
835 YAC_ASSERT_F(optind >= argc, "non-option ARGV-element: \"%s\"", argv[optind])
836 YAC_ASSERT(argc != 1, "too few arguments")
837 YAC_ASSERT(*weight_filename != NULL, "weight_filename argument is missing")
838 YAC_ASSERT(*vtk_filename != NULL, "vtk_filename argument is missing")
839
840 interpret_grid_arg(src_grid_config, src_arg, "source");
841 interpret_grid_arg(tgt_grid_config, tgt_arg, "target");
842}
843
844static double * generate_vertices(double start, double end, size_t count) {
845
846 double * vertices = malloc(count * sizeof(*vertices));
847
848 double d = (end - start) / (double)(count - 1);
849
850 for (size_t i = 0; i < count; ++i)
851 vertices[i] = start + d * (double)i;
852 vertices[count - 1] = end;
853
854 return vertices;
855}
856
858 double * first_corner, double * last_corner, size_t * num_cells) {
859
860 size_t num_vertices[2] = {num_cells[0] + 1, num_cells[1] + 1};
861 int cyclic[2] = {0, 0};
862 double * lon_vertices =
863 generate_vertices(first_corner[0], last_corner[0], num_vertices[0]);
864 double * lat_vertices =
865 generate_vertices(first_corner[1], last_corner[1], num_vertices[1]);
866
867 struct yac_basic_grid_data grid_data =
869 num_vertices, cyclic, lon_vertices, lat_vertices);
870
871 free(lon_vertices);
872 free(lat_vertices);
873
874 return grid_data;
875}
876
878
880 (grid_config.type == CUBE) ||
881 (grid_config.type == CURVE) ||
883 (grid_config.type == GAUSS) ||
884 (grid_config.type == SCRIP), "invalid grid configuration")
885 switch(grid_config.type) {
886 default:
887 case CUBE:
889 case CURVE:
892 "File %s does not exist.", grid_config.config.curve.filename);
893 return
896 case UNSTRUCT:
899 "File %s does not exist.", grid_config.config.unstruct.filename);
900 return
903 case GAUSS:
904 return
909 case SCRIP:
912 "File %s does not exist.", grid_config.config.scrip.grid_filename);
915 "File %s does not exist.", grid_config.config.scrip.mask_filename);
916 return
920 (char*)(grid_config.config.scrip.grid_name), 0, 0);
921 }
922}
923
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)
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
#define YAC_HANDLE_ERROR(exp)
Definition io_utils.h:30
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::@67::@69 unstruct
char const * grid_name
char const * filename
union grid_config::@67 config
struct grid_config::@67::@69 curve
double corners[2][2]
enum grid_type type
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
size_t num_cells[2]
yac_coordinate_pointer vertex_coordinates
yac_size_t_2_pointer edge_to_vertex
size_t * cell_to_vertex_offsets
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)
int main(int argc, char **argv)
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
grid_type
@ 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:136
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:19
#define YAC_ASSERT(exp, msg)
Definition yac_assert.h:16
Xt_int yac_int
Definition yac_types.h:15
double(* yac_coordinate_pointer)[3]
Definition yac_types.h:19