diff options
author | tlatorre <tlatorre@uchicago.edu> | 2018-11-26 09:53:28 -0600 |
---|---|---|
committer | tlatorre <tlatorre@uchicago.edu> | 2018-11-26 09:53:28 -0600 |
commit | 9777b92d16cb3a3434c43b084d88f59321567e2d (patch) | |
tree | 6e020a8bf708cad52adcaf3f7e838bac76c6308b /src/calculate-csda-range.c | |
parent | 4372a0bb54b374061e1b00bca9da45aa0325e7c5 (diff) | |
download | sddm-9777b92d16cb3a3434c43b084d88f59321567e2d.tar.gz sddm-9777b92d16cb3a3434c43b084d88f59321567e2d.tar.bz2 sddm-9777b92d16cb3a3434c43b084d88f59321567e2d.zip |
update electron range tables
This commit also adds a script to calculate the CSDA range for electrons from a
table of the stopping power as a function of energy. We need this script since
the NIST ESTAR website will only output the stopping power above a certain
energy threshold (1 GeV for electrons).
See https://physics.nist.gov/PhysRefData/Star/Text/ESTAR.html.
Diffstat (limited to 'src/calculate-csda-range.c')
-rw-r--r-- | src/calculate-csda-range.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/src/calculate-csda-range.c b/src/calculate-csda-range.c new file mode 100644 index 0000000..7d71096 --- /dev/null +++ b/src/calculate-csda-range.c @@ -0,0 +1,176 @@ +#include <stdio.h> +#include <gsl/gsl_spline.h> +#include <stdlib.h> /* for size_t, strtod() */ +#include <errno.h> /* for errno */ +#include <string.h> /* for strerror(), strtok() */ +#include "sno.h" + +static double *x, *dEdx_rad, *dEdx, *csda_range; +static size_t size; + +static gsl_interp_accel *acc_dEdx_rad; +static gsl_spline *spline_dEdx_rad; + +static gsl_interp_accel *acc_dEdx; +static gsl_spline *spline_dEdx; + +static gsl_interp_accel *acc_range; +static gsl_spline *spline_range; + +static int init() +{ + int i, j; + char line[256]; + char *str; + double value; + int n; + + FILE *f = fopen("e_water_liquid.txt", "r"); + + if (!f) { + fprintf(stderr, "failed to open e_water_liquid.txt: %s\n", strerror(errno)); + return -1; + } + + i = 0; + n = 0; + /* For the first pass, we just count how many values there are. */ + while (fgets(line, sizeof(line), f)) { + size_t len = strlen(line); + if (len && (line[len-1] != '\n')) { + fprintf(stderr, "got incomplete line on line %i: '%s'\n", i, line); + goto err; + } + + i += 1; + + /* Skip the first 8 lines since it's just a header. */ + if (i <= 8) continue; + + if (!len) continue; + else if (line[0] == '#') continue; + + str = strtok(line," \n"); + + while (str) { + value = strtod(str, NULL); + str = strtok(NULL," \n"); + } + + n += 1; + } + + x = malloc(sizeof(double)*n); + dEdx_rad = malloc(sizeof(double)*n); + dEdx = malloc(sizeof(double)*n); + csda_range = malloc(sizeof(double)*n); + size = n; + + i = 0; + n = 0; + /* Now, we actually store the values. */ + rewind(f); + while (fgets(line, sizeof(line), f)) { + size_t len = strlen(line); + if (len && (line[len-1] != '\n')) { + fprintf(stderr, "got incomplete line on line %i: '%s'\n", i, line); + goto err; + } + + i += 1; + + /* Skip the first 8 lines since it's just a header. */ + if (i <= 8) continue; + + if (!len) continue; + else if (line[0] == '#') continue; + + str = strtok(line," \n"); + + j = 0; + while (str) { + value = strtod(str, NULL); + switch (j) { + case 0: + x[n] = value; + break; + case 2: + dEdx_rad[n] = value; + break; + case 3: + dEdx[n] = value; + break; + case 4: + csda_range[n] = value; + break; + } + j += 1; + str = strtok(NULL," \n"); + } + + n += 1; + } + + fclose(f); + + acc_dEdx_rad = gsl_interp_accel_alloc(); + spline_dEdx_rad = gsl_spline_alloc(gsl_interp_linear, size); + gsl_spline_init(spline_dEdx_rad, x, dEdx_rad, size); + + acc_dEdx = gsl_interp_accel_alloc(); + spline_dEdx = gsl_spline_alloc(gsl_interp_linear, size); + gsl_spline_init(spline_dEdx, x, dEdx, size); + + acc_range = gsl_interp_accel_alloc(); + spline_range = gsl_spline_alloc(gsl_interp_linear, size); + gsl_spline_init(spline_range, x, csda_range, size); + + return 0; + +err: + fclose(f); + + return -1; +} + +double electron_get_dEdx(double T, double rho) +{ + /* Returns the approximate dE/dx for a electron in water with kinetic energy + * `T`. + * + * `T` should be in MeV and `rho` in g/cm^3. + * + * Return value is in MeV/cm. + * + * See http://pdg.lbl.gov/2018/AtomicNuclearProperties/adndt.pdf. */ + if (T < spline_dEdx->x[0]) return spline_dEdx->y[0]; + + return gsl_spline_eval(spline_dEdx, T, acc_dEdx)*rho; +} + +int main(int argc, char **argv) +{ + int i; + double T0, T, dx, range; + + init(); + + dx = 1e-5; + + for (i = 0; i < size; i++) { + T0 = x[i]; + + T = T0; + + range = 0.0; + while (T > 0) { + double dEdx2 = electron_get_dEdx(T, WATER_DENSITY); + T -= dEdx2*dx; + range += dx; + } + + printf("%.3E %.3E\n", T0, range); + } + + return 0; +} |