63 const std::vector<double> &y_cell,
65 const std::string &projection) {
67 if (projection.empty()) {
74 std::vector<double> x_node(x_cell.size() + 1), y_node(y_cell.size() + 1);
77 double dx = x_cell[1] - x_cell[0];
78 double dy = y_cell[1] - y_cell[0];
80 for (
size_t k = 0;
k < x_cell.size(); ++
k) {
81 x_node[
k] = x_cell[
k] - 0.5 * dx;
83 x_node.back() = x_cell.back() + 0.5 * dx;
85 for (
size_t k = 0;
k < y_cell.size(); ++
k) {
86 y_node[
k] = y_cell[
k] - 0.5 * dy;
88 y_node.back() = y_cell.back() + 0.5 * dy;
98 int cyclic[] = { 0, 0 };
102 int n_nodes[2] = { (
int)x_node.size(), (
int)y_node.size() };
103 yac_cdef_grid_curve2d(
grid_name.c_str(), n_nodes, cyclic, nodes.
lon.data(), nodes.
lat.data(),
106 int n_cells[2] = { (
int)x_cell.size(), (
int)y_cell.size() };
107 yac_cdef_points_curve2d(grid_id, n_cells, YAC_LOCATION_CELL, cells.
lon.data(), cells.
lat.data(),
201 const std::string &variable_name,
203 : m_instance_id(0), m_source_field_id(0), m_target_field_id(0) {
204 auto ctx = target_grid.
ctx();
206 std::string target_proj_params = target_grid.
get_mapping_info()[
"proj_params"];
208 if (target_proj_params.empty()) {
213 auto log = ctx->log();
215 auto source_grid_name =
grid_name(input_file, variable_name, ctx->unit_system(),
219 2,
"* Initializing 2D interpolation on the sphere from '%s' to the internal grid...\n",
220 source_grid_name.c_str());
227 std::string grid_mapping_name = source_grid_mapping[
"grid_mapping_name"];
229 log->message(2,
"Input grid:\n");
230 if (not grid_mapping_name.empty()) {
231 log->message(2,
" Grid mapping: %s\n", grid_mapping_name.c_str());
234 std::string source_proj_params = source_grid_mapping[
"proj_params"];
235 if (not source_proj_params.empty()) {
236 log->message(2,
" PROJ string: '%s'\n", source_proj_params.c_str());
238 source_grid_info.
report(*log, 2, ctx->unit_system());
240 grid::Parameters P(*ctx->config(), source_grid_info.
x.size(), source_grid_info.
y.size(),
241 source_grid_info.
Lx, source_grid_info.
Ly);
243 P.
x0 = source_grid_info.
x0;
244 P.
y0 = source_grid_info.
y0;
250 auto source_grid = std::make_shared<Grid>(ctx, P);
252 source_grid->set_mapping_info(source_grid_mapping);
254 if (source_proj_params.empty()) {
256 "unsupported or missing projection info for the grid '%s'",
257 source_grid_name.c_str());
260 m_buffer = std::make_shared<pism::array::Scalar>(source_grid, variable_name);
262 std::string target_grid_name =
"internal for " + source_grid_name;
267 yac_cdef_calendar(YAC_YEAR_OF_365_DAYS);
269 yac_cdef_datetime_instance(
m_instance_id,
"-1-01-01",
"+1-01-01");
274 const int n_comps = 2;
275 const char *comp_names[n_comps] = {
"source_component",
"target_component" };
276 int comp_ids[n_comps] = { 0, 0 };
277 yac_cdef_comps_instance(
m_instance_id, comp_names, n_comps, comp_ids);
279 double source_grid_spacing = 0.0;
280 log->message(2,
"Defining the source grid (%s)...\n", source_grid_name.c_str());
282 auto x =
grid_subset(source_grid->xs(), source_grid->xm(), source_grid_info.
x);
283 auto y =
grid_subset(source_grid->ys(), source_grid->ym(), source_grid_info.
y);
286 comp_ids[0], x, y, source_proj_params, source_grid_name);
291 dx =
dx_min(source_proj_params, x, y);
292 dy =
dy_min(source_proj_params, x, y);
294 dx = std::abs(x[1] - x[0]);
295 dy = std::abs(y[1] - y[0]);
297 source_grid_spacing =
GlobalMin(ctx->com(), std::min(dx, dy));
298 log->message(2,
" Source grid spacing: ~%3.3f m\n", source_grid_spacing);
301 double target_grid_spacing = 0.0;
302 log->message(2,
"Defining the target grid (%s)...\n", target_grid_name.c_str());
308 comp_ids[1], x, y, target_proj_params, target_grid_name);
310 target_grid_spacing =
GlobalMin(ctx->com(), std::min(target_grid.
dx(), target_grid.
dy()));
311 log->message(2,
" Target grid spacing: %3.3f m\n", target_grid_spacing);
317 int interp_stack_id = 0;
318 yac_cget_interp_stack_config(&interp_stack_id);
321 method =
"nearest neighbor";
327 double scaling = 1.0;
328 double max_search_distance = 0.0;
329 yac_cadd_interp_stack_config_nnn(interp_stack_id, YAC_NNN_DIST, n_neighbors,
330 max_search_distance, scaling);
333 int partial_coverage = 0;
334 if (source_grid_spacing < target_grid_spacing) {
335 method =
"1st order conservative";
338 int enforce_conservation = 1;
340 yac_cadd_interp_stack_config_conservative(interp_stack_id, order, enforce_conservation,
341 partial_coverage, YAC_CONSERV_DESTAREA);
343 method =
"weighted average of source cell nodes";
346 yac_cadd_interp_stack_config_average(interp_stack_id, YAC_AVG_BARY, partial_coverage);
352 double scaling = 1.0;
353 double max_search_distance = 0.0;
354 yac_cadd_interp_stack_config_nnn(interp_stack_id, YAC_NNN_DIST, n_neighbors,
355 max_search_distance, scaling);
359 log->message(2,
"Interpolation method: %s\n", method.c_str());
362 const int src_lag = 0;
363 const int tgt_lag = 0;
366 source_grid_name.c_str(),
367 source_grid_name.c_str(),
369 target_grid_name.c_str(),
370 target_grid_name.c_str(),
372 YAC_TIME_UNIT_SECOND,
373 YAC_REDUCTION_TIME_NONE,
375 interp_stack_id, src_lag, tgt_lag);
378 yac_cfree_interp_stack_config(interp_stack_id);
381 double start = MPI_Wtime();
383 double end = MPI_Wtime();
384 log->message(2,
"Initialized interpolation from %s in %f seconds.\n",
385 source_grid_name.c_str(), end - start);
388 e.
add_context(
"initializing interpolation from %s to the internal grid",
389 input_file.
name().c_str());