RMS.cc
/*
Authors
Martin Schlather, schlather@math.uni-mannheim.de
Definition of auxiliary correlation functions
Note:
* Never use the below functions directly, but only by the functions indicated
in RFsimu.h, since there is gno error check (e.g. initialization of RANDOM)
* VARIANCE, SCALE are not used here
* definitions for the random coin method can be found in MPPFcts.cc
* definitions for genuinely anisotropic or nonsta tionary models are in
SophisticatedModel.cc; hyper models also in Hypermodel.cc
Copyright (C) 2001 -- 2003 Martin Schlather
Copyright (C) 2004 -- 2004 Yindeng Jiang & Martin Schlather
Copyright (C) 2005 -- 2017 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 3
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 "def.h"
#include <Basic_utils.h>
#include <General_utils.h>
#include <zzz_RandomFieldsUtils.h>
#include "extern.h"
#include "questions.h"
#include "operator.h"
#include "Processes.h"
#include "startGetNset.h"
#include "variogramAndCo.h"
#include "rf_interfaces.h"
#include "shape.h"
#include "primitive.others.h"
/*
Authors
Martin Schlather, schlather@math.uni-mannheim.de
Definition of auxiliary correlation functions
Copyright (C) 2017 -- 2017 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 3
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.
*/
// $
bool hasVarOnly(model *cov) {
if (cov == NULL || !isDollar(cov)) BUG;
if (!PisNULL(DSCALE) && P0(DSCALE) != 1.0) return false;
if (!PisNULL(DANISO) || !PisNULL(DPROJ)) return false;
int i,
kappas = DefList[COVNR].kappas;
for (i=0; i<kappas; i++)
if (cov->kappasub[i] != NULL) return false;
return true;
}
void kappaS(int i, model *cov, int *nr, int *nc){
// PMI(cov);
switch(i) {
case DVAR : case DSCALE :
*nr = *nc = 1;
break;
case DANISO :
*nr = OWNTOTALXDIM;
*nc = SIZE_NOT_DETERMINED;
break;
case DAUSER :
*nr = SIZE_NOT_DETERMINED;
*nc = OWNTOTALXDIM;
break;
case DPROJ :
*nr = SIZE_NOT_DETERMINED;
*nc = 1;
break;
default : *nr = *nc = OUT_OF_RANGE;
}
}
// simple transformations as variance, scale, anisotropy matrix, etc.
void Siso(double *x, model *cov, double *v){
model *next = cov->sub[DOLLAR_SUB];
int i,
vdim = VDIM0,
vdimSq = vdim * vdim;
double y,
*aniso=P(DANISO),
*scale =P(DSCALE),
var = P0(DVAR);
assert(cov->Sdollar->simplevar);
y = *x;
if (aniso != NULL) y = FABS(y * aniso[0]);
if (scale != NULL)
y = scale[0]>0.0 ? y / scale[0] : (y==0.0 && scale[0]==0.0) ? 0.0 : RF_INF;
// letzteres darf nur passieren wenn dim = 1!!
COV(&y, next, v);
for (i=0; i<vdimSq; i++) v[i] *= var;
}
// simple transformations as variance, scale, anisotropy matrix, etc.
void logSiso(double *x, model *cov, double *v, double *Sign){
model *next = cov->sub[DOLLAR_SUB];
int i,
vdim = VDIM0,
vdimSq = vdim * vdim;
double y,
*aniso=P(DANISO),
*scale =P(DSCALE),
logvar = LOG(P0(DVAR));
assert(cov->Sdollar->simplevar);
y = *x;
if (aniso != NULL) y = FABS(y * aniso[0]);
if (scale != NULL)
y = scale[0]>0.0 ? y / scale[0]
: (y == 0.0 && scale[0]==0.0) ? 0.0 : RF_INF;
LOGCOV(&y, next, v, Sign);
for (i=0; i<vdimSq; i++) v[i] += logvar;
}
void Sstat(double *x, model *cov, double *v){
logSstat(x, cov, v, NULL);
}
void logSstat(double *x, model *cov, double *v, double *Sign){
assert(cov->kappasub[DSCALE] == NULL &&
(cov->kappasub[DANISO]==NULL ||
DefList[MODELNR(cov->kappasub[DANISO])].check==checkAngle)&&
(cov->kappasub[DAUSER]==NULL ||
DefList[MODELNR(cov->kappasub[DAUSER])].check==checkAngle));
model *next = cov->sub[DOLLAR_SUB];
// *Aniso = cov->kappasub[DAUSER],
// *Scale = cov->kappasub[DSCALE];
double
*scale =P(DSCALE),
*aniso=P(DANISO);
int i,
nproj = Nproj,
vdim = VDIM0,
vdimSq = vdim * vdim;
bool notdelete = false;
TALLOC_DOUBLE(z);
if (nproj > 0) {
int *proj = PPROJ;
TALLOC_GLOBAL_X1(z, nproj);
if (scale == NULL || scale[0] > 0.0) {
if (scale == NULL) for (i=0; i<nproj; i++) z[i] = x[proj[i] - 1];
else {
double invscale = 1.0 / scale[0];
for (i=0; i<nproj; i++) {
z[i] = invscale * x[proj[i] - 1];
}
}
} else {
// projection and aniso may not be given at the same time
for (i=0; i<nproj; i++)
z[i] = (x[proj[i] - 1] == 0 && scale[0] == 0) ? 0.0 : RF_INF;
}
// } else if (Aniso != NULL) {
// int dim = Aniso->vdim[0];
// A LLOC_DOLLAR(z, dim);
// FCTN(x, Aniso, z);
// z1 = z;
// } else if (Scale != NULL) {
// int dim = Aniso->vdim[0];
// A LLOC_DOLLAR(z, dim);
// FCTN(x, Aniso, z);
// z1 = z;
} else if ((notdelete = aniso==NULL && (scale == NULL || scale[0] == 1.0))) {
z = x;
} else {
int xdimown = OWNTOTALXDIM;
double *xz;
TALLOC_GLOBAL_X1(z, xdimown);
if (aniso!=NULL) {
xA(x, aniso, cov->nrow[DANISO], cov->ncol[DANISO], z);
xz = z;
} else xz = x;
if (scale != NULL) {
double s = scale[0];
if (s > 0.0) {
double invscale = 1.0 / s;
for (i=0; i < xdimown; i++) z[i] = invscale * xz[i];
} else {
for (i=0; i < xdimown; i++)
z[i] = (xz[i] == 0.0 && s == 0.0) ? 0.0 : RF_INF;
}
}
}
double var;
if (cov->Sdollar->simplevar) {
var = P0(DVAR);
} else {
FCTN(x, cov->kappasub[DVAR], &var);
}
if (Sign==NULL) {
COV(z, next, v);
for (i=0; i<vdimSq; i++) v[i] *= var;
} else {
LOGCOV(z, next, v, Sign);
var = LOG(var);
for (i=0; i<vdimSq; i++) v[i] += var;
}
if (!notdelete) {
FREE_TALLOC(z);
}
}
void Snonstat(double *x, double *y, model *cov, double *v){
logSnonstat(x, y, cov, v, NULL);
}
void logSnonstat(double *x, double *y, model *cov, double *v, double *Sign){
model
*next = cov->sub[DOLLAR_SUB],
*Aniso = cov->kappasub[DANISO] == NULL ? cov->kappasub[DAUSER]
: cov->kappasub[DANISO],
*Scale = cov->kappasub[DSCALE];
double
s1 = RF_NA, s2 = RF_NA, smeanSq=RF_NA,
*scale =P(DSCALE),
*aniso=P(DANISO);
int i,
// nr = NA_INTEGER,
nproj = Nproj,
vdim = VDIM0,
vdimSq = vdim * vdim;
bool notdelete = false;
TALLOC_DOUBLE(z1);
TALLOC_DOUBLE(z2);
// printf("%ld %ld\n", z1, z2);
if (nproj > 0) {
int *proj = PPROJ;
TALLOC_GLOBAL_X1(z1, nproj);
TALLOC_GLOBAL_X2(z2, nproj);
if (scale==NULL || scale[0] > 0.0) {
double invscale = scale==NULL ? 1.0 : 1.0 / scale[0];
for (i=0; i<nproj; i++) {
z1[i] = invscale * x[proj[i] - 1];
z2[i] = invscale * y[proj[i] - 1];
}
} else {
double s = scale[0]; // kann auch negativ sein ...
for (i=0; i<nproj; i++) {
z1[i] = (x[proj[i] - 1] == 0.0 && s == 0.0) ? 0.0 : RF_INF;
z2[i] = (y[proj[i] - 1] == 0.0 && s == 0.0) ? 0.0 : RF_INF;
}
}
} else if (Aniso != NULL) {
int dim = Aniso->vdim[0];
TALLOC_GLOBAL_X1(z1, dim);
TALLOC_GLOBAL_X2(z2, dim);
FCTN(x, Aniso, z1);
FCTN(y, Aniso, z2);
} else if (Scale != NULL && !isnowRandom(Scale)) {// see also code below variance
int xdimown = OWNTOTALXDIM;
double s;
// nr = MODELNR(Scale);
TALLOC_GLOBAL_X1(z1, xdimown);
TALLOC_GLOBAL_X2(z2, xdimown);
FCTN(x, Scale, &s1);
FCTN(y, Scale, &s2);
if (s1 <= 0.0 || s2 <= 0.0)
ERR1("'%.50s' must be a positive function", KNAME(DSCALE));
// if (x[0]!=1.0) printf("\n%.50s x=%10g,%10g %10g y=%10g,%10g %10g; %d\n", NAME(Scale), x[0], x[1], s1, y[0], y[1], s2, xdimown);
smeanSq = 0.5 * (s1 * s1 + s2 * s2);
// printf("s_x[0]=%10g %10g s=%10g %10g %10g ", x[0], x[1], s1, s2, smeanSq);
s = SQRT(smeanSq);
for (i=0; i<xdimown; i++) {
z1[i] = x[i] / s;
z2[i] = y[i] / s;
}
//printf("h/s= %10g\n", SQRT((z1[0] - z2[0]) * (z1[0] - z2[0]) + (z1[1] - z2[1]) * (z1[1] - z2[1])));
// if (x[0]!=1.0) printf("s=%10g, %10g %10g; %10g %10g \n", s, z1[0], z1[1], z2[0], z2[1]);
// assert(z2[1] < 0.3);
} else if ((notdelete = aniso==NULL && (scale==NULL || scale[0] == 1.0))) {
z1 = x;
z2 = y;
} else {
int xdimown = OWNTOTALXDIM;
double *xz1, *xz2;
TALLOC_GLOBAL_X1(z1, xdimown);
TALLOC_GLOBAL_X2(z2, xdimown);
if (aniso != NULL) {
xA( x, y, aniso,cov->nrow[DANISO], cov->ncol[DANISO], z1, z2);
xz1 = z1;
xz2 = z2;
} else {
xz1 = x;
xz2 = y;
}
if (scale != NULL) {
double s = scale[0];
if (s > 0.0) {
double invscale = 1.0 / s;
for (i=0; i<xdimown; i++) {
z1[i] = invscale * xz1[i];
z2[i] = invscale * xz2[i];
}
} else {
for (i=0; i<nproj; i++) {
z1[i] = (xz1[i] == 0.0 && s == 0.0) ? 0.0 : RF_INF;
z2[i] = (xz2[i] == 0.0 && s == 0.0) ? 0.0 : RF_INF;
}
}
}
}
double var;
if (cov->Sdollar->simplevar) {
var = P0(DVAR);
if (Sign != NULL) var = LOG(var);
} else {
assert(equalsCoordinateSystem(OWNISO(0)))
double w;
FCTN(y, cov->kappasub[DVAR], &w);
FCTN(x, cov->kappasub[DVAR], &var);
var *= w;
if (Sign == NULL) var = SQRT(var); else var = 0.5 * LOG(var);
}
if (Scale != NULL) {
int xdimown = OWNTOTALXDIM;
double s12 = s1 * s2 /smeanSq,
dimhalf = 0.5 * xdimown;
if (Sign == NULL)
if (xdimown == 2) var *= s12; // deal most frequent case faster
else var *= POW(s12, dimhalf);
else var += dimhalf * LOG(s12);
}
assert(Sign == NULL);
if (Sign == NULL) {
NONSTATCOV(z1, z2, next, v);
for (i=0; i<vdimSq; i++) v[i] *= var;
} else { // Sign != NULL
LOGNONSTATCOV(z1, z2, next, v, Sign);
for (i=0; i<vdimSq; i++) v[i] += var;
}
if (!notdelete) {
FREE_TALLOC(z1);
FREE_TALLOC(z2);
}
}
void covmatrixS(model *cov, double *v) {
// location_type *loc = Loc(cov);
model *next = cov->sub[DOLLAR_SUB];
assert(next != NULL);
location_type *locnext = Loc(next);
assert(locnext != NULL);
int i, tot, totSq,
dim = GetLoctsdim(cov),
vdim = VDIM0;
KEY_type *KT = cov->base;
assert(dim == PREVTOTALXDIM);
SPRINTF(KT->error_loc, "'%.50s'", NICK(cov));
if ((!PisNULL(DSCALE) && P0(DSCALE) != 1.0) ||
!PisNULL(DANISO) || !PisNULL(DPROJ) ||
cov->kappasub[DSCALE] != NULL ||
cov->kappasub[DAUSER] != NULL || cov->kappasub[DANISO] != NULL ||
cov->kappasub[DPROJ] != NULL ||
!DefList[NEXTNR].is_covmatrix(next)
) {
StandardCovMatrix(cov, v);
return;
}
if (cov->Spgs == NULL && alloc_cov(cov, dim, vdim, vdim) != NOERROR)
XERR(ERRORMEMORYALLOCATION);
int L = OWNLASTSYSTEM; if (L != LASTSYSTEM(PREVSYSOF(next))) BUG;
for (int s=0; s<=L; s++)
if (XDIM(PREVSYSOF(next), s) != NEXTXDIM(s)) {
BUG; // fuehrt zum richtigen Resultat, sollte aber nicht
// vorkommen!
CovarianceMatrix(cov, v);
return;
}
// save trafos
Systems_type prev, gatter, own;
COPYALLSYSTEMS(prev, PREVSYSOF(next), false);
COPYALLSYSTEMS(gatter, GATTERSYSOF(next), false);
COPYALLSYSTEMS(own, NEXT, false);
// next trafos reset by trafos of cov
COPYALLSYSTEMS(PREVSYSOF(next), PREV, false);
COPYALLSYSTEMS(GATTERSYSOF(next), GATTER, false);
COPYALLSYSTEMS(NEXT, OWN, true);
DefList[NEXTNR].covmatrix(next, v);//hier wird uU next->totalpoints gesetzt
// restore trafos
COPYALLSYSTEMS(PREVSYSOF(next), prev, false);
COPYALLSYSTEMS(GATTERSYSOF(next), gatter, false);
COPYALLSYSTEMS(NEXT, own, false);
tot = VDIM0 * locnext->totalpoints;
totSq = tot * tot;
if (cov->Sdollar->simplevar) {
double var = P0(DVAR);
if (var == 1.0) return;
for (i=0; i<totSq; v[i++] *= var);
} else {
BUG;
}
}
char iscovmatrixS(model *cov) {
model *sub = cov->sub[DOLLAR_SUB];
return (int) ((PisNULL(DSCALE) || P0(DSCALE) ==1.0) &&
PisNULL( DAUSER) && PisNULL( DANISO) &&
PisNULL(DPROJ) &&
cov->Sdollar->simplevar && // to do
PisNULL(DANISO)) * DefList[SUBNR].is_covmatrix(sub);
}
void DS(double *x, model *cov, double *v){
model *next = cov->sub[DOLLAR_SUB];
assert( cov->kappasub[DAUSER] == NULL && cov->kappasub[DANISO] == NULL && cov->kappasub[DSCALE] == NULL);
int i,
vdim = VDIM0,
vdimSq = vdim * vdim,
nproj = Nproj;
double y[2], varSc,
*scale =P(DSCALE),
*aniso=P(DANISO),
spinvscale = 1.0;
assert(cov->Sdollar->simplevar);
assert(isCartesian(OWNISO(0)));
if (aniso != NULL) {
spinvscale *= aniso[0];
// was passiert, wenn es aniso nicht vom TypeIso ist ??
}
if (scale != NULL) spinvscale /= scale[0];
varSc = P0(DVAR) * spinvscale;
if (nproj == 0) {
y[0] = x[0] * spinvscale;
y[1] = (equalsIsotropic(OWNISO(0)) || cov->ncol[DANISO]==1) ? 0.0
: x[1] * aniso[3]; // temporal; temporal scale
} else {
assert(equalsSpaceIsotropic(OWNISO(0)));
// assert(P0 INT(DPROJ) == PROJ_SPACE); // #define Nproj
y[0] = x[0] * spinvscale;
y[1] = RF_NAN;
}
Abl1(y, next, v);
for (i=0; i<vdimSq; i++) v[i] *= varSc;
}
void DDS(double *x, model *cov, double *v){
model *next = cov->sub[DOLLAR_SUB];
assert(cov->kappasub[DAUSER] == NULL && cov->kappasub[DANISO] == NULL );
int i,
vdim = VDIM0,
vdimSq = vdim * vdim,
nproj = Nproj,
*proj = PPROJ;
double y[2], varScSq,
*scale =P(DSCALE),
*aniso=P(DANISO),
spinvscale = 1.0;
assert(isCartesian(OWNISO(0)));
assert(cov->Sdollar->simplevar);
if (aniso != NULL) {
spinvscale *= aniso[0];
// was passiert, wenn es aniso nicht vom TypeIso ist ??
}
if (scale != NULL) spinvscale /= scale[0];
varScSq = P0(DVAR) * spinvscale * spinvscale;
if (nproj == 0) {
y[0] = x[0] * spinvscale;
y[1] = (equalsIsotropic(OWNISO(0)) || cov->ncol[DANISO]==1) ? 0.0
: x[1] * aniso[3]; // temporal; temporal scale
} else {
BUG;
for (i=0; i<nproj; i++) {
y[0] += x[proj[i] - 1] * x[proj[i] - 1];
}
y[0] = SQRT(y[0]) * spinvscale;
}
Abl2(y, next, v);
for (i=0; i<vdimSq; i++) v[i] *= varScSq;
}
void D3S(double *x, model *cov, double *v){
model *next = cov->sub[DOLLAR_SUB];
assert(cov->kappasub[DAUSER] == NULL && cov->kappasub[DANISO] == NULL);
int i,
vdim = VDIM0,
vdimSq = vdim * vdim,
nproj = Nproj,
*proj = PPROJ;
double y[2], varScS3,
*scale =P(DSCALE),
*aniso=P(DANISO),
spinvscale = 1.0;
assert(isCartesian(OWNISO(0)));
assert(cov->Sdollar->simplevar);
if (aniso != NULL) {
spinvscale *= aniso[0];
// was passiert, wenn es aniso nicht vom TypeIso ist ??
}
if (scale != NULL) spinvscale /= scale[0];
varScS3 = P0(DVAR) * spinvscale * spinvscale * spinvscale;
if (nproj == 0) {
y[0] = x[0] * spinvscale;
y[1] = (OWNISO(0)==ISOTROPIC || cov->ncol[DANISO]==1) ? 0.0
: x[1] * aniso[3]; // temporal; temporal scale
} else {
BUG;
for (i=0; i<nproj; i++) {
y[0] += x[proj[i] - 1] * x[proj[i] - 1];
}
y[0] = SQRT(y[0]) * spinvscale;
}
Abl3(y, next, v);
for (i=0; i<vdimSq; i++) v[i] *= varScS3;
}
void D4S(double *x, model *cov, double *v){
model *next = cov->sub[DOLLAR_SUB];
assert(cov->kappasub[DAUSER] == NULL && cov->kappasub[DANISO] == NULL);
int i,
vdim = VDIM0,
vdimSq = vdim * vdim,
nproj = Nproj,
*proj = PPROJ;
double y[2], varScS4,
*scale =P(DSCALE),
*aniso=P(DANISO),
spinvscale = 1.0;
assert(isCartesian(OWNISO(0)));
if (aniso != NULL) {
spinvscale *= aniso[0];
// was passiert, wenn es aniso nicht vom TypeIso ist ??
}
if (scale != NULL) spinvscale /= scale[0];
varScS4 = spinvscale * spinvscale;
varScS4 *= varScS4 * P0(DVAR);
if (nproj == 0) {
y[0] = x[0] * spinvscale;
y[1] = (equalsIsotropic(OWNISO(0)) || cov->ncol[DANISO]==1) ? 0.0
: x[1] * aniso[3]; // temporal; temporal scale
} else {
BUG;
for (i=0; i<nproj; i++) {
y[0] += x[proj[i] - 1] * x[proj[i] - 1];
}
y[0] = SQRT(y[0]) * spinvscale;
}
Abl4(y, next, v);
for (i=0; i<vdimSq; i++) v[i] *= varScS4;
}
void nablahessS(double *x, model *cov, double *v, bool nabla){
model *next = cov->sub[DOLLAR_SUB],
*Aniso = cov->kappasub[DANISO] == NULL ? cov->kappasub[DAUSER] :
cov->kappasub[DANISO];
if (Aniso != NULL) BUG;
int i, endfor,
dim = cov->nrow[DANISO],// == ncol == x d i m ?
xdimown = OWNTOTALXDIM,
nproj = Nproj;
double *xy, *vw,
*scale =P(DSCALE),
*aniso=P(DANISO),
var = P0(DVAR);
if (nproj != 0) BUG;
if (dim != xdimown) BUG;
if (!cov->Sdollar->simplevar)
NotProgrammedYet("nabla not programmed for arbitrary 'var'");
TALLOC_DOUBLE(z0);
TALLOC_DOUBLE(w0);
if (aniso != NULL) {
TALLOC_GLOBAL_X1(z0, xdimown);
TALLOC_GLOBAL_X2(w0, xdimown);
xA(x, aniso, xdimown, xdimown, z0);
xy = z0;
vw = w0;
} else {
xy = x;
vw = v;
}
TALLOC_DOUBLE(y0);
if (scale != NULL) {
TALLOC_GLOBAL_X3(y0, xdimown);
assert(scale[0] > 0.0);
double spinvscale = 1.0 / scale[0];
var *= spinvscale;
if (!nabla) var *= spinvscale; // gives spinvscale^2 in case of hess
for (i=0; i<xdimown; i++) y0[i] = xy[i] * spinvscale;
xy = y0;
}
endfor = xdimown;
if (nabla) {
NABLA(xy, next, vw);
} else {
HESSE(xy, next, vw);
endfor *= xdimown;
}
if (aniso != NULL) {
if (nabla) Ax(aniso, vw, xdimown, xdimown, v);
else {
XCXt(aniso, vw, v, xdimown, xdimown); //todo:?reprogramm XCXt with alloc here ?
}
FREE_TALLOC(z0);
FREE_TALLOC(w0);
}
FREE_TALLOC(y0);
for (i=0; i<endfor; i++) v[i] *= var;
}
void nablaS(double *x, model *cov, double *v){
nablahessS(x, cov, v, true);
}
void hessS(double *x, model *cov, double *v){
nablahessS(x, cov, v, false);
}
void inverseS(double *x, model *cov, double *v) {
model *next = cov->sub[DOLLAR_SUB];
int i,
idx[3] = {DANISO, DAUSER, DPROJ};
double
scale;
if (cov->kappasub[DVAR] != NULL)
NotProgrammedYet("nabla not programmed for arbitrary 'var'");
for (i=0; i<3; i++) {
if (cov->kappasub[idx[i]] != NULL) {
ERR1( "inverse can only be calculated if '%.20s' is not an arbitrary function",
KNAME(idx[i]));
}
}
if (cov->kappasub[DSCALE] != NULL) {
double left;
model *sub = cov->kappasub[DSCALE];
NONSTATINVERSE(ZERO(sub), sub, &left, &scale);
if (left < 0.0) ERR("scale not defined to be non-negative.");
} else scale = PisNULL(DSCALE) ? 1.0 : P0(DSCALE);
int
dim = PREVTOTALXDIM,
nproj = Nproj;
// *proj = (int *)P(DPROJ];
double y,
s = 1.0,
*aniso=P(DANISO),
var = P0(DVAR);
//PMI(cov); crash();
if (dim != 1) BUG;
if (aniso != NULL) {
if (isMiso(Type(aniso, cov->nrow[DANISO], cov->ncol[DANISO])))
s /= aniso[0];
else NotProgrammedYet(""); // to do
}
s *= scale;
if (nproj == 0) {
y= *x / var; // inversion, so variance becomes scale
} else {
BUG; //ERR("nproj is not allowed in invS");
}
if (DefList[NEXTNR].inverse == ErrInverse) BUG;
INVERSE(&y, next, v);
for (i=0; i<dim; i++) v[i] *= s; //!
}
void nonstatinverseS(double *x, model *cov, double *left, double*right,
bool log){
model
*next = cov->sub[DOLLAR_SUB],
*Aniso = cov->kappasub[DANISO] == NULL ? cov->kappasub[DAUSER]
: cov->kappasub[DANISO],
*Scale = cov->kappasub[DSCALE];
int i,
dim = PREVTOTALXDIM,
nproj = Nproj;
// *proj = (int *)P(DPROJ];
double y,
s = 1.0,
*scale =P(DSCALE),
*aniso=P(DANISO),
var = P0(DVAR);
if (cov->kappasub[DVAR] != NULL)
NotProgrammedYet("nabla not programmed for arbitrary 'var'");
if (nproj == 0) {
y= *x / var; // inversion, so variance becomes scale
} else {
BUG; //ERR("nproj is not allowed in invS");
}
if (DefList[NEXTNR].nonstat_inverse == ErrInverseNonstat) BUG;
if (log) {
NONSTATLOGINVERSE(&y, next, left, right);
// printf("S %f %f %f %s\n", y, *left, *right, NAME(next));
} else {
NONSTATINVERSE(&y, next, left, right);
}
if (aniso != NULL) {
if (isMiso(Type(aniso, cov->nrow[DANISO], cov->ncol[DANISO]))) s/=aniso[0];
else {
dollar_storage *S = cov->Sdollar;
int
ncol = cov->ncol[DANISO],
nrow = cov->nrow[DANISO],
ncnr = ncol * nrow,
size = ncol * sizeof(double);
bool redo;
long bytes = ncnr * sizeof(double);
if (ncol != nrow) BUG;
redo = S->save_aniso == NULL;
ALLC_NEW(Sdollar, save_aniso, ncnr, save_aniso);
ALLC_NEW(Sdollar, inv_aniso, ncnr, inv_aniso);
TALLOC_X1(LR, ncol);
S->done = false;
int pid;
if (!redo) {
for (i=0; i<ncnr;i++) if ((redo = save_aniso[i] != P(DANISO)[i])) break;
Ext_pid(&pid);
if (S->pid == 0) {
S->pid = pid;
if (S->pid == pid) { // two processes writing on the same place
S->busy = true; // one process doing the job
} else if (GLOBAL_UTILS->basic.cores == 1 || !S->busy)
ERR("Multiprocessor conflict. Plse inform maintainer & try again");
} else if (GLOBAL_UTILS->basic.cores == 1 || !S->busy)
ERR("Multiprocessor conflict. Plse inform maintainer & try again");
}
if (redo && S->pid == pid) {
MEMCOPY(save_aniso, P(DANISO), bytes);
MEMCOPY(inv_aniso, P(DANISO), bytes);
if (Ext_invertMatrix(inv_aniso, nrow) != NOERROR) XERR(ERRORANISO_INV);
S->busy = false;
S->done = true;
}
while(S->busy && !S->done) {
int sleep = (double) nrow * nrow * nrow / 1e8;
sleep = sleep == 0 ? 1 : sleep;
if (PL >= PL_BRANCHING) { PRINTF("|");}
Ext_sleepMicro(&sleep);
}
MEMCOPY(LR, right, size);
xA(LR, inv_aniso, nrow, ncol, right);
MEMCOPY(LR, left, size);
xA(LR, inv_aniso, nrow, ncol, left);
END_TALLOC_X1;
}
}
if (Aniso != NULL) {
if (aniso != NULL) BUG;
if (DefList[MODELNR(Aniso)].inverse == ErrInverse) XERR(ERRORANISO_INV);
int
nrow = Aniso->vdim[0],
ncol = Aniso->vdim[1],
size = nrow * sizeof(double);
if (dim != ncol || ncol != 1)
ERR("anisotropy function not of appropriate form");
TALLOC_X1(LR, nrow);
MEMCOPY(LR, right, size);
INVERSE(LR, Aniso, right);
MEMCOPY(LR, left, size);
INVERSE(LR, Aniso, left);
END_TALLOC_X1;
}
if (Scale != NULL && !isnowRandom(Scale)) {
double dummy;
COV(ZERO(Scale), Scale, &dummy);
s *= dummy;
} else if (scale != NULL) s *= scale[0];
if (s != 1.0) {
for (i=0; i<dim; i++) {
left[i] *= s; //!
right[i] *= s;
}
}
}
void nonstatinverseS(double *x, model *cov, double *left, double*right) {
nonstatinverseS(x, cov, left, right, false);
}
void nonstat_loginverseS(double *x, model *cov, double *left, double*right){
nonstatinverseS(x, cov, left, right, true);
}
void coinitS(model *cov, localinfotype *li) {
assert(cov->Sdollar->simplevar);
model *next = cov->sub[DOLLAR_SUB];
if ( DefList[NEXTNR].coinit == NULL)
ERR("# cannot find coinit -- please inform author");
DefList[NEXTNR].coinit(next, li);
}
void ieinitS(model *cov, localinfotype *li) {
assert(cov->Sdollar->simplevar);
model *next = cov->sub[DOLLAR_SUB];
if ( DefList[NEXTNR].ieinit == NULL)
ERR("# cannot find ieinit -- please inform author");
DefList[NEXTNR].ieinit(next, li);
}
void tbm2S(double *x, model *cov, double *v){
assert(cov->Sdollar->simplevar);
model *next = cov->sub[DOLLAR_SUB];
// defn *C = DefList + NEXTNR; // kein gatternr, da isotrop
double y[2], *xy,
*scale =P(DSCALE),
*aniso = P(DANISO);
assert(cov->kappasub[DAUSER] == NULL && cov->kappasub[DANISO] == NULL);
assert(Nproj == 0);
if (aniso!=NULL) {
if (cov->ncol[DANISO]==2) { // turning layers
y[0] = x[0] * aniso[0]; // spatial
y[1] = x[1] * aniso[3]; // temporal
assert(aniso[1] == 0.0 && aniso[2] == 0.0);
if (y[0] == 0.0) COV(y, next, v) else TBM2CALL(y, next, v);
} else {
assert(cov->ncol[DANISO]==1);
if (cov->nrow[DANISO] == 1) { // turning bands
y[0] = x[0] * aniso[0]; // purely spatial
TBM2CALL(y, next, v);
} else { // turning layers, dimension reduction
if (P0(DANISO) == 0.0) {
y[0] = x[1] * aniso[1]; // temporal
COV(y, next, v);
} else {
y[0] = x[0] * aniso[0]; // temporal
TBM2CALL(y, next, v);
}
}
}
xy = y;
} else xy = x;
if (scale != NULL) {
double s = scale[0];
if (s > 0) {
double invscale = 1.0 / s;
if (OWNTOTALXDIM == 2){
y[0] = xy[0] * invscale; // spatial
y[1] = xy[1] * invscale; // temporal
if (y[0] == 0.0) COV(y, next, v) else TBM2CALL(y, next, v);
} else {
y[0] = xy[0] * invscale; // purely spatial
TBM2CALL(y, next, v);
}
} else {
y[0] = (s < 0.0 || xy[0] != 0.0) ? RF_INF : 0.0;
if (OWNTOTALXDIM == 2)
y[1] = (s < 0.0 || xy[1] != 0.0) ? RF_INF : 0.0;
TBM2CALL(y, next, v);
}
} else {
TBM2CALL(xy, next, v);
}
*v *= P0(DVAR);
}
// TODO : Aniso=Matrix: direkte implementierung in S,
// sodass nicht ueber initS gegangen werden muss, sondern
// e < - e^\top Aniso
int TaylorS(model *cov) {
model
*next = cov->sub[DOLLAR_SUB],
*sub = cov->key == NULL ? next : cov->key;
int i;
if (PisNULL(DPROJ) && PisNULL(DANISO)) {
double scale = PisNULL(DSCALE) ? 1.0 : P0(DSCALE);
cov->taylorN = sub->taylorN;
for (i=0; i<cov->taylorN; i++) {
cov->taylor[i][TaylorPow] = sub->taylor[i][TaylorPow];
cov->taylor[i][TaylorConst] = sub->taylor[i][TaylorConst] *
P0(DVAR) * POW(scale, -sub->taylor[i][TaylorPow]);
}
cov->tailN = sub->tailN;
for (i=0; i<cov->tailN; i++) {
cov->tail[i][TaylorPow] = sub->tail[i][TaylorPow];
cov->tail[i][TaylorExpPow] = sub->tail[i][TaylorExpPow];
cov->tail[i][TaylorConst] = sub->tail[i][TaylorConst] *
P0(DVAR) * POW(scale, -sub->tail[i][TaylorPow]);
cov->tail[i][TaylorExpConst] = sub->tail[i][TaylorExpConst] *
POW(scale, -sub->tail[i][TaylorExpPow]);
}
} else {
cov->taylorN = cov->tailN = 0;
}
RETURN_NOERROR;
}
int checkS(model *cov) {
// printf("checkS!!\n");
// hier kommt unerwartet ein scale == nan rein ?!!
// PMI(cov);
model
*next = cov->sub[DOLLAR_SUB],
*Aniso = cov->kappasub[DANISO] == NULL ? cov->kappasub[DAUSER]
: cov->kappasub[DANISO],
*Scale = cov->kappasub[DSCALE],
*Var = cov->kappasub[DVAR],
*sub = cov->key == NULL ? next : cov->key;
isotropy_type owniso = OWNISO(0);
int err,
//xdimgatter = GATTERTOTALXDIM,
// KOMMENTAR NICHT LOESCHEN
// *proj = PPROJ, // auf keinen Fall setzen, da Pointer unten neu
// gesetzt wird!!!!
last = OWNLASTSYSTEM;
// bool skipchecks = GLOBAL.general.skipchecks;
matrix_type mtype = TypeMany;
// if (Aniso == NULL && Scale == NULL && Var == NULL &&
// PisNULL(DANISO) && PisNULL(DAUSER) && PisNULL(DSCALE) && PisNULL(DVAR))
// SERR("no parameter is set.");
assert(isAnyDollar(cov));
if (!isDollarProc(cov)) set_nr(OWN, DOLLAR); //wegen nr++ unten! NICHT SET_NR!
// cov->q[1] not NULL then A has been given
if ((err = checkkappas(cov, false)) != NOERROR) { // muss weit vorne stehen!
RETURN_ERR(err);
}
kdefault(cov, DVAR, 1.0);
// printf("checkS2!!\n");
if ( (!PisNULL(DSCALE) || Scale != NULL) && OWNLASTSYSTEM != 0)
SERR1("'%.50s' may be used only if a single coordinate system is envolved",
KNAME(DSCALE));
bool angle = isAngle(Aniso);
int dim = OWNLOGDIM(0);
if (angle && PisNULL(DANISO) && PisNULL(DAUSER) &&
OWNLASTSYSTEM == 0 && OWNXDIM(0) == dim) {
ASSERT_CARTESIAN;
if (!isCartesian(owniso)) RETURN_ERR(ERRORANISO);
if ((err = CHECK(Aniso, dim, dim, ShapeType, XONLY, CARTESIAN_COORD,
SUBMODEL_DEP, cov->frame)) == NOERROR) {
if (isverysimple(Aniso)) {
PALLOC(DAUSER, dim, dim);
AngleMatrix(Aniso, P(DAUSER));
COV_DELETE(cov->kappasub + DAUSER, cov);
Aniso = cov->kappasub[DAUSER] = NULL;
angle = false;
}
}
}
if (cov->kappasub[DANISO] != NULL) // kann auch weggelassen werden. sollte aufgefangen werden
SERR1("'%.50s' may not be a function.", KNAME(DANISO));
if (!PisNULL(DAUSER)) {
if (!isCartesian(owniso)) RETURN_ERR(ERRORANISO);
// if (GLOBAL.internal.warn_Aniso) {
// PRINTF("NOTE! Starting with RandomFields 3.0, the use of '%.50s' is different from\nthe former '%.50s' insofar that '%.50s' is multiplied from the right by 'x' (i.e. Ax),\nwhereas '%.50s' had been multiplied from the left by 'x' (i.e. xA).\n", KNAME(DAUSER), KNAME(DANISO), KNAME(DANISO), KNAME(DAUSER));
// }
GLOBAL.internal.warn_Aniso = false;
// here for the first time
if (!PisNULL(DANISO)) RETURN_ERR(ERRORANISO_T);
int
lnrow = cov->nrow[DAUSER],
lncol = cov->ncol[DAUSER];
long
total = lncol * lnrow;
double
*pA = P(DAUSER);
PALLOC(DANISO, lncol, lnrow); // !! ACHTUNG col, row gekreuzt
for (int i=0, k=0; i<lnrow; i++) {
for (long j=i; j<total; j+=lnrow) P(DANISO)[k++] = pA[j];
}
PFREE(DAUSER);
}
bool simplevar = Var == NULL || isnowRandom(Var); // checkkappa s.o.
if (!simplevar) {
ptwise_type ptt = cov->ptwise_definite;
assert(equalsCoordinateSystem(owniso));
if ((err = CHECK(Var, OWNLOGDIM(0), OWNXDIM(0),
ShapeType, // only!! -- for pos def use RMprod
XONLY, owniso,
SCALAR, TrendType)) != NOERROR) RETURN_ERR(err);
if (Var->ptwise_definite != pt_posdef) {
if (Var->ptwise_definite == pt_unknown) {
if (GLOBAL.internal.warn_negvar && cov->q==NULL) { // just a flag
QALLOC(1);
warning("positivity of the variance in '%.50s' cannot be detected.",
NICK(next));
}
} else {
SERR2("positivity of '%.50s' required. Got '%.50s'", KNAME(DVAR),
POSITIVITY_NAMES[Var->ptwise_definite]);
}
}
cov->ptwise_definite = ptt;
}
ONCE_NEW_STORAGE(dollar);
EXTRA_STORAGE;
int xdimNeu = OWNXDIM(0);
// printf("checkS ff !!\n");
if (Aniso != NULL) { // CASE 1: Aniso is given by arbitrary fctn
if (!isDollarProc(cov) && !angle && !isKernel(OWN)) RETURN_ERR(ERRORFAILED);
if (!PisNULL(DANISO) || !PisNULL(DPROJ) || !PisNULL(DSCALE) ||
(Scale!=NULL && !isnowRandom(Scale)) )
SERR2("if '%.50s' is an arbitrary function, only '%.50s' may be given as additional parameter.", KNAME(DAUSER), KNAME(DVAR));
//assert(equalsCartCoord(owniso) || (angle && equalsSymmetric(owniso)));
cov->full_derivs = cov->rese_derivs = 0;
cov->loggiven = wahr;
if ((err = CHECK(Aniso, OWNLOGDIM(0), OWNXDIM(0), ShapeType, XONLY,
CARTESIAN_COORD, SUBMODEL_DEP, cov->frame)) != NOERROR) {
RETURN_ERR(err);
}
if (Aniso->vdim[1] != 1)
SERR3("'%.50s' returns a matrix of dimension %d x %d, but a vector is need.",
KNAME(DANISO), Aniso->vdim[0], Aniso->vdim[1]);
if (cov->key==NULL) {
ASSERT_QUASIONESYSTEM;
if ((err = CHECK(sub, Aniso->vdim[0], Aniso->vdim[0],
OWNTYPE(0), OWNDOM(0), owniso,
SUBMODEL_DEP, cov->frame)) != NOERROR) {
RETURN_ERR(err);
}
}
cov->pref[Nugget] = cov->pref[RandomCoin] = cov->pref[Average] =
cov->pref[Hyperplane] = cov->pref[SpectralTBM] = cov->pref[TBM] =
PREF_NONE;
sub->pref[CircEmbed] = sub->pref[CircEmbedCutoff] =
sub->pref[CircEmbedIntrinsic] = sub->pref[Sequential] =
sub->pref[Specific] = PREF_NONE;
} else if (Scale != NULL && !isnowRandom(Scale)) {
// CASE 2: Scale is given by arbitrary function
if (!isDollarProc(cov) && !isKernel(OWN)) RETURN_ERR(ERRORFAILED);
if (!PisNULL(DANISO) || !PisNULL(DPROJ) || !PisNULL(DSCALE))
SERR2("if '%.50s' is an arbitrary function, only '%.50s' may be given as additional parameter.", KNAME(DSCALE), KNAME(DVAR));
assert(equalsCartCoord(owniso));
cov->full_derivs = cov->rese_derivs = 0;
cov->loggiven = wahr;
assert(equalsCartCoord(owniso));
if ((err = CHECK(Scale, OWNLOGDIM(0), OWNXDIM(0), ShapeType, XONLY,
owniso, SCALAR, TrendType)) != NOERROR) {
RETURN_ERR(err);
}
if (Scale->vdim[1] != 1 || Scale->vdim[0] != 1)
SERR3("'%.50s' must be scalar, not %d x %d",
KNAME(DSCALE), Aniso->vdim[0], Aniso->vdim[1]);
if (cov->key==NULL) {
ASSERT_QUASIONESYSTEM;
if ((err = CHECK(sub, OWNLOGDIM(0), OWNXDIM(0),
SYSTYPE(OWN, 0), OWNDOM(0),
owniso, SUBMODEL_DEP, cov->frame)) != NOERROR) {
RETURN_ERR(err);
}
if (!isNormalMixture(next))
SERR("scale function only allowed for normal mixtures.");
}
// APMI(cov);
cov->pref[Nugget] = cov->pref[RandomCoin] = cov->pref[Average] =
cov->pref[Hyperplane] = cov->pref[SpectralTBM] = cov->pref[TBM] =
PREF_NONE;
sub->pref[CircEmbed] = sub->pref[CircEmbedCutoff] =
sub->pref[CircEmbedIntrinsic] = sub->pref[Sequential] =
sub->pref[Specific] = PREF_NONE;
} else if (!PisNULL(DANISO)) { // CASE 3, anisotropy matrix is given
int
nrow = cov->nrow[DANISO],
ncol = cov->ncol[DANISO];
if (nrow==0 || ncol==0) SERR("dimension of the matrix is 0");
if (!PisNULL(DPROJ)) RETURN_ERR(ERRORANISO_T);
int xdimown = OWNTOTALXDIM;
if (xdimown != nrow) {
if (PL >= PL_ERRORS) {LPRINT("xdim=%d != nrow=%d\n", xdimown, nrow);}
SERR("#rows of anisotropy matrix does not match dim. of coordinates");
}
if (xdimown != OWNLOGDIM(0) && nrow != ncol)
SERR("non-quadratic anisotropy matrices only allowed if dimension of coordinates equals spatio-temporal dimension");
// PMI0(cov);
// printf("nrow=%d %d\n", nrow, ncol);
mtype = Type(P(DANISO), nrow, ncol);
cov->full_derivs = cov->rese_derivs = 0;
cov->loggiven = wahr;
if (last == 0 || isSpaceIsotropic(OWN)) {
if (!equalsSpaceIsotropic(OWN)) {
switch (owniso) {
case ISOTROPIC :
if (OWNXDIM(0) != 1) RETURN_ERR(ERRORANISO);
cov->full_derivs = cov->rese_derivs = 2;
break;
case VECTORISOTROPIC :
if (!isMiso(mtype)) RETURN_ERR(ERRORANISO);
break;
case SYMMETRIC: case CARTESIAN_COORD :
break;
case PREVMODEL_I : BUG;
case GNOMONIC_PROJ : case ORTHOGRAPHIC_PROJ:
if (!isnowProcess(cov)) RETURN_ERR(ERRORANISO);
break;
default :
if (isCartesian(owniso)) { BUG; }
else RETURN_ERR(ERRORANISO);
}
if (!isMiso(mtype)) cov->pref[SpectralTBM] = cov->pref[TBM] = PREF_NONE;
ASSERT_ONESYSTEM;
err = CHECK(sub, ncol, ncol, SYSTYPE(OWN, 0), OWNDOM(0),
ncol==1 && !isnowProcess(cov)
? IsotropicOf(owniso) : owniso,
SUBMODEL_DEP, cov->frame);
} else {
// spaceisotropic
/*
case DOUBLEISOTROPIC :
cov->full_derivs = cov->rese_derivs = isMdiag(mtype) ? 2 : 0;
if (nrow != 2 || !isMdiag(mtype)) {
SERR("spaceisotropy needs a 2x2 diagonal matrix");
}
break;
*/
cov->full_derivs = cov->rese_derivs = isMdiag(mtype) ? 2 : 0;
if (nrow != 2 || !isMdiag(mtype))
SERR("spaceisotropy needs a 2x2 diagonal matrix");
if (nrow != ncol) BUG;
COPYALLSYSTEMS(PREVSYSOF(sub), OWN, false);
err = CHECK_GEN(sub, SUBMODEL_DEP, SUBMODEL_DEP, cov->frame, false);
}
if (err != NOERROR) RETURN_ERR(err);
} else { // more than 1 coordinate system
if (!isMdiag(mtype) )
SERR1("If several coordinate systems are envolved, currently '%.50s' can only be a diagonal matrix", KNAME(DANISO));
COPYALLSYSTEMS(PREVSYSOF(sub), OWN, false);
if ((err = CHECK_GEN(sub, SUBMODEL_DEP, SUBMODEL_DEP, cov->frame, false))
!= NOERROR) {
RETURN_ERR(err);
}
cov->pref[SpectralTBM] = cov->pref[TBM] = PREF_NONE;
/*
if (!isMdiag(mtype))
cov->pref[Nugget] = cov->pref[RandomCoin] = cov->pref[Average] = cov->pref[Hyperplane] = PREF_NONE;
if (owniso != DOUBLEISOTROPIC && !isMiso(mtype))
cov->pref[SpectralTBM] = cov->pref[TBM] = PREF_NONE;
if ((err = CHECK(suib, ncol, ncol, cov->typus, OWNDOM(0),
ncol==1 && !isProcess(cov->typus) ? ISOTROPIC : owniso,
SUBMODEL_DEP, cov->frame))
!= NOERROR) {
RETURN_ERR(err);
}
*/
}
if (!isMdiag(mtype))
cov->pref[Nugget] = cov->pref[RandomCoin] = cov->pref[Average] =
cov->pref[Hyperplane] = PREF_NONE;
} else if (!PisNULL(DPROJ)) { // geaendert werden: xdim, logdim, iso
COPYALLSYSTEMS(PREVSYSOF(sub), OWN, false);
int xdim = OWNTOTALXDIM,
p = PINT(DPROJ)[0]; // OK
FREE(PPROJ);
if (p > 0) {
Nproj = cov->nrow[DPROJ]; // #define Nproj
int bytes = sizeof(int) * Nproj;
PPROJ = (int*) MALLOC(bytes);
MEMCOPY(PPROJ, PINT(DPROJ), bytes); // #define PPROJ
} else {
int nproj = cov->nrow[DPROJ]; // OK // #define Nproj
if (nproj != 1)
SERR1("values 'space' and 'time' in argument '%.50s' do not allow additional values", KNAME(DPROJ));
if (!(Loc(cov)->Time && xdim >= 2 &&
(isCartesian(OWNISO(last))
#if MAXSYSTEMS == 1
|| (isAnySpherical(PREVISO(0)) && PREVXDIM(0) > 2)
#endif
)))
SERR1("unallowed use of '%.50s' or model too complicated.", KNAME(DPROJ));
bool Space = p == PROJ_SPACE;
assert(Space || p == PROJ_TIME);
if (Space) {
Nproj = xdim - 1;
PPROJ = (int*) MALLOC(sizeof(int) * Nproj);
for (int i=1; i<=Nproj; i++) PPROJ[i-1] = i;
} else { // Time
Nproj = 1;
PPROJ = (int*) MALLOC(sizeof(int) * Nproj);
PPROJ[0] = xdim;
}
}
xdimNeu = Nproj;
int max = xdim;
if (xdimNeu == 0) SERR("Projection to null space not allowed.");
if (xdimNeu < xdim) {
cov->pref[CircEmbed] = cov->pref[CircEmbedCutoff] =
cov->pref[CircEmbedIntrinsic] = cov->pref[Direct] =
cov->pref[Sequential] = 1;
cov->pref[TBM] = cov->pref[SpectralTBM] = cov->pref[Average]
= cov->pref[Nugget]= cov->pref[RandomCoin] = cov->pref[Hyperplane]
= PREF_NONE;
cov->pref[Specific] = PREF_BEST;
}
/// hier Aenderung ab version 3.2.2 so dass spaceisotropic
// nicht mehr ueber 2 coordinatensysteme dargestellt werden kann
int nproj = Nproj;
for (int i=0; i<nproj; i++) {
int idx = PPROJ[i];
if (idx < 1) SERR1("only positive values allowed for '%.50s'", KNAME(DPROJ))
else if (idx > max) SERR2("value of %.50s[%d] too large", KNAME(DPROJ), i);
for (int j=i+1; j<nproj; j++) {
int jdx = PPROJ[j];
if (jdx == idx) SERR1("values of '%.50s' must be distinct.", KNAME(DPROJ));
}
}
set_xdim(PREVSYSOF(sub), 0, xdimNeu);
set_logdim(PREVSYSOF(sub), 0, xdimNeu);
if (equalsSpaceIsotropic(OWN)) {
// printf("%d %d\n", xdimNeu, nproj);
if (xdimNeu > 2) SERR("maximum length of projection vector is 2");
if (xdimNeu == 2) {
if (PPROJ[0] >= PPROJ[1])
SERR1("in case of '%.50s' projection directions must be ordered",
ISO_NAMES[DOUBLEISOTROPIC]);
} else {
#if MAXSSYSTEMS == 1
RETURN_ERR(ERRORWRONGISO);
#else
assert(xdimNeu == 1);
set_iso(PREVSYSOF(sub), 0, ISOTROPIC);
if (PPROJ[0] == 1) { // space
set_logdim(PREVSYSOF(sub), 0, OWNLOGDIM(0) - 1);
} else { // time
// PMI0(cov);
// printf("%d %d\n", PPROJ[0], OWNLOGDIM(0));
assert(PPROJ[0] == 2);
set_logdim(PREVSYSOF(sub), 0, 1);
}
#endif
}
} else {// ! spaceisotropic
switch (OWNISO(0)) {
case ISOTROPIC : case EARTH_ISOTROPIC : case SPHERICAL_ISOTROPIC :
if (OWNXDIM(0) != 1) RETURN_ERR(ERRORANISO);
break;
case VECTORISOTROPIC :
SERR("projection of vectorisotropic fields not programmed yet"); // to do: vdim muss auch reduziert werden ... --- das wird
// grausam !
break;
case SYMMETRIC: case CARTESIAN_COORD:
break;
case GNOMONIC_PROJ : case ORTHOGRAPHIC_PROJ :
set_iso(PREVSYSOF(sub), 0, CARTESIAN_COORD);
break;
case PREVMODEL_I : BUG;
break;
case SPHERICAL_SYMMETRIC : case EARTH_SYMMETRIC :
if (nproj != 2 || PPROJ[0] != 1 || PPROJ[1] != 2) {
for (int ii=0; ii<nproj; ii++)
if (PPROJ[ii] <= 2) APMI0(cov); // RETURN_ERR(ERRORANISO);
/// ehemals owniso = SYMMETRIC; -- ueberall owniso
set_iso(PREVSYSOF(sub), 0, SYMMETRIC);
}
break;
case SPHERICAL_COORD : case EARTH_COORD :
if (nproj != 2 || PPROJ[0] != 1 || PPROJ[1] != 2) {
for (int ii=0; ii<nproj; ii++) // ??
if (PPROJ[ii] <= 2) RETURN_ERR(ERRORANISO);
set_iso(PREVSYSOF(sub), 0, CARTESIAN_COORD);
}
break;
default :
if (isCartesian(OWNISO(0))) {BUG;}
else return ERRORANISO; // todo
}
}
// if ((err = CHECK(sub, nproj, nproj, OWNTYPE(0), OWNDOM(0), owniso,
// SUBMODEL_DEP, cov->frame)) != NOERROR) RETURN_ERR(err);
if ((err = CHECK_GEN(sub,
VDIM0, // SUBMODEL_DEP; geaendert 20.7.14
VDIM1, cov->frame, true)) != NOERROR) {
//APMI(cov->calling->calling);
RETURN_ERR(err);
}
} else { // nproj == 0
// printf("checkS u!!\n");
COPYALLSYSTEMS(PREVSYSOF(sub), OWN, false);
// verhindern, dass die coordinaten-transformation anlaeuft,
// da aus z.B. Erd-coordinaten durch Projektion (auf die Zeitachse)
// kartesische werden
if ((err = CHECK_GEN(sub,
VDIM0, // SUBMODEL_DEP; geaendert 20.7.14
VDIM1, cov->frame, true)) != NOERROR) {
// printf("\n\n\n\n\nRMS err = %d\n", err); APMI(sub);
RETURN_ERR(err);
}
/* if (cov->key==NULL) {
if ((err = CHECK_NO_TRAFO(next, tsdim, xdim Neu, cov->typus, OWNDOM(0),
owniso,
VDIM0, // SUBMODEL_DEP; geaendert 20.7.14
cov->frame)) != NOERROR) {
RETURN_ERR(err);
}
if (next->domown == OWNDOM(0) &&
next->owniso == owniso) // darf nicht nach C-HECK als allgemeine Regel ruebergezogen werden, u.a. nicht wegen stat/nicht-stat wechsel !!
// hier geht es, da domown und owniso nur durchgegeben werden und die Werte // bereits ein Schritt weiter oben richtig/minimal gesetzt werden.
} else {
if ((err = CHECK_NO_TRAFO(cov->key, tsdim, xdimN eu, cov->typus,
OWNDOM(0), owniso,
SUBMODEL_DEP, cov->frame)) != NOERROR) RETURN_ERR(err);
}
// PMI(cov);
*/
} // end no aniso ((end of CASE 4))
// printf("checkS 664!!\n");
if (( err = checkkappas(cov, false)) != NOERROR) {
RETURN_ERR(err);
}
// printf("checkS 4!!\n");
setbackward(cov, sub);
for (int s=0; s<=last; s++) set_maxdim(OWN, s, OWNLOGDIM(s));
if ((Aniso != NULL || (Scale != NULL && !isnowRandom(Scale)) ||
!PisNULL(DANISO) || !PisNULL(DPROJ))) {
for (int s=0; s<=last; s++) {
int max = MAXDIM(SUB, s);
if (MAXDIM(OWN, s) < max) set_maxdim(OWN, s, max);
}
}
if ((!isAnyIsotropic(owniso) && !isDollarProc(cov)) || last > 0){
// multivariate kann auch xdimNeu == 1 problematisch sein
set_nr(OWN, COVNR + 1); // JA NICHT SET_NR!!
}
// if (!isAnyIsotropic(owniso) && !isDollarProc(cov)) { // multivariate kann auch xdimNeu == 1 problematisch sein
// COVNR++;
// }
if (xdimNeu > 1) {
cov->pref[CircEmbedCutoff] = cov->pref[CircEmbedIntrinsic] = 0;
}
// 30.10.11 kommentiert:
// cov->pref[CircEmbedCutoff] = cov->pref[CircEmbedIntrinsic] =
// cov->pref[TBM] = cov->pref[SpectralTBM] = 0;
if ( (PisNULL(DANISO) || isMiso(mtype)) && PisNULL(DPROJ)) {
cov->logspeed = sub->logspeed * P0(DVAR);
}
////////////////
if (sub->pref[Nugget] > PREF_NONE) cov->pref[Specific] = 100;
if (PisNULL(DPROJ)) cov->matrix_indep_of_x = sub->matrix_indep_of_x;
if ((err = TaylorS(cov)) != NOERROR) RETURN_ERR(err);
cov->Sdollar->simplevar = simplevar;
ASSERT_ONESYSTEM;
cov->Sdollar->orig_owniso = owniso; // for struct Sproc !
if (isnowProcess(cov)) {
MEMCOPY(cov->pref, PREF_NOTHING, sizeof(pref_shorttype));
}
if (GLOBAL.coords.coord_system == earth &&
(PisNULL(DPROJ) ||
(PPROJ[0] != PROJ_TIME && (Nproj != 1 || PPROJ[0] <= 2))) &&
isCartesian(DEFSYS(next)) &&//is_all(isCartesian, DefList + NEXTNR) &&
GLOBAL.internal.warn_scale &&
(PisNULL(DSCALE) ||
P0(DSCALE) < (STRCMP(GLOBAL.coords.newunits[0], "km")== 0 ? 10 : 6.3))) {
GLOBAL.internal.warn_scale = false;
PRINTF("Value of the scale parameter equals '%4.2f', which is less than 100,\nalthough models defined on R^3 are used in the context of earth coordinates,\nwhere larger scales are expected. (This message appears only ones per session.)\n", PisNULL(DSCALE) ? 1.0 : P0(DSCALE));
}
// printf("checkS! end!\n");
//PMI0(cov);
RETURN_NOERROR;
}
bool allowedDS(model *cov) {
model
*Aniso =cov->kappasub[DANISO] == NULL ? cov->kappasub[DAUSER]
: cov->kappasub[DANISO], // nur cartesian, nur kernel (ausser angle)
*Daniso = cov->kappasub[DANISO],
*Scale = cov->kappasub[DSCALE], // && !isRandom(Scale) if (!isDollarProc(cov) && !isKernel(OWN)) RETURN_ERR(ERRORFAILED); NUR cartesian
*Var = cov->kappasub[DVAR];
bool angle = isAngle(Aniso) || isAngle(Daniso),
*D = cov->allowedD;
if ((Scale != NULL && !isRandom(Scale) && !isDollarProc(cov) ) ||
(Aniso != NULL && !angle) || // angle erlaubt XONLY!
(Var != NULL && ! isRandom(Var))) {
assert(LAST_DOMAINUSER == 1);
D[XONLY] = false;
D[KERNEL] = true;
return false;
}
return allowedDstandard(cov);
}
bool allowedIS(model *cov) {
model
*Aniso = cov->kappasub[DANISO] == NULL ? cov->kappasub[DAUSER]
: cov->kappasub[DANISO], // nur cartesian, nur kernel (auch angle)
*Daniso = cov->kappasub[DANISO],
*Scale = cov->kappasub[DSCALE], // && !isRandom(Scale) if (!isDollarProc(cov) && !isKernel(OWN)) RETURN_ERR(ERRORFAILED); NUR cartesian
*Var = cov->kappasub[DVAR];
bool ScaleAniso = (Scale != NULL && !isRandom(Scale)) || Aniso != NULL ||
Daniso != NULL,
//angle = isAngle(Aniso),
var = Var != NULL && !isRandom(Var);
bool *I = cov->allowedI;
bool allowed = allowedIstandard(cov);
if (allowed) for (int i=FIRST_ISOUSER; i<=LAST_ISOUSER; I[i++] = true);
//
//for (int i=0; i<LAST_ISOUSER; i++) printf("%d ", I[i]); BUG;
// assert(!angle);
// printf("%d %d %d\n", Scale != NULL && !isRandom(Scale), Aniso != NULL || Daniso != NULL, !angle);
// APMI(cov);
int nproj = cov->nrow[DPROJ], // OK // #define Nproj
*proj = PINT(DPROJ);// #define PPROJ
if (nproj>0) {
allowed = false;
assert(SYMMETRIC == 2 + DOUBLEISOTROPIC);
bool hasprev = PREV_INITIALISED;
isotropy_type previso = hasprev ? PREVISO(0) : ISO_MISMATCH;
bool anyEarth = hasprev && (isEarth(previso) || isSpherical(previso)),
time = proj[0] == PROJ_TIME || (nproj == 1 && proj[0] == OWNLOGDIM(0));
if (!time && anyEarth) {
int min = proj[0];
for (int i=1; i<nproj; i++) if (proj[i] < min) min = proj[i];
time = min > 2;
}
if (time) {
cov->IallowedDone = false;
if (anyEarth && !isAnyIsotropic(previso))
set_iso(PREV, 0,
equalsAnySymmetric(previso) ? SYMMETRIC : CARTESIAN_COORD);
if (hasprev && (!anyEarth || PREVLOGDIM(0)<=2)) {
for (int i = 1 + (int) CARTESIAN_COORD; i <= (int) LAST_ISOUSER;
I[i++]=false);
}
}
}
// aniso matrix
if (ScaleAniso || var) {
allowed = false;
int i = (int) FIRST_ISOUSER,
last = //angle ? SYMMETRIC :
CARTESIAN_COORD;
while (i <= last && !I[i]) i++;
I[last] = i <= last;
for ( ; i < (int) last; I[i++] = false);
if (ScaleAniso) {
for (i = 1 + (int)CARTESIAN_COORD; i <= (int) LAST_ISOUSER; I[i++]=false);
return false;
} else {
i = (int) FIRST_EARTH;
while (i <= (int) EARTH_COORD && !I[i]) i++;
I[EARTH_COORD] = i <= EARTH_COORD;
for ( ; i < (int) EARTH_COORD; I[i++] = false);
i = (int) FIRST_SPHERICAL;
while (i <= (int) SPHERICAL_COORD && !I[i]) i++;
I[SPHERICAL_COORD] = i <= SPHERICAL_COORD;
for ( ; i < (int) SPHERICAL_COORD; I[i++] = false);
}
}
else if ((!PisNULL(DANISO) /* internal */ && cov->nrow[DANISO] > 1) ||
(!PisNULL(DAUSER) && cov->ncol[DAUSER] > 1) || nproj > 0){
allowed = false;
int i = (int) FIRST_ISOUSER;
while (i <= (int) SYMMETRIC && !I[i]) i++;
I[SYMMETRIC] = i <= SYMMETRIC;
for ( ; i < (int) SYMMETRIC; I[i++] = false);
I[EARTH_SYMMETRIC] |= I[EARTH_ISOTROPIC];
I[EARTH_ISOTROPIC] = false;
I[SPHERICAL_SYMMETRIC] |= I[SPHERICAL_ISOTROPIC];
I[SPHERICAL_ISOTROPIC] = false;
if (GetTime(cov)) {
I[DOUBLEISOTROPIC] = (!PisNULL(DANISO) && cov->nrow[DANISO] == 2) ||
(!PisNULL(DAUSER) && cov->ncol[DAUSER] == 2) ||
nproj > 0; // nicht sehr praezise...
}
}
return allowed;
}
void rangeS(model *cov, range_type* range){
int i;
bool negdef = isnowNegDef(cov);
range->min[DVAR] = negdef ? 0.0 : RF_NEGINF;
range->max[DVAR] = RF_INF;
range->pmin[DVAR] = negdef ? 0.0 : -10000;
range->pmax[DVAR] = 100000;
range->openmin[DVAR] = !negdef;
range->openmax[DVAR] = true;
range->min[DSCALE] = 0.0;
range->max[DSCALE] = RF_INF;
range->pmin[DSCALE] = 0.0001;
range->pmax[DSCALE] = 10000;
range->openmin[DSCALE] = true;
range->openmax[DSCALE] = true;
for (i=DANISO; i<= DAUSER; i++) {
range->min[i] = RF_NEGINF;
range->max[i] = RF_INF;
range->pmin[i] = - 10000;
range->pmax[i] = 10000;
range->openmin[i] = true;
range->openmax[i] = true;
}
range->min[DPROJ] = -2;
range->max[DPROJ] = GATTERTOTALXDIM;
range->pmin[DPROJ] = 1;
range->pmax[DPROJ] = range->max[DPROJ];
range->openmin[DPROJ] = false;
range->openmax[DPROJ] = false;
}
Types TypeS(Types required, model *cov, isotropy_type required_iso){
bool ok =(COVNR != DOLLAR_PROC &&
(isShape(required) || isTrend(required) || equalsRandom(required)))
|| (COVNR == DOLLAR_PROC && isProcess(required));
// printf("ok=%d\n", ok);
if (!ok) return BadType;
model *sub = cov->key==NULL ? cov->sub[0] : cov->key;
return TypeConsistency(required, sub, required_iso);
}
void spectralS(model *cov, gen_storage *s, double *e) {
model *next = cov->sub[DOLLAR_SUB];
int d,
ncol = PisNULL(DANISO) ? OWNLOGDIM(0) : cov->ncol[DANISO];
double sube[MAXTBMSPDIM],
*scale =P(DSCALE),
invscale = 1.0;
SPECTRAL(next, s, sube); // nicht gatternr
// Reihenfolge nachfolgend extrem wichtig, da invscale auch bei aniso
// verwendet wird
if (scale != NULL) invscale /= scale[0];
if (!PisNULL(DANISO)) {
int
nrow = cov->nrow[DANISO];
long j, k, m,
total = ncol * nrow;
double
*A = P(DANISO);
for (d=0, k=0; d<nrow; d++, k++) {
e[d] = 0.0;
for (m=0, j=k; j<total; j+=nrow) {
e[d] += sube[m++] * A[j] * invscale;
}
}
} else {
for (d=0; d<ncol; d++) e[d] = sube[d] * invscale;
}
}
void ScaleDollarToLoc(model *to, model *from,
int VARIABLE_IS_NOT_USED depth) {
assert(!PARAMisNULL(to, LOC_SCALE));
assert(isDollar(from));
assert(!PARAMisNULL(from, DSCALE));
PARAM(to, LOC_SCALE)[0] = PARAM0(from, DSCALE);
}
bool ScaleOnly(model *cov) {
return isDollar(cov) &&
PisNULL(DPROJ) && cov->kappasub[DPROJ] == NULL &&
PisNULL(DAUSER) && cov->kappasub[DAUSER] == NULL &&
PisNULL(DANISO) && cov->kappasub[DANISO] == NULL &&
(PisNULL(DVAR) || P0(DVAR)==1.0) && cov->kappasub[DVAR] == NULL;
}
int addScales(model **newmodel, model *calling, model *Scale, double scale) {
if (scale != 1.0) {
addModel(newmodel, LOC, calling);
kdefault(*newmodel, LOC_SCALE, scale);
}
if (Scale != NULL) { // could happen that scale != 1.0 && Scale != NULL
// since scale includes also scale from aniso
if (!isnowRandom(Scale)) RETURN_ERR_COV(Scale, XERRORNONSTATSCALE);
addModel(newmodel, LOC, calling);
addSetDistr(newmodel, Scale->calling, ScaleDollarToLoc, true, MAXINT);
}
return NOERROR;
}
int addPGSLocal(model **Key, // struct of shape
model *shape,// shape itself
model *local_pts,
int dim, int vdim, Types frame) {
// SEE ALSO addPGS in extremes.cc
/// random coin und smith
// versucht die automatische Anpassung einer PointShapeType-Funktion;
// derzeit wird
// * PGS und
// * STANDARD_SHAPE (weiss nicht mehr wieso -> coins?)
// versucht; inklusive Init
//
// ruft t.w. FillInPts auf
#define specific (nPOISSON_SCATTER - 1)
bool maxstable = hasMaxStableFrame(shape);
int i,
err = NOERROR,
method = GLOBAL.extreme.scatter_method,
pgs[specific] = {maxstable ? ZHOU : BALLANI, STANDARD_SHAPE};
#define infoN 200
char info[nPOISSON_SCATTER - 1][LENERRMSG];
assert(shape != NULL);
assert(*Key == NULL);
// to do: strokorbball: raeumlich waere Standard/Uniform besser;
// praeferenzen programmieren?
for (i=0; i<specific; i++) {
if (method != POISSON_SCATTER_ANY && method != i) continue;
if (i > 0) {
errorMSG(err, info[i-1]);
// XERR(err); // eigentlich muss das hier weg
}
// if (i > 0) XERR(err); assert(i ==0);
if (*Key != NULL) COV_DELETE(Key, shape);
assert(shape->calling != NULL);
addModel(Key, pgs[i], shape->calling);
if ((err = FillInPts(*Key, shape)) != NOERROR) continue;
if (MODELNR(*Key) != ZHOU) continue;
model *local, *dummy,
*cov = *Key;
if ((err = covcpy(&local, false, local_pts, shape->prevloc, NULL,
true, true, false)) != NOERROR) RETURN_ERR(err);
SET_CALLING(local, (*Key)->calling);
dummy = local;
while (dummy->sub[DOLLAR_SUB] != NULL) dummy = dummy->sub[DOLLAR_SUB];
if (MODELNR(dummy) != LOC) BUG;
dummy->sub[DOLLAR_SUB] = *Key;
SET_CALLING(*Key, dummy);
SET_CALLING(cov, shape->calling);
SET_CALLING(cov->sub[PGS_FCT], cov);
SET_CALLING(cov->sub[PGS_LOC], cov);
assert(cov->sub[PGS_LOC] != NULL && cov->sub[PGS_FCT] != NULL);
cov->nsub = 2;
if ((err = CHECK(*Key, dim, dim, PointShapeType, XONLY,
CoordinateSystemOf(ISO(SYSOF(shape), 0)),
vdim, frame)) != NOERROR) {
continue;
}
NEW_COV_STORAGE(cov, gen);
if ((err = INIT(cov, 1, cov->Sgen)) == NOERROR) break;
} // for i_pgs
model *cov = *Key;
if (err != NOERROR) {
SERR("error occured when creating the local point-shape fctn");
// errorstring_type xx = "error occured when creating a local point-shape fctn";
// errorMSG(err, xx, cov->base, info[i-1]);
// SERR2("no method found to simulate the given model:\n\tpgs: %.50s\n\tstandard: %.50s)", info[0], info[1]);
}
RETURN_NOERROR;
}
int structS(model *cov, model **newmodel) {
if (isnowProcess(cov)) {
assert(hasGaussMethodFrame(cov));
SET_NR(cov, DOLLAR_PROC);
return structSproc(cov, newmodel); // kein S-TRUCT(...) !!
}
model *local = NULL,
*dummy = NULL,
*next = cov->sub[DOLLAR_SUB],
*Aniso = cov->kappasub[DANISO] == NULL ? cov->kappasub[DAUSER]
: cov->kappasub[DANISO],
*Scale = cov->kappasub[DSCALE];
int err = NOERROR;
bool generalAniso = (Aniso != NULL && !isAngle(Aniso)) ||
(Scale != NULL && !isnowRandom(Scale));
if (generalAniso)
GERR1("complicated models including arbitrary functions for '%.50s' cannot be simulated yet", KNAME(DAUSER));
ASSERT_NEWMODEL_NOT_NULL;
if (cov->kappasub[DVAR] != NULL) {
GERR2("Arbitrary functions for '%.50s' should be replaced by multiplicative models using '%.50s'", KNAME(DVAR), DefList[PROD].nick);
}
switch (cov->frame) {
case PoissonGaussType :
BUG;
break;
case SmithType : {
ASSERT_ONESYSTEM;
ASSERT_NEWMODEL_NOT_NULL; // ?
if (next->randomkappa) GERR("random shapes not programmed yet");
if (!PisNULL(DANISO)){err=ERRORANISO; goto ErrorHandling;}
if (!PisNULL(DANISO)) {
if (!isMonotone(next) || !isIsotropicXonly(next) ||
PisNULL(DANISO) || cov->ncol[DANISO] != cov->nrow[DANISO])
GERR("anisotropy parameter only allowed for simple models up to now");
}
if (!PisNULL(DPROJ)) GERR("projections not allowed yet");
if ((err = STRUCT(next, newmodel)) > NOERROR) RETURN_ERR(err);
assert(*newmodel != NULL);
double anisoScale = 1.0;
if (!PisNULL(DANISO)) {
anisoScale = 1.0 / getMinimalAbsEigenValue(P(DANISO), cov->nrow[DANISO]);
if (!R_FINITE(anisoScale)) {err=ERRORANISO_INV; goto ErrorHandling;}
if (anisoScale < 0) {
err = -anisoScale;
goto ErrorHandling;
}
}
Types type = BadType;
double scale = PisNULL(DSCALE) ? 1.0 :P0(DSCALE);
int logdim = OWNLOGDIM(0),
xdim = OWNXDIM(0);
// in same cases $ must be set in front of a pointshape function
// and becomes a pointshape function too, see addpointshapelocal here
if (isPointShape(*newmodel)) type = PointShapeType;
else if ((err = CHECK_R(*newmodel, logdim)) == NOERROR) {
type = RandomType;
if ((err=addScales(newmodel, *newmodel, Scale, scale * anisoScale))
!=NOERROR) goto ErrorHandling;
SET_CALLING(*newmodel, cov);
}
if (!equalsRandom(type)) {
type = type == BadType ? ShapeType : type;
if ((err = CHECK(*newmodel, logdim, xdim, type, OWNDOM(0), OWNISO(0),
cov->vdim, cov->frame)) != NOERROR)
goto ErrorHandling;
// crash();
BUG;
// ?? addModel(newmodel, DOLLAR); // 2.2.19
// ??assert( (*newmodel)->calling == cov);
// ?? if (!PisNULL(DVAR)) kdefault(*newmodel, DVAR, P0(DVAR));
// ?? double scale = 1.0;
// if (!PisNULL(DSCALE)) {
// kdefault(*newmodel, DSCALE, P0(DSCALE));
// scale = P0(DSCALE);}
if (type == PointShapeType &&
(err = addScales((*newmodel)->sub + PGS_LOC, *newmodel,
Scale, anisoScale *
scale)) != NOERROR) goto ErrorHandling;
if ((err = CHECK(*newmodel, OWNLOGDIM(0), PREVXDIM(0), type,
PREVDOM(0), PREVISO(0), cov->vdim,
cov->frame))
!= NOERROR) goto ErrorHandling;
if (type==PointShapeType) {
if ((err = FillInPts(*newmodel, cov)) != NOERROR) goto ErrorHandling;
} else {
dummy = *newmodel;
*newmodel = NULL;
// suche nach geeigneten locationen
if ((err = addScales(&local, dummy, Scale, scale * anisoScale))
!= NOERROR) goto ErrorHandling;
if ((err = addPGSLocal(newmodel, dummy, local,
OWNLOGDIM(0), VDIM0, cov->frame))
!= NOERROR) goto ErrorHandling;
}
} // ! randomtype
}
break;
case SchlatherType: case BrMethodType:
if (next->randomkappa) GERR("random shapes not programmed yet");
if (!PisNULL(DPROJ)) GERR("projections not allowed yet");
// P(DVAR) hat keine Auswirkungen
if (!PisNULL(DANISO)) {
if (!isMonotone(next) || !isIsotropicXonly(next) ||
PisNULL(DANISO) || cov->ncol[DANISO] != cov->nrow[DANISO])
GERR("anisotropy parameter only allowed for simple models up to now");
}
assert(cov->calling != NULL);
BUG;
//
if ((err = STRUCT(next, newmodel)) > NOERROR) RETURN_ERR(err);
break;
case GaussMethodType :
if (cov->key != NULL) COV_DELETE(&(cov->key), cov);
if (PrevLoc(cov)->distances)
GERR("distances do not allow for more sophisticated simulation methods");
if ((err = STRUCT(next, newmodel)) > NOERROR) RETURN_ERR(err);
assert(*newmodel != NULL);
addModel(newmodel, DOLLAR);
if (!PisNULL(DVAR)) kdefault(*newmodel, DVAR, P0(DVAR));
if (!PisNULL(DSCALE) ) kdefault(*newmodel, DSCALE, P0(DSCALE));
if (next->randomkappa) GERR("random shapes not programmed yet");
break;
default :
BUG;
GERR2("%.50s : changes in scale/variance not programmed yet for '%.50s'",
NICK(cov), TYPE_NAMES[cov->frame]);
}
ErrorHandling:
if (dummy != NULL) COV_DELETE(&dummy, cov);
if (local != NULL) COV_DELETE(&local, cov);
RETURN_ERR(err);
}
int initS(model *cov, gen_storage *s){
// am liebsten wuerde ich hier die Koordinaten transformieren;
// zu grosser Nachteil ist dass GetDiameter nach trafo
// grid def nicht mehr ausnutzen kann -- umgehbar?!
model *next = cov->sub[DOLLAR_SUB],
*Var = cov->kappasub[DVAR],
*Scale = cov->kappasub[DSCALE],
*Aniso = cov->kappasub[DANISO] == NULL ? cov->kappasub[DAUSER]
: cov->kappasub[DANISO],
*projM = cov->kappasub[DPROJ];
int
vdim = VDIM0,
nm = cov->mpp.moments,
nmvdim = (nm + 1) * vdim,
err = NOERROR;
bool
angle = isAngle(Aniso),
smith = hasSmithFrame(cov);// Realisationsweise
if (smith || hasAnyPoissonFrame(cov)) {//Average !!ohne smith selbst!!
ASSERT_ONESYSTEM;
double
var[MAXMPPVDIM],
scale = PisNULL(DSCALE) ? 1.0 : P0(DSCALE);
int dim = OWNLOGDIM(0);
if (!PisNULL(DPROJ) || !PisNULL(DANISO) ||
projM!= NULL || (Aniso != NULL && (!angle || Aniso->randomkappa))){
SERR("(complicated) anisotropy ond projection not allowed yet in Poisson related models");
}
// Achtung I-NIT_RANDOM ueberschreibt mpp.* !!
if (Var != NULL) {
int nm_neu = nm == 0 && !smith ? 1 : nm;
if ((err = INIT_RANDOM(Var, nm_neu, s, P(DVAR))) != NOERROR) RETURN_ERR(err);
int nmP1 = Var->mpp.moments + 1;
for (int i=0; i<vdim; i++) {
int idx = i * nmP1;
var[i] = smith ? P0(DVAR) : Var->mpp.mM[idx + 1];
}
} else for (int i=0; i<vdim; var[i++] = P0(DVAR));
if (Scale != NULL) {
if (dim + nm < 1) SERR("found dimension <= 0");
int dim_neu = smith ? nm : (dim + nm) < 1 ? 1 : dim + nm;
if ((err = INIT_RANDOM(Scale, dim_neu, s, P(DSCALE)))
!= NOERROR) RETURN_ERR(err);
scale = smith ? P0(DSCALE) : Scale->mpp.mM[1];
}
if ((err = INIT(next, nm, s)) != NOERROR) RETURN_ERR(err);
for (int i=0; i < nmvdim; i++) {
cov->mpp.mM[i] = next->mpp.mM[i];
cov->mpp.mMplus[i] = next->mpp.mMplus[i];
}
if (Var != NULL && !smith) {
for (int i=0; i < nmvdim; i++) {
cov->mpp.mM[i] *= Var->mpp.mM[i];
cov->mpp.mMplus[i] *= Var->mpp.mMplus[i];
}
} else {
int j, k;
double pow_var;
for (k=j=0; j<vdim; j++) {
pow_var = 1.0;
for (int i=0; i <= nm; i++, pow_var *= var[j], k++) {
cov->mpp.mM[k] *= pow_var;
cov->mpp.mMplus[k] *= pow_var;
}
}
}
if (Scale != NULL && !smith) {
if (Scale->mpp.moments < dim) SERR("moments can not be calculated.");
int j, k,
nmP1 = Scale->mpp.moments + 1;
for (k=j=0; j<vdim; j++) {
double pow_scale = Scale->mpp.mM[dim + j * nmP1];
for (int i=0; i <= nm; i++, k++) {
cov->mpp.mM[k] *= pow_scale;
cov->mpp.mMplus[k] *= pow_scale;
}
}
} else {
double pow_scale = POW(scale, dim);
for (int i=0; i < nmvdim; i++) {
cov->mpp.mM[i] *= pow_scale;
cov->mpp.mMplus[i] *= pow_scale;
}
}
if (!PisNULL(DANISO)) {
if (cov->nrow[DANISO] != cov->ncol[DANISO]) RETURN_ERR(ERRORANISO_SQUARE);
double invdet = FABS(1.0 / getDet(P(DANISO), cov->nrow[DANISO]));
if (!R_FINITE(invdet)) RETURN_ERR(ERRORANISO_DET);
for (int i=0; i < nmvdim; i++) {
cov->mpp.mM[i] *= invdet;
cov->mpp.mMplus[i] *= invdet;
}
}
if (Aniso != NULL) {
double invdet;
if (angle) {
int
ncol = Aniso->vdim[0],
nrow = Aniso->vdim[1];
if (nrow != ncol) RETURN_ERR(ERRORANISO_SQUARE);
double
*diag = PARAM(Aniso, ANGLE_DIAG);
if (diag != NULL) {
invdet = 1.0;
for (int i=0; i<ncol; i++) invdet /= diag[i];
} else {
invdet = PARAM0(Aniso, ANGLE_RATIO);
}
} else {
SERR("only anisotropy matrices basesd on RMangle allowed.");
}
invdet = FABS(invdet);
if (!R_FINITE(invdet)) RETURN_ERR(ERRORANISO_DET);
for (int i=0; i < nmvdim; i++) {
cov->mpp.mM[i] *= invdet;
cov->mpp.mMplus[i] *= invdet;
}
}
bool unnormed = R_FINITE(next->mpp.unnormedmass);
if (unnormed) {
//printf("unnormedmass in $ %.50s\n", NAME(next));
if (vdim > 1) BUG;
cov->mpp.unnormedmass = next->mpp.unnormedmass * var[0];
} else cov->mpp.unnormedmass = RF_NAN;
if (isnowRandom(next)) {
if (unnormed) for (int i=0; i<vdim; i++) cov->mpp.maxheights[i] = RF_INF;
else RETURN_ERR(ERRORNOTPROGRAMMEDYET);
} else {
for (int i=0; i<vdim; i++)
cov->mpp.maxheights[i] = next->mpp.maxheights[i] * var[i];
}
} // hasSmithFrame
else if (hasGaussMethodFrame(cov) || hasAnyEvaluationFrame(cov)) {
model
*key = cov->key,
*sub = key == NULL ? next : key;
assert(sub != NULL);
assert(key == NULL || ({PMI(cov);false;}));//
if ((err=INIT(sub, 0, s)) != NOERROR) RETURN_ERR(err);
} else {
if ((err=INIT(next, 0, s)) != NOERROR) RETURN_ERR(err); // e.g. from MLE
}
if ((err = TaylorS(cov)) != NOERROR) RETURN_ERR(err);
RETURN_NOERROR;
}
void doS(model *cov, gen_storage *s){
model
*Var = cov->kappasub[DVAR],
*Scale = cov->kappasub[DSCALE];
int vdim = VDIM0;
if (Var != NULL) {
if (isnowRandom(Var)) {
if (isProcess(Var)) BUG;
assert(!PisNULL(DVAR));
DORANDOM(Var, P(DVAR));
} else if (Var->randomkappa) {
assert(!PisNULL(DVAR));
DO(Var, s);
} else BUG;
}
if (Scale != NULL) {
if (isnowRandom(Scale)) {
if (isProcess(Scale)) BUG;
assert(!PisNULL(DSCALE));
DORANDOM(Scale, P(DSCALE));
} else if (Scale->randomkappa) {
BUG;
assert(!PisNULL(DSCALE));
DO(Scale, s);
} else BUG;
}
if (hasSmithFrame(cov) || hasAnyPoissonFrame(cov)) {
model *next = cov->sub[DOLLAR_SUB];
DO(next, s);// nicht gatternr
for (int i=0; i<vdim; i++)
cov->mpp.maxheights[i] = next->mpp.maxheights[i] * P0(DVAR);
return;
}
else if (hasGaussMethodFrame(cov)) {
double
*res = cov->rf,
sd = SQRT(P0(DVAR));
int
totalpoints = Gettotalpoints(cov);
assert(res != NULL);
if (cov->key == NULL) BUG;
if (sd != 1.0) for (int i=0; i<totalpoints; i++) res[i] *= (double) sd;
return;
}
BUG;
}
//////////////////////////////////////////////////////////////////////
// PROCESSES
//////////////////////////////////////////////////////////////////////
int structSproc(model *cov, model **newmodel) {
model
*next = cov->sub[DOLLAR_SUB],
*Scale = cov->kappasub[DSCALE],
*Aniso = cov->kappasub[DANISO] == NULL ? cov->kappasub[DAUSER]
: cov->kappasub[DANISO];
int
dim = GetLoctsdim(cov),
newdim = dim,
err = NOERROR;
// model *sub;
assert(isDollarProc(cov));
assert(newdim > 0);
if ((Aniso != NULL && Aniso->randomkappa) ||
(Scale != NULL && Scale->randomkappa)
) {
SERR1("complicated models including arbitrary functions for '%.50s' cannot be simulated yet", KNAME(DAUSER));
}
switch (cov->frame) {
case GaussMethodType : {
location_type *loc = Loc(cov); // do not move before TransformLoc!!
ASSERT_NEWMODEL_NULL;
if (cov->key != NULL) COV_DELETE(&(cov->key), cov);
if (PrevLoc(cov)->distances)
SERR("distances do not allow for more sophisticated simulation methods");
if (Aniso!= NULL) { // Aniso fctn
TransformLoc(cov, false, True, true);
loc = Loc(cov);
assert(!loc->grid && !loc->Time);
newdim = Aniso->vdim[0];
if (newdim != dim)
ERR("change of dimension in struct S not programmed yet");
int bytes = newdim * sizeof(double);
long total = loc->totalpoints;
double *v = NULL,
*x = loc->x,
*xnew = x; // not correct for newdim != dim;
// instead partial_loc_set should be used to reset loc
assert(x != NULL);
assert(!loc->grid);
if ((v = (double*) MALLOC(bytes)) == NULL) RETURN_ERR(ERRORMEMORYALLOCATION);
for (long i=0; i<total; i++, x+=dim, xnew += newdim) {
FCTN(x, Aniso, v);
MEMCOPY(xnew, v, bytes);
}
FREE(v);
} else if (Scale != NULL) {
// check code wether it will still work
if (isnowRandom(Scale)) {
SERR("no specific simulation technique available for random scale");
}
SERR("no specific simulation technique available for arbitrary scale");
} else {
double scale = PisNULL(DSCALE) ? 1.0 : P0(DSCALE);
cov->Sdollar->separable = !PisNULL(DPROJ) &&
(loc->grid || (loc->Time && PINT(DPROJ)[0] < 0)); // #define PPROJ
if (cov->Sdollar->separable) {
int *proj = PPROJ,
nproj = Nproj;
if (loc->grid || PPROJ[0] == dim) {
double *x = (double*) MALLOC(sizeof(double) * dim * 3);
for (int i=0; i<nproj; i++) {
MEMCOPY(x + i * 3,
proj[i] == dim && loc->Time ? loc->T : loc->xgr[proj[i] -1],
3 * sizeof(double));
x[i * 3 + 1] /= scale;
}
loc_set(x, NULL, NULL, nproj, nproj, 3, 0, false, true, false, cov);
FREE(x);
} else { // space
int i = 0;
for ( ; i<nproj; i++) if (PPROJ[i] != i + 1) break;
if (i >= nproj)
loc_set(loc->x, NULL, NULL,
nproj, nproj,
loc->spatialtotalpoints, 0,
false, loc->grid, false,
cov);
else {
int pts = Getspatialpoints(cov);
long int bytes = sizeof(double) * nproj * pts;
double *x = (double*) MALLOC(bytes),
*xx = x,
*L = loc->x;
for (i=0 ; i<pts; i++, L += dim) {
for (int j=0 ; j<nproj; j++, xx++) *(xx++) = L[proj[j]];
}
loc_set(x, NULL, NULL,
nproj, nproj,
loc->spatialtotalpoints, 0,
false, loc->grid, false,
cov);
FREE(x);
}
}
newdim = GetLoctsdim(cov);
assert(newdim > 0 );
} else {
// falls Aniso-matrix vom projektionstyp und zeitseparabel und
// zeitkomponente fehlt
usr_bool gridexpand = NEXTNR == TBM_PROC_INTERN || isAnyNugget(NEXTNR)
? False : GRIDEXPAND_AVOID;
// LocReduce: ausschiesslich Projektionen werden reduziert
// TransformLocReduce(cov, true /* timesep*/, gridexpand,
// true /* involveddollar */);
TransformLoc(cov, true /* timesep*/, gridexpand,
true /* involveddollar */);
newdim = GetLoctsdim(cov);
assert(newdim > 0 );
}
}
if ((err = covcpy(&(cov->key), next)) != NOERROR) RETURN_ERR(err);
if (!isGaussMethod(cov->key)) addModel(&(cov->key), GAUSSPROC);
SetLoc2NewLoc(cov->key, PLoc(cov));
model *key;
key = cov->key;
assert(key->calling == cov);
assert(newdim > 0);
ASSERT_ONESYSTEM;
if ((err = CHECK_NO_TRAFO(key, newdim, newdim, ProcessType, XONLY,
CoordinateSystemOf(cov->Sdollar->orig_owniso),
VDIM0, GaussMethodType)) != NOERROR) {
RETURN_ERR(err);
}
err = STRUCT(key, NULL);
RETURN_ERR(err);
}
default :
SERR2("%.50s: changes in scale/variance not programmed yet for '%.50s'",
NICK(cov), TYPE_NAMES[cov->frame]);
}
RETURN_NOERROR;
}
int initSproc(model *cov, gen_storage *s){
// am liebsten wuerde ich hier die Koordinaten transformieren;
// zu grosser Nachteil ist dass GetDiameter nach trafo
// grid def nicht mehr ausnutzen kann -- umgehbar?!
//model *next = cov->sub[DOLLAR_SUB];
//mppinfotype *info = &(s->mppinfo);
// location_type *loc = cov->prevloc;
model
*key = cov->key;
//*sub = key == NULL ? next : key;
location_type *prevloc = PrevLoc(cov);
int
prevdim = prevloc->timespacedim,
//dim = GetLoctsdim(cov),
err = NOERROR;
int //zaehler,
prevtotalpts = prevloc->totalpoints,
owntotalpts = Loc(cov)->totalpoints;
assert(key != NULL);
if ((err = INIT(key, 0, s)) != NOERROR) {
RETURN_ERR(err);
}
key->simu.active = true;
assert(s != NULL);
cov->fieldreturn = wahr;
cov->origrf = prevtotalpts != owntotalpts;
if (cov->origrf) {
assert(cov->Sdollar->separable);
assert(prevtotalpts % owntotalpts == 0);
assert(!PisNULL(DPROJ) || !PisNULL(DANISO));
// projection or reducing anisotropy matrix
if (VDIM0 != VDIM1) BUG;
cov->rf = (double*) MALLOC(sizeof(double) * VDIM0 * prevloc->totalpoints);
COND_NEW_STORAGE(dollar, cumsum);
EXTRA_STORAGE;
int *proj = PPROJ;
ALLC_NEWINT(Sdollar, cumsum, prevdim + 1, cumsum);
ALLC_NEWINT(Sdollar, total, prevdim + 1, total);
ALLC_NEWINT(Sdollar, len, prevdim + 1, len);
if (cov->Sdollar->separable) {
for (int d=0; d<prevdim; d++) {
cumsum[d] = 0;
len[d] = prevloc->xgr[d][XLENGTH];
}
if (proj != NULL) {
int d=0,
nproj = Nproj;
assert(proj[d] > 0);
cumsum[proj[d] - 1] = 1;
for (d = 1; d < nproj; d++) {
cumsum[proj[d] - 1] = cumsum[proj[d - 1] - 1] * len[d-1];
}
} else { // A eine projektionsmatrix
int i,
iold = 0,
nrow = cov->nrow[DANISO],
ncol = cov->ncol[DANISO];
double *A = P(DANISO);
for (int d=0; d<ncol; d++, A += nrow) {
for (i = 0; i < nrow && A[i] == 0.0; i++);
if (i == nrow) i = nrow - 1;
if (d > 0) {
cumsum[i] = cumsum[iold] * len[d-1];
} else { // d ==0
cumsum[i] = 1;
}
iold = i;
for (i++; i < nrow; i++) if (A[i] != 0.0) BUG; // just a check
}
}
} else BUG; /* { // !prevloc->grid spaeter fuer matrizen
// die proj-character haben
if (!prevloc->Time) goto Standard;
len[0] = prevloc->spatialtotalpoints;
len[1] = prevloc->T[XLENGTH];
int nproj = Nproj;
if (proj[0] != prevdim) { // spatial
for (d=1; d<nproj; d++) if (proj[d] == prevdim) goto Standard;
cumsum[0] = 1;
cumsum[1] = 0;
} else {
if (nproj != 1) goto Standard;
cumsum[0] = 0;
cumsum[1] = 1;
}
prevdim = 2;
} */
for (int d=0; d<prevdim; d++) total[d] = cumsum[d] * len[d];
} else cov->rf = cov->key->rf;
model *Var = cov->kappasub[DVAR];
if (Var != NULL) {
if (isnowRandom(Var) || Var->randomkappa) {
if (isProcess(Var)) {
RETURN_ERR(ERRORNOTPROGRAMMEDYET);
} else {
if ((err = INIT(Var, 0, s)) != NOERROR)
RETURN_ERR(err);
}
} else {
assert(cov->Sdollar != NULL);
int totptsvdim = prevloc->totalpoints * VDIM0;
cov->Sdollar->sd = (double*) MALLOC(sizeof(double) * totptsvdim);
double *sd = cov->Sdollar->sd;
Fctn(NULL, cov, sd);
for (int i=0; i<totptsvdim; i++) sd[i] = SQRT(sd[i]);
}
}
model *Scale = cov->kappasub[DSCALE];
if (Scale != NULL) {
RETURN_ERR(ERRORNOTPROGRAMMEDYET);
}
RETURN_NOERROR;
}
//int zz = 0;
void doSproc(model *cov, gen_storage *s){
int i,
vdim = VDIM0;
if (hasGaussMethodFrame(cov)) {
assert(cov->key != NULL);
double *res = cov->key->rf;
int
totalpoints = Gettotalpoints(cov),
totptsvdim = totalpoints * vdim;
DO(cov->key, s);
model *Var = cov->kappasub[DVAR];
if (Var != NULL) {
if (isnowRandom(Var) || Var->randomkappa) {
if (isProcess(Var)) {
XERR(ERRORNOTPROGRAMMEDYET);
} else {
DORANDOM(Var, P(DVAR));
}
double sd = SQRT(P0(DVAR));
for (i=0; i<totptsvdim; i++) res[i] *= sd;
} else {
double *sd = cov->Sdollar->sd;
assert(sd != NULL);
for (i=0; i<totptsvdim; i++) res[i] *= sd[i];
}
} else {
assert(!PisNULL(DVAR));
double sd = SQRT(P0(DVAR));
if (sd != 1.0) {
for (i=0; i<totptsvdim; i++) res[i] *= sd;
}
}
}
else if (hasMaxStableFrame(cov) || hasAnyPoissonFrame(cov)) {
BUG; // 2.2.19: darf eigentlich nicht (so) genutzt werden
assert(vdim == 1);
model *next = cov->sub[DOLLAR_SUB],
*Var = cov->kappasub[DVAR],
*Scale = cov->kappasub[DSCALE];
assert(VDIM0 == VDIM1);
if (Var != NULL && Var->randomkappa) {
BUG; // Da muss irgenduas dann auf rf draufmultipliziert werden
assert(!PisNULL(DVAR) && isnowRandom(Var));
VTLG_R(NULL, Var, P(DVAR));
}
if (Scale != NULL && Scale->randomkappa) {
// remote could be deterministic although local ist not
BUG; // otherwise do must depend on the new scale oder man muss
// interpolieren o.ae.
assert(!PisNULL(DSCALE));
VTLG_R(NULL, Scale, P(DSCALE));
}
DO(next, s);// nicht gatternr
for (i=0; i<vdim; i++)
cov->mpp.maxheights[i] = next->mpp.maxheights[i] * P0(DVAR);
}
else {
//PMI(cov);
BUG;
}
if (cov->origrf) { // es wird in cov->key->rf nur
// der projezierte Teil simuliert. Dieser Teil
// muss auf das gesamte cov->rf hochgezogen werden
//if (vdim != 1) BUG;
assert(cov->Sdollar->separable)
location_type *prevloc = PrevLoc(cov);
int zaehler, d,
// 2 below: one for arbitrary space and one for timesollte
prevdim = prevloc->timespacedim,
dim = prevloc->grid ? prevdim : 2,
prevtotalpts = prevloc->totalpoints,
owntotalpts = Loc(cov)->totalpoints,
*cumsum = cov->Sdollar->cumsum,
*len = cov->Sdollar->len,
*total = cov->Sdollar->total;
if (cov->Sdollar->separable) {
assert(cov->key != NULL);
assert(total != NULL && cumsum != NULL);
TALLOC_L1(nx, prevdim);
for (d=0; d<dim; d++) {
nx[d] = 0;
}
zaehler = 0;
i = 0;
// PMI0(cov->calling); PMI(cov);
for (int v=0; v<vdim; v++) {
double *res = cov->rf + v * prevtotalpts,
*rf = cov->key->rf + v * owntotalpts;
while (true) {
res[i++] = rf[zaehler];
d = 0;
nx[d]++;
zaehler += cumsum[d];
while (nx[d] >= len[d]) {
nx[d] = 0;
zaehler -= total[d];
if (++d >= dim) break;
nx[d]++;
zaehler += cumsum[d];
}
if (d >= dim) break;
}
}
END_TALLOC_L1;
}
}
}