GRASS 8 Programmer's Manual 8.6.0dev(2026)-0f6a7341fc
Loading...
Searching...
No Matches
n_gwflow.c
Go to the documentation of this file.
1/*****************************************************************************
2 *
3 * MODULE: Grass PDE Numerical Library
4 * AUTHOR(S): Soeren Gebbert, Berlin (GER) Dec 2006
5 * soerengebbert <at> gmx <dot> de
6 *
7 * PURPOSE: groundwater flow in porous media
8 * part of the gpde library
9 *
10 * SPDX-FileCopyrightText: 2000 GRASS Development Team
11 * SPDX-License-Identifier: GPL-2.0-or-later
12 *
13 *****************************************************************************/
14
15#include <grass/N_gwflow.h>
16
17/* *************************************************************** */
18/* ***************** N_gwflow_data3d ***************************** */
19/* *************************************************************** */
20/*!
21 * \brief Allocate memory for the groundwater calculation data structure in 3
22 * dimensions
23 *
24 * The groundwater calculation data structure will be allocated including
25 * all appendant 3d and 2d arrays. The offset for the 3d arrays is one
26 * to establish homogeneous Neumann boundary conditions at the calculation area
27 * border. This data structure is used to create a linear equation system based
28 * on the computation of groundwater flow in porous media with the finite volume
29 * method.
30 *
31 * \param cols int
32 * \param rows int
33 * \param depths int
34 * \return N_gwflow_data3d *
35 * */
36N_gwflow_data3d *N_alloc_gwflow_data3d(int cols, int rows, int depths,
37 int river, int drain)
38{
39 N_gwflow_data3d *data;
40
41 data = (N_gwflow_data3d *)G_calloc(1, sizeof(N_gwflow_data3d));
42
43 data->phead = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
44 data->phead_start = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
45 data->status = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
46 data->hc_x = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
47 data->hc_y = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
48 data->hc_z = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
49 data->q = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
50 data->s = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
51 data->nf = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
52 data->r = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
53
54 if (river) {
55 data->river_head = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
56 data->river_leak = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
57 data->river_bed = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
58 }
59 else {
60 data->river_head = NULL;
61 data->river_leak = NULL;
62 data->river_bed = NULL;
63 }
64
65 if (drain) {
66 data->drain_leak = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
67 data->drain_bed = N_alloc_array_3d(cols, rows, depths, 1, DCELL_TYPE);
68 }
69 else {
70 data->drain_leak = NULL;
71 data->drain_bed = NULL;
72 }
73
74 return data;
75}
76
77/* *************************************************************** */
78/* ********************* N_free_gwflow_data3d ******************** */
79/* *************************************************************** */
80/*!
81 * \brief Release the memory of the groundwater flow data structure in three
82 * dimensions
83 *
84 * \param data N_gwflow_data3d *
85 * \return void *
86 * */
87
89{
90 if (data->phead)
92 if (data->phead_start)
94 if (data->status)
96 if (data->hc_x)
97 N_free_array_3d(data->hc_x);
98 if (data->hc_y)
99 N_free_array_3d(data->hc_y);
100 if (data->hc_z)
101 N_free_array_3d(data->hc_z);
102 if (data->q)
103 N_free_array_3d(data->q);
104 if (data->s)
105 N_free_array_3d(data->s);
106 if (data->nf)
107 N_free_array_3d(data->nf);
108 if (data->r)
109 N_free_array_2d(data->r);
110 if (data->river_head)
112 if (data->river_leak)
114 if (data->river_bed)
116 if (data->drain_leak)
118 if (data->drain_bed)
120
121 G_free(data);
122
123 data = NULL;
124
125 return;
126}
127
128/* *************************************************************** */
129/* ******************** N_alloc_gwflow_data2d ******************** */
130/* *************************************************************** */
131/*!
132 * \brief Allocate memory for the groundwater calculation data structure in 2
133 * dimensions
134 *
135 * The groundwater calculation data structure will be allocated including
136 * all appendant 2d arrays. The offset for the 3d arrays is one
137 * to establish homogeneous Neumann boundary conditions at the calculation area
138 * border. This data structure is used to create a linear equation system based
139 * on the computation of groundwater flow in porous media with the finite volume
140 * method.
141 *
142 * \param cols int
143 * \param rows int
144 * \param river
145 * \param drain
146 * \return N_gwflow_data2d *
147 * */
148N_gwflow_data2d *N_alloc_gwflow_data2d(int cols, int rows, int river, int drain)
149{
150 N_gwflow_data2d *data;
151
152 data = (N_gwflow_data2d *)G_calloc(1, sizeof(N_gwflow_data2d));
153
154 data->phead = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
155 data->phead_start = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
156 data->status = N_alloc_array_2d(cols, rows, 1, CELL_TYPE);
157 data->hc_x = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
158 data->hc_y = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
159 data->q = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
160 data->s = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
161 data->nf = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
162 data->r = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
163 data->top = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
164 data->bottom = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
165
166 if (river) {
167 data->river_head = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
168 data->river_leak = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
169 data->river_bed = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
170 }
171 else {
172 data->river_head = NULL;
173 data->river_leak = NULL;
174 data->river_bed = NULL;
175 }
176
177 if (drain) {
178 data->drain_leak = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
179 data->drain_bed = N_alloc_array_2d(cols, rows, 1, DCELL_TYPE);
180 }
181 else {
182 data->drain_leak = NULL;
183 data->drain_bed = NULL;
184 }
185
186 return data;
187}
188
189/* *************************************************************** */
190/* ****************** N_free_gwflow_data2d *********************** */
191/* *************************************************************** */
192/*!
193 * \brief Release the memory of the groundwater flow data structure in two
194 * dimensions
195 *
196 * \param data N_gwflow_data2d *
197 * \return void
198 * */
200{
201 if (data->phead)
202 N_free_array_2d(data->phead);
203 if (data->phead_start)
205 if (data->status)
206 N_free_array_2d(data->status);
207 if (data->hc_x)
208 N_free_array_2d(data->hc_x);
209 if (data->hc_y)
210 N_free_array_2d(data->hc_y);
211 if (data->q)
212 N_free_array_2d(data->q);
213 if (data->s)
214 N_free_array_2d(data->s);
215 if (data->nf)
216 N_free_array_2d(data->nf);
217 if (data->r)
218 N_free_array_2d(data->r);
219 if (data->top)
220 N_free_array_2d(data->top);
221 if (data->bottom)
222 N_free_array_2d(data->bottom);
223 if (data->river_head)
225 if (data->river_leak)
227 if (data->river_bed)
229 if (data->drain_leak)
231 if (data->drain_bed)
233
234 G_free(data);
235
236 data = NULL;
237 ;
238
239 return;
240}
241
242/* *************************************************************** */
243/* ***************** N_callback_gwflow_3d ************************ */
244/* *************************************************************** */
245/*!
246 * \brief This callback function creates the mass balance of a 7 point star
247 *
248 * The mass balance is based on the common groundwater flow equation:
249 *
250 * \f[Ss \frac{\partial h}{\partial t} = \nabla {\bf K} \nabla h + q \f]
251 *
252 * This equation is discretizised with the finite volume method in three
253 * dimensions.
254 *
255 *
256 * \param gwdata N_gwflow_data3d *
257 * \param geom N_geom_data *
258 * \param col int
259 * \param row int
260 * \param depth int
261 * \return N_data_star *
262 *
263 * */
265 int row, int depth)
266{
267 double hc_e = 0, hc_w = 0, hc_n = 0, hc_s = 0, hc_t = 0, hc_b = 0;
268 double dx, dy, dz, Ax, Ay, Az;
269 double hc_x, hc_y, hc_z;
270 double hc_xw, hc_yn, hc_zt;
271 double hc_xe, hc_ys, hc_zb;
272 double hc_start;
273 double Ss, r, /* nf, */ q;
274 double C, W, E, N, S, T, B, V;
276 N_gwflow_data3d *data;
277
278 /*cast the void pointer to the right data structure */
279 data = (N_gwflow_data3d *)gwdata;
280
281 dx = geom->dx;
282 dy = geom->dy;
283 dz = geom->dz;
285 Ay = geom->dx * geom->dz;
286 Ax = geom->dz * geom->dy;
287
288 /*read the data from the arrays */
289 hc_start = N_get_array_3d_d_value(data->phead_start, col, row, depth);
290
291 hc_x = N_get_array_3d_d_value(data->hc_x, col, row, depth);
292 hc_y = N_get_array_3d_d_value(data->hc_y, col, row, depth);
293 hc_z = N_get_array_3d_d_value(data->hc_z, col, row, depth);
294
295 hc_xw = N_get_array_3d_d_value(data->hc_x, col - 1, row, depth);
296 hc_xe = N_get_array_3d_d_value(data->hc_x, col + 1, row, depth);
297 hc_yn = N_get_array_3d_d_value(data->hc_y, col, row - 1, depth);
298 hc_ys = N_get_array_3d_d_value(data->hc_y, col, row + 1, depth);
299 hc_zt = N_get_array_3d_d_value(data->hc_z, col, row, depth + 1);
300 hc_zb = N_get_array_3d_d_value(data->hc_z, col, row, depth - 1);
301
308
309 /*inner sources */
310 q = N_get_array_3d_d_value(data->q, col, row, depth);
311 /*storativity */
312 Ss = N_get_array_3d_d_value(data->s, col, row, depth);
313 /*porosity */
314 /* nf = N_get_array_3d_d_value(data->nf, col, row, depth); */
315
316 /*mass balance center cell to western cell */
317 W = -1 * Ax * hc_w / dx;
318 /*mass balance center cell to eastern cell */
319 E = -1 * Ax * hc_e / dx;
320 /*mass balance center cell to northern cell */
321 N = -1 * Ay * hc_n / dy;
322 /*mass balance center cell to southern cell */
323 S = -1 * Ay * hc_s / dy;
324 /*mass balance center cell to top cell */
325 T = -1 * Az * hc_t / dz;
326 /*mass balance center cell to bottom cell */
327 B = -1 * Az * hc_b / dz;
328
329 /*storativity */
330 Ss = Az * dz * Ss;
331
332 /*the diagonal entry of the matrix */
333 C = -1 * (W + E + N + S + T + B - Ss / data->dt * Az);
334
335 /*the entry in the right side b of Ax = b */
336 V = (q + hc_start * Ss / data->dt * Az);
337
338 /*only the top cells will have recharge */
339 if (depth == geom->depths - 2) {
340 r = N_get_array_2d_d_value(data->r, col, row);
341 V += r * Az;
342 }
343
344 G_debug(5, "N_callback_gwflow_3d: called [%i][%i][%i]", depth, col, row);
345
346 /*create the 7 point star entries */
347 mat_pos = N_create_7star(C, W, E, N, S, T, B, V);
348
349 return mat_pos;
350}
351
352/* *************************************************************** */
353/* ****************** N_gwflow_3d_calc_water_budget ************** */
354/* *************************************************************** */
355/*!
356 * \brief This function computes the water budget of the entire groundwater
357 *
358 * The water budget is calculated for each active and dirichlet cell from
359 * its surrounding neighbours. This is based on the 7 star mass balance
360 * computation of N_callback_gwflow_3d and the gradient of the water heights in
361 * the cells. The sum of the water budget of each active/dirichlet cell must be
362 * near zero due the effect of numerical inaccuracy of cpu's.
363 *
364 * \param gwdata N_gwflow_data3d *
365 * \param geom N_geom_data *
366 * \param budget N_array_3d
367 * \return void
368 *
369 * */
372{
373 int z, y, x, stat;
374 double h, hc;
375 double val;
376 double sum;
378
379 int rows = data->status->rows;
380 int cols = data->status->cols;
381 int depths = data->status->depths;
382
383 sum = 0;
384
385 for (z = 0; z < depths; z++) {
386 for (y = 0; y < rows; y++) {
387 G_percent(y, rows - 1, 10);
388 for (x = 0; x < cols; x++) {
389 stat = (int)N_get_array_3d_d_value(data->status, x, y, z);
390
391 val = 0.0;
392
393 if (stat != N_CELL_INACTIVE) { /*all active/dirichlet cells */
394
395 /* Compute the flow parameter */
396 dstar = N_callback_gwflow_3d(data, geom, x, y, z);
397 /* Compute the gradient in each direction pointing from the
398 * center */
399 hc = N_get_array_3d_d_value(data->phead, x, y, z);
400
401 if ((int)N_get_array_3d_d_value(data->status, x + 1, y,
402 z) != N_CELL_INACTIVE) {
403 h = N_get_array_3d_d_value(data->phead, x + 1, y, z);
404 val += dstar->E * (hc - h);
405 }
406 if ((int)N_get_array_3d_d_value(data->status, x - 1, y,
407 z) != N_CELL_INACTIVE) {
408 h = N_get_array_3d_d_value(data->phead, x - 1, y, z);
409 val += dstar->W * (hc - h);
410 }
411 if ((int)N_get_array_3d_d_value(data->status, x, y + 1,
412 z) != N_CELL_INACTIVE) {
413 h = N_get_array_3d_d_value(data->phead, x, y + 1, z);
414 val += dstar->S * (hc - h);
415 }
416 if ((int)N_get_array_3d_d_value(data->status, x, y - 1,
417 z) != N_CELL_INACTIVE) {
418 h = N_get_array_3d_d_value(data->phead, x, y - 1, z);
419 val += dstar->N * (hc - h);
420 }
421 if ((int)N_get_array_3d_d_value(data->status, x, y,
422 z + 1) != N_CELL_INACTIVE) {
423 h = N_get_array_3d_d_value(data->phead, x, y, z + 1);
424 val += dstar->T * (hc - h);
425 }
426 if ((int)N_get_array_3d_d_value(data->status, x, y,
427 z - 1) != N_CELL_INACTIVE) {
428 h = N_get_array_3d_d_value(data->phead, x, y, z - 1);
429 val += dstar->B * (hc - h);
430 }
431 sum += val;
432
433 G_free(dstar);
434 }
435 else {
437 }
438 N_put_array_3d_d_value(budget, x, y, z, val);
439 }
440 }
441 }
442
443 if (fabs(sum) < 0.0000000001)
444 G_message(_("The total sum of the water budget: %g\n"), sum);
445 else
446 G_warning(_("The total sum of the water budget is significantly larger "
447 "then 0: %g\n"),
448 sum);
449
450 return;
451}
452
453/* *************************************************************** */
454/* ****************** N_callback_gwflow_2d *********************** */
455/* *************************************************************** */
456/*!
457 * \brief This callback function creates the mass balance of a 5 point star
458 *
459 * The mass balance is based on the common groundwater flow equation:
460 *
461 * \f[Ss \frac{\partial h}{\partial t} = \nabla {\bf K} \nabla h + q \f]
462 *
463 * This equation is discretizised with the finite volume method in two
464 * dimensions.
465 *
466 * \param gwdata N_gwflow_data2d *
467 * \param geom N_geom_data *
468 * \param col int
469 * \param row int
470 * \return N_data_star *
471 *
472 * */
474 int row)
475{
476 double T_e = 0, T_w = 0, T_n = 0, T_s = 0;
477 double z_e = 0, z_w = 0, z_n = 0, z_s = 0;
478 double dx, dy, Az;
479 double hc_x, hc_y;
480 double z, top;
481 double hc_xw, hc_yn;
482 double z_xw, z_yn;
483 double hc_xe, hc_ys;
484 double z_xe, z_ys;
485 double hc, hc_start;
486 double Ss, r, q;
487 double C, W, E, N, S, V;
488 N_gwflow_data2d *data;
490 double river_vect = 0; /*entry in vector */
491 double river_mat = 0; /*entry in matrix */
492 double drain_vect = 0; /*entry in vector */
493 double drain_mat = 0; /*entry in matrix */
494
495 /*cast the void pointer to the right data structure */
496 data = (N_gwflow_data2d *)gwdata;
497
498 dx = geom->dx;
499 dy = geom->dy;
501
502 /*read the data from the arrays */
504 hc = N_get_array_2d_d_value(data->phead, col, row);
505 top = N_get_array_2d_d_value(data->top, col, row);
506
507 /* Inner sources */
508 q = N_get_array_2d_d_value(data->q, col, row);
509
510 /* storativity or porosity of current cell face [-] */
511 Ss = N_get_array_2d_d_value(data->s, col, row);
512 /* recharge */
513 r = N_get_array_2d_d_value(data->r, col, row) * Az;
514
515 if (hc > top) { /*If the aquifer is confined */
516 z = N_get_array_2d_d_value(data->top, col, row) -
517 N_get_array_2d_d_value(data->bottom, col, row);
518 z_xw = N_get_array_2d_d_value(data->top, col - 1, row) -
519 N_get_array_2d_d_value(data->bottom, col - 1, row);
520 z_xe = N_get_array_2d_d_value(data->top, col + 1, row) -
521 N_get_array_2d_d_value(data->bottom, col + 1, row);
522 z_yn = N_get_array_2d_d_value(data->top, col, row - 1) -
523 N_get_array_2d_d_value(data->bottom, col, row - 1);
524 z_ys = N_get_array_2d_d_value(data->top, col, row + 1) -
525 N_get_array_2d_d_value(data->bottom, col, row + 1);
526 }
527 else { /* the aquifer is unconfined */
528
529 /* If the aquifer is unconfied use an explicit scheme to solve
530 * the nonlinear equation. We use the phead from the first iteration */
531 z = N_get_array_2d_d_value(data->phead, col, row) -
532 N_get_array_2d_d_value(data->bottom, col, row);
533 z_xw = N_get_array_2d_d_value(data->phead, col - 1, row) -
534 N_get_array_2d_d_value(data->bottom, col - 1, row);
535 z_xe = N_get_array_2d_d_value(data->phead, col + 1, row) -
536 N_get_array_2d_d_value(data->bottom, col + 1, row);
537 z_yn = N_get_array_2d_d_value(data->phead, col, row - 1) -
538 N_get_array_2d_d_value(data->bottom, col, row - 1);
539 z_ys = N_get_array_2d_d_value(data->phead, col, row + 1) -
540 N_get_array_2d_d_value(data->bottom, col, row + 1);
541 }
542
543 /*geometrical mean of cell height */
544 if (z_w > 0 || z_w < 0 || z_w == 0)
546 else
547 z_w = z;
548 if (z_e > 0 || z_e < 0 || z_e == 0)
550 else
551 z_e = z;
552 if (z_n > 0 || z_n < 0 || z_n == 0)
554 else
555 z_n = z;
556 if (z_s > 0 || z_s < 0 || z_s == 0)
558 else
559 z_s = z;
560
561 /*get the surrounding permeabilities */
562 hc_x = N_get_array_2d_d_value(data->hc_x, col, row);
563 hc_y = N_get_array_2d_d_value(data->hc_y, col, row);
564 hc_xw = N_get_array_2d_d_value(data->hc_x, col - 1, row);
565 hc_xe = N_get_array_2d_d_value(data->hc_x, col + 1, row);
566 hc_yn = N_get_array_2d_d_value(data->hc_y, col, row - 1);
567 hc_ys = N_get_array_2d_d_value(data->hc_y, col, row + 1);
568
569 /* calculate the transmissivities */
574
575 /* Compute the river leakage, this is an explicit method
576 * Influent and effluent flow is computed.
577 */
578 if (data->river_leak &&
579 (N_get_array_2d_d_value(data->river_leak, col, row) != 0) &&
580 N_get_array_2d_d_value(data->river_bed, col, row) <= top) {
581 /* Groundwater surface is above the river bed */
582 if (hc > N_get_array_2d_d_value(data->river_bed, col, row)) {
586 } /* Groundwater surface is below the river bed */
587 else if (hc < N_get_array_2d_d_value(data->river_bed, col, row)) {
589 N_get_array_2d_d_value(data->river_bed, col, row)) *
591 river_mat = 0;
592 }
593 }
594
595 /* compute the drainage, this is an explicit method
596 * Drainage is only enabled, if the drain bed is lower the groundwater
597 * surface
598 */
599 if (data->drain_leak &&
600 (N_get_array_2d_d_value(data->drain_leak, col, row) != 0) &&
601 N_get_array_2d_d_value(data->drain_bed, col, row) <= top) {
602 if (hc > N_get_array_2d_d_value(data->drain_bed, col, row)) {
606 }
607 else if (hc <= N_get_array_2d_d_value(data->drain_bed, col, row)) {
608 drain_vect = 0;
609 drain_mat = 0;
610 }
611 }
612
613 /*mass balance center cell to western cell */
614 W = -1 * T_w * dy / dx;
615 /*mass balance center cell to eastern cell */
616 E = -1 * T_e * dy / dx;
617 /*mass balance center cell to northern cell */
618 N = -1 * T_n * dx / dy;
619 /*mass balance center cell to southern cell */
620 S = -1 * T_s * dx / dy;
621
622 /*the diagonal entry of the matrix */
623 C = -1 *
624 (W + E + N + S - Az * Ss / data->dt - river_mat * Az - drain_mat * Az);
625
626 /*the entry in the right side b of Ax = b */
627 V = (q + hc_start * Az * Ss / data->dt) + r + river_vect * Az +
628 drain_vect * Az;
629
630 G_debug(5, "N_callback_gwflow_2d: called [%i][%i]", row, col);
631
632 /*create the 5 point star entries */
633 mat_pos = N_create_5star(C, W, E, N, S, V);
634
635 return mat_pos;
636}
637
638/* *************************************************************** */
639/* ****************** N_gwflow_2d_calc_water_budget ************** */
640/* *************************************************************** */
641/*!
642 * \brief This function computes the water budget of the entire groundwater
643 *
644 * The water budget is calculated for each active and dirichlet cell from
645 * its surrounding neighbours. This is based on the 5 star mass balance
646 * computation of N_callback_gwflow_2d and the gradient of the water heights in
647 * the cells. The sum of the water budget of each active/dirichlet cell must be
648 * near zero due the effect of numerical inaccuracy of cpu's.
649 *
650 * \param data N_gwflow_data2d *
651 * \param geom N_geom_data *
652 * \param budget N_array_2d
653 * \return void
654 *
655 * */
658{
659 int y, x, stat;
660 double h, hc;
661 double val;
662 double sum;
664
665 int rows = data->status->rows;
666 int cols = data->status->cols;
667
668 sum = 0;
669
670 for (y = 0; y < rows; y++) {
671 G_percent(y, rows - 1, 10);
672 for (x = 0; x < cols; x++) {
673 stat = N_get_array_2d_c_value(data->status, x, y);
674
675 val = 0.0;
676
677 if (stat != N_CELL_INACTIVE) { /*all active/dirichlet cells */
678
679 /* Compute the flow parameter */
680 dstar = N_callback_gwflow_2d(data, geom, x, y);
681 /* Compute the gradient in each direction pointing from the
682 * center */
683 hc = N_get_array_2d_d_value(data->phead, x, y);
684
685 if ((int)N_get_array_2d_d_value(data->status, x + 1, y) !=
687 h = N_get_array_2d_d_value(data->phead, x + 1, y);
688 val += dstar->E * (hc - h);
689 }
690 if ((int)N_get_array_2d_d_value(data->status, x - 1, y) !=
692 h = N_get_array_2d_d_value(data->phead, x - 1, y);
693 val += dstar->W * (hc - h);
694 }
695 if ((int)N_get_array_2d_d_value(data->status, x, y + 1) !=
697 h = N_get_array_2d_d_value(data->phead, x, y + 1);
698 val += dstar->S * (hc - h);
699 }
700 if ((int)N_get_array_2d_d_value(data->status, x, y - 1) !=
702 h = N_get_array_2d_d_value(data->phead, x, y - 1);
703 val += dstar->N * (hc - h);
704 }
705
706 sum += val;
707
708 G_free(dstar);
709 }
710 else {
712 }
714 }
715 }
716
717 if (fabs(sum) < 0.0000000001)
718 G_message(_("The total sum of the water budget: %g\n"), sum);
719 else
720 G_warning(_("The total sum of the water budget is significantly larger "
721 "then 0: %g\n"),
722 sum);
723
724 return;
725}
#define N_CELL_INACTIVE
Definition N_pde.h:27
double N_calc_arith_mean(double a, double b)
Calculate the arithmetic mean of values a and b.
Definition n_tools.c:28
double N_calc_harmonic_mean(double a, double b)
Calculate the harmonical mean of values a and b.
Definition n_tools.c:112
#define NULL
Definition ccmath.h:32
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
#define G_calloc(m, n)
Definition defs/gis.h:137
void G_warning(const char *,...) __attribute__((format(printf
void G_message(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
void Rast_set_null_value(void *, int, RASTER_MAP_TYPE)
To set one or more raster values to null.
Definition null_val.c:96
#define N
#define _(str)
Definition glocale.h:10
N_array_3d * N_alloc_array_3d(int cols, int rows, int depths, int offset, int type)
Allocate memory for a N_array_3d data structure.
Definition n_arrays.c:716
CELL N_get_array_2d_c_value(N_array_2d *data, int col, int row)
Returns the value of type CELL at position col, row.
Definition n_arrays.c:311
void N_free_array_3d(N_array_3d *data)
Release the memory of a N_array_3d.
Definition n_arrays.c:771
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:377
void N_free_array_2d(N_array_2d *data)
Release the memory of a N_array_2d structure.
Definition n_arrays.c:129
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:1145
N_array_2d * N_alloc_array_2d(int cols, int rows, int offset, int type)
Allocate memory for a N_array_2d data structure.
Definition n_arrays.c:72
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:976
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:573
double N_get_geom_data_area_of_cell(N_geom_data *geom, int row)
Get the areay size in square meter of one cell (x*y) at row.
Definition n_geom.c:193
N_data_star * N_callback_gwflow_2d(void *gwdata, N_geom_data *geom, int col, int row)
This callback function creates the mass balance of a 5 point star.
Definition n_gwflow.c:473
void N_gwflow_3d_calc_water_budget(N_gwflow_data3d *data, N_geom_data *geom, N_array_3d *budget)
This function computes the water budget of the entire groundwater.
Definition n_gwflow.c:370
N_gwflow_data2d * N_alloc_gwflow_data2d(int cols, int rows, int river, int drain)
Allocate memory for the groundwater calculation data structure in 2 dimensions.
Definition n_gwflow.c:148
void N_gwflow_2d_calc_water_budget(N_gwflow_data2d *data, N_geom_data *geom, N_array_2d *budget)
This function computes the water budget of the entire groundwater.
Definition n_gwflow.c:656
void N_free_gwflow_data3d(N_gwflow_data3d *data)
Release the memory of the groundwater flow data structure in three dimensions.
Definition n_gwflow.c:88
N_gwflow_data3d * N_alloc_gwflow_data3d(int cols, int rows, int depths, int river, int drain)
Allocate memory for the groundwater calculation data structure in 3 dimensions.
Definition n_gwflow.c:36
void N_free_gwflow_data2d(N_gwflow_data2d *data)
Release the memory of the groundwater flow data structure in two dimensions.
Definition n_gwflow.c:199
N_data_star * N_callback_gwflow_3d(void *gwdata, N_geom_data *geom, int col, int row, int depth)
This callback function creates the mass balance of a 7 point star.
Definition n_gwflow.c:264
N_data_star * N_create_5star(double C, double W, double E, double N, double S, double V)
allocate and initialize a 5 point star data structure
N_data_star * N_create_7star(double C, double W, double E, double N, double S, double T, double B, double V)
allocate and initialize a 7 point star data structure
#define W
Definition ogsf.h:144
double r
Definition r_raster.c:37
#define DCELL_TYPE
Definition raster.h:13
#define CELL_TYPE
Definition raster.h:11
int cols
Definition N_pde.h:131
int rows
Definition N_pde.h:131
int rows
Definition N_pde.h:174
int depths
Definition N_pde.h:174
int cols
Definition N_pde.h:174
Matrix entries for a mass balance 5/7/9 star system.
Definition N_pde.h:292
Geometric information about the structured grid.
Definition N_pde.h:98
This data structure contains all data needed to compute the groundwater mass balance in two dimension...
Definition N_gwflow.h:62
N_array_2d * hc_y
Definition N_gwflow.h:66
N_array_2d * nf
Definition N_gwflow.h:70
N_array_2d * top
Definition N_gwflow.h:81
N_array_2d * drain_leak
Definition N_gwflow.h:78
N_array_2d * bottom
Definition N_gwflow.h:82
N_array_2d * phead_start
Definition N_gwflow.h:64
N_array_2d * river_leak
Definition N_gwflow.h:73
N_array_2d * s
Definition N_gwflow.h:69
N_array_2d * hc_x
Definition N_gwflow.h:65
N_array_2d * r
Definition N_gwflow.h:68
N_array_2d * drain_bed
Definition N_gwflow.h:79
N_array_2d * q
Definition N_gwflow.h:67
N_array_2d * river_bed
Definition N_gwflow.h:75
N_array_2d * river_head
Definition N_gwflow.h:74
N_array_2d * phead
Definition N_gwflow.h:63
N_array_2d * status
Definition N_gwflow.h:84
This data structure contains all data needed to compute the groundwater mass balance in three dimensi...
Definition N_gwflow.h:31
N_array_3d * phead
Definition N_gwflow.h:32
N_array_3d * hc_z
Definition N_gwflow.h:36
N_array_3d * phead_start
Definition N_gwflow.h:33
N_array_3d * hc_x
Definition N_gwflow.h:34
N_array_3d * drain_leak
Definition N_gwflow.h:48
N_array_3d * status
Definition N_gwflow.h:51
N_array_3d * drain_bed
Definition N_gwflow.h:49
N_array_3d * river_bed
Definition N_gwflow.h:45
N_array_3d * river_head
Definition N_gwflow.h:44
N_array_3d * s
Definition N_gwflow.h:39
N_array_2d * r
Definition N_gwflow.h:38
N_array_3d * q
Definition N_gwflow.h:37
N_array_3d * hc_y
Definition N_gwflow.h:35
N_array_3d * nf
Definition N_gwflow.h:40
N_array_3d * river_leak
Definition N_gwflow.h:43
#define x