segmen2d_parallel.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  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. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <math.h>
  21. #if defined(_OPENMP)
  22. #include <omp.h>
  23. #endif
  24. #include <grass/gis.h>
  25. #include <grass/glocale.h>
  26. #include <grass/interpf.h>
  27. #include <grass/gmath.h>
  28. static int cut_tree(struct multtree *, struct multtree **, int *);
  29. /*!
  30. * See documentation for IL_interp_segments_2d.
  31. * This is a parallel processing implementation.
  32. */
  33. int IL_interp_segments_2d_parallel(struct interp_params *params, 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;
  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. all_leafs =
  60. (struct multtree **)G_malloc(sizeof(struct multtree *) * totsegm);
  61. data_local =
  62. (struct quaddata **)G_malloc(sizeof(struct quaddata *) * threads);
  63. matrix = (double ***)G_malloc(sizeof(double **) * threads);
  64. indx = (int **)G_malloc(sizeof(int *) * threads);
  65. b = (double **)G_malloc(sizeof(double *) * threads);
  66. A = (double **)G_malloc(sizeof(double *) * threads);
  67. for (i_cnt = 0; i_cnt < threads; i_cnt++) {
  68. if (!
  69. (matrix[i_cnt] =
  70. G_alloc_matrix(params->KMAX2 + 1, params->KMAX2 + 1))) {
  71. G_fatal_error(_("Out of memory"));
  72. return -1;
  73. }
  74. }
  75. for (i_cnt = 0; i_cnt < threads; i_cnt++) {
  76. if (!(indx[i_cnt] = G_alloc_ivector(params->KMAX2 + 1))) {
  77. G_fatal_error(_("Out of memory"));
  78. return -1;
  79. }
  80. }
  81. for (i_cnt = 0; i_cnt < threads; i_cnt++) {
  82. if (!(b[i_cnt] = G_alloc_vector(params->KMAX2 + 3))) {
  83. G_fatal_error(_("Out of memory"));
  84. return -1;
  85. }
  86. }
  87. for (i_cnt = 0; i_cnt < threads; i_cnt++) {
  88. if (!
  89. (A[i_cnt] =
  90. G_alloc_vector((params->KMAX2 + 2) * (params->KMAX2 + 2) + 1))) {
  91. G_fatal_error(_("Out of memory"));
  92. return -1;
  93. }
  94. }
  95. smseg = smallest_segment(tree, 4);
  96. cut_tree(tree, all_leafs, &i);
  97. G_message(_("Starting parallel work"));
  98. #pragma omp parallel firstprivate(tid, i, j, zmin, zmax, tree, totsegm, offset1, dnorm, smseg, ertot, params, info, all_leafs, bitmask, b, indx, matrix, data_local, A) shared(cursegm, threads, some_thread_failed, zminac, zmaxac, gmin, gmax, c1min, c1max, c2min, c2max) default(none)
  99. {
  100. #pragma omp for schedule(dynamic)
  101. for (i_cnt = 0; i_cnt < totsegm; i_cnt++) {
  102. /* Obtain thread id */
  103. #if defined(_OPENMP)
  104. tid = omp_get_thread_num();
  105. #endif
  106. double xmn, xmx, ymn, ymx, distx, disty, distxp, distyp, temp1,
  107. temp2;
  108. int npt, nptprev, MAXENC;
  109. double ew_res, ns_res;
  110. int MINPTS;
  111. double pr;
  112. struct triple *point;
  113. struct triple skip_point;
  114. int m_skip, skip_index, k, segtest;
  115. double xx, yy, zz;
  116. //struct quaddata *data_local;
  117. ns_res = (((struct quaddata *)(tree->data))->ymax -
  118. ((struct quaddata *)(tree->data))->y_orig) /
  119. params->nsizr;
  120. ew_res =
  121. (((struct quaddata *)(tree->data))->xmax -
  122. ((struct quaddata *)(tree->data))->x_orig) / params->nsizc;
  123. if (all_leafs[i_cnt] == NULL) {
  124. some_thread_failed = -1;
  125. continue;
  126. }
  127. if (all_leafs[i_cnt]->data == NULL) {
  128. some_thread_failed = -1;
  129. continue;
  130. }
  131. if (((struct quaddata *)(all_leafs[i_cnt]->data))->points == NULL) {
  132. continue;
  133. }
  134. else {
  135. distx =
  136. (((struct quaddata *)(all_leafs[i_cnt]->data))->n_cols *
  137. ew_res) * 0.1;
  138. disty =
  139. (((struct quaddata *)(all_leafs[i_cnt]->data))->n_rows *
  140. ns_res) * 0.1;
  141. distxp = 0;
  142. distyp = 0;
  143. xmn = ((struct quaddata *)(all_leafs[i_cnt]->data))->x_orig;
  144. xmx = ((struct quaddata *)(all_leafs[i_cnt]->data))->xmax;
  145. ymn = ((struct quaddata *)(all_leafs[i_cnt]->data))->y_orig;
  146. ymx = ((struct quaddata *)(all_leafs[i_cnt]->data))->ymax;
  147. i = 0;
  148. MAXENC = 0;
  149. /* data is a window with zero points; some fields don't make sense in this case
  150. so they are zero (like resolution,dimensions */
  151. /* CHANGE */
  152. /* Calcutaing kmin for surrent segment (depends on the size) */
  153. /*****if (smseg <= 0.00001) MINPTS=params->kmin; else {} ***/
  154. pr = pow(2., (xmx - xmn) / smseg - 1.);
  155. MINPTS =
  156. params->kmin * (pr /
  157. (1 + params->kmin * pr / params->KMAX2));
  158. /* fprintf(stderr,"MINPTS=%d, KMIN=%d, KMAX=%d, pr=%lf, smseg=%lf, DX=%lf \n", MINPTS,params->kmin,params->KMAX2,pr,smseg,xmx-xmn); */
  159. data_local[tid] =
  160. (struct quaddata *)quad_data_new(xmn - distx, ymn - disty,
  161. xmx + distx, ymx + disty,
  162. 0, 0, 0, params->KMAX2);
  163. npt =
  164. MT_region_data(info, tree, data_local[tid], params->KMAX2,
  165. 4);
  166. while ((npt < MINPTS) || (npt > params->KMAX2)) {
  167. if (i >= 70) {
  168. G_warning(_("Taking too long to find points for interpolation - "
  169. "please change the region to area where your points are. "
  170. "Continuing calculations..."));
  171. break;
  172. }
  173. i++;
  174. if (npt > params->KMAX2)
  175. /* decrease window */
  176. {
  177. MAXENC = 1;
  178. nptprev = npt;
  179. temp1 = distxp;
  180. distxp = distx;
  181. distx = distxp - fabs(distx - temp1) * 0.5;
  182. temp2 = distyp;
  183. distyp = disty;
  184. disty = distyp - fabs(disty - temp2) * 0.5;
  185. /* decrease by 50% of a previous change in window */
  186. }
  187. else {
  188. nptprev = npt;
  189. temp1 = distyp;
  190. distyp = disty;
  191. temp2 = distxp;
  192. distxp = distx;
  193. if (MAXENC) {
  194. disty = fabs(disty - temp1) * 0.5 + distyp;
  195. distx = fabs(distx - temp2) * 0.5 + distxp;
  196. }
  197. else {
  198. distx += distx;
  199. disty += disty;
  200. }
  201. /* decrease by 50% of extra distance */
  202. }
  203. data_local[tid]->x_orig = xmn - distx; /* update window */
  204. data_local[tid]->y_orig = ymn - disty;
  205. data_local[tid]->xmax = xmx + distx;
  206. data_local[tid]->ymax = ymx + disty;
  207. data_local[tid]->n_points = 0;
  208. npt =
  209. MT_region_data(info, tree, data_local[tid],
  210. params->KMAX2, 4);
  211. }
  212. if (totsegm != 0 && tid == 0) {
  213. G_percent(cursegm, totsegm, 1);
  214. }
  215. data_local[tid]->n_rows =
  216. ((struct quaddata *)(all_leafs[i_cnt]->data))->n_rows;
  217. data_local[tid]->n_cols =
  218. ((struct quaddata *)(all_leafs[i_cnt]->data))->n_cols;
  219. /* for printing out overlapping segments */
  220. ((struct quaddata *)(all_leafs[i_cnt]->data))->x_orig =
  221. xmn - distx;
  222. ((struct quaddata *)(all_leafs[i_cnt]->data))->y_orig =
  223. ymn - disty;
  224. ((struct quaddata *)(all_leafs[i_cnt]->data))->xmax =
  225. xmx + distx;
  226. ((struct quaddata *)(all_leafs[i_cnt]->data))->ymax =
  227. ymx + disty;
  228. data_local[tid]->x_orig = xmn;
  229. data_local[tid]->y_orig = ymn;
  230. data_local[tid]->xmax = xmx;
  231. data_local[tid]->ymax = ymx;
  232. /* allocate memory for CV points only if cv is performed */
  233. if (params->cv) {
  234. if (!
  235. (point =
  236. (struct triple *)G_malloc(sizeof(struct triple) *
  237. data_local[tid]->
  238. n_points))) {
  239. G_warning(_("Out of memory"));
  240. some_thread_failed = -1;
  241. continue;
  242. }
  243. }
  244. /*normalize the data so that the side of average segment is about 1m */
  245. /* put data_points into point only if CV is performed */
  246. for (i = 0; i < data_local[tid]->n_points; i++) {
  247. data_local[tid]->points[i].x =
  248. (data_local[tid]->points[i].x -
  249. data_local[tid]->x_orig) / dnorm;
  250. data_local[tid]->points[i].y =
  251. (data_local[tid]->points[i].y -
  252. data_local[tid]->y_orig) / dnorm;
  253. if (params->cv) {
  254. point[i].x = data_local[tid]->points[i].x; /*cv stuff */
  255. point[i].y = data_local[tid]->points[i].y; /*cv stuff */
  256. point[i].z = data_local[tid]->points[i].z; /*cv stuff */
  257. }
  258. /* commented out by Helena january 1997 as this is not necessary
  259. although it may be useful to put normalization of z back?
  260. data->points[i].z = data->points[i].z / dnorm;
  261. this made smoothing self-adjusting based on dnorm
  262. if (params->rsm < 0.) data->points[i].sm = data->points[i].sm / dnorm;
  263. */
  264. }
  265. /* cv stuff */
  266. if (params->cv) {
  267. m_skip = data_local[tid]->n_points;
  268. }
  269. else {
  270. m_skip = 1;
  271. }
  272. /* remove after cleanup - this is just for testing */
  273. skip_point.x = 0.;
  274. skip_point.y = 0.;
  275. skip_point.z = 0.;
  276. for (skip_index = 0; skip_index < m_skip; skip_index++) {
  277. if (params->cv) {
  278. segtest = 0;
  279. j = 0;
  280. xx = point[skip_index].x * dnorm +
  281. data_local[tid]->x_orig + params->x_orig;
  282. yy = point[skip_index].y * dnorm +
  283. data_local[tid]->y_orig + params->y_orig;
  284. zz = point[skip_index].z;
  285. if (xx >= data_local[tid]->x_orig + params->x_orig &&
  286. xx <= data_local[tid]->xmax + params->x_orig &&
  287. yy >= data_local[tid]->y_orig + params->y_orig &&
  288. yy <= data_local[tid]->ymax + params->y_orig) {
  289. segtest = 1;
  290. skip_point.x = point[skip_index].x;
  291. skip_point.y = point[skip_index].y;
  292. skip_point.z = point[skip_index].z;
  293. for (k = 0; k < m_skip; k++) {
  294. if (k != skip_index && params->cv) {
  295. data_local[tid]->points[j].x = point[k].x;
  296. data_local[tid]->points[j].y = point[k].y;
  297. data_local[tid]->points[j].z = point[k].z;
  298. j++;
  299. }
  300. }
  301. } /* segment area test */
  302. }
  303. if (!params->cv) {
  304. if ( /* params */
  305. IL_matrix_create_alloc(params,
  306. data_local[tid]->points,
  307. data_local[tid]->
  308. n_points, matrix[tid],
  309. indx[tid],
  310. A[tid]) < 0) {
  311. some_thread_failed = -1;
  312. continue;
  313. }
  314. }
  315. else if (segtest == 1) {
  316. if ( /* params */
  317. IL_matrix_create_alloc(params,
  318. data_local[tid]->points,
  319. data_local[tid]->
  320. n_points - 1,
  321. matrix[tid], indx[tid],
  322. A[tid]) < 0) {
  323. some_thread_failed = -1;
  324. continue;
  325. }
  326. }
  327. if (!params->cv) {
  328. for (i = 0; i < data_local[tid]->n_points; i++) {
  329. b[tid][i + 1] = data_local[tid]->points[i].z;
  330. }
  331. b[tid][0] = 0.;
  332. G_lubksb(matrix[tid], data_local[tid]->n_points + 1,
  333. indx[tid], b[tid]);
  334. /* put here condition to skip error if not needed */
  335. params->check_points(params, data_local[tid], b[tid],
  336. ertot, zmin, dnorm, skip_point);
  337. }
  338. else if (segtest == 1) {
  339. for (i = 0; i < data_local[tid]->n_points - 1; i++) {
  340. b[tid][i + 1] = data_local[tid]->points[i].z;
  341. }
  342. b[tid][0] = 0.;
  343. G_lubksb(matrix[tid], data_local[tid]->n_points,
  344. indx[tid], b[tid]);
  345. params->check_points(params, data_local[tid], b[tid],
  346. ertot, zmin, dnorm, skip_point);
  347. }
  348. } /*end of cv loop */
  349. if (!params->cv) {
  350. if ((params->Tmp_fd_z != NULL) ||
  351. (params->Tmp_fd_dx != NULL) ||
  352. (params->Tmp_fd_dy != NULL) ||
  353. (params->Tmp_fd_xx != NULL) ||
  354. (params->Tmp_fd_yy != NULL) ||
  355. (params->Tmp_fd_xy != NULL)) {
  356. #pragma omp critical
  357. {
  358. if (params->grid_calc
  359. (params, data_local[tid], bitmask, zmin, zmax,
  360. zminac, zmaxac, gmin, gmax, c1min, c1max,
  361. c2min, c2max, ertot, b[tid], offset1,
  362. dnorm) < 0) {
  363. some_thread_failed = -1;
  364. }
  365. }
  366. }
  367. }
  368. /* show after to catch 100% */
  369. #pragma omp atomic
  370. cursegm++;
  371. if (totsegm < cursegm) {
  372. G_debug(1, "%d %d", totsegm, cursegm);
  373. }
  374. if (totsegm != 0 && tid == 0) {
  375. G_percent(cursegm, totsegm, 1);
  376. }
  377. /*
  378. G_free_matrix(matrix);
  379. G_free_ivector(indx);
  380. G_free_vector(b);
  381. */
  382. G_free(data_local[tid]->points);
  383. G_free(data_local[tid]);
  384. }
  385. }
  386. } /* All threads join master thread and terminate */
  387. for (i_cnt = 0; i_cnt < threads; i_cnt++) {
  388. G_free(matrix[i_cnt]);
  389. G_free(indx[i_cnt]);
  390. G_free(b[i_cnt]);
  391. G_free(A[i_cnt]);
  392. }
  393. G_free(all_leafs);
  394. G_free(data_local);
  395. G_free(matrix);
  396. G_free(indx);
  397. G_free(b);
  398. G_free(A);
  399. if (some_thread_failed != 0) {
  400. return -1;
  401. }
  402. return 1;
  403. }
  404. /* cut given tree into separate leafs */
  405. int cut_tree(struct multtree *tree, /* tree we want to cut */
  406. struct multtree **cut_leafs, /* array of leafs */
  407. int *where_to_add /* index of leaf which will be next */ )
  408. {
  409. if (tree == NULL)
  410. return -1;
  411. if (tree->data == NULL)
  412. return -1;
  413. if (((struct quaddata *)(tree->data))->points == NULL) {
  414. int i;
  415. for (i = 0; i < 4; i++) {
  416. cut_tree(tree->leafs[i], cut_leafs, where_to_add);
  417. }
  418. return 1;
  419. }
  420. else {
  421. cut_leafs[*where_to_add] = tree;
  422. (*where_to_add)++;
  423. return 1;
  424. }
  425. }