21 #include "grass/N_pde.h"
24 static int make_les_entry_2d(
int i,
int j,
int offset_i,
int offset_j,
26 G_math_spvector * spvect,
31 static int make_les_entry_3d(
int i,
int j,
int k,
int offset_i,
int offset_j,
33 G_math_spvector * spvect,
139 G_debug(5,
"N_create_5star: w %g e %g n %g s %g c %g v %g\n", star->
W,
140 star->
E, star->
N, star->
S, star->
C, star->
V);
162 double S,
double T,
double B,
double V)
177 G_debug(5,
"N_create_7star: w %g e %g n %g s %g t %g b %g c %g v %g\n",
178 star->
W, star->
E, star->
N, star->
S, star->
T, star->
B, star->
C,
203 double S,
double NW,
double SW,
double NE,
222 "N_create_9star: w %g e %g n %g s %g nw %g sw %g ne %g se %g c %g v %g\n",
223 star->
W, star->
E, star->
N, star->
S, star->
NW, star->
SW, star->
NE,
224 star->
SE, star->
C, star->
V);
266 double NW,
double SW,
double NE,
double SE,
267 double T,
double W_T,
double E_T,
double N_T,
268 double S_T,
double NW_T,
double SW_T,
269 double NE_T,
double SE_T,
double B,
double W_B,
270 double E_B,
double N_B,
double S_B,
double NW_B,
271 double SW_B,
double NE_B,
double SE_B,
double V)
311 "N_create_27star: w %g e %g n %g s %g nw %g sw %g ne %g se %g c %g v %g\n",
312 star->
W, star->
E, star->
N, star->
S, star->
NW, star->
SW, star->
NE,
313 star->
SE, star->
C, star->
V);
316 "N_create_27star: w_t %g e_t %g n_t %g s_t %g nw_t %g sw_t %g ne_t %g se_t %g t %g \n",
321 "N_create_27star: w_b %g e_b %g n_b %g s_b %g nw_b %g sw_b %g ne_b %g se_B %g b %g\n",
429 star->
E = 1 / geom->
dx;
430 star->
W = 1 / geom->
dx;
431 star->
N = 1 / geom->
dy;
432 star->
S = 1 / geom->
dy;
433 star->
T = 1 / geom->
dz;
434 star->
B = 1 / geom->
dz;
435 star->
C = -1 * (2 / geom->
dx + 2 / geom->
dy + 2 / geom->
dz);
439 "N_callback_template_3d: w %g e %g n %g s %g t %g b %g c %g v %g\n",
440 star->
W, star->
E, star->
N, star->
S, star->
T, star->
B, star->
C,
468 star->
E = 1 / geom->
dx;
469 star->
NE = 1 / sqrt(geom->
dx * geom->
dx + geom->
dy * geom->
dy);
470 star->
SE = 1 / sqrt(geom->
dx * geom->
dx + geom->
dy * geom->
dy);
471 star->
W = 1 / geom->
dx;
472 star->
NW = 1 / sqrt(geom->
dx * geom->
dx + geom->
dy * geom->
dy);
473 star->
SW = 1 / sqrt(geom->
dx * geom->
dx + geom->
dy * geom->
dy);
474 star->
N = 1 / geom->
dy;
475 star->
S = 1 / geom->
dy;
477 -1 * (star->
E + star->
NE + star->
SE + star->
W + star->
NW + star->
SW +
567 int cell_type_count = 0;
576 "N_assemble_les_2d: starting to assemble the linear equation system");
587 for (j = 0; j < geom->
rows; j++) {
588 for (i = 0; i < geom->
cols; i++) {
598 for (j = 0; j < geom->
rows; j++) {
599 for (i = 0; i < geom->
cols; i++) {
607 G_debug(2,
"N_assemble_les_2d: number of used cells %i\n",
610 if (cell_type_count == 0)
612 (
"Not enough cells [%i] to create the linear equation system. Check the cell status. Only active cells (value = 1) are used to create the equation system.",
617 index_ij = (
int **)G_calloc(cell_type_count,
sizeof(
int *));
618 for (i = 0; i < cell_type_count; i++)
619 index_ij[i] = (
int *)G_calloc(2,
sizeof(
int));
627 for (j = 0; j < geom->
rows; j++) {
628 for (i = 0; i < geom->
cols; i++) {
634 index_ij[
count][0] = i;
635 index_ij[
count][1] = j;
638 "N_assemble_les_2d: non-inactive cells count %i at pos x[%i] y[%i]\n",
645 index_ij[
count][0] = i;
646 index_ij[
count][1] = j;
649 "N_assemble_les_2d: active cells count %i at pos x[%i] y[%i]\n",
655 G_debug(2,
"N_assemble_les_2d: starting the parallel assemble loop");
658 #pragma omp parallel for private(i, j, pos, count) schedule(static)
659 for (count = 0; count < cell_type_count; count++) {
660 i = index_ij[
count][0];
661 j = index_ij[
count][1];
667 G_math_spvector *spvect =
NULL;
685 spvect->values[
pos] = items->
C;
692 pos = make_les_entry_2d(i, j, -1, 0, count,
pos, les, spvect,
693 cell_count, status, start_val, items->
W,
697 if (i < geom->
cols - 1) {
698 pos = make_les_entry_2d(i, j, 1, 0, count,
pos, les, spvect,
699 cell_count, status, start_val, items->
E,
705 make_les_entry_2d(i, j, 0, -1, count,
pos, les, spvect,
706 cell_count, status, start_val, items->
N,
710 if (j < geom->rows - 1) {
711 pos = make_les_entry_2d(i, j, 0, 1, count,
pos, les, spvect,
712 cell_count, status, start_val, items->
S,
718 if (i > 0 && j > 0) {
719 pos = make_les_entry_2d(i, j, -1, -1, count,
pos, les, spvect,
720 cell_count, status, start_val,
721 items->
NW, cell_type);
724 if (i < geom->
cols - 1 && j > 0) {
725 pos = make_les_entry_2d(i, j, 1, -1, count,
pos, les, spvect,
726 cell_count, status, start_val,
727 items->
NE, cell_type);
730 if (i > 0 && j < geom->rows - 1) {
731 pos = make_les_entry_2d(i, j, -1, 1, count,
pos, les, spvect,
732 cell_count, status, start_val,
733 items->
SW, cell_type);
736 if (i < geom->
cols - 1 && j < geom->rows - 1) {
737 pos = make_les_entry_2d(i, j, 1, 1, count,
pos, les, spvect,
738 cell_count, status, start_val,
739 items->
SE, cell_type);
745 spvect->cols =
pos + 1;
756 for (i = 0; i < cell_type_count; i++)
797 int i, j, x,
y,
stat;
804 "N_les_integrate_dirichlet_2d: integrating the dirichlet boundary condition");
810 dvect1 = (
double *)G_calloc(les->
cols,
sizeof(
double));
811 dvect2 = (
double *)G_calloc(les->
cols,
sizeof(
double));
815 for (y = 0; y < rows; y++) {
816 for (x = 0; x <
cols; x++) {
829 #pragma omp parallel default(shared)
836 #pragma omp for schedule (static) private(i)
837 for (i = 0; i < les->
cols; i++)
838 les->
b[i] = les->
b[i] - dvect2[i];
844 for (y = 0; y < rows; y++) {
845 for (x = 0; x <
cols; x++) {
850 for (i = 0; i < les->
Asp[
count]->cols; i++)
851 les->
Asp[count]->values[i] = 0.0;
853 for (i = 0; i < les->
rows; i++) {
854 for (j = 0; j < les->
Asp[i]->cols; j++) {
855 if (les->
Asp[i]->index[j] == count)
856 les->
Asp[i]->values[j] = 0.0;
866 for (i = 0; i < les->
cols; i++)
867 les->
A[count][i] = 0.0;
869 for (i = 0; i < les->
rows; i++)
870 les->
A[i][count] = 0.0;
873 les->
A[count][count] = 1.0;
888 int make_les_entry_2d(
int i,
int j,
int offset_i,
int offset_j,
int count,
889 int pos,
N_les * les, G_math_spvector * spvect,
891 N_array_2d * start_val,
double entry,
int cell_type)
911 if ((count + K) >= 0 && (count + K) < les->
cols) {
913 " make_les_entry_2d: (N_CELL_ACTIVE) create matrix entry at row[%i] col[%i] value %g\n",
914 count, count + K, entry);
917 spvect->index[
pos] = count + K;
918 spvect->values[
pos] = entry;
921 les->
A[
count][count + K] = entry;
931 if ((count + K) >= 0 && (count + K) < les->
cols) {
933 " make_les_entry_2d: (N_CELL_DIRICHLET) create matrix entry at row[%i] col[%i] value %g\n",
934 count, count + K, entry);
937 spvect->index[
pos] = count + K;
938 spvect->values[
pos] = entry;
941 les->
A[
count][count + K] = entry;
1027 int i, j, k, count = 0, pos = 0;
1029 int cell_type_count = 0;
1038 "N_assemble_les_3d: starting to assemble the linear equation system");
1049 for (k = 0; k < geom->
depths; k++) {
1050 for (j = 0; j < geom->
rows; j++) {
1051 for (i = 0; i < geom->
cols; i++) {
1064 for (k = 0; k < geom->
depths; k++) {
1065 for (j = 0; j < geom->
rows; j++) {
1066 for (i = 0; i < geom->
cols; i++) {
1078 "N_assemble_les_3d: number of used cells %i\n", cell_type_count);
1080 if (cell_type_count == 0.0)
1082 (
"Not enough active cells [%i] to create the linear equation system. Check the cell status. Only active cells (value = 1) are used to create the equation system.",
1089 index_ij = (
int **)G_calloc(cell_type_count,
sizeof(
int *));
1090 for (i = 0; i < cell_type_count; i++)
1091 index_ij[i] = (
int *)G_calloc(3,
sizeof(
int));
1096 for (k = 0; k < geom->
depths; k++) {
1097 for (j = 0; j < geom->
rows; j++) {
1098 for (i = 0; i < geom->
cols; i++) {
1105 index_ij[
count][0] = i;
1106 index_ij[
count][1] = j;
1107 index_ij[
count][2] = k;
1110 "N_assemble_les_3d: non-inactive cells count %i at pos x[%i] y[%i] z[%i]\n",
1117 index_ij[
count][0] = i;
1118 index_ij[
count][1] = j;
1119 index_ij[
count][2] = k;
1122 "N_assemble_les_3d: active cells count %i at pos x[%i] y[%i] z[%i]\n",
1129 G_debug(2,
"N_assemble_les_3d: starting the parallel assemble loop");
1131 #pragma omp parallel for private(i, j, k, pos, count) schedule(static)
1132 for (count = 0; count < cell_type_count; count++) {
1133 i = index_ij[
count][0];
1134 j = index_ij[
count][1];
1135 k = index_ij[
count][2];
1140 G_math_spvector *spvect =
NULL;
1158 spvect->values[
pos] = items->
C;
1166 make_les_entry_3d(i, j, k, -1, 0, 0, count, pos, les, spvect,
1167 cell_count, status, start_val, items->
W,
1171 if (i < geom->
cols - 1) {
1172 pos = make_les_entry_3d(i, j, k, 1, 0, 0, count, pos, les, spvect,
1173 cell_count, status, start_val, items->
E,
1179 make_les_entry_3d(i, j, k, 0, -1, 0, count, pos, les, spvect,
1180 cell_count, status, start_val, items->
N,
1184 if (j < geom->rows - 1) {
1185 pos = make_les_entry_3d(i, j, k, 0, 1, 0, count, pos, les, spvect,
1186 cell_count, status, start_val, items->
S,
1192 if (k < geom->depths - 1) {
1194 make_les_entry_3d(i, j, k, 0, 0, 1, count, pos, les,
1195 spvect, cell_count, status, start_val,
1196 items->
T, cell_type);
1201 make_les_entry_3d(i, j, k, 0, 0, -1, count, pos, les,
1202 spvect, cell_count, status, start_val,
1203 items->
B, cell_type);
1209 spvect->cols = pos + 1;
1219 for (i = 0; i < cell_type_count; i++)
1256 int rows,
cols, depths;
1260 int i, j, x,
y, z,
stat;
1267 "N_les_integrate_dirichlet_3d: integrating the dirichlet boundary condition");
1274 dvect1 = (
double *)G_calloc(les->
cols,
sizeof(
double));
1275 dvect2 = (
double *)G_calloc(les->
cols,
sizeof(
double));
1279 for (z = 0; z < depths; z++) {
1280 for (y = 0; y < rows; y++) {
1281 for (x = 0; x <
cols; x++) {
1289 dvect1[
count] = 0.0;
1296 #pragma omp parallel default(shared)
1303 #pragma omp for schedule (static) private(i)
1304 for (i = 0; i < les->
cols; i++)
1305 les->
b[i] = les->
b[i] - dvect2[i];
1311 for (z = 0; z < depths; z++) {
1312 for (y = 0; y < rows; y++) {
1313 for (x = 0; x <
cols; x++) {
1318 for (i = 0; i < les->
Asp[
count]->cols; i++)
1319 les->
Asp[count]->values[i] = 0.0;
1321 for (i = 0; i < les->
rows; i++) {
1322 for (j = 0; j < les->
Asp[i]->cols; j++) {
1323 if (les->
Asp[i]->index[j] == count)
1324 les->
Asp[i]->values[j] = 0.0;
1334 for (i = 0; i < les->
cols; i++)
1335 les->
A[count][i] = 0.0;
1337 for (i = 0; i < les->
rows; i++)
1338 les->
A[i][count] = 0.0;
1341 les->
A[count][count] = 1.0;
1356 int make_les_entry_3d(
int i,
int j,
int k,
int offset_i,
int offset_j,
1357 int offset_k,
int count,
int pos,
N_les * les,
1358 G_math_spvector * spvect,
N_array_3d * cell_count,
1360 double entry,
int cell_type)
1383 if ((count + K) >= 0 && (count + K) < les->
cols) {
1385 " make_les_entry_3d: (N_CELL_ACTIVE) create matrix entry at row[%i] col[%i] value %g\n",
1386 count, count + K, entry);
1389 spvect->index[
pos] = count + K;
1390 spvect->values[
pos] = entry;
1393 les->
A[
count][count + K] = entry;
1401 if ((count + K) >= 0 && (count + K) < les->
cols) {
1403 " make_les_entry_3d: (N_CELL_DIRICHLET) create matrix entry at row[%i] col[%i] value %g\n",
1404 count, count + K, entry);
1407 spvect->index[
pos] = count + K;
1408 spvect->values[
pos] = entry;
1411 les->
A[
count][count + K] = entry;
void N_free_array_2d(N_array_2d *data)
Release the memory of a N_array_2d structure.
void G_free(void *buf)
Free allocated memory.
Matrix entries for a mass balance 5/7/9 star system.
N_data_star * N_alloc_27star(void)
allocate a 27 point star data structure
N_les_callback_3d * N_alloc_les_callback_3d(void)
Allocate the structure holding the callback function.
N_les * N_assemble_les_3d_active(int les_type, N_geom_data *geom, N_array_3d *status, N_array_3d *start_val, void *data, N_les_callback_3d *call)
Assemble a linear equation system (les) based on 3d location data (g3d) active cells.
G_math_spvector * G_math_alloc_spvector(int cols)
Allocate memory for a sparse vector.
N_les * N_alloc_les_Ax_b(int rows, int type)
Allocate memory for a quadratic linear equation system which includes the Matrix A, vector x and vector b.
void N_free_array_3d(N_array_3d *data)
Release the memory of a N_array_3d.
N_les * N_assemble_les_2d(int les_type, N_geom_data *geom, N_array_2d *status, N_array_2d *start_val, void *data, N_les_callback_2d *call)
Assemble a linear equation system (les) based on 2d location data (raster) and active cells...
void G_math_d_Ax(double **A, double *x, double *y, int rows, int cols)
Compute the matrix - vector product of matrix A and vector x.
#define N_MAX_CELL_STATE
the maximum number of available cell states (eg: boundary condition, inactiven active) ...
N_array_2d * N_alloc_array_2d(int cols, int rows, int offset, int type)
Allocate memory for a N_array_2d data structure.
callback structure for 2d matrix assembling
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.
N_data_star * N_alloc_5star(void)
allocate a 5 point star data structure
N_data_star * N_alloc_9star(void)
allocate a 9 point star data structure
Geometric information about the structured grid.
void N_set_les_callback_3d_func(N_les_callback_3d *data, N_data_star *(*callback_func_3d)())
Set the callback function which is called while assembling the les in 3d.
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
N_data_star * N_create_27star(double C, double W, double E, double N, double S, double NW, double SW, double NE, double SE, double T, double W_T, double E_T, double N_T, double S_T, double NW_T, double SW_T, double NE_T, double SE_T, double B, double W_B, double E_B, double N_B, double S_B, double NW_B, double SW_B, double NE_B, double SE_B, double V)
allocate and initialize a 27 point star data structure
N_les * N_assemble_les_2d_param(int les_type, N_geom_data *geom, N_array_2d *status, N_array_2d *start_val, void *data, N_les_callback_2d *call, int cell_type)
Assemble a linear equation system (les) based on 2d location data (raster)
void N_put_array_2d_c_value(N_array_2d *data, int col, int row, CELL value)
Writes a CELL value to the N_array_2d struct at position col, row.
N_data_star * N_create_9star(double C, double W, double E, double N, double S, double NW, double SW, double NE, double SE, double V)
allocate and initialize a 9 point star data structure
N_les * N_assemble_les_2d_dirichlet(int les_type, N_geom_data *geom, N_array_2d *status, N_array_2d *start_val, void *data, N_les_callback_2d *call)
Assemble a linear equation system (les) based on 2d location data (raster) and active and dirichlet c...
int N_les_integrate_dirichlet_3d(N_les *les, N_geom_data *geom, N_array_3d *status, N_array_3d *start_val)
Integrate Dirichlet or Transmission boundary conditions into the les (3d)
N_les * N_assemble_les_3d(int les_type, N_geom_data *geom, N_array_3d *status, N_array_3d *start_val, void *data, N_les_callback_3d *call)
Assemble a linear equation system (les) based on 3d location data (g3d) active cells.
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_callback_template_3d(void *data, N_geom_data *geom, int col, int row, int depth)
A callback template creates a 7 point star structure.
N_data_star *(* callback)()
void N_set_les_callback_2d_func(N_les_callback_2d *data, N_data_star *(*callback_func_2d)())
Set the callback function which is called while assembling the les in 2d.
N_les * N_assemble_les_3d_param(int les_type, N_geom_data *geom, N_array_3d *status, N_array_3d *start_val, void *data, N_les_callback_3d *call, int cell_type)
Assemble a linear equation system (les) based on 3d location data (g3d)
N_data_star * N_alloc_7star(void)
allocate a 7 point star data structure
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.
int G_debug(int level, const char *msg,...)
Print debugging message.
void G_math_Ax_sparse(G_math_spvector **Asp, double *x, double *y, int rows)
Compute the matrix - vector product of sparse matrix **Asp and vector x.
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.
N_data_star * N_callback_template_2d(void *data, N_geom_data *geom, int col, int row)
A callback template creates a 9 point star structure.
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.
N_data_star *(* callback)()
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.
callback structure for 3d matrix assembling
int G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
int N_les_integrate_dirichlet_2d(N_les *les, N_geom_data *geom, N_array_2d *status, N_array_2d *start_val)
Integrate Dirichlet or Transmission boundary conditions into the les (2s)
N_les * N_assemble_les_3d_dirichlet(int les_type, N_geom_data *geom, N_array_3d *status, N_array_3d *start_val, void *data, N_les_callback_3d *call)
Assemble a linear equation system (les) based on 3d location data (g3d) active and dirichlet cells...
int G_math_add_spvector(G_math_spvector **Asp, G_math_spvector *spvector, int row)
Adds a sparse vector to a sparse linear equation system at position row.
N_les * N_assemble_les_2d_active(int les_type, N_geom_data *geom, N_array_2d *status, N_array_2d *start_val, void *data, N_les_callback_2d *call)
Assemble a linear equation system (les) based on 2d location data (raster) and active cells...
The linear equation system (les) structure.
N_les_callback_2d * N_alloc_les_callback_2d(void)
Allocate the structure holding the callback function.