Skip to content

Commit

Permalink
r.flowaccumulation: Support FCELL and DCELL outputs (#1027)
Browse files Browse the repository at this point in the history
* r.flowaccumulation: Support FCELL and DCELL outputs

* Consistent labels for -z and -Z
  • Loading branch information
HuidaeCho committed Feb 18, 2024
1 parent 14ca147 commit 701e8f1
Show file tree
Hide file tree
Showing 29 changed files with 674 additions and 188 deletions.
252 changes: 101 additions & 151 deletions src/raster/r.flowaccumulation/accumulate.c
Original file line number Diff line number Diff line change
@@ -1,164 +1,114 @@
#include <stdlib.h>
#include <grass/raster.h>
#include "global.h"

#define ACCUM(row, col) accum_map->cells[(size_t)(row)*ncols + (col)]
#define FIND_UP(row, col) \
((row > 0 ? (col > 0 && DIR(row - 1, col - 1) == SE ? NW : 0) | \
(DIR(row - 1, col) == S ? N : 0) | \
(col < ncols - 1 && DIR(row - 1, col + 1) == SW ? NE : 0) \
: 0) | \
(col > 0 && DIR(row, col - 1) == E ? W : 0) | \
(col < ncols - 1 && DIR(row, col + 1) == W ? E : 0) | \
(row < nrows - 1 \
? (col > 0 && DIR(row + 1, col - 1) == NE ? SW : 0) | \
(DIR(row + 1, col) == N ? S : 0) | \
(col < ncols - 1 && DIR(row + 1, col + 1) == NW ? SE : 0) \
: 0))

#ifdef USE_LESS_MEMORY
#define UP(row, col) FIND_UP(row, col)
#else
#define UP(row, col) up_cells[(size_t)(row)*ncols + (col)]
static unsigned char *up_cells;
#endif

static int nrows, ncols;

static void trace_down(struct raster_map *, struct raster_map *, int, int, int);
static int sum_up(struct raster_map *, int, int, int);

void accumulate(struct raster_map *dir_map, struct raster_map *accum_map)
{
int row, col;

nrows = dir_map->nrows;
ncols = dir_map->ncols;

#ifndef USE_LESS_MEMORY
up_cells = calloc((size_t)nrows * ncols, sizeof *up_cells);

#pragma omp parallel for schedule(dynamic) private(col)
for (row = 0; row < nrows; row++) {
for (col = 0; col < ncols; col++)
if (!Rast_is_c_null_value(&DIR(row, col)))
UP(row, col) = FIND_UP(row, col);
}
#endif

#pragma omp parallel for schedule(dynamic) private(col)
for (row = 0; row < nrows; row++) {
for (col = 0; col < ncols; col++)
/* if the current cell is not null and has no upstream cells, start
* tracing down */
if (!Rast_is_c_null_value(&DIR(row, col)) && !UP(row, col))
trace_down(dir_map, accum_map, row, col, 1);
}

#ifndef USE_LESS_MEMORY
free(up_cells);
#endif
}

static void trace_down(struct raster_map *dir_map, struct raster_map *accum_map,
int row, int col, int accum)
void accumulate(struct raster_map *dir_map, struct raster_map *accum_map,
int check_overflow, int use_less_memory, int use_zero)
{
int up, accum_up = 0;

/* accumulate the current cell itself */
ACCUM(row, col) = accum;

/* find the downstream cell */
switch (DIR(row, col)) {
case NW:
row--;
col--;
break;
case N:
row--;
break;
case NE:
row--;
col++;
switch (accum_map->type) {
case CELL_TYPE:
if (check_overflow) {
if (use_less_memory) {
if (use_zero)
accumulate_comz(dir_map, accum_map);
else
accumulate_com(dir_map, accum_map);
}
else {
if (use_zero)
accumulate_coz(dir_map, accum_map);
else
accumulate_co(dir_map, accum_map);
}
}
else {
if (use_less_memory) {
if (use_zero)
accumulate_cmz(dir_map, accum_map);
else
accumulate_cm(dir_map, accum_map);
}
else {
if (use_zero)
accumulate_cz(dir_map, accum_map);
else
accumulate_c(dir_map, accum_map);
}
}
break;
case W:
col--;
case FCELL_TYPE:
if (check_overflow) {
if (use_less_memory) {
if (use_zero)
accumulate_fomz(dir_map, accum_map);
else
accumulate_fom(dir_map, accum_map);
}
else {
if (use_zero)
accumulate_foz(dir_map, accum_map);
else
accumulate_fo(dir_map, accum_map);
}
}
else {
if (use_less_memory) {
if (use_zero)
accumulate_fmz(dir_map, accum_map);
else
accumulate_fm(dir_map, accum_map);
}
else {
if (use_zero)
accumulate_fz(dir_map, accum_map);
else
accumulate_f(dir_map, accum_map);
}
}
break;
case E:
col++;
break;
case SW:
row++;
col--;
break;
case S:
row++;
break;
case SE:
row++;
col++;
default:
if (check_overflow) {
if (use_less_memory) {
if (use_zero)
accumulate_domz(dir_map, accum_map);
else
accumulate_dom(dir_map, accum_map);
}
else {
if (use_zero)
accumulate_doz(dir_map, accum_map);
else
accumulate_do(dir_map, accum_map);
}
}
else {
if (use_less_memory) {
if (use_zero)
accumulate_dmz(dir_map, accum_map);
else
accumulate_dm(dir_map, accum_map);
}
else {
if (use_zero)
accumulate_dz(dir_map, accum_map);
else
accumulate_d(dir_map, accum_map);
}
}
break;
}

/* if the downstream cell is null or any upstream cells of the downstream
* cell have never been visited, stop tracing down */
if (row < 0 || row >= nrows || col < 0 || col >= ncols ||
Rast_is_c_null_value(&DIR(row, col)) || !(up = UP(row, col)) ||
!(accum_up = sum_up(accum_map, row, col, up)))
return;

/* use gcc -O2 or -O3 flags for tail-call optimization
* (-foptimize-sibling-calls) */
trace_down(dir_map, accum_map, row, col, accum_up + 1);
}

/* if any upstream cells have never been visited, 0 is returned; otherwise, the
* sum of upstream accumulation is returned */
static int sum_up(struct raster_map *accum_map, int row, int col, int up)
void nullify_zero(struct raster_map *accum_map)
{
int sum = 0, accum;

#pragma omp flush(accum_map)
if (up & NW) {
if (!(accum = ACCUM(row - 1, col - 1)))
return 0;
sum += accum;
}
if (up & N) {
if (!(accum = ACCUM(row - 1, col)))
return 0;
sum += accum;
}
if (up & NE) {
if (!(accum = ACCUM(row - 1, col + 1)))
return 0;
sum += accum;
}
if (up & W) {
if (!(accum = ACCUM(row, col - 1)))
return 0;
sum += accum;
}
if (up & E) {
if (!(accum = ACCUM(row, col + 1)))
return 0;
sum += accum;
}
if (up & SW) {
if (!(accum = ACCUM(row + 1, col - 1)))
return 0;
sum += accum;
}
if (up & S) {
if (!(accum = ACCUM(row + 1, col)))
return 0;
sum += accum;
}
if (up & SE) {
if (!(accum = ACCUM(row + 1, col + 1)))
return 0;
sum += accum;
switch (accum_map->type) {
case CELL_TYPE:
nullify_zero_c(accum_map);
break;
case FCELL_TYPE:
nullify_zero_f(accum_map);
break;
default:
nullify_zero_d(accum_map);
break;
}

return sum;
}
2 changes: 2 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define ACCUM_RAST_TYPE CELL_TYPE
#include "accumulate_funcs.h"
3 changes: 3 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_cm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#define ACCUM_RAST_TYPE CELL_TYPE
#define USE_LESS_MEMORY
#include "accumulate_funcs.h"
4 changes: 4 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_cmz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#define ACCUM_RAST_TYPE CELL_TYPE
#define USE_LESS_MEMORY
#define USE_ZERO
#include "accumulate_funcs.h"
3 changes: 3 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_co.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#define ACCUM_RAST_TYPE CELL_TYPE
#define CHECK_OVERFLOW
#include "accumulate_funcs.h"
4 changes: 4 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_com.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#define ACCUM_RAST_TYPE CELL_TYPE
#define CHECK_OVERFLOW
#define USE_LESS_MEMORY
#include "accumulate_funcs.h"
5 changes: 5 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_comz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#define ACCUM_RAST_TYPE CELL_TYPE
#define CHECK_OVERFLOW
#define USE_LESS_MEMORY
#define USE_ZERO
#include "accumulate_funcs.h"
4 changes: 4 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_coz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#define ACCUM_RAST_TYPE CELL_TYPE
#define CHECK_OVERFLOW
#define USE_ZERO
#include "accumulate_funcs.h"
3 changes: 3 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_cz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#define ACCUM_RAST_TYPE CELL_TYPE
#define USE_ZERO
#include "accumulate_funcs.h"
2 changes: 2 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_d.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define ACCUM_RAST_TYPE DCELL_TYPE
#include "accumulate_funcs.h"
3 changes: 3 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_dm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#define ACCUM_RAST_TYPE DCELL_TYPE
#define USE_LESS_MEMORY
#include "accumulate_funcs.h"
4 changes: 4 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_dmz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#define ACCUM_RAST_TYPE DCELL_TYPE
#define USE_LESS_MEMORY
#define USE_ZERO
#include "accumulate_funcs.h"
3 changes: 3 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_do.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#define ACCUM_RAST_TYPE DCELL_TYPE
#define CHECK_OVERFLOW
#include "accumulate_funcs.h"
4 changes: 4 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_dom.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#define ACCUM_RAST_TYPE DCELL_TYPE
#define CHECK_OVERFLOW
#define USE_LESS_MEMORY
#include "accumulate_funcs.h"
5 changes: 5 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_domz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#define ACCUM_RAST_TYPE DCELL_TYPE
#define CHECK_OVERFLOW
#define USE_LESS_MEMORY
#define USE_ZERO
#include "accumulate_funcs.h"
4 changes: 4 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_doz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#define ACCUM_RAST_TYPE DCELL_TYPE
#define CHECK_OVERFLOW
#define USE_ZERO
#include "accumulate_funcs.h"
3 changes: 3 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_dz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#define ACCUM_RAST_TYPE DCELL_TYPE
#define USE_ZERO
#include "accumulate_funcs.h"
2 changes: 2 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_f.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define ACCUM_RAST_TYPE FCELL_TYPE
#include "accumulate_funcs.h"
3 changes: 3 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_fm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#define ACCUM_RAST_TYPE FCELL_TYPE
#define USE_LESS_MEMORY
#include "accumulate_funcs.h"
4 changes: 4 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_fmz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#define ACCUM_RAST_TYPE FCELL_TYPE
#define USE_LESS_MEMORY
#define USE_ZERO
#include "accumulate_funcs.h"
3 changes: 3 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_fo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#define ACCUM_RAST_TYPE FCELL_TYPE
#define CHECK_OVERFLOW
#include "accumulate_funcs.h"
4 changes: 4 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_fom.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#define ACCUM_RAST_TYPE FCELL_TYPE
#define CHECK_OVERFLOW
#define USE_LESS_MEMORY
#include "accumulate_funcs.h"
5 changes: 5 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_fomz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#define ACCUM_RAST_TYPE FCELL_TYPE
#define CHECK_OVERFLOW
#define USE_LESS_MEMORY
#define USE_ZERO
#include "accumulate_funcs.h"
4 changes: 4 additions & 0 deletions src/raster/r.flowaccumulation/accumulate_foz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#define ACCUM_RAST_TYPE FCELL_TYPE
#define CHECK_OVERFLOW
#define USE_ZERO
#include "accumulate_funcs.h"

0 comments on commit 701e8f1

Please sign in to comment.