/* Authors Martin Schlather, schlather@math.uni-mannheim.de Simulation of a random field by circulant embedding (see Wood and Chan, or Dietrich and Newsam for the theory) and variants by Stein and by Gneiting Copyright (C) 2001 -- 2003 Martin Schlather Copyright (C) 2004 -- 2005 Yindeng Jiang & Martin Schlather Copyright (C) 2006 -- 2011 Martin Schlather Copyright (C) 2011 -- 2015 Peter Menck & 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 #include "def.h" #ifdef DO_PARALLEL #include #endif #include #include #include #include // MULT #include #include #include "extern.h" #include "questions.h" #include "operator.h" #include "Processes.h" #include "Coordinate_systems.h" extern const char *CE[CEN]; /*********************************************************************/ /* CIRCULANT EMBEDDING METHOD (1994) ALGORITHM */ /* (it will always be refered to the paper of Wood & Chan 1994) */ /*********************************************************************/ int fastfourierInit(int *m, int dim, FFT_storage *FFT) /* this function is taken from the fft function by Robert Gentleman and Ross Ihaka, in R */ { int Err, maxp, maxmaxf,maxmaxp, nseg = maxmaxf = maxmaxp = 1; /* do whole loop just for err checking and maxmax[fp] .. */ for (int i = 0; i 1) { if (fft_factor(m[i], FFT->maxf + i, &maxp, FFT->kt + i, FFT->m_fac + i, FFT->NFAC[i])) FAILED("fft factorization failed"); if (FFT->maxf[i] > maxmaxf) maxmaxf = FFT->maxf[i]; if (maxp > maxmaxp) maxmaxp = maxp; nseg *= m[i]; } } FREE(FFT->work); FREE(FFT->iwork); // if ((FFT->work = (double*) MALLOC(4 * maxmaxf * sizeof(double)))==NULL || (FFT->iwork = (int*) MALLOC(maxmaxp * sizeof(int)))==NULL) { Err=ERRORMEMORYALLOCATION; goto ErrorHandling; } FFT->nseg = nseg; // nseg = leng th(z); see loop above return NOERROR; ErrorHandling: return Err; } int fastfourier(double *data, int *m, int dim, bool first, bool inverse, FFT_storage *FFT) { int Err; if (first && (Err = fastfourierInit(m, dim, FFT)) != NOERROR) return Err; return fastfourier(data, m, dim, inverse, FFT); } int fastfourier(double *data, int *m, int dim, bool inverse, FFT_storage *FFT) { /* this function is taken from the fft function by Robert Gentleman and Ross Ihaka, in R */ int nfac[21]; long int inv = (inverse) ? 2 : -2, n = 1, nspn = 1, nseg = FFT->nseg; for (long int i = 0; i < dim; i++) { if (m[i] > 1) { nspn *= n; n = m[i]; nseg /= n; MEMCOPY(nfac, FFT->NFAC[i], sizeof(int) * 21); // printf("%d: %d %d %d; fnax=%d %d %d %d %d %d %d %d \n", L, FFT->maxf[i], FFT->kt[i], FFT->m_fac[i], nfac[0], nfac[1], nfac[2], nfac[3], nfac[4], nfac[5], nfac[6], nfac[7]); if (!fft_work(data, data + 1, nseg, n, nspn, inv, FFT->work, FFT->iwork, FFT->maxf[i], FFT->kt[i], FFT->m_fac[i], nfac)) return XERRORFOURIER; } } return NOERROR; } #define LOCPROC_DIAM (CE_LAST + 1)// parameter p #define LOCPROC_A (CE_LAST + 2) // always last of LOCPROC_* #define LOCPROC_R LOCPROC_A // always last of LOCPROC_* int init_circ_embed(model *cov, gen_storage VARIABLE_IS_NOT_USED *S){ int err=NOERROR; if (!Getgrid(cov)) SERR("circ embed requires a grid"); double steps[MAXCEDIM], **c = NULL, // For multivariate *c->**c **Lambda = NULL; long int hilfsm[MAXCEDIM], mtot=0; model *next = cov->sub[0]; location_type *loc = Loc(cov); double maxGB = P0(CE_MAXGB), tolRe = P0(CE_TOLRE), tolIm = P0(CE_TOLIM), *caniso = loc->caniso, *mmin = P(CE_MMIN); int dim = OWNLOGDIM(0), dimM1 = dim - 1, vdim = VDIM0, cani_ncol = loc->cani_ncol, cani_nrow = loc->cani_nrow, lenmmin = cov->nrow[CE_MMIN], vdimSq = vdim * vdim, // PM 12/12/2008 maxmem = P0INT(CE_MAXMEM), trials = GLOBAL.internal.examples_reduced ? 1 : P0INT(CE_TRIALS), strategy = P0INT(CE_STRATEGY); bool isaniso = loc->caniso != NULL, force = (bool) P0INT(CE_FORCE), useprimes = (bool) P0INT(CE_USEPRIMES), dependent = (bool) P0INT(CE_DEPENDENT); assert(VDIM0 == VDIM1); if (loc->distances) RETURN_ERR(ERRORFAILED); if (dim > MAXCEDIM) RETURN_ERR(ERRORMAXDIMMETH); if (vdim > MAXVDIM) RETURN_ERR(ERRORMAXVDIM); cov->method = CircEmbed; NEW_STORAGE(ce); ce_storage *s = cov->Sce; int *mm = s->m, *halfm= s->halfm, *cumm = s->cumm; // since 20 Aug 17: in NEW_STORAGE // s->trials=0; // s->cur_call_odd = 0; // first one is set to be odd at beginning of // // do_circ_embed // s->positivedefinite = false; /* Eq. (3.12) shows that only j\in I(m) [cf. (3.2)] is needed, so only the first two rows of (3.9) (without the taking the modulus of h in the first row) The following variable 'index' corresponds to h(l) in the following way: index[l]=h[l] if 0<=h[l]<=mm[l]/2 index[l]=h[l]-mm[l] if mm[l]/2+1<=h[l]<=mm[l]-1 Then h[l]=(index[l]+mm[l]) % mm[l] !! */ for (int d=0; dnn[d]=(int) loc->xgr[d][XLENGTH]; steps[d]=loc->xgr[d][XSTEP]; } s->vdim = vdim; // PM 12/12/2008 // in case of multiple calls: possible to use imaginary part of // field generated in preceding run. If s->dependent is set, fields // are read off in the following order: // 1. real field 1st square // 2. imag field 1st square // 3. real field 2nd square // 4. imag field 2nd square // ... // 2k+1. real field (2k+1)th square // 2k+2. imag field (2k+1)th square // // i.e. read off imag fields in even calls. Generate new ones in // odd calls resp. read off real squares if s->dependent==1 /* cumm[i+1]=\prod_{j=0}^i m[j] cumm is used for fast transforming the matrix indices into an index of the vector (the way the matrix is stored) corresponding to the matrix */ /* calculate the dimensions of the matrix C, eq. (2.2) in W&C */ // ("CE missing strategy for matrix entension in case of anisotropic fields %d\n) // for (i=0;i 1; assert(VDIM0 == VDIM1); // multivariate = !true; // checken !! for (int i=0;i 10000.0) { GERR1("maximimal modulus of mmin is 10000. Got %10g", mmin[i % lenmmin]); } hilfsm_d = (double) s->nn[i]; if (mmin[i % lenmmin]>0.0) { if (hilfsm_d > (1 + (int) CEIL(mmin[i % lenmmin])) / 2) { // plus 1 since // mmin might be odd; so the next even number should be used GERR3("Minimum size in direction %d is %10g. Got %10g\n", (int) i, hilfsm_d, CEIL(mmin[i % lenmmin])); } hilfsm_d = (double) ( (1 + (int) CEIL(mmin[i % lenmmin])) / 2); } else if (mmin[i % lenmmin] < 0.0) { assert(mmin[i % lenmmin] <= - 1.0); hilfsm_d = CEIL((double) hilfsm_d * - mmin[i % lenmmin]); } if (hilfsm_d >= MAXINT) {err=ERRORMEMORYALLOCATION; goto ErrorHandling;} if (useprimes) { // Note! algorithm fails if hilfsm_d is not a multiple of 2 // 2 may not be put into NiceFFTNumber since it does not // guarantee that the result is even even if the input is even ! hilfsm_d = 2.0 * NiceFFTNumber((int) hilfsm_d); } else { double dummy; if (multivariate) dummy = POW(3.0, 1.0 + CEIL(LOG(hilfsm_d) / LOG3 - EPSILON1000)); else dummy = POW(2.0, 1.0 + CEIL(LOG(hilfsm_d) * INVLOG2-EPSILON1000)); hilfsm_d =ROUND(dummy); } if (hilfsm_d >= MAXINT) {err=ERRORMEMORYALLOCATION; goto ErrorHandling;} hilfsm[i] = (int) hilfsm_d; } // print("trials %d strat=%d force=%d prim=%d dep=%d max=%10g re=%10g im=%10g\n", // trials, strategy, force, useprimes, dependent, // maxmem, tol_re, tol_im); /* The algorithm below is as follows: while (!s->positivedefinite && (s->trialstrials)++; calculate the covariance values "c" according to the given "m" fastfourier(c) if (!force || (s->trialspositivedefinite && (s->trials=PL_STRUCTURE) { LPRINT("calculating the Fourier transform\n"); } while (!s->positivedefinite && (s->trials < trials)) { // print("trials %d %d\n", trials, s->trials); (s->trials)++; cumm[0]=1; double realmtot = 1.0; for (int i=0; imtot = mtot = cumm[dim]; if (PL>=PL_BRANCHING) { LPRINT("Memory need for "); for (int i=0; i 0) { PRINTF(" x "); } PRINTF("%d", mm[i]); } PRINTF(" %.50s is 2 x %ld complex numbers.\n", dim == 1 ? "locations" : "grid", mtot * vdimSq); } if ( (maxmem != NA_INTEGER && realmtot * vdimSq > maxmem)) GERR4("total real numbers needed=%.0f > '%.50s'=%d -- increase '%.50s'", realmtot * vdimSq, CE[CE_MAXMEM - COMMON_GAUSS - 1], maxmem, CE[CE_MAXMEM - COMMON_GAUSS - 1]) else if (R_FINITE(maxGB) && realmtot * vdimSq * 32e-9 > maxGB) GERR4("total memory needed=%4.4f GB > '%.50s'=%4.4f GB -- increase '%.50s'", realmtot* vdimSq * 32e-9, CE[CE_MAXGB - COMMON_GAUSS - 1], maxGB, CE[CE_MAXGB - COMMON_GAUSS - 1]); if (c != NULL) { for (int l=0; l 1L) #endif for (int i=0; iFFT + l #define END vdim #else #define S_FFT(l) &(s->FFT) #define END 1 #endif for (int j=0; j= j) { // nicht aendern; bei do_ce brauche ich die erste Spalte von s->FFT[] gefuellt int VARIABLE_IS_NOT_USED l= j*vdim + k; // unused in some cases!! if ((err = fastfourierInit(mm, dim, S_FFT(l))) != NOERROR) goto ErrorHandling; } } } err_occurred = NOERROR; #ifdef DO_PARALLEL #pragma omp parallel for num_threads(CORES) if (vdim > 1) collapse(2) schedule(dynamic, 1) reduction(+:err_occurred) #endif for (int j=0; j= j) { // nicht aendern; bei do_ce brauche ich die erste Spalte von s->FFT[] gefuellt int l= j*vdim + k; /* assert({bool ok__ = true; \ for (int ii =0; ii=PL_STRUCTURE) { LPRINT("FFT.0.."); } #endif err_occurred += fastfourier(c[l], mm, dim, !false, S_FFT(l)); // for (int t=0; t=PL_STRUCTURE) { LPRINT("done %d.\n", l); } #endif // if (false) { // for (int ii =0; ii=PL_STRUCTURE) { LPRINT("finished\n"); } // here the A(k) have been constructed; A(k) = c[0][k], c[1][k], ..., c[p-1][k] // c[p][k], ... c[2p-1][k] // ... ... // c[(p-1)*p][k], ..., c[p*p-1][k] // NOTE: only the upper triangular part of A(k) has actually been filled; A is Hermitian. // Now: // A(k) is placed into R (cf W&C 1999) // application of zheev puts eigenvectors // of A(k) into R if(Lambda!=NULL) { for(int l = 0; l tolIm || Lambda[0][i] <= tolRe; // if (!s->positivedefinite) printf("%10e %10e\n", c[0][2*i+1], tolIm); c[0][2*i] = 1.0; c[0][2*i+1] = 0.0; } } else { int index1, index2, Sign; // printf("ABC\n"); #ifdef DO_PARALLEL #pragma omp parallel for num_threads(CORES) if (vdim > 1L) reduction(+:notposdef) #endif for(int i = 0; i=k) { index2=index1; Sign=1; notposdef += k==l && FABS(c[index2][twoi_plus1]) > tolIm; // c[index2][twoi_plus1].r = 0.0; ?!!! } // obtain lower triangular bit of c as well with else{ index2= vdim * l + k; Sign=-1;} // (-1) times imaginary part of upper triangular bit R[index1].r = c[index2][twoi]; R[index1].i = Sign*c[index2][twoi_plus1]; // printf("%d:%f+%fi ", i, R[index1].r, R[index1].i); } } // diagonalize R via Fortran call zheev // initialization if(false && i==0) { #define INI_LWORK -1 lwork = INI_LWORK; // for initialization call to get optimal size of array 'work' F77zheev("V", "U", &vdim, R, // Eigen,cmplx &vdim, // integer tmpLambda, // double &optim_lwork, // complex &lwork, rwork, &info FCONE FCONE); //// martin 29.12.: nur einmal aufrufen] //// ganz weit vorne, oder haengt //// optim_lwork.r von den Werten der Matrix ab ?? lwork = (int) optim_lwork.r; // printf("lwork = %d %d\n", lwork, WORKSIZE); if (lwork > WORKSIZE) BUG; // INTEGER FUNCTION ILAENV( ISPEC, NAME, OPTS, N1, N2, N3, N4 ) // NB = ILAENV( 1, 'ZHETRD', UPLO, N, -1, -1, -1 ) // IC = Z, IZ = z, // C2 = SUBNAM( 2: 3 ) // C3 = SUBNAM( 4: 6 ) // C4 = C3( 2: 3 ) } // optim vdim * F77zheev("V", "U", &vdim, R, &vdim, // Eigen tmpLambda, work, &lwork, rwork, &info FCONE FCONE); for (int l=0;l= 0 (non-negative definiteness) // and do check this within this loop... in case of some lambda <0 there is no point in going // on diagonalizing if there are free trial... or not? Hmm. } } s->positivedefinite = !notposdef; // if (s->positivedefinite) { // for (int i=0; itrials 0: int ll=0; while( (llpositivedefinite &= Lambda[ll][i] >= tolRe) ) // eigenvalues ARE real: drop former line {ll++;} // s->positivedefinite = (lambda.real>=cepar->tol_re) && (lambda.imag<=cepar->tol_im) if ( !s->positivedefinite) { int *sum = NULL; double *smallest=NULL; long int *idx = NULL; if (PL>=PL_BRANCHING) { if (Lambda[ll][i] < 0.0) { LPRINT("There are complex eigenvalues\n"); } else if (vdim==1) { LPRINT("non-positive eigenvalue: Lambda[%d]=%10e (< %10e).\n", i, Lambda[ll][i], tolRe); } else { LPRINT("non-pos. eigenvalue in dim %d: Lambda[%d][%d]=%10e.\n", ll, i, ll, Lambda[ll][i]); } } if (PL>=PL_ERRORS) { // just for printing the smallest // eigenvalue (min(c)) if( (sum = (int *) CALLOC(vdim, sizeof(int))) == NULL || (smallest = (double *)CALLOC(vdim, sizeof(double))) == NULL || (idx = (long int *) CALLOC(vdim, sizeof(long int))) == NULL) { FREE(sum); FREE(smallest); FREE(idx); err=ERRORMEMORYALLOCATION; goto ErrorHandling; } char percent[]="%"; for (int j=i; jpositivedefinite, s->trials, trials, force); if (!s->positivedefinite && (s->trialsFFT + i); #else FFT_destruct(&(s->FFT)); #endif switch (strategy) { case 0 : for (int i=0; i2) { LPRINT("%d cc=%10e (%10e)",i,cc,hx[i]); } if (cc>maxcc) { maxcc = cc; maxi = i; } hx[i] = 0.0; } assert(maxi>=0); hilfsm[maxi] *= multivariate ? 3 : 2; break; default: GERR("unknown strategy for circulant embedding"); } } } else {if (PL>=PL_BRANCHING) {LPRINT("forced.\n");} } R_CheckUserInterrupt(); // printf("trials=%d %d %d\n", s->trials, trials, s->positivedefinite); } // while (!s->positivedefinite && (s->trials0); if (s->positivedefinite || force) { // correct theoretically impossible values, that are still within // tolerance CIRCEMBED.tol_re/CIRCEMBED.tol_im double r; r = Lambda[0][0]; // MULT // keine Parallelisierung! for (int i=0; i 0.0) Lambda[l][i] = SQRT(Lambda[l][i]); else { if(Lambda[l][i] < r) r = Lambda[l][i]; Lambda[l][i] = 0; } } // now compute R[i]*Lambda^(1/2)[i] for(int j=0;j=PL_BRANCHING) { if (r < -GENERAL_PRECISION) { LPRINT("using approximating circulant embedding:\n"); LPRINT("\tsmallest real part has been %10e \n", r); } } } else { //printf("FEHLER\n"); GERR("embedded matrix has (repeatedly) negative eigenvalues and approximation is not allowed (force=FALSE)"); } if (PL >= PL_SUBDETAILS) { for (int i=0; i < 2 * mtot; i++) for (int l=0; ldependent = dependent; s->new_simulation_next = true; for(int i=0; icur_square[i] = 0; s->max_squares[i] = hilfsm[i] / s->nn[i]; s->square_seg[i] = cumm[i] * (s->nn[i] + (hilfsm[i] - s->max_squares[i] * s->nn[i]) / s->max_squares[i]); } if ( (s->d=(double **) CALLOC(vdim, sizeof(double *))) == NULL ) { err=ERRORMEMORYALLOCATION; goto ErrorHandling; } for(int l=0; ld[l] = (double *) CALLOC(2 * mtot, sizeof(double))) == NULL) { err=ERRORMEMORYALLOCATION;goto ErrorHandling; } } if ((s->gauss1 = (complex *) MALLOC(sizeof(complex) * vdim)) == NULL) { err=ERRORMEMORYALLOCATION; goto ErrorHandling; } if ((s->gauss2 = (complex *) MALLOC(sizeof(complex) * vdim)) == NULL) { err=ERRORMEMORYALLOCATION; goto ErrorHandling; } err = ReturnOwnField(cov); ErrorHandling: s->c = c; if (Lambda != NULL) { for(int l = 0; lsimu.active = err == NOERROR; RETURN_ERR(err); } void kappa_ce(int i, model *cov, int *nr, int *nc){ kappaGProc(i, cov, nr, nc); if (i == CE_MMIN) *nr = 0; } int check_ce_basic(model *cov) { // auf co/stein ebene ! // model *next=cov->sub[0]; // location_type *loc = Loc(cov); int i, //err, dim = ANYDIM; // taken[MAX DIM], ce_param *gp = &(GLOBAL.ce); // ok FRAME_ASSERT_GAUSS_INTERFACE; ASSERT_CARTESIAN; ASSERT_UNREDUCED; kdefault(cov, CE_FORCE, (int) gp->force); if (PisNULL(CE_MMIN)) { PALLOC(CE_MMIN, dim, 1); for (i=0; immin[i]; } } kdefault(cov, CE_STRATEGY, (int) gp->strategy); kdefault(cov, CE_MAXGB, gp->maxGB); kdefault(cov, CE_MAXMEM, (int) gp->maxmem); kdefault(cov, CE_TOLIM, gp->tol_im); kdefault(cov, CE_TOLRE, gp->tol_re); kdefault(cov, CE_TRIALS, gp->trials); kdefault(cov, CE_USEPRIMES, (int) gp->useprimes); kdefault(cov, CE_DEPENDENT, (int) gp->dependent); kdefault(cov, CE_APPROXSTEP, gp->approx_grid_step); kdefault(cov, CE_APPROXMAXGRID, gp->maxgridsize); RETURN_NOERROR; } int check_ce(model *cov) { model *next=cov->sub[0]; // location_type *loc = Loc(cov); int err, dim = ANYDIM; FRAME_ASSERT_GAUSS_INTERFACE; ASSERT_UNREDUCED; ASSERT_ONESYSTEM; if (dim > MAXCEDIM) RETURN_ERR(ERRORCEDIM); if ((err = check_ce_basic(cov)) != NOERROR) RETURN_ERR(err); if ((err = checkkappas(cov, false)) != NOERROR) RETURN_ERR(err); if (GetLoctsdim(cov) > MAXCEDIM || OWNTOTALXDIM > MAXCEDIM) RETURN_ERR(ERRORCEDIM); if (cov->key != NULL) { if ((err = CHECK_PASSFRAME(cov->key, GaussMethodType)) != NOERROR) { //PMI(cov->key); XERR(err); //printf("specific ok\n"); // crash(); RETURN_ERR(err); } } else { if ((err = CHECK(next, dim, dim, PosDefType, XONLY, CARTESIAN_COORD, SUBMODEL_DEP, GaussMethodType)) != NOERROR) { // APMI(cov); // XERR(err); APMI(cov); if ((err = CHECK(next, dim, dim, VariogramType, XONLY, SYMMETRIC, SUBMODEL_DEP, GaussMethodType)) != NOERROR) { RETURN_ERR(err); } } if (next->pref[CircEmbed] == PREF_NONE) { //PMI(cov); // assert(false); RETURN_ERR(ERRORPREFNONE); } if (!isPosDef(SYSTYPE(NEXT, 0))) SERR("only covariance functions allowed."); } setbackward(cov, next); if (VDIM0 > MAXVDIM) RETURN_ERR(ERRORMAXVDIM); if ((err = kappaBoxCoxParam(cov, GAUSS_BOXCOX)) != NOERROR) RETURN_ERR(err); if ((err = checkkappas(cov, true)) != NOERROR) RETURN_ERR(err); RETURN_NOERROR; } void range_ce(model VARIABLE_IS_NOT_USED *cov, range_type *range){ GAUSS_COMMON_RANGE; booleanRange(CE_FORCE); range->min[CE_MMIN] = RF_NEGINF; range->max[CE_MMIN] = RF_INF; range->pmin[CE_MMIN] = -3; range->pmax[CE_MMIN] = 10000; range->openmin[CE_MMIN] = true; range->openmax[CE_MMIN] = true; range->min[CE_STRATEGY] = 0; range->max[CE_STRATEGY] = 1; range->pmin[CE_STRATEGY] = 0; range->pmax[CE_STRATEGY] = 1; range->openmin[CE_STRATEGY] = false; range->openmax[CE_STRATEGY] = false; range->min[CE_MAXGB] = 0; range->max[CE_MAXGB] = RF_INF; range->pmin[CE_MAXGB] = 0; range->pmax[CE_MAXGB] = 10; range->openmin[CE_MAXGB] = false; range->openmax[CE_MAXGB] = false; range->min[CE_MAXMEM] = 0; range->max[CE_MAXMEM] = MAXINT; range->pmin[CE_MAXMEM] = 0; range->pmax[CE_MAXMEM] = 50000000; range->openmin[CE_MAXMEM] = false; range->openmax[CE_MAXMEM] = false; range->min[CE_TOLIM] = 0.0; range->max[CE_TOLIM] = RF_INF; range->pmin[CE_TOLIM] = 0.0; range->pmax[CE_TOLIM] = 1e-2; range->openmin[CE_TOLIM] = false; range->openmax[CE_TOLIM] = false; range->min[CE_TOLRE] = RF_NEGINF; range->max[CE_TOLRE] = RF_INF; range->pmin[CE_TOLRE] = 1e-2; range->pmax[CE_TOLRE] = 0; range->openmin[CE_TOLRE] = false; range->openmax[CE_TOLRE] = false; range->min[CE_TRIALS] = 1; range->max[CE_TRIALS] = 10; range->pmin[CE_TRIALS] = 1; range->pmax[CE_TRIALS] = 3; range->openmin[CE_TRIALS] = false; range->openmax[CE_TRIALS] = true; booleanRange(CE_USEPRIMES); booleanRange(CE_DEPENDENT); range->min[CE_APPROXSTEP] = 0.0; range->max[CE_APPROXSTEP] = RF_INF; range->pmin[CE_APPROXSTEP] = 1e-4; range->pmax[CE_APPROXSTEP] = 1e4; range->openmin[CE_APPROXSTEP] = true; range->openmax[CE_APPROXSTEP] = true; range->min[CE_APPROXMAXGRID] = 1; range->max[CE_APPROXMAXGRID] = RF_INF; range->pmin[CE_APPROXMAXGRID] = 100; range->pmax[CE_APPROXMAXGRID] = 5e7; range->openmin[CE_APPROXMAXGRID] = false; range->openmax[CE_APPROXMAXGRID] = false; } void do_circ_embed(model *cov, gen_storage VARIABLE_IS_NOT_USED *S){ //printf("start do\n"); assert(cov != NULL); assert(Getgrid(cov)); SAVE_GAUSS_TRAFO; int HalfMp1[MAXCEDIM], HalfMaM[2][MAXCEDIM], index[MAXCEDIM], dim, *mm, *cumm, *halfm, // MULT added vars l, pos vdim; double invsqrtmtot, **c=NULL, **d=NULL, *dd=NULL, *res = cov->rf; // MULT *c->**c bool vfree[MAXCEDIM+1], noexception; // MULT varname free->vfree long mtot, start[MAXCEDIM], end[MAXCEDIM]; ce_storage *s = cov->Sce; location_type *loc = Loc(cov); complex *gauss1 = s->gauss1, *gauss2 = s->gauss2; if (s->stop) XERR(ERRORNOTINITIALIZED); /* implemented here only for rotationsinvariant covariance functions for arbitrary dimensions; (so it works only for even covariance functions in the sense of Wood and Chan,p. 415, although they have suggested a more general algorithm;) */ dim = OWNLOGDIM(0); mm = s->m; cumm = s->cumm; halfm = s->halfm; c = s->c; d = s->d; mtot= s->mtot; vdim = s->vdim; // so p=vdim #ifdef DO_PARALLEL omp_set_num_threads(GLOBAL_UTILS->basic.cores); #endif for (int i=0; i=PL_STRUCTURE) { LPRINT("Creating Gaussian variables... \n"); } /* now the Gaussian r.v. have to defined and multiplied with SQRT(FFT(c))*/ for (int i=0; icur_call_odd = !(s->cur_call_odd); s->new_simulation_next = (s->new_simulation_next && s->cur_call_odd); if (s->new_simulation_next) { // MULT // martin: 13.12. check //for(k=0; k=10) { LPRINT("cumm..."); } i <<= 1; // since we have to index imaginary numbers j <<= 1; // print("ij %d %d (%d)\n", i, j, noexception); if (noexception) { // case 3 in prop 3 of W&C for(int k=0; k endfor==mm[] */ int k=0; if (++index[k]>HalfMaM[vfree[k]][k]) { // in case k increases the number of indices that run over 0..m increases vfree[k] = true; index[k]= 0; k++; while((kHalfMaM[vfree[k]][k])) { vfree[k] = true; index[k]= 0; k++; } if (k>=dim) break; // except the very last (new) number is halfm and the next index is // restricted to 0..halfm // then k decreases as long as the index[k] is 0 or halfm if (!vfree[k] && (index[k]==halfm[k])){//index restricted to 0..halfm? // first: index[k] is halfm? (test on ==0 is superfluent) k--; while ( (k>=0) && ((index[k]==0) || (index[k]==halfm[k]))) { // second and following: index[k] is 0 or halfm? vfree[k] = false; k--; } } } } // MULT // // printf("xx ABCD %d %d %d\n", vdim, omp_get_num_threads(),GLOBAL_UTILS->basic.cores); #ifdef DO_PARALLEL #pragma omp parallel for num_threads(CORES) schedule(static,1) #endif for(int k=0; kcur_square[i] * s->square_seg[i]; end[i] = start[i] + cumm[i] * s->nn[i]; // print("%d start=%d end=%d cur=%d max=%d seq=%d cumm=%d, nn=%d\n", // i, (int) start[i], (int) end[i], // s->cur_square[i], s->max_squares[i], // (int) s->square_seg[i], cumm[i], s->nn[i]); } long totpts = loc->totalpoints; // MULT /* for(l=0; lcur_call_odd)] * invsqrtmtot; res[i] += d[l][2 * j] * invsqrtmtot; for(k=0; (k= end[k]); k++) { index[k]=start[k]; } } } */ // for(int k=0; kcur_call_odd)] * invsqrtmtot); } for(int k=0; (k= end[k]); k++) { index[k]=start[k]; } } s->new_simulation_next = true; if (s->dependent && !(s->cur_call_odd)) { int k=0; while(kcur_square[k]) >= s->max_squares[k])) { s->cur_square[k++]=0; } s->new_simulation_next = k == dim; } // // print("dep=%d odd=%d squ=%d %d\n", s->dependent, s->cur_call_odd, // s->cur_square[0],s->cur_square[1]); s->stop |= s->new_simulation_next && s->d == NULL; BOXCOX_INVERSE; } int GetOrthogonalUnitExtensions(double * aniso, int dim, double *grid_ext) { int k,i,j,l,m, job=01, Err, dimsq, ev0, jump, endfor; double *s=NULL, G[MAXCEDIM+1], e[MAXCEDIM], D[MAXCEDIM], *V=NULL; dimsq = dim * dim; assert(aniso != NULL); s = (double*) MALLOC(dimsq * sizeof(double)); V = (double*) MALLOC(dimsq * sizeof(double)); for (k=0; k aniso_k // s = aniso %*% aniso_k // s hat somit mindestens Eigenwert der 0 ist. //der zugeheorige EVektor wird miit der k-ten Spalte von aniso multipliziert // und ergibt dann den Korrekturfaktor for (i=0; ikey, *next = cov->sub[0], *sub = key != NULL ? key : next; // location_type *loc = Loc(cov); bool cutoff = COVNR == CE_CUTOFFPROC_USER || COVNR==CE_CUTOFFPROC_INTERN; if (!cutoff && COVNR!=CE_INTRINPROC_USER && COVNR!=CE_INTRINPROC_INTERN) BUG; FRAME_ASSERT_GAUSS_INTERFACE; ASSERT_UNREDUCED; ASSERT_ONESYSTEM; if ((err = check_ce_basic(cov)) != NOERROR) RETURN_ERR(err); if (dim > MAXCEDIM) RETURN_ERR(ERRORCEDIM); if (key != NULL) { // falls nicht intern muessen die parameter runter und rauf kopiert // werden, ansonsten sind die kdefaults leer. // falls hier gelandet, wird RP*INTERN von RP* aufgerufen. // oder RP*INTERN wird Circulant aufrufen model *intern = cov, *RMintrinsic = key->sub[0]; while (intern != NULL && MODELNR(intern) != CE_INTRINPROC_INTERN && MODELNR(intern) != CE_CUTOFFPROC_INTERN) { // normalerweise ->key, aber bei $ ist es ->sub[0] intern = intern->key == NULL ? intern->sub[0] : intern->key; } if (intern == NULL) { BUG; } else if (intern != cov) // cov not intern, ie user paramcpy(intern, cov, true, true, false, false, false); // i.e. INTERN else if (MODELNR(key) == CE_INTRINPROC_INTERN || MODELNR(key) == CE_CUTOFFPROC_INTERN) { // 2x intern hintereinander, d.h. es wird eine approximation durchgefuehrt paramcpy(key, cov, true, true, false, false, false); } else { //if (RMintrinsic->nr == GAUSSPROC) RMintrinsic = RMintrinsic->sub[0]; if (MODELNR(RMintrinsic) != CUTOFF && MODELNR(RMintrinsic) != STEIN) { BUG; } if (!PisNULL(LOCPROC_DIAM)) kdefault(RMintrinsic, pLOC_DIAM, P0(LOCPROC_DIAM)); if (!PisNULL(LOCPROC_R)) kdefault(RMintrinsic, pLOC_DIAM, P0(LOCPROC_R)); } if ((err = CHECK(sub, dim, dim, ProcessType, KERNEL, CARTESIAN_COORD, SUBMODEL_DEP, GaussMethodType)) != NOERROR) { RETURN_ERR(err); } if (intern == cov) { // all the other parameters are not needed on the // upper levels if (PisNULL(LOCPROC_DIAM)) kdefault(cov, LOCPROC_DIAM, PARAM0(RMintrinsic, pLOC_DIAM)); } } else { if ((err = CHECK(sub, dim, 1, VariogramType, //cutoff ? PosDefType : VariogramType, XONLY, ISOTROPIC, SUBMODEL_DEP, GaussMethodType)) != NOERROR) { if (isDollar(next) && !PARAMisNULL(next, DANISO)) { // if aniso is given then xdimprev 1 does not make sense err = CHECK(sub, dim, dim, VariogramType, //cutoff ? PosDefType : VariogramType, XONLY, ISOTROPIC, SUBMODEL_DEP, GaussMethodType); } // if (err != NOERROR) RETURN_ERR(err); // PMI(cov, "out"); //assert(false); } } //printf("check intern end\n"); // no setbackward ?! setbackward(cov, sub); VDIM0 = VDIM1 = sub->vdim[0]; if ((err = kappaBoxCoxParam(cov, GAUSS_BOXCOX)) != NOERROR) RETURN_ERR(err); RETURN_NOERROR; } int init_circ_embed_local(model *cov, gen_storage *S){ // being here, leadin $ have already been put away // so a new $ is included below model //*dummy = NULL, *key = cov->key; location_type *loc = Loc(cov); // simu_storage *simu = &(cov->simu); int instance, i, d, timespacedim = GetLoctsdim(cov), cncol = ANYDIM, err = NOERROR; // localCE_storage *s=NULL; double grid_ext[MAXCEDIM], old_mmin[MAXCEDIM]; int first_instance; double *mmin = P(CE_MMIN); double sqrt2a2; bool is_cutoff = COVNR == CE_CUTOFFPROC_INTERN; ASSERT_ONESYSTEM; cov->method = is_cutoff ? CircEmbedCutoff : CircEmbedIntrinsic; if (loc->distances) RETURN_ERR(ERRORFAILED); if (loc->caniso != NULL) { if (loc->cani_ncol != loc->cani_nrow || loc->cani_ncol != timespacedim) RETURN_ERR(ERRORCEDIM); err = GetOrthogonalUnitExtensions(loc->caniso, timespacedim, grid_ext); if (err != NOERROR) RETURN_ERR(err); } else { for (i=0; isub[0], LOCPROC_R)) kdefault(key, pLOC_DIAM, P0(LOCPROC_R)); kdefault(key, CE_FORCE, P0INT(CE_FORCE)); PARAMFREE(key, CE_MMIN); PARAMALLOC(key, CE_MMIN, ANYDIM, 1); PCOPY(key, cov, CE_MMIN); kdefault(key, CE_STRATEGY, P0INT(CE_STRATEGY)); kdefault(key, CE_MAXGB, P0(CE_MAXGB)); kdefault(key, CE_MAXMEM, P0INT(CE_MAXMEM)); kdefault(key, CE_TOLIM, P0(CE_TOLIM)); kdefault(key, CE_TOLRE, P0(CE_TOLRE)); kdefault(key, CE_TRIALS, P0INT(CE_TRIALS)); kdefault(key, CE_USEPRIMES, P0INT(CE_USEPRIMES)); kdefault(key, CE_DEPENDENT, P0INT(CE_DEPENDENT)); // APMI(key); assert(VDIM0 == VDIM1); err = CHECK_PASSTF(key, GaussMethodType, VDIM0, GaussMethodType); // err = CHECK(key, cov->tsdim, cov->xdimprev, // GaussMethodType, // OWNDOM(0), OWNISO(0), SUBMODEL_DEP, GaussMethodType); if ((err < MSGLOCAL_OK && err != NOERROR) || err >=MSGLOCAL_ENDOFLIST // 30.5.13 : neu ) RETURN_ERR(err); first_instance = err != NOERROR; for (d=0; dsub[0]; localCE_storage *ss = local->SlocalCE; assert(ss != NULL); localvariab *q = ss->q; assert(q != NULL); assert(err == NOERROR); for (instance = first_instance; instance < 2; instance++) { if (instance == 1) { if (q->msg != MSGLOCAL_OK) { if (!DefList[MODELNR(local)].alternative(local)) break; } else { if (first_instance == 0 && err != NOERROR) goto ErrorHandling; else BUG; } } else assert(instance == 0); for (d=0; dR / (grid_ext[d] * (loc->xgr[d][XLENGTH] - 1.0) * loc->xgr[d][XSTEP]); if (mmin[d] > -1.0) mmin[d] = - 1.0; } } if ((err = init_circ_embed(key, S)) == NOERROR) break; } if (err != NOERROR) goto ErrorHandling; if (COVNR == CE_INTRINPROC_INTERN) { sqrt2a2 = SQRT(2.0 * q->intrinsic.A2); // see Stein (2002) timespacedim * cncol if (loc->caniso == NULL) { ALLCCOV_NEW(local, SlocalCE, correction, 1, correction); correction[0] = sqrt2a2; } else { int rowcol = timespacedim * cncol; ALLCCOV_NEW(local, SlocalCE, correction, rowcol, correction); for (i=0; icaniso[i]; } } } else { assert(COVNR == CE_CUTOFFPROC_INTERN); } if ((err = kappaBoxCoxParam(cov, GAUSS_BOXCOX)) !=NOERROR) goto ErrorHandling; assert(err == NOERROR); ReturnOtherField(cov, cov->key); ErrorHandling : for (d=0; dsimu.active = err == NOERROR; // printf("%d\n", local->SlocalCE != NULL); // APMI(cov); RETURN_ERR(err); } int struct_ce_local(model *cov, model VARIABLE_IS_NOT_USED **newmodel) { model *next = cov->sub[0]; int err; bool cutoff = COVNR == CE_CUTOFFPROC_INTERN; if (next->pref[cutoff ? CircEmbedCutoff : CircEmbedIntrinsic] == PREF_NONE) RETURN_ERR(ERRORPREFNONE); if (cov->key != NULL) COV_DELETE(&(cov->key), cov); if ((err = covcpy(&(cov->key), next)) != NOERROR) RETURN_ERR(err); addModel(&(cov->key), cutoff ? CUTOFF : STEIN); addModel(&(cov->key), CIRCEMBED); // crash(cov); // da durch init die relevanten dinge gesetzt werden, sollte // erst danach bzw. innerhalb von init der check zum ersten Mal //APMI(cov); RETURN_NOERROR; } void do_circ_embed_cutoff(model *cov, gen_storage *S) { double *res = cov->rf; model *key = cov->key, *sub = key; assert(key != NULL); sub = sub->key != NULL ? sub->key : sub->sub[0]; assert(sub != NULL); int // k, row = loc->timespacedim, vdim = VDIM0; long totpts = Gettotalpoints(cov); // printf("--- \n \n do_circ_embed_cutoff \n \n ---"); //PMI(sub); localCE_storage *s = sub->SlocalCE; assert(s != NULL); localvariab *q = s->q; assert(q != NULL); // PMI(sub); do_circ_embed(key, S); if ( VDIM0 > 1) { double normal1 = GAUSS_RANDOM(1.0), normal2 = GAUSS_RANDOM(1.0), c11 = q[0].cutoff.constant, c12 = q[1].cutoff.constant, c22 = q[3].cutoff.constant, x[2]; if (c11 < 0.0 || c22*c11 - c12*c12 < 0.0 ) RFERROR("Cannot simulate field with cutoff, matrix of constants is not positive definite."); x[0] = SQRT(c11)*normal1 ; x[1] = c12/SQRT(c11)*normal1 + SQRT(c22 - c12*c12/c11 )*normal2; if (GLOBAL.general.vdim_close_together) { //one location two values for (int i = 0; i < totpts; i++) { for (int j = 0; j < vdim; j++) { res[i*vdim + j] += x[j]; } } } else { // the first field, the second field for (int j = 0; j < vdim; j++) { for (int i = 0; i < totpts; i++) { res[i+j*totpts] += x[j]; } } } } } void kappa_localproc(int i, model *cov, int *nr, int *nc){ kappaGProc(i, cov, nr, nc); if (i == CE_MMIN) *nr = 0; // $(proj=1) ->intrinsicinternal as $ copies the parameters // to intrinsicinternal and at the same time proj=1 reduces // the logicaldim } void range_co_proc(model *cov, range_type *range){ range_ce(cov, range); range->min[LOCPROC_DIAM] = 0.0; // CUTOFF_DIAM range->max[LOCPROC_DIAM] = RF_INF; range->pmin[LOCPROC_DIAM] = 1e-10; range->pmax[LOCPROC_DIAM] = 1e10; range->openmin[LOCPROC_DIAM] = true; range->openmax[LOCPROC_DIAM] = true; range->min[LOCPROC_A] = 0.0; // cutoff_a range->max[LOCPROC_A] = RF_INF; range->pmin[LOCPROC_A] = 0.5; range->pmax[LOCPROC_A] = 2.0; range->openmin[LOCPROC_A] = true; range->openmax[LOCPROC_A] = true; } void range_intrinCE(model *cov, range_type *range) { range_ce(cov, range); range->min[LOCPROC_DIAM] = 0.0; // CUTOFF_DIAM range->max[LOCPROC_DIAM] = RF_INF; range->pmin[LOCPROC_DIAM] = 0.01; range->pmax[LOCPROC_DIAM] = 100; range->openmin[LOCPROC_DIAM] = true; range->openmax[LOCPROC_DIAM] = true; range->min[LOCPROC_R] = 1.0; // stein_r range->max[LOCPROC_R] = RF_INF; range->pmin[LOCPROC_R] = 1.0; range->pmax[LOCPROC_R] = 20.0; range->openmin[LOCPROC_R] = false; range->openmax[LOCPROC_R] = true; } void do_circ_embed_intr(model *cov, gen_storage *S) { model *key = cov->key, *sub = key; assert(key != NULL); sub = sub->key != NULL ? sub->key : sub->sub[0]; location_type *loc = Loc(cov); double x[MAXCEDIM], dx[MAXCEDIM], *res = cov->rf; long index[MAXCEDIM]; int dim = ANYDIM, row = dim, col = dim, rowcol = row * col; localCE_storage *s = sub->SlocalCE; assert(s != NULL); assert(s->correction != NULL); SAVE_GAUSS_TRAFO; do_circ_embed(key, S); for (int k=0; kcalling); //printf("%d\n", cov->key->SlocalCE != NULL); if (loc->caniso == NULL) { for (int k=0; kcorrection[0]); dx[k] += s->correction[0] * normal; // } } else { for (int i=0; icorrection[i++] * normal; } } for (int k=0; kxgr[k][XSTEP]; int r; for(r=0; ; ) { for (int k=0; k=loc->xgr[k][XLENGTH])) { index[k]=0; x[k] = 0.0; k++; } if (k>=row) break; x[k] += dx[k]; } BOXCOX_INVERSE; } int struct_ce_approx(model *cov, model **newmodel) { assert(COVNR==CE_CUTOFFPROC_INTERN || COVNR==CE_INTRINPROC_INTERN || COVNR==CIRCEMBED); model *next = cov->sub[0]; bool cutoff = COVNR == CE_CUTOFFPROC_INTERN; if (next->pref[COVNR==CIRCEMBED ? CircEmbed : cutoff ? CircEmbedCutoff : CircEmbedIntrinsic] == PREF_NONE) RETURN_ERR(ERRORPREFNONE); //PMI(cov); // assert(!Getgrid(cov)); if (!Getgrid(cov)) { ASSERT_NEWMODEL_NULL; location_type *loc = Loc(cov); double max[MAXCEDIM], min[MAXCEDIM], centre[MAXCEDIM], x[3 * MAXCEDIM], approx_gridstep = P0(CE_APPROXSTEP); int k, d, len, err, maxgridsize = P0INT(CE_APPROXMAXGRID), spatialdim = loc->spatialdim; if (approx_gridstep < 0) SERR("approx_step < 0 forbids approximative circulant embedding"); if (OWNTOTALXDIM != GetLoctsdim(cov)) SERR("the dimensions of the coordinates and those of the process differ"); GetDiameter(loc, min, max, centre); if (loc->Time) { if (loc->T[XLENGTH] > maxgridsize) SERR("temporal grid too long"); maxgridsize /= loc->T[XLENGTH]; } if (ISNAN(approx_gridstep)) { // hier assert(false); double size = loc->spatialtotalpoints * 3; if (size > maxgridsize) size = maxgridsize; for (k=d=0; d maxgridsize) SERR("userdefined, approximate grid is too large"); } if (cov->key!=NULL) COV_DELETE(&(cov->key), cov); err = covcpy(&(cov->key), cov, x, loc->T, spatialdim, spatialdim, 3, loc->Time, true, false); if (err != NOERROR) RETURN_ERR(err); SET_CALLING(cov->key, cov); if ((err = CHECK_GEN(cov->key,// cov 11.1.19 VDIM0, VDIM1, GaussMethodType, false)) //C H E C K(cov, cov->tsdim, cov->xdimprev, cov->typus, // cov->domprev, cov->isoprev, VDIM0, cov->fr ame) != NOERROR) RETURN_ERR(err); } if (COVNR == CIRCEMBED) { RETURN_NOERROR; } else return struct_ce_local(Getgrid(cov) ? cov : cov->key, newmodel); } int init_ce_approx(model *cov, gen_storage *S) { if (Getgrid(cov)) { if (COVNR==CIRCEMBED) return init_circ_embed(cov, S); else return init_circ_embed_local(cov, S); } ASSERT_UNREDUCED; location_type *loc = Loc(cov), *keyloc = Loc(cov->key); assert(cov->key != NULL && keyloc != NULL); long i, cumgridlen[MAXCEDIM], totspatialpts = loc->spatialtotalpoints; int d, err, // maxgridsize = P0INT(CE_APPROXMAXGRID), spatialdim = loc->spatialdim, dim = ANYDIM; ASSERT_ONESYSTEM; cov->method = COVNR==CIRCEMBED ? CircEmbed : COVNR== CE_CUTOFFPROC_INTERN ? CircEmbedCutoff : CircEmbedIntrinsic; if (loc->distances) RETURN_ERR(ERRORFAILED); NEW_STORAGE(approxCE); ALLC_NEWINT(SapproxCE, idx, totspatialpts, idx); cumgridlen[0] = 1; for (d=1; dxgr[d-1][XLENGTH]; } double *xx = loc->x; for (i=0; ixgr[d][XSTART]) / keyloc->xgr[d][XSTEP]); } idx[i] = dummy; assert(dummy >= 0); } if (COVNR==CIRCEMBED) err = init_circ_embed(cov->key, S); else err = init_circ_embed_local(cov->key, S); if (err != NOERROR) RETURN_ERR(err); if ((err = ReturnOwnField(cov)) != NOERROR) RETURN_ERR(err); cov->key->initialised = cov->simu.active = err == NOERROR; RETURN_NOERROR; } void do_ce_approx(model *cov, gen_storage *S){ if (Getgrid(cov)) { if (COVNR==CIRCEMBED) do_circ_embed(cov, S); else if (COVNR== CE_CUTOFFPROC_INTERN) do_circ_embed_cutoff(cov, S); else do_circ_embed_intr(cov, S); return; } // PMI(cov); model *key=cov->key; location_type *loc = Loc(cov); approxCE_storage *s = cov->SapproxCE; //model *cov = meth->cov; long i; int vdim = VDIM0, *idx = s->idx; double *res = cov->rf, *internalres = key->rf; // APMI(key); DO(key, S); location_type *key_loc = Loc(key); if (key_loc->Time) { // time separately given long t, j = 0, instances = (long) loc->T[XLENGTH], totspatialpts = loc->spatialtotalpoints, gridpoints = Loc(key)->spatialtotalpoints; for (int v=0; vtotalpoints; int j = 0, totalkey = Loc(key)->totalpoints; for (int v=0; vx[i], idx[i]); // print(" %d %d %10g %10g", i, idx[i], loc->x[i*2], loc->x[i*2 +1]); // print(" %10g\n", internalres[idx[i]]); res[j++] = internalres[idx[i]]; } } } }