GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
Loading...
Searching...
No Matches
segmen2d_parallel.c
Go to the documentation of this file.
1/*!
2 * \file segmen2d.c
3 *
4 * \author H. Mitasova, I. Kosinovsky, D. Gerdes (single core)
5 * \author Stanislav Zubal, Michal Lacko (OpenMP version)
6 * \author Anna Petrasova (OpenMP version GRASS integration)
7 *
8 * SPDX-FileCopyrightText: 1993-2017 Helena Mitasova
9 * SPDX-FileCopyrightText: GRASS Development Team
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
12 */
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <math.h>
17#if defined(_OPENMP)
18#include <omp.h>
19#endif
20#include <grass/gis.h>
21#include <grass/glocale.h>
22#include <grass/interpf.h>
23#include <grass/gmath.h>
24
25static int cut_tree(struct multtree *, struct multtree **, int *);
26
27/*!
28 * See documentation for IL_interp_segments_2d.
29 * This is a parallel processing implementation.
30 */
32 struct interp_params *params,
33 struct tree_info *info, /*!< info for the quad tree */
34 struct multtree *tree, /*!< current leaf of the quad tree */
35 struct BM *bitmask, /*!< bitmask */
36 double zmin, double zmax, /*!< min and max input z-values */
37 double *zminac, double *zmaxac, /*!< min and max interp. z-values */
38 double *gmin, double *gmax, /*!< min and max inperp. slope val. */
39 double *c1min, double *c1max, /*!< min and max interp. curv. val. */
40 double *c2min, double *c2max, /*!< min and max interp. curv. val. */
41 double *ertot, /*!< total interplating func. error */
42 int totsegm, /*!< total number of segments */
43 off_t offset1, /*!< offset for temp file writing */
44 double dnorm, int threads)
45{
46 int some_thread_failed = 0;
47 int tid = 0;
48 int i = 0;
49 int j = 0;
50 int i_cnt;
51 int cursegm = 0;
52 double smseg;
53 double ***matrix = NULL;
54 int **indx = NULL;
55 double **b = NULL;
56 double **A = NULL;
57 struct quaddata **data_local;
58 struct multtree **all_leafs;
59
60 all_leafs =
61 (struct multtree **)G_malloc(sizeof(struct multtree *) * totsegm);
63 (struct quaddata **)G_malloc(sizeof(struct quaddata *) * threads);
64 matrix = (double ***)G_malloc(sizeof(double **) * threads);
65 indx = (int **)G_malloc(sizeof(int *) * threads);
66 b = (double **)G_malloc(sizeof(double *) * threads);
67 A = (double **)G_malloc(sizeof(double *) * threads);
68
69 for (i_cnt = 0; i_cnt < threads; i_cnt++) {
70 if (!(matrix[i_cnt] =
71 G_alloc_matrix(params->KMAX2 + 1, params->KMAX2 + 1))) {
72 G_fatal_error(_("Out of memory"));
73 return -1;
74 }
75 }
76
77 for (i_cnt = 0; i_cnt < threads; i_cnt++) {
78 if (!(indx[i_cnt] = G_alloc_ivector(params->KMAX2 + 1))) {
79 G_fatal_error(_("Out of memory"));
80 return -1;
81 }
82 }
83
84 for (i_cnt = 0; i_cnt < threads; i_cnt++) {
85 if (!(b[i_cnt] = G_alloc_vector(params->KMAX2 + 3))) {
86 G_fatal_error(_("Out of memory"));
87 return -1;
88 }
89 }
90
91 for (i_cnt = 0; i_cnt < threads; i_cnt++) {
92 if (!(A[i_cnt] = G_alloc_vector(
93 (params->KMAX2 + 2) * (params->KMAX2 + 2) + 1))) {
94 G_fatal_error(_("Out of memory"));
95 return -1;
96 }
97 }
98
99 smseg = smallest_segment(tree, 4);
100 cut_tree(tree, all_leafs, &i);
101
102 G_message(_("Starting parallel work"));
103#pragma omp parallel firstprivate( \
104 tid, i, j, zmin, zmax, tree, totsegm, offset1, dnorm, smseg, ertot, \
105 params, info, all_leafs, bitmask, b, indx, matrix, data_local, A) \
106 shared(cursegm, threads, some_thread_failed, zminac, zmaxac, gmin, gmax, \
107 c1min, c1max, c2min, c2max) default(none)
108 {
109#pragma omp for schedule(dynamic)
110 for (i_cnt = 0; i_cnt < totsegm; i_cnt++) {
111 /* Obtain thread id */
112#if defined(_OPENMP)
114#endif
115
116 double xmn, xmx, ymn, ymx, distx, disty, distxp, distyp, temp1,
117 temp2;
118 int npt, MAXENC;
119 double ew_res, ns_res;
120 int MINPTS;
121 double pr;
122 struct triple *point;
123 struct triple target_point;
124 int npoints, point_index, k;
125 double xx, yy /*, zz */;
126 double xmm, ymm, err, pointz;
127
128 // struct quaddata *data_local;
129
130 ns_res = (((struct quaddata *)(tree->data))->ymax -
131 ((struct quaddata *)(tree->data))->y_orig) /
132 params->nsizr;
133 ew_res = (((struct quaddata *)(tree->data))->xmax -
134 ((struct quaddata *)(tree->data))->x_orig) /
135 params->nsizc;
136
137 if (all_leafs[i_cnt] == NULL) {
139 continue;
140 }
141 if (all_leafs[i_cnt]->data == NULL) {
143 continue;
144 }
145 if (((struct quaddata *)(all_leafs[i_cnt]->data))->points == NULL) {
146 continue;
147 }
148 else {
149 distx = (((struct quaddata *)(all_leafs[i_cnt]->data))->n_cols *
150 ew_res) *
151 0.1;
152 disty = (((struct quaddata *)(all_leafs[i_cnt]->data))->n_rows *
153 ns_res) *
154 0.1;
155 distxp = 0;
156 distyp = 0;
157 xmn = ((struct quaddata *)(all_leafs[i_cnt]->data))->x_orig;
158 xmx = ((struct quaddata *)(all_leafs[i_cnt]->data))->xmax;
159 ymn = ((struct quaddata *)(all_leafs[i_cnt]->data))->y_orig;
160 ymx = ((struct quaddata *)(all_leafs[i_cnt]->data))->ymax;
161 i = 0;
162 MAXENC = 0;
163 /* data is a window with zero points; some fields don't make
164 sense in this case so they are zero (like
165 resolution,dimensions */
166 /* CHANGE */
167 /* Calcutaing kmin for surrent segment (depends on the size) */
168
169 /*****if (smseg <= 0.00001) MINPTS=params->kmin; else {} ***/
170 pr = pow(2., (xmx - xmn) / smseg - 1.);
171 MINPTS = params->kmin *
172 (pr / (1 + params->kmin * pr / params->KMAX2));
173 /* fprintf(stderr,"MINPTS=%d, KMIN=%d, KMAX=%d, pr=%lf,
174 * smseg=%lf, DX=%lf \n",
175 * MINPTS,params->kmin,params->KMAX2,pr,smseg,xmx-xmn); */
176
178 xmn - distx, ymn - disty, xmx + distx, ymx + disty, 0, 0, 0,
179 params->KMAX2);
180 npt = MT_region_data(info, tree, data_local[tid], params->KMAX2,
181 4);
182
183 while ((npt < MINPTS) || (npt > params->KMAX2)) {
184 if (i >= 70) {
185 G_warning(_("Taking too long to find points for "
186 "interpolation - "
187 "please change the region to area where "
188 "your points are. "
189 "Continuing calculations..."));
190 break;
191 }
192 i++;
193 if (npt > params->KMAX2)
194 /* decrease window */
195 {
196 MAXENC = 1;
197 temp1 = distxp;
198 distxp = distx;
199 distx = distxp - fabs(distx - temp1) * 0.5;
200 temp2 = distyp;
201 distyp = disty;
202 disty = distyp - fabs(disty - temp2) * 0.5;
203 /* decrease by 50% of a previous change in window */
204 }
205 else {
206 temp1 = distyp;
207 distyp = disty;
208 temp2 = distxp;
209 distxp = distx;
210 if (MAXENC) {
211 disty = fabs(disty - temp1) * 0.5 + distyp;
212 distx = fabs(distx - temp2) * 0.5 + distxp;
213 }
214 else {
215 distx += distx;
216 disty += disty;
217 }
218 /* decrease by 50% of extra distance */
219 }
220 data_local[tid]->x_orig = xmn - distx; /* update window */
221 data_local[tid]->y_orig = ymn - disty;
222 data_local[tid]->xmax = xmx + distx;
223 data_local[tid]->ymax = ymx + disty;
224 data_local[tid]->n_points = 0;
225 npt = MT_region_data(info, tree, data_local[tid],
226 params->KMAX2, 4);
227 }
228
229 if (totsegm != 0 && tid == 0) {
231 }
232 data_local[tid]->n_rows =
233 ((struct quaddata *)(all_leafs[i_cnt]->data))->n_rows;
234 data_local[tid]->n_cols =
235 ((struct quaddata *)(all_leafs[i_cnt]->data))->n_cols;
236
237 /* for printing out overlapping segments */
238 ((struct quaddata *)(all_leafs[i_cnt]->data))->x_orig =
239 xmn - distx;
240 ((struct quaddata *)(all_leafs[i_cnt]->data))->y_orig =
241 ymn - disty;
242 ((struct quaddata *)(all_leafs[i_cnt]->data))->xmax =
243 xmx + distx;
244 ((struct quaddata *)(all_leafs[i_cnt]->data))->ymax =
245 ymx + disty;
246
247 data_local[tid]->x_orig = xmn;
248 data_local[tid]->y_orig = ymn;
249 data_local[tid]->xmax = xmx;
250 data_local[tid]->ymax = ymx;
251
252 /* allocate memory for CV points only if cv is performed */
253 if (params->cv) {
254 if (!(point = (struct triple *)G_malloc(
255 sizeof(struct triple) *
256 data_local[tid]->n_points))) {
257 G_warning(_("Out of memory"));
259 continue;
260 }
261 }
262
263 /*normalize the data so that the side of average segment is
264 * about 1m */
265 /* put data_points into point only if CV is performed */
266
267 for (i = 0; i < data_local[tid]->n_points; i++) {
268 data_local[tid]->points[i].x =
269 (data_local[tid]->points[i].x -
270 data_local[tid]->x_orig) /
271 dnorm;
272 data_local[tid]->points[i].y =
273 (data_local[tid]->points[i].y -
274 data_local[tid]->y_orig) /
275 dnorm;
276 if (params->cv) {
277 point[i].x = data_local[tid]->points[i].x; /*cv stuff */
278 point[i].y = data_local[tid]->points[i].y; /*cv stuff */
279 point[i].z = data_local[tid]->points[i].z; /*cv stuff */
280 }
281
282 /* commented out by Helena january 1997 as this is not
283 necessary although it may be useful to put normalization
284 of z back? data->points[i].z = data->points[i].z / dnorm;
285 this made smoothing self-adjusting based on dnorm
286 if (params->rsm < 0.) data->points[i].sm =
287 data->points[i].sm / dnorm;
288 */
289 }
290
291 target_point.x = 0;
292 target_point.y = 0;
293 target_point.z = 0;
294
295 /* one time interpolation and devi */
296 if (!params->cv) {
297 if (/* params */
300 matrix[tid], indx[tid],
301 A[tid]) < 0) {
303 continue;
304 }
305
306 for (i = 0; i < data_local[tid]->n_points; i++) {
307 b[tid][i + 1] = data_local[tid]->points[i].z;
308 }
309 b[tid][0] = 0.;
311 indx[tid], b[tid]);
312 /* put here condition to skip error if not needed */
313
314 if (!params->create_devi) { /* check_points only for one
315 time interpolation */
316 params->check_points(params, data_local[tid], b[tid],
317 ertot, zmin, dnorm, &target_point);
318 }
319 }
320
321 npoints = (params->cv || params->create_devi)
323 : 0;
324 for (point_index = 0; point_index < npoints;
325 point_index++) { /* loop only for cv or devi*/
326 if (params->cv) { /* cv: skip one point */
327 /* skip point for cv */
328 target_point.x = point[point_index].x;
329 target_point.y = point[point_index].y;
330 target_point.z = point[point_index].z;
331
332 xx = target_point.x * dnorm + data_local[tid]->x_orig +
333 params->x_orig;
334 yy = target_point.y * dnorm + data_local[tid]->y_orig +
335 params->y_orig;
336 /* zz = point[point_index].z; */
337
338 if (xx >= data_local[tid]->x_orig + params->x_orig &&
339 xx <= data_local[tid]->xmax + params->x_orig &&
340 yy >= data_local[tid]->y_orig + params->y_orig &&
341 yy <= data_local[tid]->ymax + params->y_orig) {
342
343 j = 0;
344 for (k = 0; k < npoints; k++) {
345 if (k != point_index) {
346 data_local[tid]->points[j].x = point[k].x;
347 data_local[tid]->points[j].y = point[k].y;
348 data_local[tid]->points[j].z = point[k].z;
349 j++;
350 }
351 }
352
353 /* segment area test for cv */
354 if (/* params */
356 params, data_local[tid]->points,
358 indx[tid], A[tid]) < 0) {
360 continue;
361 }
362
363 for (i = 0; i < data_local[tid]->n_points - 1;
364 i++) {
365 b[tid][i + 1] = data_local[tid]->points[i].z;
366 }
367 b[tid][0] = 0.;
369 indx[tid], b[tid]);
370 }
371 else {
372 continue;
373 }
374 } /* cv: skip one point */
375
376 if (params->create_devi) {
377 target_point.x = data_local[tid]->points[point_index].x;
378 target_point.y = data_local[tid]->points[point_index].y;
379 target_point.z = data_local[tid]->points[point_index].z;
380 }
381
382 /* x, y, z is required input, while xmm, ymm, err output*/
384 params->check_points(params, data_local[tid], b[tid], ertot,
385 zmin, dnorm, &target_point);
386
387 err = target_point.z;
388 target_point.z = pointz + zmin;
389 xmm = target_point.x;
390 ymm = target_point.y;
391
392 /* write out vector (point), if the point is inside the
393 * region*/
394 if (xmm >= data_local[tid]->x_orig + params->x_orig &&
395 xmm <= data_local[tid]->xmax + params->x_orig &&
396 ymm >= data_local[tid]->y_orig + params->y_orig &&
397 ymm <= data_local[tid]->ymax + params->y_orig) {
398 /* vect append, count, vect_write, db_execute will have
399 * conflicts between threads */
400#pragma omp critical
401 {
402 params->check_points(params, NULL, NULL, &err, 0.0,
403 0.0, &target_point);
404 }
405 }
406 } /* end of computations for every point in cv or devi*/
407
408 /* write out grid*/
409 if (!params->cv) {
410 if ((params->Tmp_fd_z != NULL) ||
411 (params->Tmp_fd_dx != NULL) ||
412 (params->Tmp_fd_dy != NULL) ||
413 (params->Tmp_fd_xx != NULL) ||
414 (params->Tmp_fd_yy != NULL) ||
415 (params->Tmp_fd_xy != NULL)) {
416#pragma omp critical
417 {
418 if (params->grid_calc(params, data_local[tid],
419 bitmask, zmin, zmax, zminac,
422 b[tid], offset1, dnorm) < 0) {
424 }
425 }
426 }
427 }
428
429 /* show after to catch 100% */
430#pragma omp atomic
431 cursegm++;
432 if (totsegm < cursegm) {
433 G_debug(1, "%d %d", totsegm, cursegm);
434 }
435
436 if (totsegm != 0 && tid == 0) {
438 }
439 /*
440 G_free_matrix(matrix);
441 G_free_ivector(indx);
442 G_free_vector(b);
443 */
446 }
447 }
448 } /* All threads join master thread and terminate */
449
450 for (i_cnt = 0; i_cnt < threads; i_cnt++) {
452 G_free(indx[i_cnt]);
453 G_free(b[i_cnt]);
454 G_free(A[i_cnt]);
455 }
458 G_free(matrix);
459 G_free(indx);
460 G_free(b);
461 G_free(A);
462
463 if (some_thread_failed != 0) {
464 return -1;
465 }
466 return 1;
467}
468
469/* cut given tree into separate leafs */
470int cut_tree(struct multtree *tree, /* tree we want to cut */
471 struct multtree **cut_leafs, /* array of leafs */
472 int *where_to_add /* index of leaf which will be next */)
473{
474 if (tree == NULL)
475 return -1;
476 if (tree->data == NULL)
477 return -1;
478 if (((struct quaddata *)(tree->data))->points == NULL) {
479 int i;
480
481 for (i = 0; i < 4; i++) {
482 cut_tree(tree->leafs[i], cut_leafs, where_to_add);
483 }
484 return 1;
485 }
486 else {
487 cut_leafs[*where_to_add] = tree;
488 (*where_to_add)++;
489 return 1;
490 }
491}
#define NULL
Definition ccmath.h:32
struct quaddata * quad_data_new(double x_or, double y_or, double xmax, double ymax, int rows, int cols, int n_points, int kmax)
Definition dataquad.c:55
void G_percent(long, long, int)
Print percent complete messages.
Definition percent.c:59
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition defs/gis.h:136
void G_message(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
int * G_alloc_ivector(size_t)
Vector matrix memory allocation.
Definition ialloc.c:38
void G_lubksb(double **a, int n, int *indx, double b[])
LU backward substitution.
Definition lu.c:98
double * G_alloc_vector(size_t)
Vector matrix memory allocation.
Definition dalloc.c:38
double ** G_alloc_matrix(int, int)
Matrix memory allocation.
Definition dalloc.c:55
#define _(str)
Definition glocale.h:10
int IL_matrix_create_alloc(struct interp_params *, struct triple *, int, double **, int *, double *)
Creates system of linear equations from interpolated points.
Definition matrix.c:66
double smallest_segment(struct multtree *, int)
Definition segmen2d.c:337
int MT_region_data(struct tree_info *info, struct multtree *tree, struct quaddata *data, int MAX, int n_leafs)
Definition qtree.c:182
double b
Definition r_raster.c:37
int IL_interp_segments_2d_parallel(struct interp_params *params, struct tree_info *info, struct multtree *tree, struct BM *bitmask, double zmin, double zmax, double *zminac, double *zmaxac, double *gmin, double *gmax, double *c1min, double *c1max, double *c2min, double *c2max, double *ertot, int totsegm, off_t offset1, double dnorm, int threads)
Definition bitmap.h:17
check_points_fn * check_points
Definition interpf.h:132
FILE * Tmp_fd_xx
Definition interpf.h:123
FILE * Tmp_fd_xy
Definition interpf.h:123
FILE * Tmp_fd_yy
Definition interpf.h:123
grid_calc_fn * grid_calc
Definition interpf.h:128
double x_orig
Definition interpf.h:112
FILE * Tmp_fd_dx
Definition interpf.h:123
double y_orig
Definition interpf.h:112
FILE * Tmp_fd_z
Definition interpf.h:123
FILE * Tmp_fd_dy
Definition interpf.h:123
bool create_devi
Definition interpf.h:126
struct multtree ** leafs
Definition qtree.h:50
struct quaddata * data
Definition qtree.h:49
double ymax
Definition dataquad.h:45
double y_orig
Definition dataquad.h:43
double x_orig
Definition dataquad.h:42
struct triple * points
Definition dataquad.h:49
int n_points
Definition dataquad.h:48
double xmax
Definition dataquad.h:44
int n_cols
Definition dataquad.h:47
int n_rows
Definition dataquad.h:46
double z
Definition dataquad.h:37
double x
Definition dataquad.h:35
double y
Definition dataquad.h:36
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)