/* Authors Martin Schlather, martin.schlather@cu.lu Simulation of a random field by spectral turning bands 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 "RFsimu.h" #ifndef MATHLIB_STANDALONE #include #endif #define CHECK if (0) InversionMethod DIRECTGAUSS_INVERSIONMETHOD=Cholesky; Real DIRECTGAUSS_PRECISION=1E-11; bool DIRECTGAUSS_CHECKPRECISION=false; 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, Real *requiredprecision, int *maxvariables) { switch (*action) { case 0 : 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_MAXVARIABLES=*maxvariables; break; case 1 : *method = (int) DIRECTGAUSS_INVERSIONMETHOD; *checkprecision = (int) DIRECTGAUSS_CHECKPRECISION; *requiredprecision = DIRECTGAUSS_PRECISION; *maxvariables = DIRECTGAUSS_MAXVARIABLES; if (GetNotPrint) break; case 2 : PRINTF("\nDirect matrix inversion\n=======================\ninversion method=%d\nmaximum number of variables %d\ncheck precision? %d\n", DIRECTGAUSS_INVERSIONMETHOD,DIRECTGAUSS_MAXVARIABLES, DIRECTGAUSS_CHECKPRECISION); if (DIRECTGAUSS_CHECKPRECISION) { PRINTF("\nprecision=%e(works only with Cholesky up to now)", DIRECTGAUSS_PRECISION);} break; default : PRINTF(" unknown action\n"); } } 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 sumgrid==TRUE // and no eror has occured if ((*S = (direct_storage*) malloc(sizeof(direct_storage)))==0){ Xerror=ERRORMEMORYALLOCATION; goto ErrorHandling; } (*S)->U = (*S)->G = NULL; if ((COV =(double *) malloc(sizeof(double) * totpnts * totpnts))==NULL){ Xerror=ERRORMEMORYALLOCATION;goto ErrorHandling; } ////////////////////////// if ((CCOV =(double *) malloc(sizeof(double) * totpnts * totpnts))==NULL){ Xerror=ERRORMEMORYALLOCATION;goto ErrorHandling; } nn = totpnts; ////////////////////////// /* calculate covariance matrix */ if (grid) { int index[MAXDIM]; Real *yy[MAXDIM]; double p[MAXDIM]; for(d=0; d=length[d]) { index[d]=0; p[d]=0.0; d++; // d--; assert(d=0); index[d]++; p[d]+=yy[d][XSTEP]; } for (d=0; d=3) PRINTF("method=Cholesky\n"); { int row,err; row=totpnts; F77_CALL(chol)(COV,&row,&row,U,&err); Xerror = err; } if (Xerror==NOERROR) { if ((DIRECTGAUSS_CHECKPRECISION) && !CHOLpreciseenough(COV,U,totpnts)) { Xerror=ERRORPRECISION; } } else Xerror=ERRORDECOMPOSITION; if (Xerror==NOERROR) break; else if (GENERAL_PRINTLEVEL>=1) PRINTF("Error code F77_CALL(chol) = %d\n",Xerror); // try next method : case SVD : /////////////////////////// { long t2; double dev, max, UV; t2 = totpnts * totpnts; for (i=0; i=3) PRINTF("method=SVD\n"); if ((V =(double *) malloc(sizeof(double) * totpnts * totpnts))==NULL){ Xerror=ERRORMEMORYALLOCATION;goto ErrorHandling; } if ((D =(double *) malloc(sizeof(double) * totpnts))==NULL){ Xerror=ERRORMEMORYALLOCATION;goto ErrorHandling; } if ((e = (double *) malloc(sizeof(double) * totpnts))==NULL){ Xerror=ERRORMEMORYALLOCATION;goto ErrorHandling; } { int row,err,jobint; row=totpnts; jobint=job; F77_CALL(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>=2) { long t2; double dev, max, UV; t2 = totpnts * totpnts; dev = 0.0; max = 0; for (i=0; i0.01) printf("%d %f %f %f\n", i, UV, U[i], V[i]); dev += UV; if (max=6) { PRINTF("\n D max=%f, D min=%f \n", D[0], D[totpnts-1]); } } free(e); e=NULL; free(V); V=NULL; // here free(COV) is already possible; // for debugging reasons it is postponed /* calculate SQRT of covariance matrix */ for (k=0,j=0;jU=U; ((direct_storage*)*S)->method=method; ((direct_storage*)*S)->G=G; if (D!=NULL) free(D); if (e!=NULL) free(e); if (V!=NULL) free(V); if (freexx) for (i=0; ianisotropy, key->timespacedim, param[v], ×pacedim, &no_last_comp, start_param, index_dim); cov = &(CovList[covnr[v]]); if ((key->Time) && no_last_comp && (cov->isotropic==SPACEISOTROPIC)) { Xerror= ERRORWITHOUTTIME; goto ErrorHandling;} else if ((cov->check!=NULL) && ((Xerror=cov->check(param[v], timespacedim, Direct)))!=NOERROR) goto ErrorHandling; } } if (key->totalpoints>DIRECTGAUSS_MAXVARIABLES) { Xerror=ERRORMETHODNOTALLOWED; goto ErrorHandling; } return(internal_init_directGauss((direct_storage**) (&(key->S[m])), key->grid, key->spatialdim, key->Time, key->x, key->length, key->totalpoints, key->T, CovFct, covnr, multiply, param, actcov, key->anisotropy)); ErrorHandling: return Xerror; } void internal_do_directGauss(direct_storage *S, bool add, long totpnts, double *res) { long i,j,k; double *G,*U; 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; iactive); internal_do_directGauss(((direct_storage*) key->S[m]), add, key->totalpoints, res); } void XXinternal_do_directGauss(direct_storage *S, bool add, long totpnts, double *res) { long i,j,k; double *G,*U; printf("XX %d \n", totpnts); U = S->U;// S^{1/2} G = S->G;// only the memory space is of interest (stored to avoid // allocation errors here) printf("X\n"); for (i=0; imethod) {\ case Cholesky :\ printf("sXX\n");\ for (k=0,i=0; i