https://github.com/cran/gstat
Tip revision: 343e50f9348fea6d29c55fb28723d1400f6b0f79 authored by Edzer Pebesma on 11 January 2017, 08:00:10 UTC
version 1.1-4
version 1.1-4
Tip revision: 343e50f
block.c
/*
* block.c: calculate block discretization at a prediction location
*/
#include "defs.h"
#include "userio.h"
#include "debug.h"
#include "data.h"
#include "utils.h"
#include "glvars.h"
#include "block.h"
/* Gaussian quadrature adapted from Carr & Palmer, MG 25(5), p. 514:
gauss[4]: -0.8611363116, -0.3399810436, 0.3399810436, 0.8611363116
gauss_w[4]: 0.3478548452, 0.6521451548, 0.6521451548, 0.3478548452
both divided by 2
*/
static double gauss[4] = {
-0.4305681558,
-0.1699905218,
0.1699905218,
0.4305681558
};
double gauss_w[4] = {
0.1739274226,
0.3260725774,
0.3260725774,
0.1739274226
};
int reset_anyway = 0;
void reset_block_discr(void) {
reset_anyway = 1;
}
DATA *block_discr(DATA *d, const DPOINT *block, const DPOINT *where) {
/*
* Purpose : get locations that discretize the estimation area
* Created by : Edzer J. Pebesma
* Date : april 6th, 1992
* Modified : jan 13, 1993, june 3, 1993, june 23 1993
* Prerequisites : where;
* the contents of block (if not NULL) may not change
* during the run of the program: only once the full
* discretisation is calculated.
* Returns : DATA list with 1 point (x,y,z) or a list;
* Side effects : dynamic memory (re)allocation for d;
* uses IS_BLOCK(where) to determine whether point or block is needed;
* discretisations is rectangular using dimensions of *block;
*
* only the x, y and z field are used for locations,
* weights are put in the weight union.
*/
int i, k, l, m, ndim;
int ndiscr = 0, restart = 0;
/*
* if restart != 0, block descretizations are re-calculated.
*/
/*
* ndim: number of dimensions (x, y, z, ..?) in data
* ndiscr: total number of points discretizing the block in this run
* lastndiscr: number of discretizing points in last call
* gl_nblockdiscr: number of points in each dimension in discretizing grid
*/
static double *dx = NULL, *dy = NULL, *dz = NULL;
static double *weight = NULL;
static int max = 0;
DATA *area = NULL, **data;
/*
* d has the points of the discretization of the estimation area;
* dx, dy, dz and weight are remembered in case blockdiscretization has not
* changed
*/
if (IS_POINT(where) && d != NULL) { /* point shortcut */
d->list[0]->x = where->x;
d->list[0]->y = where->y;
d->list[0]->z = where->z;
d->list[0]->u.weight = 1.0; /* weight */
d->n_list = 1;
if (DEBUG_BLOCK) {
printlog("block discretization (dist is weight):\n");
d->mode = X_BIT_SET | Y_BIT_SET | Z_BIT_SET;
print_data_list(d);
}
return d;
}
/*
* calculate the neccesary number of block discrimination points:
*/
ndim = 0;
ndiscr = 1;
if (IS_BLOCK(where)) {
if ((area = get_data_area()) == NULL) {
if (block->x > 0.0) ndim++;
if (block->y > 0.0) ndim++;
if (block->z > 0.0) ndim++;
for (i = 0; i < ndim; i++)
ndiscr *= gl_nblockdiscr;
} else
ndiscr = area->n_list;
}
if (area == NULL && ndiscr > max) {
dx = (double *) erealloc(dx, ndiscr * sizeof(double));
dy = (double *) erealloc(dy, ndiscr * sizeof(double));
dz = (double *) erealloc(dz, ndiscr * sizeof(double));
weight = (double *) erealloc(weight, ndiscr * sizeof(double));
max = ndiscr;
}
/*
* (re)allocate the memory neccesary:
*/
if (d == NULL) { /* allocate ndiscr: */
d = (DATA *) emalloc (sizeof(DATA));
init_one_data(d);
assert(get_n_vars() > 0);
data = get_gstat_data();
d->pp_norm2 = data[0]->pp_norm2; /* assign distance function */
d->what_is_u = U_ISWEIGHT;
d->n_X = 0;
d->colnx = d->colny = d->colnz = 1;
d->list = (DPOINT **) emalloc(ndiscr * sizeof(DPOINT *));
for (i = 0; i < ndiscr; i++)
d->list[i] = (DPOINT *) emalloc (sizeof(DPOINT));
d->n_max = d->n_list = ndiscr;
restart = 1;
} else if (ndiscr > d->n_max) { /* resize if n_max < ndiscr: */
d->list = (DPOINT **) erealloc(d->list, ndiscr * sizeof(DPOINT *));
for (i = d->n_max; i < ndiscr; i++)
d->list[i] = (DPOINT *) emalloc (sizeof(DPOINT));
d->n_max = d->n_list = ndiscr;
restart = 1;
} else if (reset_anyway) {
reset_anyway = 0;
restart = 1;
}
if (restart && ndim > 0 && area == NULL) {
/* set up block regular or Gaussian block discretisation */
i = 0;
switch (ndim) {
case 1:
if (block->y > 0 || block->z > 0)
ErrMsg(ER_IMPOSVAL,
"block_discr(): block y and z dimensions must be 0");
if (gl_gauss) {
for (k = 0; k < 4; k++) {
dx[i] = block->x * gauss[k];
dy[i] = dz[i] = 0.0;
weight[i] = gauss_w[k];
i++;
}
} else {
for (k = 0; k < gl_nblockdiscr; k++) {
dx[i] = block->x *
(-0.5 + (1.0/gl_nblockdiscr) * (0.5 + k));
dy[i] = dz[i] = 0.0;
weight[i] = 1.0 / (1.0 * ndiscr);
i++;
}
}
break;
case 2:
if (block->z > 0)
ErrMsg(ER_IMPOSVAL, "block_discr(): 2D block->z must be zero");
if (gl_gauss) {
for (k = 0; k < 4; k++) {
for (l = 0; l < 4; l++) {
dx[i] = block->x * gauss[k];
dy[i] = block->y * gauss[l];
weight[i] = gauss_w[k] * gauss_w[l];
dz[i] = 0.0;
i++;
} /* for l */
} /* for k */
} else {
for (k = 0; k < gl_nblockdiscr; k++) {
for (l = 0; l < gl_nblockdiscr; l++) {
dx[i] = block->x *
(-0.5 + (1.0/gl_nblockdiscr) * (0.5 + k));
dy[i] = block->y *
(-0.5 + (1.0/gl_nblockdiscr) * (0.5 + l));
dz[i] = 0.0;
weight[i] = 1.0 / (1.0 * ndiscr);
i++;
} /* for l */
} /* for k */
}
break;
case 3:
if (gl_gauss) {
for (k = 0; k < 4; k++) {
for (l = 0; l < 4; l++) {
for (m = 0; m < 4; m++) {
dx[i] = block->x * gauss[k];
dy[i] = block->y * gauss[l];
dz[i] = block->z * gauss[m];
weight[i] = gauss_w[k] *
gauss_w[l] * gauss_w[m];
i++;
} /* for m */
} /* for l */
} /* for k */
} else {
for (k = 0; k < gl_nblockdiscr; k++) {
for (l = 0; l < gl_nblockdiscr; l++) {
for (m = 0; m < gl_nblockdiscr; m++) {
dx[i] = block->x *
(-0.5+(1.0/gl_nblockdiscr) * (0.5 + k));
dy[i] = block->y *
(-0.5+(1.0/gl_nblockdiscr) * (0.5 + l));
dz[i] = block->z *
(-0.5+(1.0/gl_nblockdiscr) * (0.5 + m));
weight[i] = 1.0 / (1.0 * ndiscr);
i++;
} /* for m */
} /* for l */
} /* for k */
}
break;
default:
ErrMsg(ER_IMPOSVAL, "block_discr()");
} /* switch */
if (i != ndiscr) /* silly check ! */
ErrMsg(ER_IMPOSVAL, "block_discr()");
} /* end if restart */
if (IS_BLOCK(where)) {
if (area != NULL) {
for (i = 0; i < ndiscr; i++) {
d->list[i]->x = area->list[i]->x + where->x;
d->list[i]->y = area->list[i]->y + where->y;
d->list[i]->z = area->list[i]->z + where->z;
if (area->colnvariance)
d->list[i]->u.weight = area->list[i]->variance;
else
d->list[i]->u.weight = 1.0 / ndiscr;
}
} else {
for (i = 0; i < ndiscr; i++) {
d->list[i]->x = where->x - dx[i];
d->list[i]->y = where->y - dy[i];
d->list[i]->z = where->z - dz[i];
d->list[i]->u.weight = weight[i];
}
}
} else { /* where is point */
d->list[0]->x = where->x;
d->list[0]->y = where->y;
d->list[0]->z = where->z;
d->list[0]->u.weight = 1.0; /* weight */
}
d->n_list = ndiscr;
if (DEBUG_BLOCK) {
printlog("block discretization (dist is weight):\n");
d->mode = X_BIT_SET | Y_BIT_SET | Z_BIT_SET;
print_data_list(d);
}
return d;
}