/* Authors Martin Schlather, martin.schlather@cu.lu library for simulation of random fields -- get's, set's, and print's Copyright (C) 2001 -- 2004 Martin Schlather, This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "RFsimu.h" #include "MPPFcts.h" #include void GetParameterIndices(int *variance, int *scale, int *kappa, int *lastkappa, int *invscale, int *aniso) { *variance=VARIANCE; *scale=SCALE; *kappa=KAPPA; *lastkappa=LASTKAPPA; *invscale=INVSCALE; *aniso=ANISO; } void GetrfParameters(int *covmaxchar, int *methodmaxchar, int *distrmaxchar, int *covnr, int *methodnr, int *distrnr, int *maxdim, int *maxmodels) { if (currentNrCov==-1) InitModelList(); *covmaxchar=COVMAXCHAR; *methodmaxchar=METHODMAXCHAR; *distrmaxchar=DISTRMAXCHAR; *covnr=currentNrCov; *methodnr=(int) Nothing; *distrnr=DISTRNR; *maxdim=MAXDIM; *maxmodels=MAXKEYS; } void GetDistrName(int *nr,char **name){ if ((*nr<0) ||(*nr>=DISTRNR)) {strncpy(*name,"",DISTRMAXCHAR); return;} strncpy(*name, DISTRNAMES[*nr], DISTRMAXCHAR); } void GetDistrNr(char **name, int *n, int *nr) { unsigned int ln,v; // == -1 if no matching function is found // == -2 if multiple matching fnts are found, without one matching exactly // if more than one match exactly, the last one is taken (enables overwriting // standard functions) for (v=0; v<*n; v++) { nr[v]=0; ln=strlen(name[v]); while ( (nr[v] < DISTRNR) && strncmp(name[v], DISTRNAMES[nr[v]], ln)) { (nr[v])++; } if (nr[v]force=(bool)*force; CE->tol_re=*tolRe; if (CE->tol_re>0) { CE->tol_re=0; if (GENERAL_PRINTLEVEL>0) PRINTF("\nWARNING! %s.tol_re had been positive.\n",name); } CE->tol_im=*tolIm; if (CE->tol_im<0) { CE->tol_im=0; if (GENERAL_PRINTLEVEL>0) PRINTF("\nWARNING! %s.tol_im had been neagtive.\n",name); } CE->trials=*trials; if (CE->trials<1) { CE->trials=1; if (GENERAL_PRINTLEVEL>0) PRINTF("\nWARNING! %s.trials had been less than 1\n",name); } for (d=0; dmmin[d] = mmin[d]; if (CE->mmin[d]>0) { CE->mmin[d] = 1 << (1+(int) (log(((double) CE->mmin[d])-0.1)/log(2.0))); if ((CE->mmin[d]!=mmin[d]) && (GENERAL_PRINTLEVEL>0)) PRINTF("\nWARNING! %s.mmin[%d] set to %d.\n",name,d,CE->mmin[d]); } } CE->userfft=(bool)*userfft; if (*strategy>LASTSTRATEGY) { if (GENERAL_PRINTLEVEL>0) PRINTF("\nWARNING! %s_STRATEGY not set\n",name); } else CE->strategy=(char) *strategy; break; case 1 : *force=CE->force; *tolRe=CE->tol_re; *tolIm=CE->tol_im; *trials=CE->trials; for (d=0; dmmin[d];} *userfft= CE->userfft; *strategy=(int) CE->strategy; if (GetNotPrint) break; case 2 : PRINTF("\n%s\n==========\nforce=%d\ntol_re=%e\ntol_im=%e\ntrials=%d\nuserfft=%d\nstrategy=%d\n",name, CE->force,CE->tol_re,CE->tol_im, CE->trials, CE->userfft, (int) CE->strategy); for (d=0; dmmin[d]); PRINTF("\n"); break; default : PRINTF(" unknown action\n"); } } void GetModelName(int *nr,char **name){ if (currentNrCov==-1) InitModelList(); if ((*nr<0) ||(*nr>=currentNrCov)) {strncpy(*name,"",COVMAXCHAR); return;} strncpy(*name,CovList[*nr].name,COVMAXCHAR); } void GetNrParameters(int *covnr, int *n, int* kappas) { int v; if (currentNrCov==-1) InitModelList(); for (v=0; v<*n; v++) { if ((covnr[v]<0) ||(covnr[v]>=currentNrCov)) {kappas[v]=-1;} else kappas[v] = CovList[covnr[v]].kappas; } } void GetModelNr(char **name, int *n, int *nr) { unsigned int ln,v; // == -1 if no matching function is found // == -2 if multiple matching fnts are found, without one matching exactly // if more than one match exactly, the last one is taken (enables overwriting // standard functions) if (currentNrCov==-1) InitModelList(); for (v=0; v<*n; v++) { nr[v]=0; ln=strlen(name[v]); while ( (nr[v]=(int) Forbidden)) { strncpy(*name,"",METHODMAXCHAR); return; } strncpy(*name,METHODNAMES[*nr],METHODMAXCHAR); } void PrintMethods() { int i; PRINTF("\n\n Methods for generating Gaussian random fields\n =============================================\n\n"); for (i=0;i<(int) Nothing;i++) { PRINTF(" * %s\n",METHODNAMES[i]); } PRINTF("\n\n Methods for non-Gaussian random fields\n ======================================\n"); for (i=1+(int) Nothing;i<(int) Forbidden; i++) { PRINTF(" * %s\n",METHODNAMES[i]); } PRINTF("\n"); } void PrintCovDetailed(int i) { PRINTF("%5d: %s cov=%d %d %d, tbm=%d %d %d, spec=%d,\n abf=%d hyp=%d, oth=%d %d\n", i,CovList[i].name,CovList[i].cov,CovList[i].cov_loc, CovList[i].square_factor, CovList[i].cov_tbm2,CovList[i].cov_tbm3,CovList[i].tbm_method, CovList[i].spectral,CovList[i].add_mpp_scl,CovList[i].hyperplane, CovList[i].initother,CovList[i].other); } void PrintModelListDetailed() { int i; if (CovList==NULL) {PRINTF("There are no functions available!\n");} else { PRINTF("\nList of covariance functions:\n=============================\n"); for (i=0;i=currentNrCov) || (*lrange != CovList[*nr].kappas * 4) ) { for (i=0; i<*lrange; i++) range[i]=RF_NAN; *index = -100; return; } assert(CovList[*nr].range != NULL); CovList[*nr].range(*dim, index, range); // index>0 : further parts of the range are missing // index=-1: no further part of the range // index=-2: dimension not valid //assert(false); } extern int IncludeModel(char *name, int kappas, checkfct check, int isotropic, bool variogram, methodfct method, rangefct range) { int i; if (currentNrCov==-1) InitModelList(); assert(CovList!=NULL); assert(currentNrCov>=0); if (currentNrCov>=MAXNRCOVFCTS) {PRINTF("Error. Model list full.\n");return -1;} strncpy(CovList[currentNrCov].name, name, COVMAXCHAR-1); CovList[currentNrCov].name[COVMAXCHAR-1]='\0'; if (strlen(name)>=COVMAXCHAR) { PRINTF("Warning! Covariance name is truncated to `%s'", CovList[currentNrCov].name); } CovList[currentNrCov].kappas = kappas; CovList[currentNrCov].check = check; CovList[currentNrCov].isotropic = isotropic; CovList[currentNrCov].cov=NULL; CovList[currentNrCov].naturalscale=NULL; CovList[currentNrCov].cov_loc=NULL; CovList[currentNrCov].cov_tbm2=NULL; CovList[currentNrCov].cov_tbm3=NULL; CovList[currentNrCov].ableitung=NULL, CovList[currentNrCov].spectral=NULL; CovList[currentNrCov].add_mpp_scl=NULL; CovList[currentNrCov].add_mpp_rnd=NULL; CovList[currentNrCov].hyperplane=NULL; CovList[currentNrCov].initother=NULL; CovList[currentNrCov].other=NULL; CovList[currentNrCov].square_factor=NULL; CovList[currentNrCov].tbm_method = Forbidden; CovList[currentNrCov].isotropic = isotropic; CovList[currentNrCov].variogram = variogram; CovList[currentNrCov].even = true; CovList[currentNrCov].range= range; assert((CovList[currentNrCov].method=method)!=NULL); for (i=0; i0) assert(check!=NULL); currentNrCov++; return(currentNrCov-1); } extern void addodd(int nr, int dim) { assert((dim>=0) && (dim=0) && (nr=0) && (nr=0) && (nr=0) && (nr=0) && (nr5) PRINTF("List of covariance functions initiated.\n"); } if (CovList==NULL) {PRINTF("There are no functions available!\n");} else { sprintf(firstcolumn,"%s%ds ",percent,COVMAXCHAR); sprintf(line,"%s3s %s3s %s3s %s3s %s2s %s2s %s2s %s2s %s2s\n", percent,percent,percent,percent,percent,percent,percent,percent, percent); PRINTF("\n\n"); PRINTF(firstcolumn,empty); PRINTF(" List of models\n"); PRINTF(firstcolumn,empty); PRINTF(" ==============\n"); PRINTF(firstcolumn,empty); PRINTF("[See also PrintMethodList()]\n\n"); PRINTF(firstcolumn,empty);PRINTF(header,empty); for (i=0;i5) PRINTF("List of covariance functions initiated.\n"); } if (CovList==NULL) return; assert(Nothing==10); methods = Nothing - 2; // nugget and nothing itself for (j=i=0; iTEN)) {TEN=0;} *natscale=0.0; if (CovList[*covnr].naturalscale!=NULL) { *natscale = CovList[*covnr].naturalscale(p,*naturalscaling-TEN); if (*natscale!=0.0) return; } if (numeric) { Real x,newx,yold,y,newy; covfct cov; int parami, wave,i; if ((cov=CovList[*covnr].cov)==NULL) {*error=ERRORNOTDEFINED;return;} if ((cov=CovList[*covnr].cov)==nugget) {*error=ERRORRESCALING; return;} // already calculated ? parami=KAPPA; // do not compare mean,variance, etc. if (oldcovnr==*covnr) { for (; parami 0.05) { Real leftx; x *= 2.0; while ( (y=cov(&x,oldp,1)) > 0.05) { if (yold10) {*error=ERRORWAVING; return;} } yold = y; x *= 2.0; if (x>1E30) {*error=ERRORRESCALING; return;} // or use a separate ERROR } leftx = x * 0.5; for (i=0; i<3 /* good choice?? */ ;i++) { if (y==yold) {*error=ERRORWAVING; return;} // should never appear newx = x + (x-leftx)/(y-yold)*(0.05-y); if ( (newy=cov(&newx,oldp,1)) >0.05) { leftx = newx; yold = newy; } else { x = newx; y = newy; } } if (y==yold) {*error=ERRORWAVING; return;} // should never appear *natscale = 1.0 / ( x + (x-leftx)/(y-yold)*(0.05-y) ); } else { Real rightx; x *= 0.5; while ( (y=cov(&x,oldp,1)) < 0.05) { if (yold>y){ wave++; if (wave>10) {*error=ERRORWAVING; return;} } yold = y; x *= 0.5; if (x<1E-30) {*error=ERRORRESCALING; return;} //or use a separate ERROR } rightx = x * 2.0; for (i=0; i<3 /* good choice?? */ ;i++) { if (y==yold) {*error=ERRORWAVING; return;} // should never appear newx = x + (x-rightx)/(y-yold)*(0.05-y); if ( (newy=cov(&newx,oldp,1)) <0.05) { rightx = newx; yold = newy; } else { x = newx; y = newy; } } if (y==yold) {*error=ERRORWAVING; return;} // should never appear *natscale = 1.0 / ( x + (x-rightx)/(y-yold)*(0.05-y) ); } oldcovnr=*covnr; /* result is reliable -> stored for next call */ OldNatScale = *natscale; } else {*error=ERRORRESCALING; } } else { *natscale = 1.0; } } void SetParam(int *action, int *storing,int *printlevel,int *naturalscaling, char **pch) { switch (*action) { case 0 : GENERAL_STORING= (bool) *storing; GENERAL_PRINTLEVEL=*printlevel; GENERAL_NATURALSCALING=*naturalscaling; if ((strlen(*pch)>1) && (GENERAL_PRINTLEVEL>0)) PRINTF("\n`pch' has more than one character -- first character taken only\n"); strncpy(GENERAL_PCH, *pch, 1); break; case 1 : *storing = GENERAL_STORING; *printlevel = GENERAL_PRINTLEVEL; *naturalscaling = GENERAL_NATURALSCALING; strcpy(*pch, GENERAL_PCH); if (GetNotPrint) break; case 2 : PRINTF("\nGeneral Parameters\n==================\nstoring=%d\nprint level=%d\nnatural scaling=%d\npch=%s\n", GENERAL_STORING,GENERAL_PRINTLEVEL,GENERAL_NATURALSCALING,*pch); break; default : PRINTF(" unknown action\n"); } } void StoreTrend(int *keyNr, int *modus, char **trend, int *lt, Real *lambda, int *ll, int *error) { unsigned long len; key_type *key; if (currentNrCov==-1) InitModelList(); assert(CovList!=NULL); if ((*keyNr<0) || (*keyNr>=MAXKEYS)) {*error=ERRORREGISTER;goto ErrorHandling;} key = &(KEY[*keyNr]); if (key->LinearTrend!=NULL) free(key->LinearTrend); key->LinearTrend = NULL; if (key->TrendFunction!=NULL) free(key->TrendFunction); key->TrendFunction = NULL; key->lTrendFct = 0; key->lLinTrend = 0; switch(*modus){ case 0 : break; case 3 : case 1 : key->LinearTrend = (Real *) malloc(len = sizeof(Real) * *ll); memcpy(key->LinearTrend, lambda, len); if (*modus==1) break; key->lLinTrend = *ll; case 2 : key->TrendFunction = (char *) malloc(len = sizeof(char) * *lt); memcpy(key->TrendFunction, *trend, len); key->lTrendFct = *lt; break; default: key->TrendModus = -1; *error=ERRORUNSPECIFIED; goto ErrorHandling; } key->TrendModus = *modus; *error = 0; return; ErrorHandling: return; } void GetTrueDim(bool anisotropy, int timespacedim, Real* param, int *TrueDim, bool *no_last_comp, int *start_aniso, int *index_dim) // output: start_aniso (where the non-zero positions start, anisotropy) // index_dim (dimension nr of the non-zero positions, aniso) // no_last_comp(last dim of aniso matrix. is identically zero, i.e, // effectively no time component) // TrueDim The reduced dimension, including the time direction { int i,j,k; unsigned long endfor, startfor; if (anisotropy) { /* check whether the dimension can be reduced */ /* TODO:this algorithm only detects zonal anisotropies -- could be improved*/ for (j=-1, i=0; i=endfor; // last i is time, if k=endfor then all // components zero *TrueDim = j+1; } else { *no_last_comp = true; *TrueDim = timespacedim; // == spatialdim } } void GetTrendLengths(int *keyNr, int *modus, int *lt, int *ll, int *lx) { key_type *key; if (currentNrCov==-1) {*modus=-1;goto ErrorHandling;} if ((*keyNr<0) || (*keyNr>=MAXKEYS)) {*modus=-2; goto ErrorHandling;} key = &(KEY[*keyNr]); if (!key->active) {*modus=-3; goto ErrorHandling;} *modus = key->TrendModus; *lt = key->lTrendFct; *ll = key->lLinTrend; *lx = key->totalpoints; return; ErrorHandling: return; } void GetTrend(int *keyNr, char **trend, Real *lambda, Real *x, int *error) { key_type *key; if (currentNrCov==-1) {*error=-1;goto ErrorHandling;} if ((*keyNr<0) || (*keyNr>=MAXKEYS)) {*error=-2; goto ErrorHandling;} key = &(KEY[*keyNr]); if (!key->active) {*error=-3; goto ErrorHandling;} switch(key->TrendModus){ case 0 : break; case 3 : case 1 : memcpy(lambda, key->LinearTrend, key->lLinTrend); if (key->TrendModus==1) break; case 2: strcpy(*trend, key->TrendFunction); break; default: *error=-4; goto ErrorHandling; } *error = 0; return; ErrorHandling: return; } void GetCoordinates(int *keyNr, Real *x, int *error) { key_type *key; if (currentNrCov==-1) {*error=-1;goto ErrorHandling;} if ((*keyNr<0) || (*keyNr>=MAXKEYS)) {*error=-2; goto ErrorHandling;} key = &(KEY[*keyNr]); if (!key->active) {*error=-3; goto ErrorHandling;} if (key->TrendModus==0) {*error=-4; goto ErrorHandling;} *error = ERRORNOTPROGRAMMED; // TODO !! return; ErrorHandling: return; } void GetKeyInfo(int *keyNr, int *total, int *lengths, int *spatialdim, int *timespacedim, int *grid, int *distr, int *maxdim) { int d; key_type *key; if (*maxdim=MAXKEYS)) {*total=-1; return;} key = &(KEY[*keyNr]); if (!key->active) {*total=-2;} else { *total=key->totalpoints; *spatialdim = key->spatialdim; *timespacedim = key->timespacedim; for (d=0; dlength[d]; *grid = (int) key->grid; *distr = (int) key->distribution; *maxdim = MAXDIM; } } void GetCornersOfGrid(key_type *key, int Stimespacedim, int* start_aniso, Real *param, Real *sxx){ // returning sequence (#=2^MAXDIM) vectors of dimension s->simutimespacedim Real sx[ZWEIHOCHMAXDIM * MAXDIM]; int index,i,k,g,endforM1; long endfor,indexx; char j[MAXDIM]; endfor = 1 << key->timespacedim; endforM1 = endfor -1; for (i=0; itimespacedim; i++) j[i]=0; for (index=i=0; itimespacedim; k++) { sx[index] = key->x[k][XSTART]; if (j[k]) sx[index] += key->x[k][XSTEP] * (double) (key->length[k]-1); index++; } k=0; (j[k])++; if (i!=endforM1) while(j[k]>=2) { assert(j[k]==2); j[k]=0; k++; (j[k])++;} } for (index=indexx=i=0; itimespacedim, indexx+=Stimespacedim) { for (k=0; ktimespacedim; g++) dummy += param[start_aniso[k]+g] * sx[index+g]; sxx[indexx + k] = dummy; } } } void GetCornersOfElement(key_type *key, int Stimespacedim, int* start_aniso, Real *param, Real *sxx){ Real sx[ZWEIHOCHMAXDIM * MAXDIM]; int index,i,k,g,endforM1; long endfor,indexx; char j[MAXDIM]; endfor = 1 << key->timespacedim; endforM1 = endfor -1; for (i=0; itimespacedim; i++) j[i]=0; for (index=i=0; itimespacedim; k++) { if (j[k]) sx[index] = key->x[k][XSTEP]; else sx[index]=0.0; index++; } k=0; (j[k])++; if (i!=endforM1) while(j[k]>=2) { assert(j[k]==2); j[k]=0; k++; (j[k])++;} } for (index=indexx=i=0; itimespacedim, indexx+=Stimespacedim) { for (k=0; ktimespacedim; g++) dummy += param[start_aniso[k]+g] * sx[index+g]; sxx[indexx + k] = dummy; } } } void GetRangeCornerDistances(key_type *key, Real *sxx, int Stimespacedim, int Ssimuspatialdim, Real *min, Real *max) { long endfor,indexx,index; int d,i,k; endfor = 1 << key->timespacedim; *min = RF_INF; *max = RF_NEGINF; for (index=i=0; i 0) && (sum < *min)) *min = sum; if ((sum > 0) && (sum > *max)) *max = sum; } *min = sqrt(*min); *max = sqrt(*max); } void niceFFTnumber(int *n) { *n = (int) NiceFFTNumber( (unsigned long) *n); } bool ok_n(int n, int *f, int nf) // taken from fourier.c of R { int i; for (i = 0; i < nf; i++) while(n % f[i] == 0) if ((n = n / f[i]) == 1) return TRUE; return n == 1; } int nextn(int n, int *f, int nf) // taken from fourier.c of R { while(!ok_n(n, f, nf)) n++; return n; } bool HOMEMADE_NICEFFT=true; unsigned long NiceFFTNumber(unsigned long n) { unsigned long i,ii,j,jj,k,kk,l,ll,min, m=1, f[4]={2,3,5,7}; if (HOMEMADE_NICEFFT) { if (n<=1) return n; for (i=0; i<4; i++) while ( ((n % f[i])==0) && (n>10000)) { m*=f[i]; n/=f[i]; } if (n>10000) { while (n>10000) {m*=10; n/=10;} n++; } min = 10000000; for (i=0, ii=1; i<=14; i++, ii<<=1) { // 2^14>10.000 if (ii>=n) { if (ii10.000 if (jj>=n) { if (jj10.000 //if (kk>=n) { if (kk10.000 // instead of (if 7 is included) for (l=0, ll=jj; l<=6; l++, ll*=5) {// 5^5>10.000 if (ll>=n) { if (ll=0; d--) D[d]=C[d]; // dsvdc destroys the // input matrix !!!!!!!!!!!!!!!!!!!! { int row,jobint; row=longrow; jobint=job; F77_CALL(dsvdc)(D,&row,&row,&row,ev,e,U,&row,V,&row,G,&jobint, &error); } ErrorHandling: if (D!=NULL) free(D); if (V!=NULL) free(V); if (e!=NULL) free(e); if (U!=NULL) free(U); if (G!=NULL) free(G); return error; }