aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortlatorre <tlatorre@uchicago.edu>2020-04-14 12:01:43 -0500
committertlatorre <tlatorre@uchicago.edu>2020-04-14 12:01:43 -0500
commit2a5152b03b6d4027b52e625c3b94a436313373be (patch)
tree137dfc7a1172bb3b7bf47c39dc085f7b5e782c72
parenteee7dfa1dd0927af1043a1a3836b7e1aa136946f (diff)
downloadsddm-2a5152b03b6d4027b52e625c3b94a436313373be.tar.gz
sddm-2a5152b03b6d4027b52e625c3b94a436313373be.tar.bz2
sddm-2a5152b03b6d4027b52e625c3b94a436313373be.zip
extend electron range tables up to 1 TeV
-rw-r--r--src/.gitignore1
-rw-r--r--src/Makefile4
-rw-r--r--src/e_water_liquid.txt20
-rw-r--r--src/extend-electron-range-table.c235
4 files changed, 259 insertions, 1 deletions
diff --git a/src/.gitignore b/src/.gitignore
index 47de265..209802f 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -10,3 +10,4 @@ release.h
calculate-csda-range
test-time-pdf
zdab-cat
+extend-electron-range-table
diff --git a/src/Makefile b/src/Makefile
index cb701cb..834bdb4 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -7,7 +7,7 @@ PREFIX?=$(HOME)/local
INSTALL_BIN=$(PREFIX)/bin
INSTALL=install
-all: test test-vector test-likelihood fit test-charge test-path calculate-csda-range test-time-pdf test-zebra test-find-peaks zdab-cat
+all: test test-vector test-likelihood fit test-charge test-path calculate-csda-range test-time-pdf test-zebra test-find-peaks zdab-cat extend-electron-range-table
Makefile.dep:
-$(CC) -MM *.c > Makefile.dep
@@ -40,6 +40,8 @@ calculate-csda-range: calculate-csda-range.o
zdab-cat: zdab-cat.o zebra.o pmt.o vector.o misc.o zdab_utils.o pack2b.o db.o dqxx.o dict.o siphash.o release.o dc.o sort.o util.o hdf5_utils.o sno_charge.o
+extend-electron-range-table: extend-electron-range-table.o misc.o
+
install:
@mkdir -p $(INSTALL_BIN)
$(INSTALL) fit $(INSTALL_BIN)
diff --git a/src/e_water_liquid.txt b/src/e_water_liquid.txt
index a4e3a8f..633440f 100644
--- a/src/e_water_liquid.txt
+++ b/src/e_water_liquid.txt
@@ -100,3 +100,23 @@ MeV MeV cm2/g MeV cm2/g MeV cm2/g g/cm2
8.000E+03 2.578E+00 2.192E+02 2.217E+02 1.740E+02 - 1.582E+01
9.000E+03 2.588E+00 2.467E+02 2.493E+02 1.782E+02 - 1.605E+01
1.000E+04 2.597E+00 2.742E+02 2.768E+02 1.820E+02 - 1.626E+01
+# Note: The values below were extrapolated by me from the actual ESTAR data above. They are most likely not 100% correct!
+2.000E+04 - 5.492E+02 5.518E+02 2.071E+02 - -
+3.000E+04 - 8.242E+02 8.268E+02 2.218E+02 - -
+4.000E+04 - 1.099E+03 1.102E+03 2.323E+02 - -
+5.000E+04 - 1.374E+03 1.377E+03 2.404E+02 - -
+6.000E+04 - 1.649E+03 1.652E+03 2.470E+02 - -
+7.000E+04 - 1.924E+03 1.927E+03 2.526E+02 - -
+8.000E+04 - 2.199E+03 2.202E+03 2.574E+02 - -
+9.000E+04 - 2.474E+03 2.477E+03 2.617E+02 - -
+1.000E+05 - 2.749E+03 2.752E+03 2.656E+02 - -
+2.000E+05 - 5.499E+03 5.502E+03 2.907E+02 - -
+3.000E+05 - 8.249E+03 8.252E+03 3.055E+02 - -
+4.000E+05 - 1.100E+04 1.100E+04 3.159E+02 - -
+5.000E+05 - 1.375E+04 1.375E+04 3.241E+02 - -
+6.000E+05 - 1.650E+04 1.650E+04 3.307E+02 - -
+7.000E+05 - 1.925E+04 1.925E+04 3.363E+02 - -
+8.000E+05 - 2.200E+04 2.200E+04 3.412E+02 - -
+9.000E+05 - 2.475E+04 2.475E+04 3.454E+02 - -
+1.000E+06 - 2.750E+04 2.750E+04 3.493E+02 - -
+
diff --git a/src/extend-electron-range-table.c b/src/extend-electron-range-table.c
new file mode 100644
index 0000000..89901df
--- /dev/null
+++ b/src/extend-electron-range-table.c
@@ -0,0 +1,235 @@
+/* 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 <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"
+#include "misc.h"
+
+static double *x, *dEdx_rad, *dEdx;
+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 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);
+ 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;
+ }
+ 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);
+
+ return 0;
+
+err:
+ fclose(f);
+
+ return -1;
+}
+
+/* Returns the approximate dE/dx for a electron in water with kinetic energy
+ * `T`. If `T` is outside the bounds of the range table, extrapolate linearly
+ * using the last two points.
+ *
+ * `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. */
+double electron_get_dEdx(double T, double rho)
+{
+ if (T < spline_dEdx->x[0]) {
+ return spline_dEdx->y[0];
+ } else if (T < spline_dEdx->x[size-1]) {
+ return gsl_spline_eval(spline_dEdx, T, acc_dEdx)*rho;
+ }
+
+ /* We extrapolate using the last two points. */
+ return spline_dEdx->y[size-1] + (spline_dEdx->y[size-1]-spline_dEdx->y[size-2])*(T-spline_dEdx->x[size-1])/(spline_dEdx->x[size-1]-spline_dEdx->x[size-2]);
+}
+
+/* Returns the approximate radiative dE/dx for a electron in water with kinetic
+ * energy `T`. If `T` is outside the bounds of the range table, extrapolate
+ * linearly using the last two points.
+ *
+ * `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. */
+double electron_get_dEdx_rad(double T, double rho)
+{
+ if (T < spline_dEdx_rad->x[0]) {
+ return spline_dEdx_rad->y[0];
+ } else if (T < spline_dEdx_rad->x[size-1]) {
+ return gsl_spline_eval(spline_dEdx_rad, T, acc_dEdx_rad)*rho;
+ }
+
+ /* We extrapolate using the last two points. */
+ return spline_dEdx_rad->y[size-1] + (spline_dEdx_rad->y[size-1]-spline_dEdx_rad->y[size-2])*(T-spline_dEdx_rad->x[size-1])/(spline_dEdx_rad->x[size-1]-spline_dEdx_rad->x[size-2]);
+}
+
+double electron_get_range(double T0)
+{
+ double T, dx, range;
+
+ T = T0;
+
+ dx = 1e-5;
+
+ range = 0.0;
+ while (T > 0) {
+ double dEdx2 = electron_get_dEdx(T, WATER_DENSITY);
+ T -= dEdx2*dx;
+ range += dx;
+ }
+
+ return range;
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+ double T0;
+ double Ts[18] = {
+ 2.000E+04,
+ 3.000E+04,
+ 4.000E+04,
+ 5.000E+04,
+ 6.000E+04,
+ 7.000E+04,
+ 8.000E+04,
+ 9.000E+04,
+ 1.000E+05,
+ 2.000E+05,
+ 3.000E+05,
+ 4.000E+05,
+ 5.000E+05,
+ 6.000E+05,
+ 7.000E+05,
+ 8.000E+05,
+ 9.000E+05,
+ 1.000E+06};
+
+ init();
+
+ for (i = 0; i < LEN(Ts); i++) {
+ T0 = Ts[i];
+
+ printf("%.3E - %.3E %.3E %.3E - -\n", T0, electron_get_dEdx_rad(T0,WATER_DENSITY), electron_get_dEdx(T0,WATER_DENSITY), electron_get_range(T0));
+ }
+
+ return 0;
+}