/* Authors Martin Schlather, schlath@hsu-hh.de Simulation of a random field by spectral turning bands Copyright (C) 2001 -- 2005 Martin Schlather, This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "RFsimu.h" #include #define CHECK if (0) InversionMethod DIRECTGAUSS_INVERSIONMETHOD=Cholesky; double DIRECTGAUSS_PRECISION=1E-11; bool DIRECTGAUSS_CHECKPRECISION=false; int DIRECTGAUSS_BESTVARIABLES=600; // see RFsimu.h int DIRECTGAUSS_MAXVARIABLES=1800; // see RFsimu.h void direct_destruct(void ** S) { if (*S!=NULL) { direct_storage *x; x = *((direct_storage**)S); if (x->U!=NULL) free(x->U); if (x->G!=NULL) free(x->G); free(*S); *S = NULL; } } void SetParamDirectGauss(int *action,int *method,int *checkprecision, double *requiredprecision, int *bestvariables, int *maxvariables) { if (*action) { if ((*method<0) || (*method>=(int) NoFurtherInversionMethod)){ PRINTF("inversion method out of range; ignored\n"); } else {DIRECTGAUSS_INVERSIONMETHOD= (InversionMethod) *method;} if ((*checkprecision<0) || (*checkprecision>1)){ PRINTF("check precion must be 0 or 1; ignored\n"); } else { if ((GENERAL_PRINTLEVEL>=3) && (DIRECTGAUSS_CHECKPRECISION!=(bool) *checkprecision)) PRINTF("Note: precision setting works only with Cholesky up to now\n"); DIRECTGAUSS_CHECKPRECISION=(bool) *checkprecision; } DIRECTGAUSS_PRECISION=*requiredprecision; if (DIRECTGAUSS_PRECISION<=0) PRINTF("Warning! Non positive value for precision. Algorithm will probably fail."); DIRECTGAUSS_BESTVARIABLES=*bestvariables; DIRECTGAUSS_MAXVARIABLES=*maxvariables; } else { *method = (int) DIRECTGAUSS_INVERSIONMETHOD; *checkprecision = (int) DIRECTGAUSS_CHECKPRECISION; *requiredprecision = DIRECTGAUSS_PRECISION; *bestvariables = DIRECTGAUSS_BESTVARIABLES; *maxvariables = DIRECTGAUSS_MAXVARIABLES; } } int CHOLpreciseenough(double *COV, double *U,long nrow) { double sum; int i,j,k; long segment,endfor; sum = 0; endfor = nrow * nrow; for (segment=i=0; iDIRECTGAUSS_PRECISION) {PRINTF("Cholesky, difference=%e\n",sum);} if (GENERAL_PRINTLEVEL>=3) PRINTF("\nChol prec %]e\n",sum); return sumtimespacedim; bool freexx=false; direct_storage* S; methodvalue_type *meth; G=COV=U=V=e=D=NULL; S=NULL; for (d=0; dmeth[m]); SET_DESTRUCT(direct_destruct, m); totpnts = key->totalpoints; if (totpnts>DIRECTGAUSS_MAXVARIABLES) { if (GENERAL_PRINTLEVEL>3) PRINTF("cur. points=%d, max points=%d", (int) totpnts, (int) DIRECTGAUSS_MAXVARIABLES); Xerror=ERRORMETHODNOTALLOWED; goto ErrorHandling; } Xerror=ERRORMEMORYALLOCATION; if ((COV =(double *) malloc(sizeof(double) * totpnts * totpnts))==NULL) goto ErrorHandling; if ((U =(double *) malloc(sizeof(double) * totpnts * totpnts))==NULL) goto ErrorHandling; //for SVD/Chol intermediate results AND memory space for do_directGauss: if ((G = (double *) malloc(sizeof(double) * (totpnts + 1)))==NULL) goto ErrorHandling; if ((meth->S = malloc(sizeof(direct_storage))) == NULL) goto ErrorHandling; S = (direct_storage*) meth->S; S->U = S->G = NULL; if ((Xerror = FirstCheck_Cov(key, m, true)) !=NOERROR) goto ErrorHandling; /* ************************* */ /* create matrix of explicit */ /* x-coordinates */ /* ************************* */ if (key->grid) { int index[MAXDIM]; double step[MAXDIM], p[MAXDIM]; // generate all the grid coordinates exlicitely! freexx = true; for (d=0; dx[d][XSTEP]; } // intialisation of index and p, and defining x[d][i=0] // index preciser than the real coordinate values (which are created in p[]) // index only used to compare with length* for (i=1; i= key->length[d]) { index[d]=0; p[d]=0.0; d++; // d--; assert(d=0); (index[d])++; p[d] += step[d]; } for (d=0; dTime) { int endfor, t, spatialdim, j; double time, step; freexx = true; spatialdim = key->spatialdim; for (d=0; dlength[spatialdim]; step = key->T[XSTEP]; for (t=0, i=0, time=key->T[XSTART]; tlength[0]; j++, i++) { for (d=0; dx[d][j]; xx[spatialdim][i] = time; } } else { freexx = false; for (i=0; ix[i]; } } /* ********************* */ /* matrix creation part */ /* ********************* */ long j, k, segment; int actcov, row, err; InversionMethod method; actcov = meth->actcov; k = 0; for (i=0; icovFct(y, dim, key->cov, meth->covlist, actcov, key->anisotropy); segment += totpnts; } } /* ********************* */ /* matrix inversion part */ /* ********************* */ method = DIRECTGAUSS_INVERSIONMETHOD; switch (method) { case Cholesky : int choljob; choljob = 0; if (GENERAL_PRINTLEVEL>=3) PRINTF("method=Cholesky\n"); row=totpnts; // dchdc destroys the input matrix; upper half of U contains result! memcpy(U, COV, sizeof(double) * row * row); F77_NAME(dchdc)(U, &row, &row, G, NULL, &choljob, &err); Xerror = err < row; if (Xerror==NOERROR) { if ((DIRECTGAUSS_CHECKPRECISION) && !CHOLpreciseenough(COV, U, totpnts)){ Xerror=ERRORPRECISION; } } else Xerror=ERRORDECOMPOSITION; if (Xerror==NOERROR) break; else if (GENERAL_PRINTLEVEL>=2) PRINTF("Error code F77_CALL(chol) = %d\n", err); // try next method : // most common error: singular matrix case SVD : int jobint; jobint = 11; method = SVD; // necessary if the value of method has been Cholesky. // originally if (GENERAL_PRINTLEVEL>=3) PRINTF("method=SVD\n"); Xerror=ERRORMEMORYALLOCATION; if ((V =(double *) malloc(sizeof(double) * totpnts * totpnts))==NULL) goto ErrorHandling; if ((D =(double *) malloc(sizeof(double) * totpnts))==NULL) goto ErrorHandling; if ((e = (double *) malloc(sizeof(double) * totpnts))==NULL) goto ErrorHandling; row=totpnts; // dsvdc destroys the input matrix !!!!!!!!!!!!!!!!!!!! F77_NAME(dsvdc)(COV, &row, &row, &row, D, e ,U, &row, V, &row, G, &jobint, &err); Xerror = err; if (Xerror!=NOERROR) { if (GENERAL_PRINTLEVEL>1) PRINTF("Error code F77_CALL(dsvdc) = %d\n",Xerror); Xerror=ERRORDECOMPOSITION; goto ErrorHandling; } if (GENERAL_PRINTLEVEL>=10) { long t2; double dev, max, UV; t2 = totpnts * totpnts; if (t2>99999) t2=99999; dev = 0.0; max = 0; for (i=0; i0.01) PRINTF("%d %f %f %f\n", (int) i, UV, U[i], V[i]); dev += UV; if (maxU=U; S->method=method; S->G=G; free(COV); if (D!=NULL) free(D); if (e!=NULL) free(e); if (V!=NULL) free(V); if (freexx) for (i=0; iactive); S = (direct_storage*) key->meth[m].S; totpnts = key->totalpoints; U = S->U;// S^{1/2} G = S->G;// only the memory space is of interest (stored to avoid // allocation errors here) for (i=0; imethod) { case Cholesky : for (k=0, i=0; i