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