Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
Arquivo: acor.c Projeto: KMLembke/acor
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;
}