analistica/ex-4/main.c

203 lines
5.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "lib.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_min.h>
#include <gsl/gsl_deriv.h>
// Process CLI arguments.
//
int parser(size_t *N, size_t *n, double *p_max, char argc, char **argv)
{
for (size_t i = 1; i < argc; i++)
{
if (!strcmp(argv[i], "-N")) *N = atol(argv[++i]);
else if (!strcmp(argv[i], "-n")) *n = atol(argv[++i]);
else if (!strcmp(argv[i], "-p")) *p_max = atof(argv[++i]);
else
{
fprintf(stderr, "Usage: %s -[hiIntp]\n", argv[0]);
fprintf(stderr, "\t-h\tShow this message.\n");
fprintf(stderr, "\t-N integer\tThe number of events to generate.\n");
fprintf(stderr, "\t-n integer\tThe number of bins of the histogram.\n");
fprintf(stderr, "\t-p float\tThe maximum value of momentum.\n");
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
int main(int argc, char **argv)
{
// Set default options.
//
size_t N = 50000; // number of events.
size_t n = 50; // number of bins.
double p_max = 10; // maximum value of momentum module.
int res = parser(&N, &n, &p_max, argc, argv);
if (res == 0) printf("\nGenerating histogram with:\n"
"%ld points\n"
"%ld bins\n"
"p_max = %.3f\n\n", N, n, p_max);
// printf("step: \t%.5f\n", step);
// Initialize an RNG.
//
gsl_rng_env_setup();
gsl_rng *r = gsl_rng_alloc(gsl_rng_default);
// Generate the angle θ uniformly distributed on a sphere using the
// inverse transform:
//
// θ = acos(1 - 2X)
//
// where X is a random uniform variable in [0,1), and the module p of
// the vector:
//
// p² = p_v² + p_h²
//
// uniformly distributed between 0 and p_max. The two components are
// then computed as:
//
// p_v = p⋅cos(θ)
// p_h = p⋅sin(θ)
//
// The histogram is updated this way.
// The j-th bin where p_h goes in is given by:
//
// step = p_max / n
// j = floor(p_h / step)
//
// Thus an histogram was created and a structure containing the number of
// entries in each bin and the sum of |p_v| in each of them is created and
// filled while generating the events (struct bin).
//
struct bin *histo = calloc(n, sizeof(struct bin));
// Some useful variables.
//
double step = p_max / n;
struct bin *b;
double theta;
double p;
double p_v;
double p_h;
size_t j;
for (size_t i = 0; i < N; i++)
{
// Generate the event.
//
theta = acos(1 - 2*gsl_rng_uniform(r));
p = p_max * gsl_rng_uniform(r);
// Compute the components.
//
p_v = p * cos(theta);
p_h = p * sin(theta);
// Update the histogram.
//
j = floor(p_h / step);
b = &histo[j];
b -> amo++;
b -> sum += fabs(p_v);
}
// Compute the mean value of each bin and print it to stodut
// together with other useful things to make the histogram.
//
// printf("bins: \t%ld\n", n);
// printf("step: \t%.5f\n", step);
for (size_t i = 0; i < n; i++)
{
histo[i].sum = histo[i].sum / histo[i].amo; // Average P_v
//printf("\n%.5f", histo[i].sum);
};
// Compare the histigram with the expected function:
//
// x * log(p_max/x)/arctan(sqrt(p_max^2/x^2 - 1))
//
// using the χ² test.
//
struct parameters params;
params.histo = histo;
params.n = n;
params.step = step;
gsl_function func;
func.function = &chi2;
func.params = &params;
double min_p = 5;
double max_p = 15;
// Initialize minimization.
//
double x = 10;
int max_iter = 100;
double prec = 1e-7;
int status;
const gsl_min_fminimizer_type *T = gsl_min_fminimizer_brent;
gsl_min_fminimizer *s = gsl_min_fminimizer_alloc(T);
gsl_min_fminimizer_set(s, &func, x, min_p, max_p);
// Minimization.
//
for (int iter = 0; status == GSL_CONTINUE && iter < max_iter; iter++)
{
status = gsl_min_fminimizer_iterate(s);
x = gsl_min_fminimizer_x_minimum(s);
min_p = gsl_min_fminimizer_x_lower(s);
max_p = gsl_min_fminimizer_x_upper(s);
status = gsl_min_test_interval(min_p, max_p, 0, prec);
}
double result = x;
printf("p_max: %.7f\n", result);
// Compute the second derivative of χ² in its minimum for the result error.
//
// p_max = α
//
// (Ei - Oi)²
// χ² = Σi ----------
// Ei
//
// / Oi² \
// ∂αχ² = Σi | 1 - --- | ∂αE
// \ Ei² /
//
// / Oi² / Oi² \ \
// ∂²αχ² = Σi | (∂αE)² 2 --- + ∂²αE | 1 - --- | |
// \ Ei³ \ Ei² / /
//
double expecto, A, B;
double error = 0;
for (size_t i = 0; i < n; i++)
{
x = (i + 0.5) * step;
expecto = expected(x, result);
A = 2 * pow(exp1d(x, result) * histo[i].sum / expecto, 2);
B = exp2d(x, result) * (1 - pow((histo[i].sum / expecto), 2));
error = error + A + B;
};
error = 1/error;
printf("ΔP_max: %.7f\n\n", error);
// Free memory.
//
gsl_min_fminimizer_free(s);
gsl_rng_free(r);
free(histo);
return EXIT_SUCCESS;
}