|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
00001 00002 /***************************************************************************** 00003 * 00004 * MODULE: Grass PDE Numerical Library 00005 * AUTHOR(S): Soeren Gebbert, Berlin (GER) Dec 2006 00006 * soerengebbert <at> gmx <dot> de 00007 * 00008 * PURPOSE: gradient management functions 00009 * part of the gpde library 00010 * 00011 * COPYRIGHT: (C) 2000 by the GRASS Development Team 00012 * 00013 * This program is free software under the GNU General Public 00014 * License (>=v2). Read the file COPYING that comes with GRASS 00015 * for details. 00016 * 00017 *****************************************************************************/ 00018 00019 #include <grass/N_pde.h> 00020 00029 void N_calc_gradient_field_2d_stats(N_gradient_field_2d * field) 00030 { 00031 double minx, miny; 00032 00033 double maxx, maxy; 00034 00035 double sumx, sumy; 00036 00037 int nonullx, nonully; 00038 00039 G_debug(3, 00040 "N_calc_gradient_field_2d_stats: compute gradient field stats"); 00041 00042 N_calc_array_2d_stats(field->x_array, &minx, &maxx, &sumx, &nonullx, 0); 00043 N_calc_array_2d_stats(field->y_array, &miny, &maxy, &sumy, &nonully, 0); 00044 00045 if (minx < miny) 00046 field->min = minx; 00047 else 00048 field->min = miny; 00049 00050 if (maxx > maxy) 00051 field->max = maxx; 00052 else 00053 field->max = maxy; 00054 00055 field->sum = sumx + sumy; 00056 field->nonull = nonullx + nonully; 00057 field->mean = field->sum / (double)field->nonull; 00058 00059 return; 00060 } 00061 00108 N_gradient_field_2d *N_compute_gradient_field_2d(N_array_2d * pot, 00109 N_array_2d * weight_x, 00110 N_array_2d * weight_y, 00111 N_geom_data * geom, 00112 N_gradient_field_2d * 00113 gradfield) 00114 { 00115 int i, j; 00116 00117 int rows, cols; 00118 00119 double dx, dy, p1, p2, r1, r2, mean, grad, res; 00120 00121 N_gradient_field_2d *field = gradfield; 00122 00123 00124 if (pot->cols != weight_x->cols || pot->cols != weight_y->cols) 00125 G_fatal_error 00126 ("N_compute_gradient_field_2d: the arrays are not of equal size"); 00127 00128 if (pot->rows != weight_x->rows || pot->rows != weight_y->rows) 00129 G_fatal_error 00130 ("N_compute_gradient_field_2d: the arrays are not of equal size"); 00131 00132 if (pot->cols != geom->cols || pot->rows != geom->rows) 00133 G_fatal_error 00134 ("N_compute_gradient_field_2d: array sizes and geometry data are different"); 00135 00136 00137 G_debug(3, "N_compute_gradient_field_2d: compute gradient field"); 00138 00139 rows = pot->rows; 00140 cols = pot->cols; 00141 dx = geom->dx; 00142 dy = geom->dy; 00143 00144 if (field == NULL) { 00145 field = N_alloc_gradient_field_2d(cols, rows); 00146 } 00147 else { 00148 if (field->cols != geom->cols || field->rows != geom->rows) 00149 G_fatal_error 00150 ("N_compute_gradient_field_2d: gradient field sizes and geometry data are different"); 00151 } 00152 00153 00154 for (j = 0; j < rows; j++) 00155 for (i = 0; i < cols - 1; i++) { 00156 grad = 0; 00157 mean = 0; 00158 00159 /* Only compute if the arrays are not null */ 00160 if (!N_is_array_2d_value_null(pot, i, j) && 00161 !N_is_array_2d_value_null(pot, i + 1, j)) { 00162 p1 = N_get_array_2d_d_value(pot, i, j); 00163 p2 = N_get_array_2d_d_value(pot, i + 1, j); 00164 grad = (p1 - p2) / dx; /* gradient */ 00165 } 00166 if (!N_is_array_2d_value_null(weight_x, i, j) && 00167 !N_is_array_2d_value_null(weight_x, i + 1, j)) { 00168 r1 = N_get_array_2d_d_value(weight_x, i, j); 00169 r2 = N_get_array_2d_d_value(weight_x, i + 1, j); 00170 mean = N_calc_harmonic_mean(r1, r2); /*harmonical mean */ 00171 } 00172 00173 res = mean * grad; 00174 00175 N_put_array_2d_d_value(field->x_array, i + 1, j, res); 00176 00177 } 00178 00179 for (j = 0; j < rows - 1; j++) 00180 for (i = 0; i < cols; i++) { 00181 grad = 0; 00182 mean = 0; 00183 00184 /* Only compute if the arrays are not null */ 00185 if (!N_is_array_2d_value_null(pot, i, j) && 00186 !N_is_array_2d_value_null(pot, i, j + 1)) { 00187 p1 = N_get_array_2d_d_value(pot, i, j); 00188 p2 = N_get_array_2d_d_value(pot, i, j + 1); 00189 grad = (p1 - p2) / dy; /* gradient */ 00190 } 00191 if (!N_is_array_2d_value_null(weight_y, i, j) && 00192 !N_is_array_2d_value_null(weight_y, i, j + 1)) { 00193 r1 = N_get_array_2d_d_value(weight_y, i, j); 00194 r2 = N_get_array_2d_d_value(weight_y, i, j + 1); 00195 mean = N_calc_harmonic_mean(r1, r2); /*harmonical mean */ 00196 } 00197 00198 res = -1 * mean * grad; 00199 00200 N_put_array_2d_d_value(field->y_array, i, j + 1, res); 00201 00202 } 00203 00204 /*Compute gradient field statistics */ 00205 N_calc_gradient_field_2d_stats(field); 00206 00207 return field; 00208 } 00209 00248 void 00249 N_compute_gradient_field_components_2d(N_gradient_field_2d * field, 00250 N_array_2d * x_comp, 00251 N_array_2d * y_comp) 00252 { 00253 int i, j; 00254 00255 int rows, cols; 00256 00257 double vx, vy; 00258 00259 N_array_2d *x = x_comp; 00260 00261 N_array_2d *y = y_comp; 00262 00263 N_gradient_2d grad; 00264 00265 00266 if (!x) 00267 G_fatal_error("N_compute_gradient_components_2d: x array is empty"); 00268 if (!y) 00269 G_fatal_error("N_compute_gradient_components_2d: y array is empty"); 00270 00271 cols = field->x_array->cols; 00272 rows = field->x_array->rows; 00273 00274 /*Check the array sizes */ 00275 if (x->cols != cols || x->rows != rows) 00276 G_fatal_error 00277 ("N_compute_gradient_components_2d: the size of the x array doesn't fit the gradient field size"); 00278 if (y->cols != cols || y->rows != rows) 00279 G_fatal_error 00280 ("N_compute_gradient_components_2d: the size of the y array doesn't fit the gradient field size"); 00281 00282 for (j = 0; j < rows; j++) 00283 for (i = 0; i < cols; i++) { 00284 N_get_gradient_2d(field, &grad, i, j); 00285 00286 /* in case a gradient is zero, we expect a no flow boundary */ 00287 if (grad.WC == 0.0 || grad.EC == 0.0) 00288 vx = (grad.WC + grad.EC); 00289 else 00290 vx = (grad.WC + grad.EC) / 2; 00291 if (grad.NC == 0.0 || grad.SC == 0.0) 00292 vy = (grad.NC + grad.SC); 00293 else 00294 vy = (grad.NC + grad.SC) / 2; 00295 00296 N_put_array_2d_d_value(x, i, j, vx); 00297 N_put_array_2d_d_value(y, i, j, vy); 00298 } 00299 00300 return; 00301 } 00302 00311 void N_calc_gradient_field_3d_stats(N_gradient_field_3d * field) 00312 { 00313 double minx, miny, minz; 00314 00315 double maxx, maxy, maxz; 00316 00317 double sumx, sumy, sumz; 00318 00319 int nonullx, nonully, nonullz; 00320 00321 G_debug(3, 00322 "N_calc_gradient_field_3d_stats: compute gradient field stats"); 00323 00324 N_calc_array_3d_stats(field->x_array, &minx, &maxx, &sumx, &nonullx, 0); 00325 N_calc_array_3d_stats(field->y_array, &miny, &maxy, &sumy, &nonully, 0); 00326 N_calc_array_3d_stats(field->z_array, &minz, &maxz, &sumz, &nonullz, 0); 00327 00328 if (minx <= minz && minx <= miny) 00329 field->min = minx; 00330 if (miny <= minz && miny <= minx) 00331 field->min = miny; 00332 if (minz <= minx && minz <= miny) 00333 field->min = minz; 00334 00335 if (maxx >= maxz && maxx >= maxy) 00336 field->max = maxx; 00337 if (maxy >= maxz && maxy >= maxx) 00338 field->max = maxy; 00339 if (maxz >= maxx && maxz >= maxy) 00340 field->max = maxz; 00341 00342 field->sum = sumx + sumy + sumz; 00343 field->nonull = nonullx + nonully + nonullz; 00344 field->mean = field->sum / (double)field->nonull; 00345 00346 return; 00347 } 00348 00349 00400 N_gradient_field_3d *N_compute_gradient_field_3d(N_array_3d * pot, 00401 N_array_3d * weight_x, 00402 N_array_3d * weight_y, 00403 N_array_3d * weight_z, 00404 N_geom_data * geom, 00405 N_gradient_field_3d * 00406 gradfield) 00407 { 00408 int i, j, k; 00409 00410 int cols, rows, depths; 00411 00412 double dx, dy, dz, p1, p2, r1, r2, mean, grad, res; 00413 00414 N_gradient_field_3d *field = gradfield; 00415 00416 00417 if (pot->cols != weight_x->cols || pot->cols != weight_y->cols || 00418 pot->cols != weight_z->cols) 00419 G_fatal_error 00420 ("N_compute_gradient_field_3d: the arrays are not of equal size"); 00421 00422 if (pot->rows != weight_x->rows || pot->rows != weight_y->rows || 00423 pot->rows != weight_z->rows) 00424 G_fatal_error 00425 ("N_compute_gradient_field_3d: the arrays are not of equal size"); 00426 00427 if (pot->depths != weight_x->depths || pot->depths != weight_y->depths || 00428 pot->depths != weight_z->depths) 00429 G_fatal_error 00430 ("N_compute_gradient_field_3d: the arrays are not of equal size"); 00431 00432 if (pot->cols != geom->cols || pot->rows != geom->rows || 00433 pot->depths != geom->depths) 00434 G_fatal_error 00435 ("N_compute_gradient_field_3d: array sizes and geometry data are different"); 00436 00437 G_debug(3, "N_compute_gradient_field_3d: compute gradient field"); 00438 00439 cols = geom->cols; 00440 rows = geom->rows; 00441 depths = geom->depths; 00442 dx = geom->dx; 00443 dy = geom->dy; 00444 dz = geom->dz; 00445 00446 if (gradfield == NULL) { 00447 field = N_alloc_gradient_field_3d(cols, rows, depths); 00448 } 00449 else { 00450 if (field->cols != geom->cols || field->rows != geom->rows || 00451 field->depths != geom->depths) 00452 G_fatal_error 00453 ("N_compute_gradient_field_3d: gradient field sizes and geometry data are different"); 00454 } 00455 00456 for (k = 0; k < depths; k++) 00457 for (j = 0; j < rows; j++) 00458 for (i = 0; i < cols - 1; i++) { 00459 grad = 0; 00460 mean = 0; 00461 00462 /*Only compute if the arrays are not null */ 00463 if (!N_is_array_3d_value_null(pot, i, j, k) && 00464 !N_is_array_3d_value_null(pot, i + 1, j, k)) { 00465 p1 = N_get_array_3d_d_value(pot, i, j, k); 00466 p2 = N_get_array_3d_d_value(pot, i + 1, j, k); 00467 grad = (p1 - p2) / dx; /* gradient */ 00468 } 00469 if (!N_is_array_3d_value_null(weight_x, i, j, k) && 00470 !N_is_array_3d_value_null(weight_x, i + 1, j, k)) { 00471 r1 = N_get_array_3d_d_value(weight_x, i, j, k); 00472 r2 = N_get_array_3d_d_value(weight_x, i + 1, j, k); 00473 mean = N_calc_harmonic_mean(r1, r2); /*harmonical mean */ 00474 } 00475 00476 res = mean * grad; 00477 00478 G_debug(6, 00479 "N_compute_gradient_field_3d: X-direction insert value %6.5g at %i %i %i ", 00480 res, k, j, i + 1); 00481 00482 N_put_array_3d_d_value(field->x_array, i + 1, j, k, res); 00483 00484 } 00485 00486 for (k = 0; k < depths; k++) 00487 for (j = 0; j < rows - 1; j++) 00488 for (i = 0; i < cols; i++) { 00489 grad = 0; 00490 mean = 0; 00491 00492 /* Only compute if the arrays are not null */ 00493 if (!N_is_array_3d_value_null(pot, i, j, k) && 00494 !N_is_array_3d_value_null(pot, i, j + 1, k)) { 00495 p1 = N_get_array_3d_d_value(pot, i, j, k); 00496 p2 = N_get_array_3d_d_value(pot, i, j + 1, k); 00497 grad = (p1 - p2) / dy; /* gradient */ 00498 } 00499 if (!N_is_array_3d_value_null(weight_y, i, j, k) && 00500 !N_is_array_3d_value_null(weight_y, i, j + 1, k)) { 00501 r1 = N_get_array_3d_d_value(weight_y, i, j, k); 00502 r2 = N_get_array_3d_d_value(weight_y, i, j + 1, k); 00503 mean = N_calc_harmonic_mean(r1, r2); /*harmonical mean */ 00504 } 00505 00506 res = -1 * mean * grad; /*invert the direction, because we count from north to south, 00507 * but the gradient is defined in y direction */ 00508 00509 G_debug(6, 00510 "N_compute_gradient_field_3d: Y-direction insert value %6.5g at %i %i %i ", 00511 res, k, j + 1, i); 00512 00513 N_put_array_3d_d_value(field->y_array, i, j + 1, k, res); 00514 00515 } 00516 00517 for (k = 0; k < depths - 1; k++) 00518 for (j = 0; j < rows; j++) 00519 for (i = 0; i < cols; i++) { 00520 grad = 0; 00521 mean = 0; 00522 00523 /* Only compute if the arrays are not null */ 00524 if (!N_is_array_3d_value_null(pot, i, j, k) && 00525 !N_is_array_3d_value_null(pot, i, j, k + 1)) { 00526 p1 = N_get_array_3d_d_value(pot, i, j, k); 00527 p2 = N_get_array_3d_d_value(pot, i, j, k + 1); 00528 grad = (p1 - p2) / dz; /* gradient */ 00529 } 00530 if (!N_is_array_3d_value_null(weight_z, i, j, k) && 00531 !N_is_array_3d_value_null(weight_z, i, j, k + 1)) { 00532 r1 = N_get_array_3d_d_value(weight_z, i, j, k); 00533 r2 = N_get_array_3d_d_value(weight_z, i, j, k + 1); 00534 mean = N_calc_harmonic_mean(r1, r2); /*harmonical mean */ 00535 } 00536 00537 res = mean * grad; 00538 00539 G_debug(6, 00540 "N_compute_gradient_field_3d: Z-direction insert value %6.5g at %i %i %i ", 00541 res, k + 1, j, i); 00542 00543 N_put_array_3d_d_value(field->z_array, i, j, k + 1, res); 00544 00545 } 00546 00547 /*Compute gradient field statistics */ 00548 N_calc_gradient_field_3d_stats(field); 00549 00550 return field; 00551 } 00552 00595 void 00596 N_compute_gradient_field_components_3d(N_gradient_field_3d * field, 00597 N_array_3d * x_comp, 00598 N_array_3d * y_comp, 00599 N_array_3d * z_comp) 00600 { 00601 int i, j, k; 00602 00603 int rows, cols, depths; 00604 00605 double vx, vy, vz; 00606 00607 N_array_3d *x = x_comp; 00608 00609 N_array_3d *y = y_comp; 00610 00611 N_array_3d *z = z_comp; 00612 00613 N_gradient_3d grad; 00614 00615 00616 if (!x) 00617 G_fatal_error("N_compute_gradient_components_3d: x array is empty"); 00618 if (!y) 00619 G_fatal_error("N_compute_gradient_components_3d: y array is empty"); 00620 if (!z) 00621 G_fatal_error("N_compute_gradient_components_3d: z array is empty"); 00622 00623 cols = field->x_array->cols; 00624 rows = field->x_array->rows; 00625 depths = field->x_array->depths; 00626 00627 /*Check the array sizes */ 00628 if (x->cols != cols || x->rows != rows || x->depths != depths) 00629 G_fatal_error 00630 ("N_compute_gradient_components_3d: the size of the x array doesn't fit the gradient field size"); 00631 if (y->cols != cols || y->rows != rows || y->depths != depths) 00632 G_fatal_error 00633 ("N_compute_gradient_components_3d: the size of the y array doesn't fit the gradient field size"); 00634 if (z->cols != cols || z->rows != rows || z->depths != depths) 00635 G_fatal_error 00636 ("N_compute_gradient_components_3d: the size of the z array doesn't fit the gradient field size"); 00637 00638 for (k = 0; k < depths; k++) 00639 for (j = 0; j < rows; j++) 00640 for (i = 0; i < cols; i++) { 00641 N_get_gradient_3d(field, &grad, i, j, k); 00642 /* in case a gradient is zero, we expect a no flow boundary */ 00643 if (grad.WC == 0.0 || grad.EC == 0.0) 00644 vx = (grad.WC + grad.EC); 00645 else 00646 vx = (grad.WC + grad.EC) / 2; 00647 if (grad.NC == 0.0 || grad.SC == 0.0) 00648 vy = (grad.NC + grad.SC); 00649 else 00650 vy = (grad.NC + grad.SC) / 2; 00651 if (grad.TC == 0.0 || grad.BC == 0.0) 00652 vz = (grad.TC + grad.BC); 00653 else 00654 vz = (grad.TC + grad.BC) / 2; 00655 00656 N_put_array_3d_d_value(x, i, j, k, vx); 00657 N_put_array_3d_d_value(y, i, j, k, vy); 00658 N_put_array_3d_d_value(z, i, j, k, vz); 00659 } 00660 00661 00662 return; 00663 }