void run_acor(sampler *samp){ /* Run acor module to compute autocorrelation time. Input: sampler *samp Pointer to sampler structure which has been initialized. Sampling must be performed before running this routine. Output: samp->acor_times Array is filled with ensemble autocorrelation time for each component. Print a short summary of the ensemble autocorrelation times. */ printf("From acor on ensemble:\n"); double mean, sigma, tau; // one ensemble mean per time step double *ensemble_means = (double *) malloc(samp->M * sizeof(double)); if(!ensemble_means){ perror("Allocation failure acor"); abort(); } // use every ensemble mean int L = samp->M; int acor_pass; // For each component for(int i=0; i<samp->num_to_save; i++){ // calculate the ensemble mean for this time step for(int t=0; t<samp->M; t++){ ensemble_means[t] = 0.0; for(int kk=0; kk<samp->K; kk++) ensemble_means[t] += (double) samp->samples_host[i + (kk * samp->num_to_save) + t*(samp->num_to_save * samp->K)]; ensemble_means[t] /= ((double) samp->K); } // generate the statistics. acor_pass = acor(&mean, &sigma, &tau, ensemble_means, L); samp->means[i] = mean; samp->sigma[i] = sigma; samp->acor_times[i] = tau; samp->acor_pass[i] = (char) acor_pass; samp->err_bar[i] = sigma / sqrt((double) samp->K); if(!acor_pass){ printf("Acor error on component %d. Stats unreliable or just plain wrong.\n", samp->indices_to_save_host[i]); } printf("Acor ensemble statistics for X_%d:\t", samp->indices_to_save_host[i]); printf("mean = %f,\tsigma = %f,\tautocorrelation time, tau = %f", mean, sigma, tau); if(acor_pass) // acor passed printf(",\teffective independent samples = %d\n", (int) (samp->total_samples / tau)); else printf("\n"); } printf("\n"); free(ensemble_means); }
int acor(double *mean, double *sigma, double *tau, double X[], int L, int maxlag) { int i, s; double D; double *C; int iMax = L - maxlag; /* Declare variables for the pairwise analysis */ int Lh = L/2, j1 = 0, j2 = 1; double newMean; /* Fail if the chain is too short */ if (L < MINFAC*maxlag) return 1; /* Allocate memory for the auto-covariance function */ if (!(C = (double*)malloc((maxlag+1)*sizeof(double)))) return -1; /* compute the mean of X and normalize the data */ *mean = 0.; for (i = 0; i < L; i++) *mean += X[i]; *mean = *mean/L; for (i = 0; i < L; i++ ) X[i] -= *mean; /* Compute the auto-covariance function */ for (s = 0; s <= maxlag; s++) C[s] = 0.; for (i = 0; i < iMax; i++) for (s = 0; s <= maxlag; s++) C[s] += X[i]*X[i+s]; for (s = 0; s <= maxlag; s++) C[s] = C[s]/iMax; /* Normalize */ /* Calculate the "diffusion coefficient" as the sum of the autocovariances */ D = C[0]; for (s = 1; s <= maxlag; s++ ) D += 2*C[s]; /* Calculate the standard error, if D were the complete sum. */ /* FIXME: why is D sometimes negative?? */ if ( D < 0 ) { return 2; } *sigma = sqrt( D / L ); /* A provisional estimate, since D is only part of the complete sum. */ *tau = D / C[0]; if ( *tau*WINMULT < maxlag ) { free(C); return 0; /* Stop if the D sum includes the given multiple of tau. */ } /* If the provisional tau is so large that we don't think tau is accurate, * apply the acor procedure to the pairwise sums of X */ for (i = 0; i < Lh; i++) { X[i] = X[j1] + X[j2]; j1 += 2; j2 += 2; } acor( &newMean, sigma, tau, X, Lh, maxlag); D = .25*(*sigma) * (*sigma) * L; *tau = D/C[0]; *sigma = sqrt( D/L ); free(C); return 0; }