https://github.com/cran/RandomFields
Tip revision: f19c5f1146d16fe5a87883e4d7cc55abcc445d0f authored by Martin Schlather on 05 September 2005, 00:00:00 UTC
version 1.3.3
version 1.3.3
Tip revision: f19c5f1
RFtbm.cc
/*
Authors
Martin Schlather, schlath@hsu-hh.de
Simulation of a random field by turning bands;
see RFspectral.cc for spectral turning bands
Copyright (C) 2001 -- 2005 Martin Schlather,
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
//#include <sys/timeb.h>
#include <unistd.h>
#include <assert.h>
#include "RFsimu.h"
#include "RFCovFcts.h"
#define MAXNN 100000000.0 /* max number of points simulated on a line */
typedef struct tbm_lines{
int lines; // number of lines simulated
double linesimufactor, /*factor by which simulation on the line is finer
than the grid */
linesimustep; /* grid lag defined absolutely */
int every;
} tbm_lines;
tbm_lines tbm2 = { 60, 2.0, 0.0, 0};
tbm_lines tbm3 = {500, 2.0, 0.0, 0};
bool TBM2NUMERIC = true;
int TBM_POINTS = 0;
double TBM_CENTER[MAXDIM] = {NA_REAL, NA_REAL, NA_REAL, NA_REAL};
ce_param TBMCE = {false, true, false, TRIVIALSTRATEGY, 3, 10000000,
-1e-7, 1e-3, 0, 0, 0, 0};
SimulationType TBM_METHOD=CircEmbed;
bool TBM_FORCELAYERS=false;
double TBM2_INTEGR_PREC=1e-10;
#define NNN 40 /* immmer gerade !! */
double TBM2integr(int covnr, double h, double u, double *param, int dim,
int fct)
{
// printf("entry\n");
// fct==0 : cov_tbm3 is coded, space & time separated
// fct==1 : cov_tbm3 is not coded, space & time separated
// fct==2 : isotropic function in space-time
double de, ialt, ineu, x, y, z[2], factor[3] = {0.5, 2.0, 0.5},
b[NNN+1], integral, delta, f, h2, u2, alpha;
unsigned long int n, k;
int i, unten, oben, mitte, kk, zz; //, zzcum
cov_fct *cov;
//zzcum=0;
cov = &(CovList[covnr]);
assert(fct>=0 && fct<=2);
h2 = h * h;
u2 = u * u;
z[1] = u;
unten = 4;
mitte = 12;
oben = 26;
b[unten] = 0.1;
b[mitte] = 0.8;
b[oben] = 0.95;
b[0] = 0.0;
b[NNN] = 1.0;
alpha = 0.2;
for (i=unten-1; i>0; i--) b[i] = alpha * b[i+1] + (1.0 - alpha) * b[0];
for (i=unten+1; i<mitte; i++)
b[i] = (double) (i - unten) / (double) (mitte - unten) *
(b[mitte] - b[unten]) + b[unten];
alpha = 0.4;
for (i=mitte+1; i<oben; i++) b[i] = alpha * b[i-1] + (1.0 - alpha) * b[oben];
alpha = 0.5;
for (i=oben+1; i<NNN; i++) b[i] = alpha * b[i-1] + (1.0 - alpha) * b[NNN];
integral = 0.0;
for (i=0; i<NNN; i++) {
n = 2;
delta = b[i+1] - b[i];
de = delta / (double) n;
ialt = 0.0;
for (k=0, x=b[i]; k<=2; k++, x+=de) {
switch(fct) {
case 0 : // cov_tbm3 coded, space & time separated
z[0] = h * sqrt(1.0 - x * x);
f = cov->cov_tbm3(z, param, dim);
break;
case 1 : // cov_tbm3 not coded, space & time separated
z[0] = h * sqrt(1.0 - x * x);
f = cov->cov(z, param, dim) + z[0] * cov->derivative(z, param, dim);
break;
case 2 : // isotropic function in space-time
assert(cov->type==FULLISOTROPIC);
y = (1.0 - x * x) * h2;
z[0] = sqrt(y + u2);
if (z[0]==0.0) f=1.0;
else f = cov->cov(z, param, dim) +
y / z[0] * cov->derivative(z, param, dim);
break;
default : assert(false);
}
ialt += factor[k] * f;
}
for (zz=0; zz<12; zz++) { // sonst rechnet der sich u.U. tot
n *= 3;
de = delta / (double) n;
ineu = 0.0;
for (k=1, x=b[i]+de; k<n; k++, x+=de) {
kk = k % 6;
if (kk == 0 || kk == 3) continue;
//zzcum++;
switch (fct) {
case 0 :
z[0] = h * sqrt(1.0 - x * x);
f = cov->cov_tbm3(z, param, dim);
break;
case 1 :
z[0] = h * sqrt(1.0 - x * x);
f = cov->cov(z, param, dim) + z[0] * cov->derivative(z, param, dim);
break;
case 2 :
y = (1.0 - x * x) * h2;
z[0] = sqrt(y + u2);
if (z[0]==0.0) f=1.0;
else f = cov->cov(z, param, dim) +
y / z[0] * cov->derivative(z, param, dim);
break;
default : assert(false);
}
if (kk==1 || kk==5) f *= 2.0;
ineu += f;
}
if ((fabs(ineu - 2 * ialt) * de < TBM2_INTEGR_PREC)) break;
ialt += ineu;
}
ialt += ineu;
integral += ialt * de / 1.5;
}
// printf("exit\n");
return integral;
}
/*
double TBM2_INTEGR_TIME_PREC=1e-9;
double TBM2integr_time(double aa, double c, covfct f, double *param, int dim) {
#define NN 26 // immmer gerade !!
double h, ialt, ineu, bb=1.0, x, y, z, factor[3]= {0.5, 2.0, 0.5},
xx[3], b[NN+1], integral, delta, alpha;
unsigned long int n,k;
int i, mitte;
b[NN] = bb;
b[0] = aa;
mitte = NN / 2 - 3;
b[mitte] = 0.5 * aa + 0.5 * bb;
alpha = 0.65;
for (i=mitte + 1; i<NN ; i++) {
b[i] = bb * alpha + (1.0 - alpha) * b[i-1];
}
alpha = 0.7;
for (i=mitte - 1; i>0 ; i--) {
b[i] = aa * alpha + (1.0 - alpha) * b[i+1];
}
integral = 0.0;
for (i=0; i<NN; i++) {
n = 2;
delta = b[i+1] - b[i];
h = delta / (double) n;
ialt = 0.0;
for (k=0, x=b[i]; k<=2; k++, x+=h) {
y = x * x;
z = c * sqrt(1.0 - y);
ialt += factor[k] * f(&z, param, dim) / y;
}
while (true) {
n *= 3;
h = delta / (double) n;
ineu = 0.0;
for (k=1, x=b[i]+h; k<n; k++, x+=h) {
switch (k % 6) {
case 0: case 3 : break;
case 1: case 5 :
y = x * x;
z = c * sqrt(1.0 - y);
ineu += 2.0 * f(&z, param, dim) / y;
break;
case 2: case 4 :
y = x * x;
z = c * sqrt(1.0 - y);
ineu += f(&z, param, dim) / y;
break;
}
}
if ((n>6) && (fabs(ineu - 2 * ialt) * h < TBM2_INTEGR_TIME_PREC)) break;
ialt += ineu;
}s->timespacedim
ialt += ineu;
integral += ialt * h / 1.5;
}
return integral;
}
*/
void unitvector3D(int projectiondim, double *deltax, double *deltay,
double *deltaz) {
switch (projectiondim) { // create random unit vector
case 1 :
*deltax= UNIFORM_RANDOM;
break;
case 2 :
*deltax= UNIFORM_RANDOM;// see Martin's tech rep for details
*deltay= sqrt(1.0 - *deltax * *deltax) * sin(UNIFORM_RANDOM*TWOPI);
break;
case 3 :
double dummy;
*deltaz = 2.0 * UNIFORM_RANDOM - 1.0;
dummy = sqrt(1.0 - *deltaz * *deltaz);
*deltay = UNIFORM_RANDOM * TWOPI;
*deltax = cos(*deltay) * dummy;
*deltay = sin(*deltay) * dummy;
break;
default : assert(false);
}
}
#define TBMTIME 3
double CovFctTBM2(double *x, int dim, covinfo_arraytype keycov,
covlist_type covlist, int ncov, bool anisotropy){
// in dieser und der naechste Funktion hat $x$ entweder
// 1 Element (Geradenpunkt der turning bands) oder 2 Elemente
// (Punkt auf Flaeche der turning layers)
int v, vold;
double zw, result;
covinfo_type *kc;
cov_fct *cov=NULL; /* no meaning -- just avoids warning from -Wall */
result = 0.0;
v = 0;
if (dim==2) { // => s->anisotropy! (time-space simulation)
int w;
double z[2]; //'' !! 2 !
while (v<ncov) {
vold = v;
v++; while ((v<ncov) && keycov[covlist[v-1]].op) v++;
zw = 1.0;
for (w=vold; w<v; w++) {
// there could be multiplication by pure time components (z[0]=0)!
kc = &(keycov[covlist[w]]);
cov = &(CovList[kc->nr]);
z[0] = kc->aniso[0] * x[0];
z[1] = kc->aniso[TBMTIME] * x[1];
if (cov->type==FULLISOTROPIC) {
if (z[0]==0.0) zw *= cov->cov(&(z[1]), kc->param, dim);
else { // called only once in the loop
zw *= TBM2integr(kc->nr, z[0], z[1], kc->param, 2, 2);
/*
// alternatively: faster, but more complicated, and uses cov_tbm2
z[0] = fabs(z[0]);
r = sqrt(z[0] * z[0] + z[1] * z[1]);
zw *= kc->param[VARIANCE] * z[0] / r *
(cov->cov_tbm2(&r, kc->param, dim) +
TBM2integr_time(z[0] / r, r, cov->cov, kc->param, dim) );
*/
}
} else {
assert(cov->type==SPACEISOTROPIC);
if (z[0]==0.0) zw *= cov->cov(z, kc->param, 2);
else if (kc->param[TBM2NUM] == 0.0) {
zw *= cov->cov_tbm2(z, kc->param,2);
} else {
assert(cov->derivative != NULL);
zw *= TBM2integr(kc->nr, z[0], z[1], kc->param, 2,
cov->cov_tbm3 == NULL);
}
}
zw *= kc->param[VARIANCE];
}
result += zw;
}
} else {
assert(dim==1);
double z;
for (v=0; v<ncov; v++) {
// printf("%d %d %d\n", v, ncov, covlist[v]);
kc = &(keycov[covlist[v]]);
cov = &(CovList[kc->nr]);
// the field must be isotropic, so the x's have been transformed
// multiplication of covariance functions is not allowed,
// in contrast to 3dim TBM
z = x[0] * kc->aniso[0];
if (z==0.0) zw = 1.0;
else if (kc->param[TBM2NUM] == 0.0) {
zw = cov->cov_tbm2(&z, kc->param, dim);
} else {
assert(cov->derivative != NULL);
zw = TBM2integr(kc->nr, z, 0, kc->param, 2, cov->cov_tbm3 == NULL);
}
result += kc->param[VARIANCE] * zw;
}
}
return result;
}
double CovFctTBM3(double *x, int dim, covinfo_arraytype keycov,
covlist_type covlist, int ncov, bool anisotropy){
int v, vold, w, y;
double dummy, zw, result;
double r, z[2]; //'' !! 2 !
double fct[MAXCOV], abl[MAXCOV];
covinfo_type *kc;
cov_fct *cov=NULL; /* no meaning -- just avoids warning from -Wall */
result = 0.0;
v = 0;
if (dim==2) { // => s->anisotropy!
while (v<ncov) {
vold = v;
v++; while ((v<ncov) && keycov[covlist[v-1]].op) v++;
zw = 1.0;
for (w=vold; w<v; w++) {
kc = &(keycov[covlist[w]]);
cov = &(CovList[kc->nr]);
z[0] = kc->aniso[0] * x[0];
z[1] = kc->aniso[TBMTIME] * x[1];
if (cov->type==FULLISOTROPIC) {
r = sqrt(z[0] * z[0] + z[1] * z[1]);
if (r==0) abl[w] = 0;
else abl[w] = kc->param[VARIANCE] * kc->aniso[0] * fabs(z[0]) /
r * cov->derivative(&r, kc->param, dim);
zw *= (fct[w] = kc->param[VARIANCE] * cov->cov(&r, kc->param, dim));
} else {
assert(cov->type==SPACEISOTROPIC);
abl[w] = kc->param[VARIANCE] *
kc->aniso[0] * cov->derivative(z, kc->param, dim);
zw *= (fct[w] = kc->param[VARIANCE] * cov->cov(z, kc->param, dim));
}
}
result += zw;
if (x[0]!=0.0) {
// TBM-OP : C + h C' -- C'(0) is often an exception for calculation
// but h C' is always zero, so do not consider z[0]=0.0
dummy = 0.0;
for (w=vold; w<v; w++) {
zw = abl[w];
for (y=vold; y<v; y++) if (y!=w) zw *= fct[y];
dummy += zw;
}
result += fabs(x[0]) * dummy;
}
}
} else {
assert(dim==1);
kc = &(keycov[covlist[0]]);
cov = &(CovList[kc->nr]);
if (ncov==1 && cov->cov_tbm3!=NULL) {
z[1] = 0.0; //in case of (CovList[covnr[v]].type==SPACESOTROPIC)
z[0] = x[0] * kc->aniso[0];
return kc->param[VARIANCE] * cov->cov_tbm3(z, kc->param, dim);
}
result = CovFct(x, dim, keycov, covlist, ncov, anisotropy);
if (x[0] != 0.0) {
result += fabs(x[0]) * DerivCovFct(x, dim, keycov, covlist, ncov);
}
// printf("%f %f\n", x[0], result);
}
return result;
}
void TBM_destruct(void **S)
{
if (*S!=NULL) {
TBM_storage *x;
x = *((TBM_storage**)S);
if (x->simuline!=NULL) free(x->simuline);
DeleteKeyNotTrend(&(x->key));
free(*S);
*S = NULL;
}
}
void SetParamTBMCE( int *action, int *force, double *tolRe, double *tolIm,
int *trials, double *mmin, int *useprimes, int *strategy,
double *maxmem, int *dependent)
{
SetParamCE(action, force, tolRe, tolIm, trials, mmin, useprimes, strategy,
maxmem, dependent, &TBMCE,"TBMCE");
}
void SetParamLines(int *action,int *nLines, double *linesimufactor,
double *linesimustep, tbm_lines *tbm, int *every, char *name) {
if (*action) {
tbm->lines=*nLines;
if (*linesimufactor < 0.0 || *linesimustep < 0.0)
PRINTF("Both linesimustep and linesimufactor and must be non-negative\n");
tbm->linesimufactor=*linesimufactor<0 ? 0 : *linesimufactor;
tbm->linesimustep=*linesimustep<0 ? 0 : *linesimustep;
if (*linesimufactor!=0.0 && *linesimustep!=0.0 && GENERAL_PRINTLEVEL>0)
PRINTF("linesimufactor is ignored\n");
// else, i.e. both are zero, the old values are kept!
tbm->every=*every;
} else {
*nLines=tbm->lines;
*linesimufactor=tbm->linesimufactor;
*linesimustep=tbm->linesimustep;
*every=tbm->every;
}
}
void SetParamTBM2(int *action, int *nLines, double *linesimufactor,
double *linesimustep, int *every, int *tbm2num) {
SetParamLines(action, nLines, linesimufactor, linesimustep, &tbm2, every,
"TBM2");
if (*action) {
TBM2NUMERIC = (bool) *tbm2num;
} else {
*tbm2num = TBM2NUMERIC;
}
}
void SetParamTBM3(int *action,int *nLines, double *linesimufactor,
double *linesimustep, int *every) {
SetParamLines(action, nLines, linesimufactor, linesimustep, &tbm3, every,
"TBM3");
}
void SetParamTBM(int *action, int *tbm_method, double *center, int *points) {
int d;
if (*action) {
for (d=0; d<MAXDIM; d++) TBM_CENTER[d] = center[d];
TBM_POINTS = *points;
// method must be the last one because of the return in the middle
if ((*tbm_method<=(int) Nothing) && (*tbm_method>=0)) {
SimulationType m;
m=(SimulationType) *tbm_method;
if ((m==CircEmbed) || (m==Direct) || (m==Nothing)){
TBM_METHOD = m;
return;
}
}
if (GENERAL_PRINTLEVEL>0) {
PRINTF("Specified method [%d] is not allowed. Method set to `Nothing'\n",
*tbm_method);
}
TBM_METHOD = Nothing;
} else {
*tbm_method = (int) TBM_METHOD;
for (d=0; d<MAXDIM; d++) center[d] = TBM_CENTER[d];
*points = TBM_POINTS;
}
}
// aufpassen auf ( * * 0 )
// ( * * 0 )
// ( 0 0 1 )
int init_turningbands(key_type *key, SimulationType method, int m)
{
methodvalue_type *meth;
covinfo_type *kc, *first;
int Xerror=NOERROR, d, tbm_dim, v, nonzero_pos, lasttimecomponent=-1,
firsttimecomponent=-1, lastmatching=-1, firstmatching=-1,
covnr[MAXCOV], cum_nParam[MAXCOV+1], op[MAXCOV], actcov,
totaltimespacedim, w, Aniso, loop, iloop;
double ParamList[TOTAL_PARAM * MAXCOV], f_epsilon = 1e-15,
linesimuscale, quot, diameter;
tbm_lines *tbm;
SimulationType tbm_method;
bool ce_dim2=false, // just to avoid error messages
newadditive, equal, spacecomponent_found;
char errorloc_save[nErrorLoc];
CovFctType CovFctTBM;
TBM_storage *s;
meth = &(key->meth[m]);
/* multiplication of the anisotropy matrix from the right */
nonzero_pos = -1;
SET_DESTRUCT(TBM_destruct, m);
// assert(key->cov[0].aniso[0] != 0.0);
// printf("tbm ansio %f\n", key->cov[0].aniso[0] );
assert(key->covFct == CovFct);
if ((meth->S = malloc(sizeof(TBM_storage)))==0){
Xerror=ERRORMEMORYALLOCATION; goto ErrorHandling;
}
s = (TBM_storage*) meth->S;
s->simuline=NULL;
s->x = NULL;
KEY_NULL(&(s->key));
first = NULL;
// get list of covariance functions that are of interest
if (method==TBM2) { CovFctTBM = CovFctTBM2; tbm_dim = 2; tbm = &tbm2;}
else { CovFctTBM = CovFctTBM3; tbm_dim = 3; tbm = &tbm3;}
/****************************************************************/
/* Extraction of matching covariances */
/****************************************************************/
// einfache checks
// extraktion von covarianzfunktion mit gleichartiger anisotropie
// time-komponente wird nicht ge-checked da letzter parameter true
// bereitstellung von param, quotient, multiply
/* in tbm, time component must be ALWAYS alone, i.e. matrix looks like
* * 0
* * 0
* * x
-- this is checked late on
here x may be any constant. In case x is zero
(for all matrices (0..actcov-1), the last dimension
vanishes (performed in the next step)
the asterixes build submatrices for (v=1..actcov-1) that are multiple of the
submatrix for v=0, already checked by FIRST_CHECK_
*/
if (GENERAL_PRINTLEVEL>4)
PRINTF("determining first nonzero_pos and TBM simulation dimension...\n");
s->ce_dim = 0;
for (v=0; v<key->ncov; v++) {
kc = &(key->cov[v]);
if ((kc->method==method) && (kc->left)) {
first = kc;
// printf("tbm ansio first %f\n", first->aniso[0] );
if (CovList[first->nr].type==ISOHYPERMODEL) {
Xerror=ERRORHYPERNOTALLOWED;
goto ErrorHandling;
}
if (key->anisotropy) {
firstmatching = ANISO;
lastmatching = key->totalparam - 1;
} else {
firstmatching = lastmatching = SCALE;
}
for (nonzero_pos=firstmatching;
nonzero_pos<=lastmatching && first->param[nonzero_pos]==0.0;
nonzero_pos++);
if (nonzero_pos > lastmatching) {Xerror=ERRORTRIVIAL; goto ErrorHandling;}
if (key->Time) {
ce_dim2=TBM_FORCELAYERS;
lasttimecomponent = lastmatching;
firsttimecomponent = key->totalparam - key->timespacedim;
assert(kc->truetimespacedim <= 4);
ce_dim2 |= CovList[kc->nr].type==SPACEISOTROPIC ||
kc->truetimespacedim==4;
while (!ce_dim2 && kc->op && (++v)<key->ncov) {
// here: only check whether within the multiplicative model
// the anisotropy matrices are not multiplicatives of each other.
// If so, ce_dim2 is necessarily true.
// At this point it is not checked whether the matrix combinations
// are allowed ones.
double quot;
int w;
kc = &(key->cov[v]);
assert(kc->truetimespacedim<=4);
ce_dim2 |= CovList[kc->nr].type==SPACEISOTROPIC ||
kc->truetimespacedim==4;
quot = kc->param[nonzero_pos] / first->param[nonzero_pos];
for (w=ANISO; w<=lasttimecomponent; w++) {
if (fabs(first->param[w] * quot - kc->param[w]) >=
(fabs(kc->param[w]) + (double)(kc->param[w]==0.0)) *
f_epsilon) {
ce_dim2 = true;
break;
}
}
}
} else {
ce_dim2 = false;
assert(kc->truetimespacedim <= 3);
}
s->ce_dim = 1 + (int) ce_dim2;
if (ce_dim2) {
lastmatching = firsttimecomponent - 1;
if (nonzero_pos >= firsttimecomponent) {
Xerror=ERRORTRIVIAL; goto ErrorHandling;}
}
break;
}
}
// printf("tbm ansio first %f\n", first->aniso[0] );
if (first == NULL) {
Xerror=ERRORFAILED;
goto ErrorHandling;
}
assert(nonzero_pos > 0);
if (s->ce_dim == 0) { /* no covariance for the considered method found */
Xerror=NOERROR_ENDOFLIST;
goto ErrorHandling;
}
s->simuspatialdim = first->truetimespacedim;
if (ce_dim2) s->simuspatialdim +=
(int) (key->Time && first->param[lasttimecomponent]==0.0) - 1;
/****************************************************************/
/* determine length and resolution of the band */
/****************************************************************/
// sort out which finer grid should be used in the spatial domain for
// low dimensional simulation
if (GENERAL_PRINTLEVEL>4) PRINTF("\ndetermination of the band length...");
// printf("tbm ansio first %f\n", first->aniso[0] );
// minimum distance between the points
loop = 1;
if (tbm->linesimustep > 0.0) linesimuscale = 1.0 / tbm->linesimustep;
else if (tbm->linesimufactor>0) {
double mindelta;
mindelta = RF_INF;
if (key->grid) {
// if linesimufactor, the fine grid scale is proportional to smallest
// distance in the grid.
for (d=0; d<s->simuspatialdim; d++) {
if ((key->x[d][XSTEP]<mindelta) && (key->x[d][XSTEP]>0))
{mindelta=key->x[d][XSTEP];}
}
} else {
int j, i, d, ix, jx;
if (key->totalpoints > 50000) {
Xerror=ERRORTOOMANYPOINTS; goto ErrorHandling;
/* algorithmus kann verbessert werden, so dass diese Fehlermeldung
nicht mehr notwendig ist! */
}
for (ix=i=0; i<key->totalpoints; i++, ix+=key->timespacedim) {
for (jx=j=0; j<i; j++, jx+=key->timespacedim) {
register double diff, dist;
for (dist=0.0, d=0; d<key->timespacedim; d++) {
diff = key->x[d][ix] - key->x[d][jx];
dist += diff * diff;
}
if (dist>0 && dist<mindelta) mindelta=dist;
}
} // if linesimustep==0.0
mindelta = sqrt(mindelta);
}
linesimuscale = tbm->linesimufactor / mindelta;
} else {
linesimuscale=1.0;
loop = 2;
if (TBM_POINTS < 4) { Xerror=ERRORTBMPOINTSZERO; goto ErrorHandling; }
}
// printf("tbm ansio first %f\n", first->aniso[0] );
// multiplication der x-skalenparameter so dass letztendlich
// auf der TBM-Geraden mit Abstand 1 der Punkte simuliert werden kann
// mit dem Vorteil des einfachen Zugriffs auf die simulierten Werte
diameter = -1.0;
for (iloop=0; iloop<loop; iloop++) {
param_type simuparam;
int i;
double dummylx[MAXDIM];
// the loop must be performed twice only if
// linesimuscale is defined by means of TBM_POINTS and diameter.
// the latter is dertermined in the first loop
if (s->x != NULL) {// i.e, if iloop==1
free(s->x);
s->x = NULL;
}
if (key->anisotropy)
for (i=firstmatching; i<=lastmatching; i++)
simuparam[i] = first->param[i] * linesimuscale;
else {
simuparam[SCALE] = first->param[SCALE] / linesimuscale;
}
bool Timedummy;
Timedummy = false;
if (ce_dim2) simuparam[lasttimecomponent] = 1.0;
GetTrueDim(key->anisotropy, key->timespacedim, simuparam,
SPACEISOTROPIC, &Timedummy, &totaltimespacedim, s->aniso);
if (ce_dim2) assert(s->simuspatialdim == totaltimespacedim - 1);
else assert(totaltimespacedim = first->truetimespacedim);
if (s->simuspatialdim > tbm_dim){Xerror = ERRORWRONGDIM; goto ErrorHandling;}
s->truetimespacedim = totaltimespacedim;
// ******************************
// diameter of the simulation area
assert(s->x == 0);
s->simugrid = first->simugrid;
if ((Xerror=Transform2NoGrid(key, s->aniso, totaltimespacedim,
s->simugrid, &(s->x))) != NOERROR)
goto ErrorHandling;
// printf("TRANSF %d %d %d %d %d %d\n", iloop, key->anisotropy, key->Time,
// key->grid, totaltimespacedim, s->simugrid);
// printf("s->x %f %f %f\n\n", s->x[0], s->x[1] , s->x[2]);
// printf("aniso %f %f %f %f %f %f %f %f %f \n\n",
// s->aniso[0], s->aniso[1], s->aniso[2], s->aniso[3],
// s->aniso[4], s->aniso[5], s->aniso[6], s->aniso[7],
// s->aniso[8]);
// printf("first %f %f %f %f \n\n",
// first->aniso[0], first->aniso[1], first->aniso[2], first->aniso[3]);
GetCenterAndDiameter(key, s->simugrid, s->simuspatialdim,
totaltimespacedim, s->x, s->aniso,
s->center, dummylx, &diameter);
if (!ISNA(TBM_CENTER[0])) {
double center[MAXDIM], diff;
int n,k,g;
for (g=1; g<key->timespacedim; g++)
if (!R_FINITE(TBM_CENTER[g])) {
Xerror=ERRORTBMCENTER; goto ErrorHandling;
}
for (n=k=0; k<s->simuspatialdim; k++) {
register double dummy;
dummy = 0.0;
for (g=0; g<key->timespacedim; g++) {
dummy += s->aniso[n++] * TBM_CENTER[g];
// printf("center %d %d %d %f %f %f\n", k, g, n,dummy, s->aniso[n-1], TBM_CENTER[g]);
}
center[k] = dummy;
}
diff = 0.0;
for (k=0; k<s->simuspatialdim; k++) {
diff += (center[k] - s->center[k]) * (center[k] - s->center[k]);
s->center[k] = center[k];
}
diameter += 2.0 * sqrt(diff);
} // else printf("ISNA CENTER ** \n");
// printf("tbm: %d %d %d %f %f %f %d %d\n",
// iloop, loop, TBM_POINTS, diameter, linesimuscale, s->aniso[0],
// key->grid, s->simugrid);
if (loop==2 && iloop==0) linesimuscale = (TBM_POINTS - 3.0) / diameter;
else diameter = trunc(3.0 + diameter);
} // loop
if (diameter<=0.0) {
assert(diameter==0.0);
// Xerror=ERRORTRIVIAL; goto ErrorHandling;
}
if (TBM_POINTS > 0) {
if (diameter > TBM_POINTS) {
PRINTF("tbm points minimum=%f, but TBM_POINTS is %d.\n",
diameter, TBM_POINTS);
Xerror=ERRORTBMPOINTS; goto ErrorHandling;
} else diameter = (double) TBM_POINTS;
}
if (diameter > MAXNN) {Xerror=ERRORNN; goto ErrorHandling;}
if (GENERAL_PRINTLEVEL>4) PRINTF("extracting matching covariances...");
actcov=0;
cum_nParam[actcov]=0;
spacecomponent_found = newadditive = true;
for (v=0; v<key->ncov; v++) {
kc = &(key->cov[v]);
if ((kc->method==method) && (kc->left)) {
cov_fct *cov;
cov = &(CovList[kc->nr]);
assert((kc->nr>=0) && (kc->nr<currentNrCov));
assert(kc->param[VARIANCE]>=0.0);
meth->covlist[actcov] = v;
if (v<key->ncov-1 && kc->op) {
if (key->cov[v+1].method!=method) {
if (GENERAL_PRINTLEVEL>0)
PRINTF("severe error -- contact author, please");
Xerror=ERRORMETHODMIX; goto ErrorHandling;
}
if (method==TBM2) {
Xerror=ERRORNOMULTIPLICATION; goto ErrorHandling;
}
}
if (cov->type==ISOHYPERMODEL) {
Xerror=ERRORHYPERNOTALLOWED; goto ErrorHandling;}
if (cov->implemented[method] != IMPLEMENTED &&
cov->implemented[method] != NUM_APPROX) {
Xerror = ERRORNOTDEFINED; goto ErrorHandling;}
if (method==TBM2 && !TBM2NUMERIC && cov->implemented[method]==NUM_APPROX){
Xerror = ERRORNOTDEFINED; goto ErrorHandling;}
if ((!key->anisotropy && cov->type!=FULLISOTROPIC) ||
cov->type==ANISOTROPIC) {
Xerror = ERRORISOTROPICMETHOD; goto ErrorHandling;}
if ((cov->type==SPACEISOTROPIC) && (s->ce_dim==1)) {
// current initialisation does not match this further (additive)
// component, so left to another initialisation of tbm
kc->left = true;
while (actcov>0 && key->cov[meth->covlist[actcov-1]].op) {
key->cov[meth->covlist[actcov-1]].left = true;
actcov--;
}
assert(actcov>=0);
while (v<key->ncov && key->cov[v].op) v++;
continue;
}
Xerror=cov->check(kc->param, tbm_dim + (int) ce_dim2, method);
if (Xerror && (Xerror!=ERRORCOVNUMERICAL || method!=TBM2 || !TBM2NUMERIC))
goto ErrorHandling;
/* check whether the multiplicative construction are consistent,*/
/* i.e. that the SPATIAL part of the anisotropy matrices are */
/* multiplicatives of each other (more precisely, the remaining */
/* ones are multiplicatives of the first.) */
/* The time part (if ce_dim2) of the matrix must be of the form */
/* (0,..,0,*). */
/* A further goal of this part is the collection of additive */
/* blocks that have the same anisotropy matrix structure, in */
/* order to minimise the simulation time */
// nonzero_pos gives the position of the first element in the
// first matrix of a multiplicative model that is not zero
quot = kc->param[nonzero_pos] / first->param[nonzero_pos];
assert(firstmatching <= lastmatching);
for (w=firstmatching; w<=lastmatching; w++) {
equal = fabs(first->param[w] * quot - kc->param[w])
< (fabs(kc->param[w]) + (double)(kc->param[w]==0.0)) *
f_epsilon;
if (!equal) break; /* even not equal up to a multiplicative constant */
}
if (!equal) {
kc->left = true;
while (actcov>0 && key->cov[meth->covlist[actcov-1]].op) {
key->cov[meth->covlist[actcov-1]].left = true;
actcov--;
}
if (actcov==0) { Xerror=ERRORANISOMIX; goto ErrorHandling; }
while (v<key->ncov && key->cov[v].op) v++;
continue;
}
cum_nParam[actcov + 1] =
cum_nParam[actcov] + 1 + cov->kappas + 1 + 3 * (int) ce_dim2;
memcpy(&(ParamList[cum_nParam[actcov]]), kc->param,
sizeof(double) * (1 + cov->kappas));
Aniso = cum_nParam[actcov] + 1 + cov->kappas;
ParamList[Aniso] = ((key->anisotropy) ? quot : 1.0 / quot) / linesimuscale;
// printf("quot %f\n", quot);
covnr[actcov] = kc->nr;
op[actcov] = kc->op;
if (ce_dim2) {
/* is it of the form * * 0
. * * 0 ?
. * * x
*/
for (w=firsttimecomponent; w<lasttimecomponent; w++) {
// hier < , sonst <= !!
if (kc->param[w]!=0.0) {
Xerror = ERRORTIMESEPARATE;
goto ErrorHandling;
}
}
ParamList[Aniso + 1] =0.0;
ParamList[Aniso + 2] =0.0;
ParamList[Aniso + 3] = kc->param[lasttimecomponent];
if (method==TBM2) {
// TBM2: per multiplication block at most 1 covariance function with
// non vanishing spatial components
// the very first matrix must have spatial components;
// otherwise the the structure is considered as trivial
if (newadditive) spacecomponent_found = false;
if (spacecomponent_found) {
for (w=firstmatching; w<=lastmatching; w++)
if (kc->param[w] != 0.0) {
Xerror = ERRORTIMESEPARATE; goto ErrorHandling;
}
} else {
for (w=firstmatching; w<=lastmatching; w++)
if (spacecomponent_found = (kc->param[w]!=0.0)) break;
}
} // methRFod==TBM2
} // cedim
kc->left=false;
actcov++;
} // kc->left
newadditive = kc->op != 0;
} // v
meth->actcov = actcov;
// xline[XEND]: number of points on the TBM line
double xline[3];
xline[XSTART] = 1.0;
xline[XSTEP] = 1.0;
xline[XEND] = (long) diameter; // diameter > MAXNN must be first since
// risk of overflow !
// CovList.tbm_method is not used yet
// if (TBM_METHOD==Nothing) {tbmmethod[i]=CovList[*covnr].tbm_method;}
tbm_method = TBM_METHOD;
strcpy(errorloc_save, ERROR_LOC);
sprintf(ERROR_LOC, "%s%s: ", errorloc_save, METHODNAMES[method]);
ce_param ce_save;
memcpy(&ce_save, &CIRCEMBED, sizeof(ce_param));
memcpy(&CIRCEMBED, &TBMCE, sizeof(ce_param));
while (tbm_method != Forbidden) {
int tbmmethod[MAXCOV], i;
for (i=0; i<meth->actcov; i++) tbmmethod[i]=tbm_method;
// printf("tbm %d %d\n", covnr[0], meth->actcov);
Xerror = internal_InitSimulateRF(xline, key->T, 1, 3, true,
ce_dim2 /* Time */, covnr, ParamList,
cum_nParam[actcov], meth->actcov,
true /* anisotropy */, op, tbmmethod,
DISTR_GAUSS, &(s->key), true /* storing */,
0 /* natural scaling */,
CovFctTBM);
if (Xerror==NOERROR) break;
switch(tbm_method) {
case Direct : tbm_method=CircEmbed; break;
case CircEmbed : tbm_method=Forbidden; break;
default: Xerror=ERRORNOTDEFINED;
}
}
memcpy(&CIRCEMBED, &ce_save, sizeof(ce_param));
strcpy(ERROR_LOC, errorloc_save);
if (Xerror != NOERROR) goto ErrorHandling; // do not put this line before the
// two preceeding ones!
if ((s->simuline=(double *) malloc(sizeof(double) * s->key.totalpoints))==0){
Xerror=ERRORMEMORYALLOCATION; goto ErrorHandling;}
if (GENERAL_PRINTLEVEL>4) PRINTF("\ntbm is now initialized.\n");
// im folgenden unterscheidung bzgl. anisotropy, da
// oben alle Kovarianzfunktionen zusammengefasst werden mit derselben
// (An)isotropie-Struktur, hei3t nur bei echter Anisotropie wird TBM2
// etc. mehrfach aufgerufen!
if (key->anisotropy) return NOERROR_REPEAT;
else return NOERROR;
ErrorHandling:
key->active = false;
return Xerror;
}
int init_turningbands2(key_type *key, int m) {
return(init_turningbands(key, TBM2, m));
}
int init_turningbands3(key_type *key, int m) {
return(init_turningbands(key, TBM3, m));
}
void do_turningbands(key_type *key, int m, double *res)
{
double phi, *simuline, centerx, centery, centerz, nnhalf, gridlent,
deltax, deltay, deltaz, stepx, stepy, stepz;
long n, nn, totpoints, ntot;
int nt, simutimespacedim, gridlenx, gridleny, gridlenz;
assert(key->active);
tbm_lines *tbm;
methodvalue_type *meth;
TBM_storage *s;
meth = &(key->meth[m]);
s = (TBM_storage*) meth->S;
nn = s->key.length[0];
ntot = s->key.totalpoints;
simutimespacedim = s->truetimespacedim;
if (s->ce_dim == 1) {
gridlent = 1;
totpoints = key->totalpoints;
} else {
assert(s->ce_dim==2);
gridlent = s->key.length[1];
totpoints = key->spatialtotalpoints;
}
assert(gridlent * nn == ntot);
nnhalf = 0.5 * (double) nn;
simuline = s->simuline;
centery = stepy = deltay = centerz = stepz = deltaz = 0.0;
gridlenx = gridleny = gridlenz = 1;
switch (key->spatialdim) {
case 3 :
centerz = s->center[2];
if (s->simugrid) centerz -= s->x[XSTARTDIM3];
gridlenz=key->length[2];
stepz = s->x[XSTEPDIM3]; // no break;
case 2 :
centery = s->center[1];
if (s->simugrid) centery -= s->x[XSTARTDIM2];
gridleny=key->length[1];
stepy = s->x[XSTEPDIM2]; // no break;
case 1 :
centerx = s->center[0];
if (s->simugrid) centerx -= s->x[XSTARTDIM1];
gridlenx=key->length[0];
stepx = s->x[XSTEPDIM1];
break;
default : assert(false);
}
tbm = (meth->unimeth==TBM2) ? &tbm2 : &tbm3;
for (n=0; n<key->totalpoints; n++) res[n]=0.0;
if (s->simugrid) { // old form, isotropic field
double xoffset, yoffset, zoffset, toffset;
int nx, ny, nz, zaehler;
if (meth->unimeth==TBM2) {// isotropy, TBM2, grid
double deltaphi;
deltaphi = PI / (double) tbm->lines;
phi = deltaphi * UNIFORM_RANDOM;
for (n=0; n<tbm->lines; n++) {
if (tbm->every>0 && (n % tbm->every == 0)) PRINTF("%d \n",n);
deltax=sin(phi);
deltay=cos(phi);
internal_DoSimulateRF(&(s->key), 1, simuline);
toffset= nnhalf - centery * deltay - centerx * deltax;
deltax *= stepx;
deltay *= stepy;
zaehler = 0;
for (nt=0; nt<gridlent; nt++) {
yoffset = toffset;
for (ny=0; ny<gridleny; ny++) {
xoffset = yoffset;
for (nx=0; nx<gridlenx; nx++) {
assert((xoffset<ntot) && (xoffset>=0) );
res[zaehler++] += simuline[(long) xoffset];
xoffset += deltax;
}
yoffset += deltay;
}
toffset += (double) nn;
}
phi += deltaphi;
}
} else {// isotropy, TBM3, grid
assert(meth->unimeth==TBM3);
for (n=0; n<tbm->lines; n++){
if (tbm->every>0 && (n % tbm->every == 0)) PRINTF("%d \n",n);
unitvector3D(key->spatialdim, &deltax, &deltay, &deltaz);
toffset= nnhalf - centerz * deltaz - centery * deltay - centerx * deltax;
deltax *= stepx;
deltay *= stepy;
deltaz *= stepz;
internal_DoSimulateRF(&(s->key), 1, simuline);
zaehler = 0;
for (nt=0; nt<gridlent; nt++) {
zoffset = toffset;
for (nz=0; nz<gridlenz; nz++) {
yoffset = zoffset;
for (ny=0; ny<gridleny; ny++) {
xoffset = yoffset;
for(nx=0; nx<gridlenx; nx++) {
assert( (xoffset<ntot) && (xoffset>=0) );
res[zaehler++] += simuline[(long) xoffset];
xoffset += deltax;
}
yoffset += deltay;
}
zoffset += deltaz;
}
toffset += (double) nn;
}
} // for n
} // isotropy, TBM3, simugrid
} else {
// not simugrid, could be time-model!
// both old and new form included
double ex=0, ey=0, ez=0, offset;
long v;
int i;
#define TBMST(UNITYVECTOR, OFFSET, INDEX) {\
for (n=0; n<tbm->lines; n++){\
if (tbm->every>0 && (n % tbm->every == 0)) PRINTF("%d \n",n); \
UNITYVECTOR;\
internal_DoSimulateRF(&(s->key), 1, simuline);\
offset= nnhalf - (OFFSET); \
for (nt=0; nt<gridlent; nt++) {\
for (v = 0, i = 0; i < totpoints; i++) {\
register long index;\
index = (long) (offset + INDEX);\
/* if (true || !((index<ntot) && (index>=0))) {\
// printf("%d %d %d %d\n",\
index, nn, ntot, v);\
} */\
assert((index<ntot) && (index>=0));\
res[i] += simuline[index];\
v += simutimespacedim;\
}\
offset += (double) nn;\
}\
}\
}
if (meth->unimeth==TBM2) {
double deltaphi;
deltaphi = PI / (double) tbm->lines;
phi = deltaphi * UNIFORM_RANDOM;
if (s->simuspatialdim==1) { // dim == 1, TBM 2, arbitrary locations
TBMST(phi += deltaphi; ex=sin(phi), //UNITYVECTOR
centerx * ex, //OFFSET
s->x[v] * ex); //INDEX
} else { // dim == 2, TBM 2
TBMST(phi += deltaphi; ex=sin(phi); ey=cos(phi),
centerx * ex + centery * ey,
s->x[v] * ex + s->x[v+1] * ey);
}
} else { // TBM3, not grid, dim=1 or 2
assert(meth->unimeth == TBM3);
switch (s->simuspatialdim) {
case 1 : //see Martin's techrep f. details
TBMST(unitvector3D(1, &ex, &ey, &ez),
centerx * ex,
s->x[v] * ex);
break;
case 2:
TBMST(unitvector3D(2, &ex, &ey, &ez),
centerx * ex + centery * ey,
s->x[v] * ex + s->x[v+1] * ey);
break;
case 3:
TBMST(unitvector3D(3, &ex, &ey, &ez),
centerx * ex + centery * ey + centerz * ez,
s->x[v] * ex + s->x[v+1] * ey + s->x[v+2] * ez);
break;
default : assert(false);
}
}
}
register long i;
register double InvSqrtNlines;
InvSqrtNlines=1.0 / sqrt((double) tbm->lines);
for(i=0;i<key->totalpoints;i++)
res[i] *= InvSqrtNlines;
}