aboutsummaryrefslogtreecommitdiff
path: root/src/scattering.c
blob: 740374e11c78ca68b16c5ed0106000870c60d861 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/* Copyright (c) 2019, Anthony Latorre <tlatorre at uchicago>
 *
 * 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 3 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, see <https://ww
/* Copyright (c) 2019, Anthony Latorre <tlatorre at uchicago>
 *
 * 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 3 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, see <https://www.gnu.org/licenses/>.
 */

#include "scattering.h"
#include "quantum_efficiency.h"
#include <gsl/gsl_sf_bessel.h>
#include <gsl/gsl_integration.h>
#include "optics.h"
#include "sno.h"
#include <stddef.h> /* for size_t */
#include <stdlib.h> /* for exit() */
#include <stdio.h> /* for fprintf() */
#include <gsl/gsl_errno.h> /* for gsl_strerror() */
#include "pdg.h"
#include "misc.h"

static int initialized = 0;

static double xlo = -1.0;
static double xhi = 1.0;
static size_t nx = 1000;
static double ylo = 0.0;
static double yhi = MAX_THETA0;
static size_t ny = 1000;

static double *x;
static double *y;
static double *z;

static double x2lo = 0.0;
static double x2hi = 1.0;
static size_t nx2 = 1000;

static double *x2;
static double *y2;

/* Quantum efficiency weighted by the Cerenkov spectrum. */
static double weighted_qe;

static double prob_scatter(double wavelength, void *params)
{
    /* Calculate the number of photons emitted per unit solid angle per cm at
     * an angle `theta` for a particle travelling with velocity `beta` with an
     * angular distribution of width `theta0`. */
    double qe, delta, index;

    double beta_cos_theta = ((double *) params)[0];
    double beta_sin_theta_theta0 = ((double *) params)[1];

    qe = get_quantum_efficiency(wavelength);

    index = get_index_snoman_d2o(wavelength);

    delta = (1.0/index - beta_cos_theta)/beta_sin_theta_theta0;

    return FINE_STRUCTURE_CONSTANT*qe*exp(-pow(delta,2)/2.0)/pow(wavelength,2)*1e7/sqrt(2*M_PI)/beta_sin_theta_theta0;
}

static double prob_scatter2(double wavelength, void *params)
{
    /* Calculate the number of photons emitted per per cm for a particle
     * travelling with velocity `beta`. */
    double qe, index;

    double beta = ((double *) params)[0];

    qe = get_quantum_efficiency(wavelength);

    index = get_index_snoman_d2o(wavelength);

    return 2*M_PI*FINE_STRUCTURE_CONSTANT*(1-(1/(beta*beta*index*index)))*qe/pow(wavelength,2)*1e7;
}

double get_weighted_quantum_efficiency(void)
{
    /* Returns the quantum efficiency weighted by the Cerenkov wavelength
     * distribution, i.e. the probability that a photon randomly sampled from
     * the Cerenkov wavelenght distribution between 200 and 800 nm is detected. */
    if (!initialized) {
        fprintf(stderr, "quantum efficiency hasn't been initialized!\n");
        exit(1);
    }

    return weighted_qe;
}

static double gsl_quantum_efficiency(double wavelength, void *params)
{
    /* Returns the quantum efficiency times the Cerenkov wavelength
     * distribution. */
    double qe;

    qe = get_quantum_efficiency(wavelength);

    return qe/pow(wavelength,2);
}

void init_interpolation(void)
{
    size_t i, j;
    double params[2];
    double result, error;
    size_t nevals;
    int status;
    gsl_integration_cquad_workspace *w;
    gsl_function F;

    x = malloc(nx*sizeof(double));
    y = malloc(ny*sizeof(double));
    z = malloc(nx*ny*sizeof(double));

    for (i = 0; i < nx; i++) {
        x[i] = xlo + (xhi-xlo)*i/(nx-1);
    }

    for (i = 0; i < ny; i++) {
        y[i] = ylo + (yhi-ylo)*i/(ny-1);
    }

    w = gsl_integration_cquad_workspace_alloc(100);

    F.function = &prob_scatter;
    F.params = params;

    for (i = 0; i < nx; i++) {
        for (j = 0; j < ny; j++) {
            params[0] = x[i];
            params[1] = y[j];

            status = gsl_integration_cquad(&F, 200, 800, 0, 1e-2, w, &result, &error, &nevals);

            if (status) {
                fprintf(stderr, "error integrating photon angular distribution: %s\n", gsl_strerror(status));
                exit(1);
            }

            z[i*ny + j] = result;
        }
    }

    x2 = malloc(nx2*sizeof(double));
    y2 = malloc(nx2*sizeof(double));

    for (i = 0; i < nx2; i++) {
        x2[i] = x2lo + (x2hi-x2lo)*i/(nx2-1);
    }

    F.function = &prob_scatter2;
    F.params = params;

    for (i = 0; i < nx2; i++) {
        params[0] = x2[i];

        status = gsl_integration_cquad(&F, 200, 800, 0, 1e-2, w, &result, &error, &nevals);

        if (status) {
            fprintf(stderr, "error integrating photon angular distribution: %s\n", gsl_strerror(status));
            exit(1);
        }

        y2[i] = result;
    }

    F.function = &gsl_quantum_efficiency;
    F.params = params;

    status = gsl_integration_cquad(&F, 200, 800, 0, 1e-2, w, &result, &error, &nevals);

    if (status) {
        fprintf(stderr, "error integrating quantum efficiency distribution: %s\n", gsl_strerror(status));
        exit(1);
    }

    weighted_qe = result*800/3.0;

    initialized = 1;

    gsl_integration_cquad_workspace_free(w);
}

double get_probability(double beta, double cos_theta, double sin_theta, double theta0)
{
    /* Make sure theta0 is less than MAX_THETA0, otherwise it's possible that
     * interp2d() will quit. */
    if (theta0 > MAX_THETA0) theta0 = MAX_THETA0;

    return beta*interp2d(beta*cos_theta, beta*sin_theta*theta0, x, y, z, nx, ny);
}

double get_probability2(double beta)
{
    return interp1d(beta, x2, y2, nx2);
}

void free_interpolation(void)
{
    free(x);
    free(y);
    free(z);

    free(x2);
    free(y2);
}