GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
N_gradient_calc.c
Go to the documentation of this file.
1 
2 /*****************************************************************************
3 *
4 * MODULE: Grass PDE Numerical Library
5 * AUTHOR(S): Soeren Gebbert, Berlin (GER) Dec 2006
6 * soerengebbert <at> gmx <dot> de
7 *
8 * PURPOSE: gradient management functions
9 * part of the gpde library
10 *
11 * COPYRIGHT: (C) 2000 by the GRASS Development Team
12 *
13 * This program is free software under the GNU General Public
14 * License (>=v2). Read the file COPYING that comes with GRASS
15 * for details.
16 *
17 *****************************************************************************/
18 
19 #include <grass/N_pde.h>
20 
30 {
31  double minx, miny;
32 
33  double maxx, maxy;
34 
35  double sumx, sumy;
36 
37  int nonullx, nonully;
38 
39  G_debug(3,
40  "N_calc_gradient_field_2d_stats: compute gradient field stats");
41 
42  N_calc_array_2d_stats(field->x_array, &minx, &maxx, &sumx, &nonullx, 0);
43  N_calc_array_2d_stats(field->y_array, &miny, &maxy, &sumy, &nonully, 0);
44 
45  if (minx < miny)
46  field->min = minx;
47  else
48  field->min = miny;
49 
50  if (maxx > maxy)
51  field->max = maxx;
52  else
53  field->max = maxy;
54 
55  field->sum = sumx + sumy;
56  field->nonull = nonullx + nonully;
57  field->mean = field->sum / (double)field->nonull;
58 
59  return;
60 }
61 
109  N_array_2d * weight_x,
110  N_array_2d * weight_y,
111  N_geom_data * geom,
113  gradfield)
114 {
115  int i, j;
116 
117  int rows, cols;
118 
119  double dx, dy, p1, p2, r1, r2, mean, grad, res;
120 
121  N_gradient_field_2d *field = gradfield;
122 
123 
124  if (pot->cols != weight_x->cols || pot->cols != weight_y->cols)
126  ("N_compute_gradient_field_2d: the arrays are not of equal size");
127 
128  if (pot->rows != weight_x->rows || pot->rows != weight_y->rows)
130  ("N_compute_gradient_field_2d: the arrays are not of equal size");
131 
132  if (pot->cols != geom->cols || pot->rows != geom->rows)
134  ("N_compute_gradient_field_2d: array sizes and geometry data are different");
135 
136 
137  G_debug(3, "N_compute_gradient_field_2d: compute gradient field");
138 
139  rows = pot->rows;
140  cols = pot->cols;
141  dx = geom->dx;
142  dy = geom->dy;
143 
144  if (field == NULL) {
145  field = N_alloc_gradient_field_2d(cols, rows);
146  }
147  else {
148  if (field->cols != geom->cols || field->rows != geom->rows)
150  ("N_compute_gradient_field_2d: gradient field sizes and geometry data are different");
151  }
152 
153 
154  for (j = 0; j < rows; j++)
155  for (i = 0; i < cols - 1; i++) {
156  grad = 0;
157  mean = 0;
158 
159  /* Only compute if the arrays are not null */
160  if (!N_is_array_2d_value_null(pot, i, j) &&
161  !N_is_array_2d_value_null(pot, i + 1, j)) {
162  p1 = N_get_array_2d_d_value(pot, i, j);
163  p2 = N_get_array_2d_d_value(pot, i + 1, j);
164  grad = (p1 - p2) / dx; /* gradient */
165  }
166  if (!N_is_array_2d_value_null(weight_x, i, j) &&
167  !N_is_array_2d_value_null(weight_x, i + 1, j)) {
168  r1 = N_get_array_2d_d_value(weight_x, i, j);
169  r2 = N_get_array_2d_d_value(weight_x, i + 1, j);
170  mean = N_calc_harmonic_mean(r1, r2); /*harmonical mean */
171  }
172 
173  res = mean * grad;
174 
175  N_put_array_2d_d_value(field->x_array, i + 1, j, res);
176 
177  }
178 
179  for (j = 0; j < rows - 1; j++)
180  for (i = 0; i < cols; i++) {
181  grad = 0;
182  mean = 0;
183 
184  /* Only compute if the arrays are not null */
185  if (!N_is_array_2d_value_null(pot, i, j) &&
186  !N_is_array_2d_value_null(pot, i, j + 1)) {
187  p1 = N_get_array_2d_d_value(pot, i, j);
188  p2 = N_get_array_2d_d_value(pot, i, j + 1);
189  grad = (p1 - p2) / dy; /* gradient */
190  }
191  if (!N_is_array_2d_value_null(weight_y, i, j) &&
192  !N_is_array_2d_value_null(weight_y, i, j + 1)) {
193  r1 = N_get_array_2d_d_value(weight_y, i, j);
194  r2 = N_get_array_2d_d_value(weight_y, i, j + 1);
195  mean = N_calc_harmonic_mean(r1, r2); /*harmonical mean */
196  }
197 
198  res = -1 * mean * grad;
199 
200  N_put_array_2d_d_value(field->y_array, i, j + 1, res);
201 
202  }
203 
204  /*Compute gradient field statistics */
206 
207  return field;
208 }
209 
248 void
250  N_array_2d * x_comp,
251  N_array_2d * y_comp)
252 {
253  int i, j;
254 
255  int rows, cols;
256 
257  double vx, vy;
258 
259  N_array_2d *x = x_comp;
260 
261  N_array_2d *y = y_comp;
262 
263  N_gradient_2d grad;
264 
265 
266  if (!x)
267  G_fatal_error("N_compute_gradient_components_2d: x array is empty");
268  if (!y)
269  G_fatal_error("N_compute_gradient_components_2d: y array is empty");
270 
271  cols = field->x_array->cols;
272  rows = field->x_array->rows;
273 
274  /*Check the array sizes */
275  if (x->cols != cols || x->rows != rows)
277  ("N_compute_gradient_components_2d: the size of the x array doesn't fit the gradient field size");
278  if (y->cols != cols || y->rows != rows)
280  ("N_compute_gradient_components_2d: the size of the y array doesn't fit the gradient field size");
281 
282  for (j = 0; j < rows; j++)
283  for (i = 0; i < cols; i++) {
284  N_get_gradient_2d(field, &grad, i, j);
285 
286  /* in case a gradient is zero, we expect a no flow boundary */
287  if (grad.WC == 0.0 || grad.EC == 0.0)
288  vx = (grad.WC + grad.EC);
289  else
290  vx = (grad.WC + grad.EC) / 2;
291  if (grad.NC == 0.0 || grad.SC == 0.0)
292  vy = (grad.NC + grad.SC);
293  else
294  vy = (grad.NC + grad.SC) / 2;
295 
296  N_put_array_2d_d_value(x, i, j, vx);
297  N_put_array_2d_d_value(y, i, j, vy);
298  }
299 
300  return;
301 }
302 
312 {
313  double minx, miny, minz;
314 
315  double maxx, maxy, maxz;
316 
317  double sumx, sumy, sumz;
318 
319  int nonullx, nonully, nonullz;
320 
321  G_debug(3,
322  "N_calc_gradient_field_3d_stats: compute gradient field stats");
323 
324  N_calc_array_3d_stats(field->x_array, &minx, &maxx, &sumx, &nonullx, 0);
325  N_calc_array_3d_stats(field->y_array, &miny, &maxy, &sumy, &nonully, 0);
326  N_calc_array_3d_stats(field->z_array, &minz, &maxz, &sumz, &nonullz, 0);
327 
328  if (minx <= minz && minx <= miny)
329  field->min = minx;
330  if (miny <= minz && miny <= minx)
331  field->min = miny;
332  if (minz <= minx && minz <= miny)
333  field->min = minz;
334 
335  if (maxx >= maxz && maxx >= maxy)
336  field->max = maxx;
337  if (maxy >= maxz && maxy >= maxx)
338  field->max = maxy;
339  if (maxz >= maxx && maxz >= maxy)
340  field->max = maxz;
341 
342  field->sum = sumx + sumy + sumz;
343  field->nonull = nonullx + nonully + nonullz;
344  field->mean = field->sum / (double)field->nonull;
345 
346  return;
347 }
348 
349 
401  N_array_3d * weight_x,
402  N_array_3d * weight_y,
403  N_array_3d * weight_z,
404  N_geom_data * geom,
406  gradfield)
407 {
408  int i, j, k;
409 
410  int cols, rows, depths;
411 
412  double dx, dy, dz, p1, p2, r1, r2, mean, grad, res;
413 
414  N_gradient_field_3d *field = gradfield;
415 
416 
417  if (pot->cols != weight_x->cols || pot->cols != weight_y->cols ||
418  pot->cols != weight_z->cols)
420  ("N_compute_gradient_field_3d: the arrays are not of equal size");
421 
422  if (pot->rows != weight_x->rows || pot->rows != weight_y->rows ||
423  pot->rows != weight_z->rows)
425  ("N_compute_gradient_field_3d: the arrays are not of equal size");
426 
427  if (pot->depths != weight_x->depths || pot->depths != weight_y->depths ||
428  pot->depths != weight_z->depths)
430  ("N_compute_gradient_field_3d: the arrays are not of equal size");
431 
432  if (pot->cols != geom->cols || pot->rows != geom->rows ||
433  pot->depths != geom->depths)
435  ("N_compute_gradient_field_3d: array sizes and geometry data are different");
436 
437  G_debug(3, "N_compute_gradient_field_3d: compute gradient field");
438 
439  cols = geom->cols;
440  rows = geom->rows;
441  depths = geom->depths;
442  dx = geom->dx;
443  dy = geom->dy;
444  dz = geom->dz;
445 
446  if (gradfield == NULL) {
447  field = N_alloc_gradient_field_3d(cols, rows, depths);
448  }
449  else {
450  if (field->cols != geom->cols || field->rows != geom->rows ||
451  field->depths != geom->depths)
453  ("N_compute_gradient_field_3d: gradient field sizes and geometry data are different");
454  }
455 
456  for (k = 0; k < depths; k++)
457  for (j = 0; j < rows; j++)
458  for (i = 0; i < cols - 1; i++) {
459  grad = 0;
460  mean = 0;
461 
462  /*Only compute if the arrays are not null */
463  if (!N_is_array_3d_value_null(pot, i, j, k) &&
464  !N_is_array_3d_value_null(pot, i + 1, j, k)) {
465  p1 = N_get_array_3d_d_value(pot, i, j, k);
466  p2 = N_get_array_3d_d_value(pot, i + 1, j, k);
467  grad = (p1 - p2) / dx; /* gradient */
468  }
469  if (!N_is_array_3d_value_null(weight_x, i, j, k) &&
470  !N_is_array_3d_value_null(weight_x, i + 1, j, k)) {
471  r1 = N_get_array_3d_d_value(weight_x, i, j, k);
472  r2 = N_get_array_3d_d_value(weight_x, i + 1, j, k);
473  mean = N_calc_harmonic_mean(r1, r2); /*harmonical mean */
474  }
475 
476  res = mean * grad;
477 
478  G_debug(6,
479  "N_compute_gradient_field_3d: X-direction insert value %6.5g at %i %i %i ",
480  res, k, j, i + 1);
481 
482  N_put_array_3d_d_value(field->x_array, i + 1, j, k, res);
483 
484  }
485 
486  for (k = 0; k < depths; k++)
487  for (j = 0; j < rows - 1; j++)
488  for (i = 0; i < cols; i++) {
489  grad = 0;
490  mean = 0;
491 
492  /* Only compute if the arrays are not null */
493  if (!N_is_array_3d_value_null(pot, i, j, k) &&
494  !N_is_array_3d_value_null(pot, i, j + 1, k)) {
495  p1 = N_get_array_3d_d_value(pot, i, j, k);
496  p2 = N_get_array_3d_d_value(pot, i, j + 1, k);
497  grad = (p1 - p2) / dy; /* gradient */
498  }
499  if (!N_is_array_3d_value_null(weight_y, i, j, k) &&
500  !N_is_array_3d_value_null(weight_y, i, j + 1, k)) {
501  r1 = N_get_array_3d_d_value(weight_y, i, j, k);
502  r2 = N_get_array_3d_d_value(weight_y, i, j + 1, k);
503  mean = N_calc_harmonic_mean(r1, r2); /*harmonical mean */
504  }
505 
506  res = -1 * mean * grad; /*invert the direction, because we count from north to south,
507  * but the gradient is defined in y direction */
508 
509  G_debug(6,
510  "N_compute_gradient_field_3d: Y-direction insert value %6.5g at %i %i %i ",
511  res, k, j + 1, i);
512 
513  N_put_array_3d_d_value(field->y_array, i, j + 1, k, res);
514 
515  }
516 
517  for (k = 0; k < depths - 1; k++)
518  for (j = 0; j < rows; j++)
519  for (i = 0; i < cols; i++) {
520  grad = 0;
521  mean = 0;
522 
523  /* Only compute if the arrays are not null */
524  if (!N_is_array_3d_value_null(pot, i, j, k) &&
525  !N_is_array_3d_value_null(pot, i, j, k + 1)) {
526  p1 = N_get_array_3d_d_value(pot, i, j, k);
527  p2 = N_get_array_3d_d_value(pot, i, j, k + 1);
528  grad = (p1 - p2) / dz; /* gradient */
529  }
530  if (!N_is_array_3d_value_null(weight_z, i, j, k) &&
531  !N_is_array_3d_value_null(weight_z, i, j, k + 1)) {
532  r1 = N_get_array_3d_d_value(weight_z, i, j, k);
533  r2 = N_get_array_3d_d_value(weight_z, i, j, k + 1);
534  mean = N_calc_harmonic_mean(r1, r2); /*harmonical mean */
535  }
536 
537  res = mean * grad;
538 
539  G_debug(6,
540  "N_compute_gradient_field_3d: Z-direction insert value %6.5g at %i %i %i ",
541  res, k + 1, j, i);
542 
543  N_put_array_3d_d_value(field->z_array, i, j, k + 1, res);
544 
545  }
546 
547  /*Compute gradient field statistics */
549 
550  return field;
551 }
552 
595 void
597  N_array_3d * x_comp,
598  N_array_3d * y_comp,
599  N_array_3d * z_comp)
600 {
601  int i, j, k;
602 
603  int rows, cols, depths;
604 
605  double vx, vy, vz;
606 
607  N_array_3d *x = x_comp;
608 
609  N_array_3d *y = y_comp;
610 
611  N_array_3d *z = z_comp;
612 
613  N_gradient_3d grad;
614 
615 
616  if (!x)
617  G_fatal_error("N_compute_gradient_components_3d: x array is empty");
618  if (!y)
619  G_fatal_error("N_compute_gradient_components_3d: y array is empty");
620  if (!z)
621  G_fatal_error("N_compute_gradient_components_3d: z array is empty");
622 
623  cols = field->x_array->cols;
624  rows = field->x_array->rows;
625  depths = field->x_array->depths;
626 
627  /*Check the array sizes */
628  if (x->cols != cols || x->rows != rows || x->depths != depths)
630  ("N_compute_gradient_components_3d: the size of the x array doesn't fit the gradient field size");
631  if (y->cols != cols || y->rows != rows || y->depths != depths)
633  ("N_compute_gradient_components_3d: the size of the y array doesn't fit the gradient field size");
634  if (z->cols != cols || z->rows != rows || z->depths != depths)
636  ("N_compute_gradient_components_3d: the size of the z array doesn't fit the gradient field size");
637 
638  for (k = 0; k < depths; k++)
639  for (j = 0; j < rows; j++)
640  for (i = 0; i < cols; i++) {
641  N_get_gradient_3d(field, &grad, i, j, k);
642  /* in case a gradient is zero, we expect a no flow boundary */
643  if (grad.WC == 0.0 || grad.EC == 0.0)
644  vx = (grad.WC + grad.EC);
645  else
646  vx = (grad.WC + grad.EC) / 2;
647  if (grad.NC == 0.0 || grad.SC == 0.0)
648  vy = (grad.NC + grad.SC);
649  else
650  vy = (grad.NC + grad.SC) / 2;
651  if (grad.TC == 0.0 || grad.BC == 0.0)
652  vz = (grad.TC + grad.BC);
653  else
654  vz = (grad.TC + grad.BC) / 2;
655 
656  N_put_array_3d_d_value(x, i, j, k, vx);
657  N_put_array_3d_d_value(y, i, j, k, vy);
658  N_put_array_3d_d_value(z, i, j, k, vz);
659  }
660 
661 
662  return;
663 }
double EC
Definition: N_pde.h:536
int N_is_array_3d_value_null(N_array_3d *data, int col, int row, int depth)
This function returns 1 if value of N_array_3d data at position col, row, depth is of type null...
Definition: N_arrays.c:878
N_gradient_field_3d * N_compute_gradient_field_3d(N_array_3d *pot, N_array_3d *weight_x, N_array_3d *weight_y, N_array_3d *weight_z, N_geom_data *geom, N_gradient_field_3d *gradfield)
This function computes the gradient based on the input N_array_3d pot (that means potential)...
int rows
Definition: N_pde.h:162
void N_compute_gradient_field_components_2d(N_gradient_field_2d *field, N_array_2d *x_comp, N_array_2d *y_comp)
Calculate the x and y vector components from a gradient field for each cell and stores them in the pr...
Gradient between the cells in X and Y direction.
Definition: N_pde.h:525
int depths
Definition: N_pde.h:218
void N_put_array_2d_d_value(N_array_2d *data, int col, int row, DCELL value)
Writes a DCELL value to the N_array_2d struct at position col, row.
Definition: N_arrays.c:581
N_gradient_field_2d * N_compute_gradient_field_2d(N_array_2d *pot, N_array_2d *weight_x, N_array_2d *weight_y, N_geom_data *geom, N_gradient_field_2d *gradfield)
This function computes the gradient based on the input N_array_2d pot (potential), a weighting factor N_array_2d named weight and the distance between two cells saved in the N_geom_data struct.
void N_calc_gradient_field_3d_stats(N_gradient_field_3d *field)
Calculate basic statistics of a gradient field.
int cols
Definition: N_pde.h:162
void N_calc_array_2d_stats(N_array_2d *a, double *min, double *max, double *sum, int *nonull, int withoffset)
Calculate basic statistics of the N_array_2d struct.
double WC
Definition: N_pde.h:536
int y
Definition: plot.c:34
int depths
Definition: N_pde.h:139
N_array_3d * y_array
Definition: N_pde.h:653
double SC
Definition: N_pde.h:536
double dy
Definition: N_pde.h:134
N_gradient_3d * N_get_gradient_3d(N_gradient_field_3d *field, N_gradient_3d *gradient, int col, int row, int depth)
Return a N_gradient_3d structure calculated from the input gradient field at position [depth][row][co...
Definition: N_gradient.c:249
double NC
Definition: N_pde.h:536
Geometric information about the structured grid.
Definition: N_pde.h:127
N_array_2d * y_array
Definition: N_pde.h:641
double dz
Definition: N_pde.h:135
N_gradient_field_2d * N_alloc_gradient_field_2d(int cols, int rows)
Allocate a N_gradient_field_2d.
Definition: N_gradient.c:928
void N_compute_gradient_field_components_3d(N_gradient_field_3d *field, N_array_3d *x_comp, N_array_3d *y_comp, N_array_3d *z_comp)
Calculate the x, y and z vector components from a gradient field for each cell and store them in the ...
int rows
Definition: N_pde.h:140
double TC
Definition: N_pde.h:536
N_array_3d * z_array
Definition: N_pde.h:654
int cols
Definition: N_pde.h:218
double BC
Definition: N_pde.h:536
double EC
Definition: N_pde.h:528
int cols
Definition: N_pde.h:141
Gradient between the cells in X, Y and Z direction.
Definition: N_pde.h:533
void N_calc_array_3d_stats(N_array_3d *a, double *min, double *max, double *sum, int *nonull, int withoffset)
Calculate basic statistics of the N_array_3d struct.
int N_is_array_2d_value_null(N_array_2d *data, int col, int row)
Returns 1 if the value of N_array_2d struct at postion col, row is of type null, otherwise 0...
Definition: N_arrays.c:228
double N_get_array_3d_d_value(N_array_3d *data, int col, int row, int depth)
This function returns the value of type float at position col, row, depth.
Definition: N_arrays.c:987
N_gradient_2d * N_get_gradient_2d(N_gradient_field_2d *field, N_gradient_2d *gradient, int col, int row)
Return a N_gradient_2d structure calculated from the input gradient field at position [row][col]...
Definition: N_gradient.c:115
return NULL
Definition: dbfopen.c:1394
tuple cols
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: gis/debug.c:51
N_array_3d * x_array
Definition: N_pde.h:652
N_gradient_field_3d * N_alloc_gradient_field_3d(int cols, int rows, int depths)
Allocate a N_gradient_field_3d.
Definition: N_gradient.c:1026
double WC
Definition: N_pde.h:528
DCELL N_get_array_2d_d_value(N_array_2d *data, int col, int row)
Returns the value of type DCELL at position col, row.
Definition: N_arrays.c:375
void N_put_array_3d_d_value(N_array_3d *data, int col, int row, int depth, double value)
Writes a double value to the N_array_3d struct at position col, row, depth.
Definition: N_arrays.c:1172
double N_calc_harmonic_mean(double a, double b)
Calculate the harmonical mean of values a and b.
Definition: N_tools.c:121
int G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
void N_calc_gradient_field_2d_stats(N_gradient_field_2d *field)
Calculate basic statistics of a gradient field.
double dx
Definition: N_pde.h:133
double SC
Definition: N_pde.h:528
double NC
Definition: N_pde.h:528
N_array_2d * x_array
Definition: N_pde.h:640
int rows
Definition: N_pde.h:218