131 const std::vector<double> &y_cell,
133 const std::string &projection) {
135 if (projection.empty()) {
142 std::vector<double> x_node(x_cell.size() + 1), y_node(y_cell.size() + 1);
145 double dx = x_cell[1] - x_cell[0];
146 double dy = y_cell[1] - y_cell[0];
148 for (
size_t k = 0;
k < x_cell.size(); ++
k) {
149 x_node[
k] = x_cell[
k] - 0.5 * dx;
151 x_node.back() = x_cell.back() + 0.5 * dx;
153 for (
size_t k = 0;
k < y_cell.size(); ++
k) {
154 y_node[
k] = y_cell[
k] - 0.5 * dy;
156 y_node.back() = y_cell.back() + 0.5 * dy;
166 int cyclic[] = { 0, 0 };
170 int n_nodes[2] = { (
int)x_node.size(), (
int)y_node.size() };
171 yac_cdef_grid_curve2d(
grid_name.c_str(), n_nodes, cyclic, nodes.
lon.data(), nodes.
lat.data(),
174 int n_cells[2] = { (
int)x_cell.size(), (
int)y_cell.size() };
175 yac_cdef_points_curve2d(grid_id, n_cells, YAC_LOCATION_CELL, cells.
lon.data(), cells.
lat.data(),
274 const std::string &variable_name,
276 : m_instance_id(0), m_source_field_id(0), m_target_field_id(0) {
277 auto ctx = target_grid.
ctx();
286 auto log = ctx->log();
288 auto source_grid_name =
grid_name(input_file, variable_name, ctx->unit_system(),
292 2,
"* Initializing 2D interpolation on the sphere from '%s' to the internal grid...\n",
293 source_grid_name.c_str());
300 std::string grid_mapping_name = source_grid_mapping.cf_mapping[
"grid_mapping_name"];
302 log->message(2,
"Input grid:\n");
303 if (not grid_mapping_name.empty()) {
304 log->message(2,
" Grid mapping: %s\n", grid_mapping_name.c_str());
306 if (not source_grid_mapping.proj_string.empty()) {
307 log->message(2,
" PROJ string: '%s'\n", source_grid_mapping.proj_string.c_str());
309 source_grid_info.
report(*log, 2, ctx->unit_system());
311 grid::Parameters P(*ctx->config(), source_grid_info.
x.size(), source_grid_info.
y.size(),
312 source_grid_info.
Lx, source_grid_info.
Ly);
314 P.
x0 = source_grid_info.
x0;
315 P.
y0 = source_grid_info.
y0;
321 auto source_grid = std::make_shared<Grid>(ctx, P);
323 source_grid->set_mapping_info(source_grid_mapping);
325 if (source_grid->get_mapping_info().proj_string.empty()) {
327 "unsupported or missing projection info for the grid '%s'",
328 source_grid_name.c_str());
331 m_buffer = std::make_shared<pism::array::Scalar>(source_grid, variable_name);
333 std::string target_grid_name =
"internal for " + source_grid_name;
338 yac_cdef_calendar(YAC_YEAR_OF_365_DAYS);
340 yac_cdef_datetime_instance(
m_instance_id,
"-1-01-01",
"+1-01-01");
345 const int n_comps = 2;
346 const char *comp_names[n_comps] = {
"source_component",
"target_component" };
347 int comp_ids[n_comps] = { 0, 0 };
348 yac_cdef_comps_instance(
m_instance_id, comp_names, n_comps, comp_ids);
350 double source_grid_spacing = 0.0;
351 log->message(2,
"Defining the source grid (%s)...\n", source_grid_name.c_str());
353 auto x =
grid_subset(source_grid->xs(), source_grid->xm(), source_grid_info.
x);
354 auto y =
grid_subset(source_grid->ys(), source_grid->ym(), source_grid_info.
y);
357 comp_ids[0], x, y, source_grid->get_mapping_info().proj_string, source_grid_name);
362 dx =
dx_min(source_grid_mapping.proj_string, x, y);
363 dy =
dy_min(source_grid_mapping.proj_string, x, y);
365 dx = std::abs(x[1] - x[0]);
366 dy = std::abs(y[1] - y[0]);
368 source_grid_spacing =
GlobalMin(ctx->com(), std::min(dx, dy));
369 log->message(2,
" Source grid spacing: ~%3.3f m\n", source_grid_spacing);
372 double target_grid_spacing = 0.0;
373 log->message(2,
"Defining the target grid (%s)...\n", target_grid_name.c_str());
381 target_grid_spacing =
GlobalMin(ctx->com(), std::min(target_grid.
dx(), target_grid.
dy()));
382 log->message(2,
" Target grid spacing: %3.3f m\n", target_grid_spacing);
388 int interp_stack_id = 0;
389 yac_cget_interp_stack_config(&interp_stack_id);
392 method =
"nearest neighbor";
398 double scaling = 1.0;
399 double max_search_distance = 0.0;
400 yac_cadd_interp_stack_config_nnn(interp_stack_id, YAC_NNN_DIST, n_neighbors,
401 max_search_distance, scaling);
404 int partial_coverage = 0;
405 if (source_grid_spacing < target_grid_spacing) {
406 method =
"1st order conservative";
409 int enforce_conservation = 1;
411 yac_cadd_interp_stack_config_conservative(interp_stack_id, order, enforce_conservation,
412 partial_coverage, YAC_CONSERV_DESTAREA);
414 method =
"weighted average of source cell nodes";
417 yac_cadd_interp_stack_config_average(interp_stack_id, YAC_AVG_BARY, partial_coverage);
423 double scaling = 1.0;
424 double max_search_distance = 0.0;
425 yac_cadd_interp_stack_config_nnn(interp_stack_id, YAC_NNN_DIST, n_neighbors,
426 max_search_distance, scaling);
430 log->message(2,
"Interpolation method: %s\n", method.c_str());
433 const int src_lag = 0;
434 const int tgt_lag = 0;
437 source_grid_name.c_str(),
438 source_grid_name.c_str(),
440 target_grid_name.c_str(),
441 target_grid_name.c_str(),
443 YAC_TIME_UNIT_SECOND,
444 YAC_REDUCTION_TIME_NONE,
446 interp_stack_id, src_lag, tgt_lag);
449 yac_cfree_interp_stack_config(interp_stack_id);
452 double start = MPI_Wtime();
454 double end = MPI_Wtime();
455 log->message(2,
"Initialized interpolation from %s in %f seconds.\n",
456 source_grid_name.c_str(), end - start);
459 e.
add_context(
"initializing interpolation from %s to the internal grid",
460 input_file.
name().c_str());