diff --git a/binder/postBuild b/binder/postBuild index bf349a42..d0f45952 100644 --- a/binder/postBuild +++ b/binder/postBuild @@ -4,4 +4,4 @@ export PREFIX=$CONDA_DEFAULT_ENV git clone https://github.com/jsalvado/SQuIDS.git $HOME/SQuIDS; cd $HOME/SQuIDS; ./configure --prefix=$HOME/software --with-gsl-incdir=$PREFIX/include --with-gsl-libdir=$PREFIX/lib; export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH; make; make test; make install; cd -; export LD_LIBRARY_PATH="$HOME/software/lib" - ./configure --prefix=$HOME/software --with-python-bindings --with-boost=$PREFIX/ --with-gsl=$PREFIX --with-squids=$HOME/software --python-bin=python; make python; make test; make install; + ./configure --prefix=$HOME/software --with-python-bindings --with-boost=$PREFIX/ --with-gsl=$PREFIX --with-squids=$HOME/software --python-bin=python; make; make test; make install; cd resources/python/src; make; diff --git a/binder/start b/binder/start index 2f5fec7e..8c700c5f 100644 --- a/binder/start +++ b/binder/start @@ -1,5 +1,5 @@ export PKG_CONFIG_PATH="$HOME/software/lib/pkgconfig:$PKG_CONFIG_PATH"; -export PYTHONPATH=$HOME/lib:$HOME/resources/python/bindings:$PYTHONPATH +export PYTHONPATH=$HOME/resources/python/bindings/:$PYTHONPATH export LD_LIBRARY_PATH="$HOME/software/lib":"/srv/conda/envs/notebook" echo $PYTHONPATH exec "$@" \ No newline at end of file diff --git a/configure b/configure index 962c4952..85ec0024 100755 --- a/configure +++ b/configure @@ -1,69 +1,14 @@ #!/bin/bash -check_os_arch(){ - if [ -x /usr/bin/lsb_release ]; then - OS_DISTRIB=$(lsb_release -si|tr '[:upper:]' '[:lower:]') - OS_VERSION=`lsb_release -sr` - elif [ -e /etc/os-release ]; then - OS_DISTRIB=$(cat /etc/os-release|grep '^ID='|cut -d '=' -f 2|sed s/\"//g|tr '[:upper:]' '[:lower:]') - OS_VERSION=$(cat /etc/os-release|grep '^VERSION='|cut -d '=' -f 2|cut -d ' ' -f 1|sed s/\"//g) - elif [ -e /etc/redhat-release ]; then - OS_DISTRIB="centos" - OS_VERSION=$(cat /etc/redhat-release|sed s/\ /\\\\n/g|grep '\.') - else - OS_DISTRIB=$(uname -s|tr '[:upper:]' '[:lower:]') - OS_VERSION=$(uname -r) - fi - ARCH=$(uname -m) - OS_NAME=$(uname -s) - - case $OS_DISTRIB in - "redhatenterpriseclient" | "redhatenterpriseserver" | "rhel" | "scientificsl" | "scientific" | "centos" | "scientificfermi" | "scientificcernslc") - OS_DISTRIB="RHEL" - OS_VERSION=$(echo "${VERSION}" | cut -d '.' -f 1) - ;; - "ubuntu") - OS_DISTRIB="Ubuntu" - ;; - "debian") - OS_DISTRIB="Ubuntu" - ;; - "linuxmint") - OS_DISTRIB="Ubuntu" - ;; - "freebsd") - OS_DISTRIB="FreeBSD" - OS_VERSION=$(uname -r | cut -d '.' -f 1) - ARCH=$(uname -p) - ;; - "darwin") - OS_DISTRIB="OSX" - OS_VERSION=$(uname -r | cut -d '.' -f 1) - ;; - "linux") - if echo $OS_VERSION | grep -q '\.el7\.\?'; then - OS_DISTRIB="RHEL" - OS_VERSION=7 - elif echo $OS_VERSION | grep -q '\.el6\.\?'; then - OS_DISTRIB="RHEL" - OS_VERSION=6 - elif echo $OS_VERSION | grep -q '\.el5\.\?'; then - OS_DISTRIB="RHEL" - OS_VERSION=5 - fi - esac - OS_ARCH=${OS_DISTRIB}_${OS_VERSION}_${ARCH} -} - check_pkgconfig(){ if [ "$CHECKED_PKGCONFIG" ]; then return; fi echo "Looking for pkg-config..." - PKG_CONFIG_BIN=$(which pkg-config 2>&1) + PKG_CONFIG_PATH=$(which pkg-config 2>&1) if [ "$?" -ne 0 ]; then echo "Error: pkg-config not found; you will need to specify library locations manually" 1>&2 exit 1 fi - echo " Found $PKG_CONFIG_BIN" + echo " Found $PKG_CONFIG_PATH" CHECKED_PKGCONFIG=1 } @@ -213,7 +158,7 @@ try_find_python(){ TMP=`echo "$PYTHON_STDLIBDIR" | sed -n s'|\(.*/lib\)/python'"${PYTHON_VERSION}"'|\1|p'` if [ "$TMP" ]; then POSSIBLE_PYTHON_LIBDIRS="${POSSIBLE_PYTHON_LIBDIRS} ${TMP}"; fi # Ubuntu is special, of course - if [ $OS_DISTRIB = "Ubuntu" ]; then + if uname -a | grep -i 'ubuntu' > /dev/null; then POSSIBLE_PYTHON_LIBDIRS="${POSSIBLE_PYTHON_LIBDIRS} /usr/lib/$(uname -i)-linux-gnu" fi @@ -272,7 +217,7 @@ try_find_boost(){ return fi if [ "$PYTHON_FOUND" ]; then - for PYV_SUFFIX in $PYV $PYVM $PYV-mt $PVM-mt ''; do + for PYV_SUFFIX in $PYV $PYVM ''; do for BOOST_LIBDIR in $POSSIBLE_BOOST_LIBDIRS; do if [ -d $BOOST_LIBDIR -a \( -e $BOOST_LIBDIR/libboost_python${PYV_SUFFIX}.a -o -e $BOOST_LIBDIR/libboost_python${PYV_SUFFIX}.so -o -e $BOOST_LIBDIR/libboost_python${PYV_SUFFIX}.dylib \) ]; then if [ ! "$PYV_SUFFIX" ]; then @@ -354,7 +299,7 @@ VERSION=`echo $VERSION_NUM | awk '{ print major"."minor"."patch; }'` -check_os_arch +OS_NAME=`uname -s` GUESS_CC=gcc GUESS_CXX=g++ @@ -735,8 +680,7 @@ echo "SQUIDS_LDFLAGS=$SQUIDS_LDFLAGS" >> ./Makefile if [ "$PYTHON_BINDINGS" ]; then echo "PYTHON_CFLAGS=$PYTHON_CFLAGS" >> ./Makefile echo "PYTHON_LDFLAGS=$PYTHON_LDFLAGS" >> ./Makefile - echo "BOOST_CFLAGS=$BOOST_CFLAGS" >> ./Makefile - echo "BOOST_PYTHON_LDFLAGS=$BOOST_LDFLAGS $BOOST_PYTHON_LDFLAGS" >> ./Makefile + echo "BOOST_PYTHON_LDFLAGS=$BOOST_PYTHON_LDFLAGS" >> ./Makefile echo "PYTHON_MODULEDIR=$PYTHON_MODULEDIR" >> ./Makefile echo "NUMPY_CFLAGS=$NUMPY_CFLAGS" >> ./Makefile fi @@ -854,8 +798,8 @@ install: $(DYN_PRODUCT) $(STAT_PRODUCT) @cp "$(INCnuSQUIDS)"/nuSQuIDS/*.h "$(PREFIX)/include/nuSQuIDS" @echo Installing libraries in $(PREFIX)/$(INSTALL_LIBDIR) @mkdir -p "$(PREFIX)/$(INSTALL_LIBDIR)" - @LC_ALL=C sed "'${REPLACE_INSTALL_FLAG}'" < $(DYN_PRODUCT) > "$(PREFIX)/$(INSTALL_LIBDIR)/lib$(NAME)$(DYN_SUFFIX)" - @LC_ALL=C sed "'${REPLACE_INSTALL_FLAG}'" < $(STAT_PRODUCT) > "$(PREFIX)/$(INSTALL_LIBDIR)/lib$(NAME).a" + @LANG=C sed "'${REPLACE_INSTALL_FLAG}'" < $(DYN_PRODUCT) > "$(PREFIX)/$(INSTALL_LIBDIR)/lib$(NAME)$(DYN_SUFFIX)" + @LANG=C sed "'${REPLACE_INSTALL_FLAG}'" < $(STAT_PRODUCT) > "$(PREFIX)/$(INSTALL_LIBDIR)/lib$(NAME).a" @chmod 755 "$(PREFIX)/$(INSTALL_LIBDIR)/lib$(NAME)$(DYN_SUFFIX)" "$(PREFIX)/$(INSTALL_LIBDIR)/lib$(NAME).a" @echo Installing config information in $(PREFIX)/$(INSTALL_LIBDIR)/pkgconfig @mkdir -p "$(PREFIX)/$(INSTALL_LIBDIR)/pkgconfig" @@ -875,8 +819,8 @@ uninstall: @echo Removing headers from $(PREFIX)/include/nuSQuIDS @rm -rf "$(PREFIX)/include/nuSQuIDS" @echo Removing libraries from $(PREFIX)/$(INSTALL_LIBDIR) - @rm -f "$(PREFIX)/$(INSTALL_LIBDIR)/lib$(NAME)$(DYN_SUFFIX)" - @rm -f "$(PREFIX)/$(INSTALL_LIBDIR)/lib$(NAME).a" + @rm -f "$(PREFIX)/$(INSTALL_LIBDIR)/$(DYN_PRODUCT)" + @rm -f "$(PREFIX)/$(INSTALL_LIBDIR)/$(STAT_PRODUCT)" @echo Removing config information from $(PREFIX)/$(INSTALL_LIBDIR)/pkgconfig @rm -f "$(PREFIX)/$(INSTALL_LIBDIR)/pkgconfig/nusquids.pc" ' >> ./Makefile @@ -892,7 +836,7 @@ $(PYTHON_LIB) : build/nuSQUIDSpy.o $(STAT_PRODUCT) build/nuSQUIDSpy.o : resources/python/src/nuSQUIDSpy.cpp @echo Compiling python bindings - @$(CXX) $(CXXFLAGS) -c -Iresources/python/inc $(PYTHON_CFLAGS) $(BOOST_CFLAGS) $(NUMPY_CFLAGS) $(CFLAGS) $< -o $@ + @$(CXX) $(CXXFLAGS) -c -Iresources/python/inc $(PYTHON_CFLAGS) $(NUMPY_CFLAGS) $(CFLAGS) $< -o $@ python-install : $(PYTHON_LIB) @echo Installing python module in $(PYTHON_MODULEDIR) @@ -908,9 +852,9 @@ fi echo " export CXX=\"${CXX}\" -export CFLAGS=\"${CFLAGS} -I${SOURCE_PATH}/inlude ${SQUIDS_CFLAGS} ${GSL_CFLAGS} ${HDF5_CFLAGS}\" +export CFLAGS=\"${CFLAGS} ${SQUIDS_CFLAGS} ${GSL_CFLAGS} ${HDF5_CFLAGS}\" export CXXFLAGS=\"${CXXFLAGS} -std=c++11\" -export LDFLAGS=\"${LDFLAGS} -L${SOURCE_PATH}/lib -Wl,-rpath -Wl,${SOURCE_PATH}/lib -lnuSQuIDS -lpthread ${SQUIDS_LDFLAGS} ${GSL_LDFLAGS} ${HDF5_LDFLAGS}\" +export LDFLAGS=\"${LDFLAGS} -lnuSQuIDS -lpthread ${SQUIDS_LDFLAGS} ${GSL_LDFLAGS} ${HDF5_LDFLAGS}\" " > test/env_vars.sh if uname | grep -q 'Darwin' ; then printf "export DYLD_LIBRARY_PATH=\"" >> test/env_vars.sh diff --git a/data/xsections/csms_neutron.h5 b/data/xsections/csms_neutron.h5 index e60c7e56..65d20032 100644 Binary files a/data/xsections/csms_neutron.h5 and b/data/xsections/csms_neutron.h5 differ diff --git a/data/xsections/csms_proton.h5 b/data/xsections/csms_proton.h5 index 6fe15e72..e112366e 100644 Binary files a/data/xsections/csms_proton.h5 and b/data/xsections/csms_proton.h5 differ diff --git a/examples/Bodies/main.cpp b/examples/Bodies/main.cpp index 153d4217..7ebc4bfc 100644 --- a/examples/Bodies/main.cpp +++ b/examples/Bodies/main.cpp @@ -164,7 +164,7 @@ int main() std::cout << "******** Earth Atmospheric Neutrino Osc **********" << std::endl; std::shared_ptr earth_atm = std::make_shared(); - auto earth_atm_track = std::make_shared(earth_atm->MakeTrack(phi)); + std::shared_ptr earth_atm_track = std::make_shared(phi); nus.Set_Body(earth_atm); nus.Set_Track(earth_atm_track); @@ -216,7 +216,7 @@ int main() std::cout << "***** Earth Modified Atmospheric Neutrino Osc ****" << std::endl; std::shared_ptr earth_mod = std::make_shared(0.1,0.1,0.1); - auto earth_mod_track = std::make_shared(earth_atm->MakeTrack(phi)); + std::shared_ptr earth_mod_track = std::make_shared(phi); earth_mod->Mod(0.1,0.1,0.1); nus.Set_Body(earth_mod); diff --git a/examples/Extended_Source/main.cpp b/examples/Extended_Source/main.cpp deleted file mode 100644 index a03d4daf..00000000 --- a/examples/Extended_Source/main.cpp +++ /dev/null @@ -1,117 +0,0 @@ - /****************************************************************************** - * 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 . * - * * - * Authors: * - * Carlos Arguelles (University of Wisconsin Madison) * - * carguelles@icecube.wisc.edu * - * Jordi Salvado (University of Wisconsin Madison) * - * jsalvado@icecube.wisc.edu * - * Christopher Weaver (University of Wisconsin Madison) * - * chris.weaver@icecube.wisc.edu * - ******************************************************************************/ - -#include -#include -#include -#include -#include "nu_source.h" - -/* - * This file demonstrates how use nuSQUIDS to propagate neutrinos - * considering oscillation as well as non-coherent interactions - * such as CC/NC interactions and tau regeneration for the Multiple energy case. - */ - -using namespace nusquids; - -int main() -{ - squids::Const units; - nuSQUIDS nus(logspace(1.*units.GeV,1.e4*units.GeV,200),3,neutrino,true); - // Defined the parameters of our emittor - double decay_length = 100.0*units.meter; - unsigned int flv = 1; // nu mu - //Body that we have defined in the header - std::shared_ptr emit_vac = std::make_shared(flv,decay_length); - //Since our body inherits from Vacuum, we can use Vacuum::Track instead of defining an specific EmittingVacuum::Track - //This works because our inheritted body has the same geometry as the parent body. - std::shared_ptr track_vac = std::make_shared(1.0*units.km); - //We set this in the nuSQuIDS object. - nus.Set_Body(emit_vac); - nus.Set_Track(track_vac); - - // set mixing angles and masses - nus.Set_MixingAngle(0,1,0.563942); - nus.Set_MixingAngle(0,2,0.154085); - nus.Set_MixingAngle(1,2,0.785398); - nus.Set_SquareMassDifference(1,7.65e-05); - nus.Set_SquareMassDifference(2,0.00247); - - //We set the GSL step function - nus.Set_GSL_step(gsl_odeiv2_step_rk4); - - //Setting the numerical precision of gsl integrator. - nus.Set_rel_error(1.0e-5); - nus.Set_abs_error(1.0e-5); - - //Set true the progress bar during the evolution. - nus.Set_ProgressBar(true); - - //Enable having neutrinos emitted from thbe body. - nus.Set_NeutrinoSources(true); - - //Construct the initial state - //E_range is an array that contains all the energies. - marray E_range = nus.GetERange(); - //Array that contains the initial state of the system, fist component is energy and second every one of the flavors - marray inistate{E_range.size(),nus.GetNumNeu()}; - std::fill(inistate.begin(),inistate.end(),0.0); - - //Set the initial state in nuSQuIDS object - nus.Set_initial_state(inistate,flavor); - //Propagate the neutrinos in the earth for the path defined in path - nus.EvolveState(); - //This functions save the stat of the system, in this case after the evolution - std::cout << std::endl << "writing the outputs..." << std::endl; - - //In this part we will save the values in a txt file to be able to plot or manipulate later. - //Notice that this is not going to have all the information about the quantum evolution, for that - //we need to save the information using the HDF5 writing function. - std::ofstream file("fluxes_flavor.txt"); - //number of energies we want the result, notice that this can be larger than the number of the internal grid of - //the nuSQuIDS object, a linear interpolation between the quantum density matrices in the interaction picture is used - //and vacuum oscillations are solved analytically for the given energy. - int Nen =1000; - double lEmin=0; - double lEmax=4; - - file << "# log10(E) E flux_i fluxRatio_i . . . ." << std::endl; - for(double lE=lEmin; lE> plt; - if(plt=="yes" || plt=="y") - return system("./plot.plt"); - - return 0; -} diff --git a/examples/Extended_Source/nu_source.h b/examples/Extended_Source/nu_source.h deleted file mode 100644 index 08713140..00000000 --- a/examples/Extended_Source/nu_source.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef EXOBJ_H -#define EXOBJ_H - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace nusquids { - -// Exponential source -// The assumption will be that it will be a single flavor neutrino source -// with an exponential decay profile. -class EmittingVacuum: public Vacuum { - private: - const unsigned int flavor; - const double decay_length; - public : - EmittingVacuum(unsigned int flavor, double decay_length): - flavor(flavor),decay_length(decay_length){} - void injected_neutrino_flux(marray& flux, const GenericTrack& track, const nuSQUIDS& nusquids) override { - double x_cur = track.GetX(); - for(unsigned int ei=0; ei < nusquids.GetNumE(); ei++){ - for(unsigned int rhoi = 0; rhoi < nusquids.GetNumRho(); rhoi++){ - for(unsigned int flv = 0; flv < nusquids.GetNumNeu(); flv++){ - flux[ei][rhoi][flv] = (flv == flavor) ? exp(-x_cur/decay_length) : 0.0; - } - } - } - } - }; -} // close nusquids namespace - -#endif diff --git a/examples/Extended_Source/plot.plt b/examples/Extended_Source/plot.plt deleted file mode 100755 index 7df4d823..00000000 --- a/examples/Extended_Source/plot.plt +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env gnuplot -if ( GPVAL_VERSION >= 4.4 && strstrt(GPVAL_TERMINALS, 'wxt') > 0 ) set terminal wxt persist -if ( GPVAL_VERSION >= 4.4 && strstrt(GPVAL_TERMINALS, 'qt') > 0 ) set terminal qt persist -if ( GPVAL_VERSION >= 4.4 && strstrt(GPVAL_TERMINALS, 'wxt') == 0 && strstrt(GPVAL_TERMINALS, 'qt') == 0 ) print "wxt and qt terminals not available, proceeding with default" -if ( GPVAL_VERSION < 4.4 ) print "gnuplot is too old to check for available terminals" ; print "attempting to use wxt terminal and hoping for the best" ; set terminal wxt persist -set key box -set key opaque -set yrange [-0.1:1.1] -set xlabel "log_{10}(E/GeV)" -set ylabel "Muon Flux Ratio" -plot "fluxes_flavor.txt" u 1:4 w l title "Electron" -replot "fluxes_flavor.txt" u 1:6 w l title "Muon" -replot "fluxes_flavor.txt" u 1:8 w l title "Tau" - -set terminal postscript enhance eps color -set output "plot.eps" -replot - - diff --git a/examples/HDF5_Write_Read/plot.plt b/examples/HDF5_Write_Read/plot.plt index 4906a405..7b828a58 100755 --- a/examples/HDF5_Write_Read/plot.plt +++ b/examples/HDF5_Write_Read/plot.plt @@ -1,4 +1,4 @@ -#!/usr/bin/env gnuplot +#!/usr/bin/env gnuplot -persist if ( GPVAL_VERSION >= 4.4 && strstrt(GPVAL_TERMINALS, 'wxt') > 0 ) set terminal wxt persist if ( GPVAL_VERSION >= 4.4 && strstrt(GPVAL_TERMINALS, 'qt') > 0 ) set terminal qt persist if ( GPVAL_VERSION >= 4.4 && strstrt(GPVAL_TERMINALS, 'wxt') == 0 && strstrt(GPVAL_TERMINALS, 'qt') == 0 ) print "wxt and qt terminals not available, proceeding with default" diff --git a/examples/HDF5_Write_Read/read.cpp b/examples/HDF5_Write_Read/read.cpp index e7d374b8..c846103f 100644 --- a/examples/HDF5_Write_Read/read.cpp +++ b/examples/HDF5_Write_Read/read.cpp @@ -38,10 +38,12 @@ int main() squids::Const units; //Here we create the nusquids object reading the state from the hdf5 file. - nuSQUIDS inus("./initial_state.hdf5"); - nuSQUIDS fnus("./final_state.hdf5"); + //nuSQUIDS inus("./initial_state.hdf5"); + //nuSQUIDS fnus("./final_state.hdf5"); - + nuSQUIDSAtm<> inus("./pion_atmospheric_initial.hdf5"); + nuSQUIDSAtm<> fnus("./pion_atmospheric_2441_1.000000_0.000000_0.160875_0.000000_0.000000_0.000000.hdf5"); + //In this part we will save the values in a txt file to be able to plot or manipulate later. //Notice that this is not going to have all the information about the quantum evolution, for that //we need to save the information using the HDF5 writing function. @@ -60,7 +62,7 @@ int main() file << lE << " " << E << " "; for(int fl=0; fl earth_atm = std::make_shared(); //Definition of the track, in encodes the trajectory inside the body, here is declared with the zenith angle. - auto track_atm = std::make_shared(earth_atm->MakeTrack(phi)); + std::shared_ptr track_atm = std::make_shared(phi); //We set this in the nusSQuID object. nus.Set_Body(earth_atm); nus.Set_Track(track_atm); diff --git a/examples/Multiple_energy/main.cpp b/examples/Multiple_energy/main.cpp index 3a702810..ab1d5f8c 100644 --- a/examples/Multiple_energy/main.cpp +++ b/examples/Multiple_energy/main.cpp @@ -61,7 +61,7 @@ int main() //Declaration of the body, EarthAtm is one of the predefined bodies std::shared_ptr earth_atm = std::make_shared(); //Definition of the track, in encodes the trajectory inside the body, here is declared with the zenith angle. - auto track_atm = std::make_shared(earth_atm->MakeTrack(phi)); + std::shared_ptr track_atm = std::make_shared(phi); //We set this in the nusSQuID object. nus.Set_Body(earth_atm); nus.Set_Track(track_atm); diff --git a/examples/NSI/NSI.h b/examples/NSI/NSI.h index 8dbb075b..c328861f 100644 --- a/examples/NSI/NSI.h +++ b/examples/NSI/NSI.h @@ -35,6 +35,8 @@ class nuSQUIDSNSI: public nuSQUIDS { squids::SU_vector HI(unsigned int ei,unsigned int index_rho) const{ double CC = HI_prefactor*current_density*current_ye; + + // // construct potential in flavor basis squids::SU_vector potential(nsun,hiBuffer.get()); potential = (3.0*CC)*NSI_evol[ei]; diff --git a/examples/NSI/main.cpp b/examples/NSI/main.cpp index b829a43d..ae745a9b 100644 --- a/examples/NSI/main.cpp +++ b/examples/NSI/main.cpp @@ -58,7 +58,7 @@ int main() double phi = acos(-1.); //Setting up the object, and the track, the second depend on the zenith angle value std::shared_ptr earth_atm = std::make_shared(); - auto track_atm = std::make_shared(earth_atm->MakeTrack(phi)); + std::shared_ptr track_atm = std::make_shared(phi); nus.Set_Body(earth_atm); nus.Set_Track(track_atm); diff --git a/examples/Single_energy/main.cpp b/examples/Single_energy/main.cpp index 2cf7eb4a..fd1ad201 100644 --- a/examples/Single_energy/main.cpp +++ b/examples/Single_energy/main.cpp @@ -75,7 +75,7 @@ int main() //here we set the zenith angle the object ant the track, that is basically parametrized with the zenith angle double phi = acos(-1.0); std::shared_ptr earth_atm = std::make_shared(); - auto earth_atm_track = std::make_shared(earth_atm->MakeTrack(phi)); + std::shared_ptr earth_atm_track = std::make_shared(phi); nus.Set_Body(earth_atm); nus.Set_Track(earth_atm_track); diff --git a/examples/Xsections/main.cpp b/examples/Xsections/main.cpp index a9febfe5..fd6794e6 100644 --- a/examples/Xsections/main.cpp +++ b/examples/Xsections/main.cpp @@ -71,7 +71,7 @@ int main() //Declaration of the body, EarthAtm is one of the predefined bodies std::shared_ptr earth_atm = std::make_shared(); //Definition of the track, in encodes the trajectory inside the body, here is declared with the zenith angle. - auto track_atm = std::make_shared(earth_atm->MakeTrack(phi)); + std::shared_ptr track_atm = std::make_shared(phi); //We set this in the nusSQuID object. nus_cc.Set_Body(earth_atm); nus_cc.Set_Track(track_atm); diff --git a/include/nuSQuIDS/Sublime b/include/nuSQuIDS/Sublime new file mode 120000 index 00000000..c5f5ea6a --- /dev/null +++ b/include/nuSQuIDS/Sublime @@ -0,0 +1 @@ +/Applications/Sublime \ No newline at end of file diff --git a/include/nuSQuIDS/body.h b/include/nuSQuIDS/body.h index 5f6b3db6..02abb101 100644 --- a/include/nuSQuIDS/body.h +++ b/include/nuSQuIDS/body.h @@ -40,9 +40,6 @@ namespace nusquids{ -// Forward declaration of nuSQuIDS class -class nuSQUIDS; - /// \class Body /// \brief Abstract body class. /// \details This abstract class serves as a prototype @@ -125,12 +122,6 @@ class Body{ virtual bool IsConstantDensity() const {return is_constant_density;} /// \brief Return true if the body is a constant density. virtual void SetIsConstantDensity(bool icd) {is_constant_density = icd;} - /// \brief Sets the injected neutrino flux from the Body at a given Track location. - /// \details This function is called by nuSQuIDS during the calculation to obtain the injected flux. - /// @param flux Is a three dimensional array with dimensions: energy, rho, and flavor, which has previously been allocated by nuSQuIDS. - /// @param Track Trajectory object. - /// @param nuSQuIDS nuSQuIDS object that queries the flux. - virtual void injected_neutrino_flux(marray& flux, const Track&, const nuSQUIDS&) {} }; // type defining @@ -703,7 +694,7 @@ class EarthAtm: public Body{ /// \brief Cosine of the zenith angle. double cosphi; /// \brief Radius of the Earth. - double earth_radius; + double radius_nu; /// \brief Height of the atmosphere. double atmheight; /// \brief Baseline. @@ -716,16 +707,15 @@ class EarthAtm: public Body{ /// \brief Construct trajectory. /// @param x_ current position [eV^-1]. /// @param phi Zenith angle in radians. - Track(double x_,double phi,double earth_radius_,double atmheight_): - Track(phi,earth_radius_,atmheight_){x=x_; assert(x >= 0);}; + Track(double x_,double phi):Track(phi){x=x_; assert(x >= 0);}; /// \brief Construct trajectory. /// @param phi Zenith angle in radians. - Track(double phi,double earth_radius_,double atmheight_); + Track(double phi); /// \brief Returns the neutrino baseline in natural units. double GetBaseline() const {return L;} virtual void FillDerivedParams(std::vector& TrackParams) const; ///Construct a track with the cosine of the zenith angle - static Track MakeWithCosine(double cosphi,double earth_radius_,double atmheight_); + static Track makeWithCosine(double cosphi); /// \brief Serialization function void Serialize(hid_t group) const; /// \brief Deserialization function @@ -743,23 +733,8 @@ class EarthAtm: public Body{ double ye(const GenericTrack&) const; /// \brief Returns the radius of the Earth in km. double GetRadius() const {return radius;} - /// \brief Returns the altitude of the top of the simulated atmosphere in km. - /// This is the altitude from which any initial neutrino flux will begin propagating. - double GetAtmosphereHeight() const {return atm_height;} - /// \brief Set the altitude of the top of the simulated atmosphere. - /// This function invalidates all tracks previously constructed for this body, so be sure to - /// use it before constructing any tracks, or to replace any previously constructed tracks. - /// \param height New height of the top of the atmosphere, in km. - void SetAtmosphereHeight(double height); - - /// \brief Construst a track with the given zenith angle, starting at the top of the atmosphere - /// \param phi Zenith angle with which the track will arrive at the surface of the Earth, - /// possibly after passing through the Earth - Track MakeTrack(double phi); - /// \brief Construst a track with the given zenith angle, starting at the top of the atmosphere - /// \param cosphi Cosine of the zenith angle with which the track will arrive at the surface of - /// the Earth, possibly after passing through the Earth - Track MakeTrackWithCosine(double cosphi); + /// \brief Returns the neutrino production altitude in km. + double GetProductionAltitude() const {return atm_height;} }; // type defining diff --git a/include/nuSQuIDS/marray.h b/include/nuSQuIDS/marray.h index 65a5f869..0e08f18b 100644 --- a/include/nuSQuIDS/marray.h +++ b/include/nuSQuIDS/marray.h @@ -1349,10 +1349,6 @@ class marray{ allocator_traits::deallocate(alloc,buffer,size); } - #ifndef __clang__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wterminate" - #endif ///Initialize a buffer by copy constructing objects from corresponding objects in another buffer /// ///May throw if value_type(const value_type&) throws @@ -1374,9 +1370,6 @@ class marray{ throw; } } - #ifndef __clang__ - #pragma GCC diagnostic pop - #endif }; template diff --git a/include/nuSQuIDS/nuSQuIDS.h b/include/nuSQuIDS/nuSQuIDS.h index a2ef4095..fcf8adfa 100644 --- a/include/nuSQuIDS/nuSQuIDS.h +++ b/include/nuSQuIDS/nuSQuIDS.h @@ -403,8 +403,6 @@ class nuSQUIDS: public squids::SQuIDS { double current_density; /// \brief The electron fraction of the body at the current point on the track double current_ye; - /// \brief The external flux from the body at the current point on the track - marray current_external_flux; /// \brief Mass basis projectors. /// \details The i-entry corresponds to the projector in the ith mass eigenstate. @@ -449,6 +447,16 @@ class nuSQUIDS: public squids::SQuIDS { /// \warning Since the RHS of the differential equation only involves flavor projectors /// we do not current evolve mass projectors. void EvolveProjectors(double t); + /// \brief User supplied function that is called when evolving the projectors. + /// @param x Position of the system. + /// @param ei The energy index. + /// @param evol_buf The per-evolution buffer of the energy index. + /// @see EvolveProjectors + virtual void AddToEvolveProjectors(double x,unsigned int ei,double evol_buf[]){} + /// \brief User supplied function that is called when evolving the projectors. + /// @param x Position of the system. + /// @see EvolveProjectors + virtual void AddToEvolveProjectors(double x){} // bool requirements private: @@ -494,11 +502,13 @@ class nuSQUIDS: public squids::SQuIDS { /// \brief Set GSL differential cross section precision. double gsl_int_precision = 1.e-3; /// \brief Cutoff for low-pass filter applied during state density evolution - double evol_lowpass_cutoff = 0; + marray evol_lowpass_cutoff; /// \brief Scale for low-pass filter applied during state density evolution - double evol_lowpass_scale = 0; - /// \brief If true the bodies can act as neutrino sources. - bool enable_neutrino_sources = false; + marray evol_lowpass_scale; + /// \brief Boolean that enables averaging during evaluation. + bool average = false; + /// \brief Boolean that enables lowpass filter during propagation and evaluation. + bool lowpass = false; protected: /// \brief Initializes flavor and mass projectors /// \warning Antineutrinos are handle by means of the AntineutrinoCPFix() function @@ -785,6 +795,8 @@ class nuSQUIDS: public squids::SQuIDS { /// is considering neutrinos (0) or antineutrinos (1). double EvalFlavor(unsigned int flv,double enu,unsigned int rho = 0) const; + double EvalFlavorLowPass(unsigned int flv,double EE,unsigned int rho = 0) const; + /// \brief Returns the flavor composition at a given energy in the multiple energy mode. /// averaging out the high frequencies. /// @param flv Neutrino flavor. @@ -818,9 +830,17 @@ class nuSQUIDS: public squids::SQuIDS { /// @param val cutoff value void Set_EvolLowPassCutoff(double val); + /// \brief Sets the cutoff for the state evolution low-pass filter. + /// @param val cutoff value + void Set_EvolLowPassCutoff(const marray& val); + /// \brief Sets the linear ramp size for the state evolution low-pass filter. /// @param val Range in frequency space over which the linear ramp is applied. - void Set_EvolLowPassScale(double val); + //void Set_EvolLowPassScale(double val); + + /// \brief Sets the linear ramp size for the state evolution low-pass filter. + /// @param val Range in frequency space over which the linear ramp is applied. + //void Set_EvolLowPassScale(const marray& val); /// \brief Toggles tau regeneration on and off. /// \param opt If \c true tau regeneration will be considered. @@ -1042,22 +1062,6 @@ class nuSQUIDS: public squids::SQuIDS { ncs=xs; interactions_initialized=false; } - - /// \brief Enables neutrino flux emission from bodies - void Set_NeutrinoSources(bool enable_neutrino_sources_){ - if(enable_neutrino_sources_){ - current_external_flux.resize(std::vector{ne,nrhos,numneu}); - std::fill(current_external_flux.begin(),current_external_flux.end(),0.0); - } - if(not iinteraction and enable_neutrino_sources_) - Set_OtherRhoTerms(true); - enable_neutrino_sources = enable_neutrino_sources_; - } - - /// \brief Returns true if neutrino flux emission from bodies is considered - bool Get_NeutrinoSources(){ - return enable_neutrino_sources; - } }; /** @@ -1070,7 +1074,7 @@ template(); for(double costh : costh_array) - track_array.push_back(std::make_shared(earth_atm->MakeTrackWithCosine(costh))); + track_array.push_back(std::make_shared(acos(costh))); for(unsigned int i = 0; i < costh_array.extent(0); i++){ nusq_array.emplace_back(args...); @@ -1369,7 +1373,8 @@ class nuSQUIDSAtm { eit--; size_t loge_M=std::distance(enu_array.begin(),eit); - EarthAtm::Track track=earth_atm->MakeTrackWithCosine(costh); + //EarthAtm::Track track(acos(costh)); + EarthAtm::Track track=EarthAtm::Track::makeWithCosine(costh); double delta_t_final = track.GetFinalX()-track.GetInitialX(); if (randomize_production_height){ double production_height = gsl_ran_flat(r_gsl,-15*units.km,15*units.km); @@ -1393,13 +1398,34 @@ class nuSQUIDSAtm { static SQUIDS_THREAD_LOCAL #endif storage_type storage(H0_at_enu.Dim()); - - storage.evol_proj = nusq_array[0].GetFlavorProj(flv,rho).Evolve(H0_at_enu,t_inter); - + //coefficients for energy interpolation double f2=(enu-enu_array[loge_M])/(enu_array[loge_M+1]-enu_array[loge_M]); double f1=1-f2; + bool lowpass = nusq_array[0].lowpass; + bool average = nusq_array[0].average; + + if(lowpass or average) { + // preevolution buffer + std::unique_ptr evol_buffer(new double[H0_at_enu.GetEvolveBufferSize()]); + H0_at_enu.PrepareEvolve(evol_buffer.get(),t_inter); + + double scale_M = nusq_array[cth_M].evol_lowpass_scale[loge_M]*f1 + nusq_array[cth_M].evol_lowpass_scale[loge_M+1]*f2; + double cutoff_M = nusq_array[cth_M].evol_lowpass_cutoff[loge_M]*f1 + nusq_array[cth_M].evol_lowpass_cutoff[loge_M+1]*f2; + double scale_P = nusq_array[cth_M+1].evol_lowpass_scale[loge_M]*f1 + nusq_array[cth_M+1].evol_lowpass_scale[loge_M+1]*f2; + double cutoff_P = nusq_array[cth_M+1].evol_lowpass_cutoff[loge_M]*f1 + nusq_array[cth_M+1].evol_lowpass_cutoff[loge_M+1]*f2; + + double scale = LinInter(costh,costh_array[cth_M],costh_array[cth_M+1],scale_M,scale_P); + double cutoff = LinInter(costh,costh_array[cth_M],costh_array[cth_M+1],cutoff_M,cutoff_P); + + //H0_at_enu.LowPassFilter(evol_buffer.get(), cutoff, scale); + storage.evol_proj = nusq_array[0].GetFlavorProj(flv,rho).Evolve(evol_buffer.get()); + } + else { + storage.evol_proj = nusq_array[0].GetFlavorProj(flv,rho).Evolve(H0_at_enu,t_inter); + } + storage.temp1 =f1*nusq_array[cth_M ].GetState(loge_M ,rho); storage.temp1+=f2*nusq_array[cth_M ].GetState(loge_M+1,rho); double phiM=squids::SUTrace(storage.temp1,storage.evol_proj); @@ -1462,7 +1488,8 @@ class nuSQUIDSAtm { eit--; size_t loge_M=std::distance(enu_array.begin(),eit); - EarthAtm::Track track=earth_atm->MakeTrackWithCosine(costh); + //EarthAtm::Track track(acos(costh)); + EarthAtm::Track track=EarthAtm::Track::makeWithCosine(costh); double delta_t_final = track.GetFinalX()-track.GetInitialX(); // assuming offsets are zero @@ -1549,11 +1576,11 @@ class nuSQUIDSAtm { /// @see WriteStateHDF5 void ReadStateHDF5(std::string hdf5_filename){ hid_t file_id,group_id,root_id; - // open HDF5 file - H5File file(H5Fopen(hdf5_filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT)); - if (file < 0) + // create HDF5 file + file_id = H5Fopen(hdf5_filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); + if (file_id < 0) throw std::runtime_error("nuSQUIDSAtm::ReadStateHDF5: Unable to open file: " + hdf5_filename + ". No such file or directory"); - root_id = H5Gopen(file, "/",H5P_DEFAULT); + root_id = H5Gopen(file_id, "/",H5P_DEFAULT); group_id = root_id; // read the zenith range dimension @@ -1578,6 +1605,8 @@ class nuSQUIDSAtm { } H5Gclose(root_id); + H5Fclose(file_id); + H5close(); // resize apropiately the nuSQUIDSAtm container vector nusq_array.clear(); @@ -1591,13 +1620,11 @@ class nuSQUIDSAtm { if(nsq.iinteraction) int_struct = nsq.GetInteractionStructure(); } else { - // re-use the shared cross sections + // read the cross sections stored in /crosssections nsq.ReadStateHDF5Internal(hdf5_filename,"/costh_"+std::to_string(costh_array[i]),int_struct); } i++; } - earth_atm = std::dynamic_pointer_cast(nusq_array.front().GetBody()); - assert(earth_atm); iinistate = true; inusquidsatm = true; @@ -1916,16 +1943,175 @@ class nuSQUIDSAtm { } } - void Set_EvolLowPassScale(double val){ - for(BaseSQUIDS& nsq : nusq_array){ - nsq.Set_EvolLowPassScale(val); - } - } - - void Set_NeutrinoSources(bool opt){ - for(BaseSQUIDS& nsq : nusq_array) - nsq.Set_NeutrinoSources(opt); - } + //void Set_EvolLowPassScale(double val){ + // for(BaseSQUIDS& nsq : nusq_array){ + // nsq.Set_EvolLowPassScale(val); + // } + //} + + //void Set_AutoEvolLowPass(double delta_phi_max, double delta_phi_scale, bool fast=false){ + // for(BaseSQUIDS& nsq : nusq_array){ + // nsq.lowpass = true; + // } + // marray times({nusq_array.size()}); + + // for(unsigned int iz=0; iz < nusq_array.size(); ++iz) { + // BaseSQUIDS & nsq = nusq_array[iz]; + // times[iz] = nsq.track->GetFinalX()-nsq.track->GetInitialX(); + // } + + // marray bounds({nusq_array.size(), enu_array.size()}); + // for(unsigned int iz=0; iz < nusq_array.size(); ++iz) { + // BaseSQUIDS & nsq = nusq_array[iz]; + // for(unsigned int ie = 0; ie < enu_array.size(); ++ie) { + // std::vector> neighbors; + // for(int dz=1; dz > -2; dz -= 2) { + // int jz = iz+dz; + // if(jz<0 or jz >= nusq_array.size()) + // continue; + // neighbors.push_back({jz,ie}); + // } + // for(int de=1; de > -2; de -= 2) { + // int je = ie+de; + // if(je<0 or je >= enu_array.size()) + // continue; + // neighbors.push_back({iz,je}); + // } + // //double min_bound = 1.00/(30.0*units.km); + // double min_bound = std::numeric_limits::max(); + // for(std::pair& neighbor : neighbors) { + // unsigned int jz = neighbor.first; + // unsigned int je = neighbor.second; + // double bound = std::numeric_limits::max(); + // if(jz != iz) { + // bound = 1.0 / std::abs(times[iz] - times[jz]); + // } + // else if(je != ie) { + // bound = enu_array[ie] / std::abs(enu_array[ie] - enu_array[je]) / times[iz]; + // } + // if(bound < min_bound) { + // min_bound = bound; + // } + // } + //bounds[{iz, ie}] = min_bound; + //} + //} + + // if(!fast) { + // double x = 1; + // double orig_t; + // marray final_times({nusq_array.size()}); + // marray delta_lambda; // iz, ie, irho, ilam, jlam + // double lambda_size; + + // bool is_initialized = false; + + // for(unsigned int iz=0; iz < nusq_array.size(); ++iz) { + // BaseSQUIDS & nsq = nusq_array[iz]; + // if( nsq.iinteraction && !nsq.interactions_initialized ) + // nsq.InitializeInteractions(); + // if( !nsq.ioscillations && nsq.iinteraction) + // nsq.SetUpInteractionCache(); + // orig_t = nsq.Get_t(); + // final_times[iz] = nsq.track->GetFinalX()-nsq.track->GetInitialX() + nsq.time_offset; + // nsq.Set_t(x*final_times[iz]); + // for(unsigned int ie = 0; ie < enu_array.size(); ++ie) { + // for(unsigned int irho = 0; irho < GetNumRho(); ++irho) { + // squids::SU_vector h0 = nsq.GetHamiltonian(ie, irho); + // std::pair, std::unique_ptr > eigen_sys = h0.GetEigenSystem(false); // false ==> do not sort + // lambda_size = eigen_sys.first->size; + // marray lambda({lambda_size}); + // for(unsigned int ilam = 0; ilam < lambda_size; ++ilam) { + // lambda[ilam] = gsl_vector_get(eigen_sys.first.get(), ilam); + // } + // if(not is_initialized) { + // delta_lambda = marray({nusq_array.size(),enu_array.size(),GetNumRho(),lambda_size,lambda_size}); + // is_initialized = true; + // } + // for(unsigned int ilam = 0; ilam < lambda_size; ++ilam) { + // for(unsigned int jlam = ilam+1; jlam < lambda_size; ++jlam) { + // double diff = std::abs(lambda[ilam] - lambda[jlam]); + // delta_lambda[{iz, ie, irho, ilam, jlam}] = diff; + // std::cout << diff << std::endl; + // delta_lambda[{iz, ie, irho, jlam, ilam}] = diff; + // } + // } + // } + // } + // nsq.Set_t(orig_t); + // nsq.PreDerive(orig_t); + // } + // std::cout << "(Zi,Ei,Rhoi) --> omega_max" << std::endl; + // for(unsigned int iz=0; iz < nusq_array.size(); ++iz) { + // for(unsigned int ie = 0; ie < enu_array.size(); ++ie) { + // double min_bound = std::numeric_limits::max(); + // for(unsigned int irho = 0; irho < GetNumRho(); ++irho) { + // std::vector> neighbors; + // for(int dz=1; dz > -2; dz -= 2) { + // int jz = iz+dz; + // if(jz<0 or jz >= nusq_array.size()) + // continue; + // neighbors.push_back({jz,ie}); + // } + // for(int de=1; de > -2; de -= 2) { + // int je = ie+de; + // if(je<0 or je >= enu_array.size()) + // continue; + // neighbors.push_back({iz,je}); + // } + // for(std::pair& neighbor : neighbors) { + // unsigned int jz = neighbor.first; + // unsigned int je = neighbor.second; + // for(unsigned int ilam = 0; ilam < lambda_size; ++ilam) { + // for(unsigned int jlam = ilam+1; jlam < lambda_size; ++jlam) { + // double omega_0 = delta_lambda[{iz,ie,irho,ilam,jlam}]; + // double omega_1 = delta_lambda[{jz,je,irho,ilam,jlam}]; + // if(omega_0 == 0.0) + // continue; + // double phi_0 = omega_0 * final_times[iz]; + // double phi_1 = omega_0 * final_times[jz]; + // double delta_phi = std::abs(phi_0 - phi_1); + // if(delta_phi == 0.0) + // continue; + // double bound = omega_0 / delta_phi; + // if(bound < min_bound) { + // min_bound = bound; + // } + // } + // } + // } + // std::cout << "(" << iz << "," << ie << "," << irho << ") --> " << min_bound << std::endl; + // // Ideally we would set a different low pass filter for each zenith/energy/rho... + // // That would happen right here + // // Instead the best we can do is set a low pass filter for each nusquids object + // //if(min_bound < nsq_min_bound) { + // // nsq_min_bound = min_bound; + // //} + // } + // if(min_bound < bounds[{iz,ie}]) { + // bounds[{iz,ie}] = min_bound; + // } + // } + // //std::cout << "nsq " << iz << " bound --> " << nsq_min_bound << std::endl; + // std::cout << std::endl; + // } + // std::cout << std::endl; + // } + // for(unsigned int iz=0; iz < nusq_array.size(); ++iz) { + // BaseSQUIDS & nsq = nusq_array[iz]; + // marray nsq_bounds({enu_array.size()}); + // double min_bound = std::numeric_limits::max(); + // for(unsigned int ie = 0; ie < enu_array.size(); ++ie) { + // nsq_bounds[ie] = bounds[{iz,ie}]; + // if(nsq_bounds[ie] < min_bound) { + // min_bound = nsq_bounds[ie]; + // } + // } + // nsq.Set_EvolLowPassCutoff(delta_phi_max * nsq_bounds); + // nsq.Set_EvolLowPassScale(delta_phi_scale * nsq_bounds); + // //nsq.Set_h(1.0/min_bound); + // } + // } }; diff --git a/include/nuSQuIDS/nuSQuIDSLV.h b/include/nuSQuIDS/nuSQuIDSLV.h new file mode 100644 index 00000000..e25cab8a --- /dev/null +++ b/include/nuSQuIDS/nuSQuIDSLV.h @@ -0,0 +1,330 @@ +#ifndef nusquidslv_H +#define nusquidslv_H + +#include +#include +#include + +namespace nusquids { + +struct LVParameters { + gsl_complex c_emu; + gsl_complex c_mutau; + gsl_complex c_etau; + gsl_complex c_ee; + gsl_complex c_mumu; +}; + +class nuSQUIDSLV: public nuSQUIDS { + private: + const squids::Const units; + bool lv_parameters_set = false; + bool lv_power_set = false; + int n_ = 1; + LVParameters c_params; + squids::SU_vector LVP; + std::vector LVP_evol; + marray energy_pow_array; + + /* + void AddToPreDerive(double x){ + if(!lv_parameters_set) + throw std::runtime_error("LV parameters not set"); + for(unsigned int ei = 0; ei < ne; ei++){ + // asumming same mass hamiltonian for neutrinos/antineutrinos + squids::SU_vector h0 = H0(E_range[ei],0); + LVP_evol[ei] = LVP.Evolve(h0,(x-Get_t_initial())); + } + } + */ + virtual void AddToEvolveProjectors(double x,unsigned int ei,double evol_buf[]) { + if(!lv_parameters_set) + throw std::runtime_error("LV parameters not set"); + if(!lv_power_set) + throw std::runtime_error("LV energy power not set"); + // asumming same mass hamiltonian for neutrinos/antineutrinos + LVP_evol[ei] = squids::detail::guarantee + (LVP.Evolve(evol_buf)); + } + + void AddToWriteHDF5(hid_t hdf5_loc_id) const { + // here we write the new parameters to be saved in the HDF5 file + ///hsize_t dim[1]{1}; + ///hid_t lv = H5LTmake_dataset(hdf5_loc_id,"c_values",1,dim,H5T_NATIVE_DOUBLE,0); + //hid_t lv = H5Dcreate(hdf5_loc_id, "c_values", H5T_NATIVE_INT, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + //hid_t lv = H5Gcreate(hdf5_loc_id, "c_values", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + std::cout << "Writing LV to HDF5!" << std::endl; + double cmutaur = GSL_REAL(c_params.c_mutau); + double cmutaui = GSL_IMAG(c_params.c_mutau); + H5LTset_attribute_double(hdf5_loc_id,"c_values","c_mu_tau_real" ,&(cmutaur),1); + H5LTset_attribute_double(hdf5_loc_id,"c_values","c_mu_tau_imag" ,&(cmutaui),1); + double cemur = GSL_REAL(c_params.c_emu); + double cemui = GSL_IMAG(c_params.c_emu); + H5LTset_attribute_double(hdf5_loc_id,"c_values","c_e_mu_real" ,&(cemur),1); + H5LTset_attribute_double(hdf5_loc_id,"c_values","c_e_mu_imag" ,&(cemui),1); + double cetaur = GSL_REAL(c_params.c_etau); + double cetaui = GSL_IMAG(c_params.c_etau); + H5LTset_attribute_double(hdf5_loc_id,"c_values","c_e_tau_real",&(cetaur),1); + H5LTset_attribute_double(hdf5_loc_id,"c_values","c_e_tau_imag",&(cetaui),1); + double cee = GSL_REAL(c_params.c_ee); + H5LTset_attribute_double(hdf5_loc_id,"c_values","c_e_e",&(cee),1); + double cmumu = GSL_REAL(c_params.c_mumu); + H5LTset_attribute_double(hdf5_loc_id,"c_values","c_mu_mu",&(cmumu),1); + } + + void AddToReadHDF5(hid_t hdf5_loc_id){ + double cmutaur,cmutaui,cemur,cemui,cetaur,cetaui,cee,cmumu; + // here we read the new parameters now saved in the HDF5 file + //hid_t lv = H5Gopen(hdf5_loc_id, "c_values", H5P_DEFAULT); + //H5Gclose(lv); + H5LTget_attribute_double(hdf5_loc_id,"c_values","c_mu_tau_real" ,&(cmutaur)); + H5LTget_attribute_double(hdf5_loc_id,"c_values","c_mu_tau_imag" ,&(cmutaui)); + H5LTget_attribute_double(hdf5_loc_id,"c_values","c_e_mu_real" ,&(cemur)); + H5LTget_attribute_double(hdf5_loc_id,"c_values","c_e_mu_imag" ,&(cemui)); + H5LTget_attribute_double(hdf5_loc_id,"c_values","c_e_tau_real" ,&(cetaur)); + H5LTget_attribute_double(hdf5_loc_id,"c_values","c_e_tau_imag" ,&(cetaui)); + H5LTget_attribute_double(hdf5_loc_id,"c_values","c_e_e" ,&(cee)); + H5LTget_attribute_double(hdf5_loc_id,"c_values","c_mu_mu" ,&(cmumu)); + c_params = {gsl_complex_rect(cemur,cemui),gsl_complex_rect(cmutaur,cmutaui),gsl_complex_rect(cetaur,cetaui),cee,cmumu}; + Set_LV_OpMatrix(c_params); + } + + public: + /* + squids::SU_vector H0(double Enu, unsigned int irho) const{ + squids::SU_vector potential = nuSQUIDS::H0(Enu, irho); + double sign = 1; + if ((irho == 1 and NT==both) or NT==antineutrino){ + // antineutrino matter potential flips sign + sign*=(-1); + } + if(!lv_parameters_set or !lv_power_set) { + } + else { + potential += sign*pow(Enu,n_)*LVP; // <- super important line here is where all the physics is set + } + return potential; + } + */ + + squids:: SU_vector HI(unsigned int ie,unsigned int irho) const { + squids::SU_vector potential = nuSQUIDS::HI(ie, irho); + double sign = 1; + if ((irho == 1 and NT==both) or NT==antineutrino){ + // antineutrino matter potential flips sign + sign*=(-1); + } + // ================= HERE WE ADD THE NEW PHYSICS =================== + potential += sign*energy_pow_array[ie]*LVP_evol[ie]; // <- super important line here is where all the physics is set + // ================= HERE WE ADD THE NEW PHYSICS =================== + return potential; + } + public: + nuSQUIDSLV() : nuSQUIDS() {} + + nuSQUIDSLV(nuSQUIDSLV&& other): + nuSQUIDS(std::move(other)), + c_params(other.c_params), + n_(other.n_), + LVP(other.LVP), + LVP_evol(other.LVP_evol), + lv_parameters_set(other.lv_parameters_set), + lv_power_set(other.lv_power_set) + { + } + + nuSQUIDSLV& operator=(nuSQUIDSLV&& other){ + if(&other==this) + return(*this); + + nuSQUIDS::operator=(std::move(other)); + + c_params = other.c_params; + n_ = other.n_; + LVP = other.LVP; + LVP_evol = other.LVP_evol; + lv_parameters_set = other.lv_parameters_set; + lv_power_set = other.lv_power_set; + } + + nuSQUIDSLV(marray E_range_,unsigned int numneu_,NeutrinoType NT_ = both, + bool iinteraction_ = false, std::shared_ptr ncs_ = nullptr): + nuSQUIDS(E_range_,numneu_,NT_, iinteraction_, ncs_) + { + // just allocate some matrices + LVP_evol.resize(ne); + for(unsigned int ei = 0; ei < ne; ei++){ + LVP_evol[ei] = squids::SU_vector(nsun); + } + init(E_range_); + } + + virtual ~nuSQUIDSLV() {}; + + + nuSQUIDSLV(unsigned int numneu, NeutrinoType NT = neutrino):nuSQUIDS(numneu, NT) {} + + nuSQUIDSLV(std::string hdf5_filename, std::string grp = "/", + std::shared_ptr int_struct = nullptr): nuSQUIDS(hdf5_filename, grp, int_struct) {} + + void Set_LV_OpMatrix(double lv_emu_re, double lv_emu_im, double lv_mutau_re, double lv_mutau_im, double lv_etau_re, double lv_etau_im, double lv_ee, double lv_mumu) { + gsl_complex lv_emu {lv_emu_re*units.eV, lv_emu_im*units.eV}; + gsl_complex lv_mutau {lv_mutau_re*units.eV, lv_mutau_im*units.eV}; + gsl_complex lv_etau {lv_etau_re*units.eV, lv_etau_im*units.eV}; + LVParameters lv {lv_emu, lv_mutau, lv_etau, lv_ee*units.eV, lv_mumu*units.eV}; + Set_LV_OpMatrix(lv); + //iniH0(); + } + + void Set_LV_OpMatrix(LVParameters & lv_params){ + // defining a complex matrix M which will contain our flavor + // violating flavor structure. + gsl_matrix_complex * M = gsl_matrix_complex_calloc(3,3); + gsl_matrix_complex_set(M,1,0,lv_params.c_emu); + gsl_matrix_complex_set(M,0,1,gsl_complex_conjugate(lv_params.c_emu)); + gsl_matrix_complex_set(M,2,1,lv_params.c_mutau); + gsl_matrix_complex_set(M,1,2,gsl_complex_conjugate(lv_params.c_mutau)); + gsl_matrix_complex_set(M,2,0,lv_params.c_etau); + gsl_matrix_complex_set(M,0,2,gsl_complex_conjugate(lv_params.c_etau)); + gsl_matrix_complex_set(M,0,0,lv_params.c_ee); + gsl_matrix_complex_set(M,1,1,lv_params.c_mumu); + gsl_matrix_complex_set(M,2,2,gsl_complex_sub(gsl_complex_negative(lv_params.c_ee), lv_params.c_mumu)); + LVP = squids::SU_vector(M); + // rotate from flavor to mass basis + LVP.RotateToB1(params); + // free allocated matrix + gsl_matrix_complex_free(M); + c_params = lv_params; + lv_parameters_set = true; + //iniH0(); + } + + void Set_LV_OpMatrix(gsl_matrix_complex * cmatrix){ + // defining a complex matrix M which will contain our flavor + // violating flavor structure. + c_params = {gsl_matrix_complex_get(cmatrix,1,0), + gsl_matrix_complex_get(cmatrix,2,1)}; + LVP = squids::SU_vector(cmatrix); + // rotate from flavor to mass basis + LVP.RotateToB1(params); + lv_parameters_set = true; + //iniH0(); + } + + void Set_LV_Operator(squids::SU_vector op){ + // we assume that the input operator is in the flavor basis + LVP = op; + // rotate from flavor to mass basis + LVP.RotateToB1(params); + lv_parameters_set = true; + //iniH0(); + } + + void Set_LV_EnergyPower(int n){ + n_ = n; + energy_pow_array = E_range; + for(unsigned int ie=0; ie& v, Basis basis=flavor){ + bool lvps = lv_parameters_set; + bool lvpows = lv_power_set; + nuSQUIDS::Set_initial_state(v,basis); + lv_parameters_set = lvps; + lv_power_set = lvpows; + } + + void Set_initial_state(const marray& v, Basis basis=flavor){ + bool lvps = lv_parameters_set; + bool lvpows = lv_power_set; + nuSQUIDS::Set_initial_state(v,basis); + lv_parameters_set = lvps; + lv_power_set = lvpows; + } + + void Set_initial_state(const marray& v, Basis basis=flavor){ + bool lvps = lv_parameters_set; + bool lvpows = lv_power_set; + nuSQUIDS::Set_initial_state(v,basis); + lv_parameters_set = lvps; + lv_power_set = lvpows; + } +}; + +class nuSQUIDSLVAtm: public nuSQUIDSAtm { + protected: + using BaseSQUIDS = nuSQUIDSLV; + public: + template + nuSQUIDSLVAtm(marray costh_array, ArgTypes&&... args):nuSQUIDSAtm(costh_array, args...) + { + } + + nuSQUIDSLVAtm(std::string hdf5_filename):nuSQUIDSAtm(hdf5_filename) {} + + void Set_LV_OpMatrix(double lv_emu_re, double lv_emu_im, double lv_mutau_re, double lv_mutau_im, double lv_etau_re, double lv_etau_im, double lv_ee, double lv_mumu) { + gsl_complex lv_emu {lv_emu_re*units.eV, lv_emu_im*units.eV}; + gsl_complex lv_mutau {lv_mutau_re*units.eV, lv_mutau_im*units.eV}; + gsl_complex lv_etau {lv_etau_re*units.eV, lv_etau_im*units.eV}; + LVParameters lv {lv_emu, lv_mutau, lv_etau, lv_ee*units.eV, lv_mumu*units.eV}; + for(BaseSQUIDS& nsq : nusq_array){ + nsq.Set_LV_OpMatrix(lv); + } + } + + void Set_LV_Operator(squids::SU_vector op){ + for(BaseSQUIDS& nsq : nusq_array){ + nsq.Set_LV_Operator(op); + } + } + + void Set_LV_EnergyPower(int n){ + for(BaseSQUIDS& nsq : nusq_array){ + nsq.Set_LV_EnergyPower(n); + } + } +}; + +} // close nusquids namespace + +#endif //nusquidslv_h + + diff --git a/include/nuSQuIDS/taudecay.h b/include/nuSQuIDS/taudecay.h index 2ffff605..01e34257 100755 --- a/include/nuSQuIDS/taudecay.h +++ b/include/nuSQuIDS/taudecay.h @@ -131,13 +131,13 @@ class TauDecaySpectra{ public : /// \brief Detault empty constructor. - TauDecaySpectra(bool polarization=true): + TauDecaySpectra(): dNdEnu_All_tbl(aligned_allocator{log2(preferred_alignment*sizeof(double))}), dNdEnu_Lep_tbl(aligned_allocator{log2(preferred_alignment*sizeof(double))}), dNdEle_All_tbl(aligned_allocator{log2(preferred_alignment*sizeof(double))}), dNdEle_Lep_tbl(aligned_allocator{log2(preferred_alignment*sizeof(double))}) { - SetParameters(polarization); + SetParameters(true); } /// \brief Constructor for a given energy range. /// @param E_range Energy nodes where the cross section will be calculated. [eV] diff --git a/include/nuSQuIDS/tools.h b/include/nuSQuIDS/tools.h index 361360d0..45e990ea 100644 --- a/include/nuSQuIDS/tools.h +++ b/include/nuSQuIDS/tools.h @@ -221,46 +221,6 @@ struct H5File{ ~H5File(){ H5Fclose(id); } operator hid_t() const{ return(id); } }; - -///\brief A general RAII wrapper around an hid_t -struct H5Handle{ - H5Handle():id(-1),deleter(nullptr){} - ///\brief Take ownership of an hid_t - ///\param id The owned HDF5 object reference - ///\param deleter The HDF5 API function used to dispose of the reference - ///\param desc A descriptive string used to form an error message if id is not valid - H5Handle(hid_t id, herr_t(*deleter)(hid_t), const char* desc): - id(id),deleter(deleter){ - if(id<0){ - if(desc) - throw std::runtime_error(std::string("Failed to ")+desc); - else - throw std::runtime_error("Failed to get HDF5 object"); - } - } - H5Handle(const H5Handle&)=delete; - H5Handle(H5Handle&& other): - id(other.id),deleter(other.deleter){ - other.id=-1; - } - ~H5Handle(){ - if(id>=0) - (*deleter)(id); - } - H5Handle& operator=(H5Handle&)=delete; - H5Handle& operator=(H5Handle&& other){ - if(&other!=this){ - std::swap(id,other.id); - std::swap(deleter,other.deleter); - } - return *this; - } - hid_t get() const{ return id; } - operator hid_t() const{ return id; } -private: - hid_t id; - herr_t(*deleter)(hid_t); -}; template struct h5Datatype{}; @@ -269,8 +229,6 @@ template<> struct h5Datatype{ static hid_t type(){ return H5T_NATIVE_INT; } template<> struct h5Datatype{ static hid_t type(){ return H5T_NATIVE_UINT; }}; template<> struct h5Datatype{ static hid_t type(){ return H5T_NATIVE_FLOAT; }}; template<> struct h5Datatype{ static hid_t type(){ return H5T_NATIVE_DOUBLE; }}; - -bool h5ObjectExists(hid_t loc_id, const char* name); template void writeArrayH5(hid_t loc_id, std::string name, const marray& data, unsigned int compressLevel=0){ diff --git a/include/nuSQuIDS/xsections.h b/include/nuSQuIDS/xsections.h index 7bf58f62..d73a2fc6 100755 --- a/include/nuSQuIDS/xsections.h +++ b/include/nuSQuIDS/xsections.h @@ -50,68 +50,33 @@ class NeutrinoCrossSections{ enum Current { CC, NC, GR }; /// \brief Returns the total neutrino cross section /// \details Used to interpolate the total cross sections. - /// \param Enu Incident lepton energy - /// \param flavor Incident lepton flavor - /// \param neutype Incident lepton matter/anti-matter type - /// \param current Interaction type - /// \return The cross section in cm^2 virtual double TotalCrossSection(double Enu, NeutrinoFlavor flavor, NeutrinoType neutype, Current current) const = 0; - /// \brief Returns the differential cross section with respect to the outgoing lepton energy. + /// \brief Returns the Differential cross section with respect to the outgoing lepton energy. /// \details The cross section will be returned in cm^2 GeV^-1. - /// \param E1 Incident lepton energy. - /// \param E2 Outgoing lepton energy. - /// \param flavor Flavor index. - /// \param neutype Can be either neutrino or antineutrino. - /// \param current Can be either CC or NC. + /// @param E1 Incident lepton energy. + /// @param E2 Outgoing lepton energy. + /// @param flavor Flavor index. + /// @param neutype Can be either neutrino or antineutrino. + /// @param current Can be either CC or NC. virtual double SingleDifferentialCrossSection(double E1, double E2, NeutrinoFlavor flavor, NeutrinoType neutype, Current current) const = 0; /// \brief Returns the double differential cross section with respect to x and y. - /// \details The cross section will be returned in cm^2 GeV^-1. As this cross sections is not - /// generally used by the library, implementation of this function is optional. - /// \param E Incident lepton energy. - /// \param x bjorken-x. - /// \param y bjorken-y. - /// \param flavor Flavor index. - /// \param neutype Can be either neutrino or antineutrino. - /// \param current Can be either CC or NC. + /// \details The cross section will be returned in cm^2 GeV^-1. As this cross sections is not requiered and thus not called by the program + /// its implementation is optional. + /// @param E Incident lepton energy. + /// @param x bjorken-x. + /// @param y bjorken-y. + /// @param flavor Flavor index. + /// @param neutype Can be either neutrino or antineutrino. + /// @param current Can be either CC or NC. virtual double DoubleDifferentialCrossSection(double E, double x, double y, NeutrinoFlavor flavor, NeutrinoType neutype, Current current) const { throw std::runtime_error("NeutrinoCrossSections::Error::DoubleDifferentialCrossSection is not implemented."); return 0; } - /// \brief Returns the total neutrino cross section, averaged over the specified energy range. - /// \param EMin Minimum incident lepton energy - /// \param EMax Maximum incident lepton energy - /// \param flavor Incident lepton flavor - /// \param neutype Incident lepton matter/anti-matter type - /// \param current Interaction type - /// \return The average cross section from EMin to Emax in cm^2 virtual double AverageTotalCrossSection(double EMin, double EMax, NeutrinoFlavor flavor, NeutrinoType neutype, Current current) const; - /// \brief Returns the the differential cross section, with respect to the outgoing lepton energy, averaged over the specified energy range. - /// \param E1 Incident lepton energy - /// \param E2Min Minimum out-going lepton energy - /// \param E2Max Maximum out-going lepton energy - /// \param flavor Incident lepton flavor - /// \param neutype Incident lepton matter/anti-matter type - /// \param current Interaction type - /// \return The average cross section from EMin to Emax in cm^2 GeV^-1 virtual double AverageSingleDifferentialCrossSection(double E1, double E2Min, double E2Max, NeutrinoFlavor flavor, NeutrinoType neutype, Current current) const; }; -struct FlavorHash{ -public: - using argument_type=NeutrinoCrossSections::NeutrinoFlavor; -private: - using underlying_type=typename std::underlying_type::type; - using hash_type=std::hash; -public: - using result_type=typename hash_type::result_type; - result_type operator()(argument_type arg) const{ - return hash_(arg); - } -private: - hash_type hash_; -}; - /// \class NullCrossSections /// \brief Simple class that defines a null cross section. class NullCrossSections: public NeutrinoCrossSections { @@ -302,30 +267,23 @@ class NeutrinoDISCrossSectionsFromTables : public NeutrinoCrossSections { ///\brief Conversion factor from GeV to eV const double GeV = 1.0e9; - ///\brief Cross section information for one neutrino flavor - /// - ///Assumed to use a common energy range. - struct perFlavorData{ - ///Total cross section for charged-current neutrino interactions - AkimaSpline s_CC_nu; - ///Total cross section for neutral-current neutrino interactions - AkimaSpline s_NC_nu; - ///Total cross section for charged-current anti-neutrino interactions - AkimaSpline s_CC_nubar; - ///Total cross section for neutral-current anti-neutrino interactions - AkimaSpline s_NC_nubar; - - ///Singly-differential cross section for charged-current neutrino interactions - BiCubicInterpolator dsdy_CC_nu; - ///Singly-differential cross section for neutral-current neutrino interactions - BiCubicInterpolator dsdy_NC_nu; - ///Singly-differential cross section for charged-current anti-neutrino interactions - BiCubicInterpolator dsdy_CC_nubar; - ///Singly-differential cross section for neutral-current anti-neutrino interactions - BiCubicInterpolator dsdy_NC_nubar; - }; - - std::unordered_map,FlavorHash> xsData; + ///Total cross section for charged-current neutrino interactions + AkimaSpline s_CC_nu; + ///Total cross section for neutral-current neutrino interactions + AkimaSpline s_NC_nu; + ///Total cross section for charged-current anti-neutrino interactions + AkimaSpline s_CC_nubar; + ///Total cross section for neutral-current anti-neutrino interactions + AkimaSpline s_NC_nubar; + + ///Singly-differential cross section for charged-current neutrino interactions + BiCubicInterpolator dsdy_CC_nu; + ///Singly-differential cross section for neutral-current neutrino interactions + BiCubicInterpolator dsdy_NC_nu; + ///Singly-differential cross section for charged-current anti-neutrino interactions + BiCubicInterpolator dsdy_CC_nubar; + ///Singly-differential cross section for neutral-current anti-neutrino interactions + BiCubicInterpolator dsdy_NC_nubar; ///Read a total cross section table from whitespace-separated text ///\param path the filesystem path from which to read input @@ -340,34 +298,10 @@ class NeutrinoDISCrossSectionsFromTables : public NeutrinoCrossSections { /// minimum tabulated energy, and maximum tabulated energy. /// Energies are in natural units. std::tuple read2DInterpolationFromText(const std::string& path); - - ///Read data for a single flavor from a set of text files with a common prefix - ///\param prefix the common initial part of the text files' path and name - ///\param erangeSrc a description of the source from which the energy range - /// has been determined, if any - std::shared_ptr readFlavorText(const std::string& prefix, - std::string& erangeSrc); - - ///Read data for a single flavor from an HDF5 group - ///\param sourceLoc the group (or file) from which to read HDF datasets - ///\param energies the common set of energy values used for all tables - ///\param zs the common set of z values used for all tables - std::shared_ptr readFlavorHDF5(hid_t sourceLoc, - const marray& energies, - const marray& zs); - - ///Write data for a single flavor to an HDF5 group - ///\param destLoc the group (or file) to which to write HDF datasets - ///\param data the data to write - ///\param compressionLevel level of zlib compression to apply to datasets - void writeFlavorHDF5(hid_t destLoc, const perFlavorData& data, unsigned int compressionLevel) const; ///\brief Check whether a path refers to an HDF5 file bool isHDF(const std::string& path); - ///\brief Get the data corresponding to a given flavor - const perFlavorData& getFlavor(NeutrinoFlavor flavor) const; - public: ///Construct a set of cross sections from a default set of tables NeutrinoDISCrossSectionsFromTables(); @@ -387,127 +321,108 @@ class NeutrinoDISCrossSectionsFromTables : public NeutrinoCrossSections { double AverageSingleDifferentialCrossSection(double E1, double E2Min, double E2Max, NeutrinoFlavor flavor, NeutrinoType neutype, Current current) const override; - /// Read a set of cross sections from text files with a common path prefix. - /// - /// This will fail messily and leave the object in an inconsistent state if - /// any file does not exist or has the wrong structure. - /// - /// The input files must have consistent names baased on the common prefix: - /// - ${prefix}${fl_id}nu_sigma_CC.dat : the total charged-current neutrino xs - /// - ${prefix}${fl_id}nu_sigma_NC.dat : the total neutral-current neutrino xs - /// - ${prefix}${fl_id}nubar_sigma_CC.dat : the total charged-current anti-neutrino xs - /// - ${prefix}${fl_id}nubar_sigma_NC.dat : the total neutral-current anti-neutrino xs - /// - ${prefix}${fl_id}nu_dsde_CC.dat : the singly-differential charged-current neutrino xs - /// - ${prefix}${fl_id}nu_dsde_NC.dat : the singly-differential neutral-current neutrino xs - /// - ${prefix}${fl_id}nubar_dsde_CC.dat : the singly-differential charged-current anti-neutrino xs - /// - ${prefix}${fl_id}nubar_dsde_NC.dat : the singly-differential neutral-current anti-neutrino xs - /// - /// The fl_id component may be the empty string, in which case the data - /// in the files is assumed to be valid for all active neutrino flavors. - /// Alternatively, there may be three sets of files with fl_id taking the - /// values "electron_", "muon_", and "tau_", respectively, in which case the - /// sets of files are interpreted as corresponding distinctly to the active - /// flavors in the obvious way. - /// - /// Each file must cover the same range of incoming neutrino energies, with - /// at least three energies being sampled. - /// Each total cross section file must contain two whitespace-separated - /// columns, incoming neutrino energy and cross section. Entries must be - /// sorted in ascending order of incoming neutrino energy. Energies must be - /// expressed in GeV, and cross sections in square centimeters. - /// Each singly-differential cross section file must have three columns: - /// incoming neutrino energy, 'z', and cross section. Energies must be in - /// GeV and cross sections in square centimeters, as before. 'z' is a - /// unitless variable which describes the out-going lepton energy. - /// 'z' is defined as: - /// z = (E_out-E_min)/(E_in-E_min) - /// where E_min is the minimum tabulated incoming neutrino energy, E_in is - /// the incoming neutrino energy for the table entry, and E_out is the - /// out-going lepton energy. Entries must be sorted in ascending order of - /// incoming neutrino energy, and ascending order of 'z' for matching - /// incoming energies. 'z' values must be uniformly sampled over the domain - /// [0,1], and the same numbers of entries must be present for all incoming - /// neutrino energies, i.e. the table must be rectangular. At least three - /// values of 'z' must be sampled. 'z' is not well-defined for the lowest - /// incoming neutrino energy in the table, E_in = E_min. This can be - /// ignored, as there can be no tabulated entry with E_out < E_in for this - /// energy (and thus a non-zero cross section), instead the same set of z - /// values as for other energies should be used, each with a cross section - /// of zero. - /// - ///\param prefix the common filesystem path prefix for all input files - void ReadText(const std::string& prefix); - - /// Write out a set of text files in the format expected by ReadText. - ///\param prefix the path prefix from which each output file's name should - /// be derived - void WriteText(const std::string& prefix) const; + /// Read a set of cross sections from text files with a common path prefix. + /// + /// This will fail messily and leave the object in an inconsistent state if + /// any file does not exist or has the wrong structure. + /// + /// The input files must have consistent names: + /// - ${prefix}nu_sigma_CC.dat : the total charged-current neutrino xs + /// - ${prefix}nu_sigma_NC.dat : the total neutral-current neutrino xs + /// - ${prefix}nubar_sigma_CC.dat : the total charged-current anti-neutrino xs + /// - ${prefix}nubar_sigma_NC.dat : the total neutral-current anti-neutrino xs + /// - ${prefix}nu_dsde_CC.dat : the singly-differential charged-current neutrino xs + /// - ${prefix}nu_dsde_NC.dat : the singly-differential neutral-current neutrino xs + /// - ${prefix}nubar_dsde_CC.dat : the singly-differential charged-current anti-neutrino xs + /// - ${prefix}nubar_dsde_NC.dat : the singly-differential neutral-current anti-neutrino xs + /// + /// Each file must cover the same range of incoming neutrino energies, with + /// at least three energies being sampled. + /// Each total cross section file must contain two whitespace-separated + /// columns, incoming neutrino energy and cross section. Entries must be + /// sorted in ascending order of incoming neutrino energy. Energies must be + /// expressed in GeV, and cross sections in square centimeters. + /// Each singly-differential cross section file must have three columns: + /// incoming neutrino energy, 'z', and cross section. Energies must be in + /// GeV and cross sections in square centimeters, as before. 'z' is a + /// unitless variable which describes the out-going lepton energy. + /// 'z' is defined as: + /// z = (E_out-E_min)/(E_in-E_min) + /// where E_min is the minimum tabulated incoming neutrino energy, E_in is + /// the incoming neutrino energy for the table entry, and E_out is the + /// out-going lepton energy. Entries must be sorted in ascending order of + /// incoming neutrino energy, and ascending order of 'z' for matching + /// incoming energies. 'z' values must be uniformly sampled over the domain + /// [0,1], and the same numbers of entries must be present for all incoming + /// neutrino energies, i.e. the table must be rectangular. At least three + /// values of 'z' must be sampled. 'z' is not well-defined for the lowest + /// incoming neutrino energy in the table, E_in = E_min. This can be + /// ignored, as there can be no tabulated entry with E_out < E_in for this + /// energy (and thus a non-zero cross section), instead the same set of z + /// values as for other energies should be used, each with a cross section + /// of zero. + /// + ///\param prefix the common filesystem path prefix for all input files + void ReadText(const std::string& prefix); - /// Read a set of cross sections from an HDF5 file. - /// - /// This will fail messily and leave the object in an inconsistent state if - /// the file has the wrong structure. - /// - /// The file must contain a set of ten datasets: - /// - energies - /// - zs - /// - s_CC_nu - /// - s_NC_nu - /// - s_CC_nubar - /// - s_NC_nubar - /// - dsdy_CC_nu - /// - dsdy_NC_nu - /// - dsdy_CC_nubar - /// - dsdy_NC_nubar - /// - /// Or, alternatively, the file may contain the energies and zs datasets - /// directly and also contain three groups: - /// - electron - /// - muon - /// - tau - /// each containing its own set of the eight s_* and dsdy_* datasets. - /// - /// In the former case all total and singly differential cross sections will - /// be assumed to be common to all active neutrino flavors, while in the - /// latter case the cross sections will be distinctly assigned to the active - /// flavors in the obvious way. - /// - /// energies and zs must be one dimensional datasets, containing the - /// base-ten logarithm of the energy values (in electronvolts) and the - /// values of the 'z' transformed variable used for the other eight tables. - /// The z variable is defined as: - /// z = (E_out-E_min)/(E_in-E_min) - /// where E_min is the minimum tabulated incoming neutrino energy, E_in is - /// the incoming neutrino energy for the table entry, and E_out is the - /// out-going lepton energy. - /// The values in energies and zs must be sorted in ascending order (and the - /// other tables must have been made to correspond to this). energies and zs - /// must each contain at least three distinct values. - /// The s_{CC|NC}_{nu|nubar} tables must be one-dimensional datasets whose - /// values are the base-ten logarithms of the total cross section, in square - /// centimeters, for the indicated current and impinging particle type. The - /// cross section values must be tabulated for the same energies that are - /// contained in the energies dataset. - /// The dsdy_{CC|NC}_{nu|nubar} tables must be two-dimensional datasets - /// whose values are the base-ten logarithms of the differential cross - /// section with respect to y, in square centimeters, for the indicated - /// current and impinging particle type. The dimensions of these datasets - /// are energy and 'z', corresponding to the values in the energies and zs - /// datasets. Since 'z' is not well-defined for the lowest incoming neutrino - /// energy in the tables, E_in = E_min, the row corresponding to this energy - /// should contain a small value (but not negative infinity), which will - /// never be used directly. -50, corresponding to a cross section of 1e-50 - /// cm^2 can be a good choice in practice. - void ReadHDF(const std::string& path); - - /// Write out an HDF5 file in the format expected by ReadHDF. - ///\param path the path to which the output should be written - void WriteHDF(const std::string& path, unsigned int compressionLevel=0) const; - - /// \brief Returns the minimum energy in [eV] - double GetEmin() const {return Emin;} - /// \brief Returns the maximum energy in [eV] - double GetEmax() const {return Emax;} + /// Write out a set of text files in the format expected by ReadText. + ///\param prefix the path prefix from which each output file's name should + /// be derived + void WriteText(const std::string& prefix) const; + + /// Read a set of cross sections from an HDF5 file. + /// + /// This will fail messily and leave the object in an inconsistent state if + /// the file has the wrong structure. + /// + /// The file must contain a minimum of ten datasets: + /// - energies + /// - zs + /// - s_CC_nu + /// - s_NC_nu + /// - s_CC_nubar + /// - s_NC_nubar + /// - dsdy_CC_nu + /// - dsdy_NC_nu + /// - dsdy_CC_nubar + /// - dsdy_NC_nubar + /// + /// energies and zs must be one dimensional datasets, containing the + /// base-ten logarithm of the energy values (in electronvolts) and the + /// values of the 'z' transformed variable used for the other eight tables. + /// The z variable is defined as: + /// z = (E_out-E_min)/(E_in-E_min) + /// where E_min is the minimum tabulated incoming neutrino energy, E_in is + /// the incoming neutrino energy for the table entry, and E_out is the + /// out-going lepton energy. + /// The values in energies and zs must be sorted in ascending order (and the + /// other tables must have been made to correspond to this). energies and zs + /// must each contain at least three distinct values. + /// The s_{CC|NC}_{nu|nubar} tables must be one-dimensional datasets whose + /// values are the base-ten logarithms of the total cross section, in square + /// centimeters, for the indicated current and impinging particle type. The + /// cross section values must be tabulated for the same energies that are + /// contained in the energies dataset. + /// The dsdy_{CC|NC}_{nu|nubar} tables must be two-dimensional datasets + /// whose values are the base-ten logarithms of the differential cross + /// section with respect to y, in square centimeters, for the indicated + /// current and impinging particle type. The dimensions of these datasets + /// are energy and 'z', corresponding to the values in the energies and zs + /// datasets. Since 'z' is not well-defined for the lowest incoming neutrino + /// energy in the tables, E_in = E_min, the row corresponding to this energy + /// should contain a small value (but not negative infinity), which will + /// never be used directly. -50, corresponding to a cross section of 1e-50 + /// cm^2 can be a good choice in practice. + void ReadHDF(const std::string& path); + + /// Write out an HDF5 file in the format expected by ReadHDF. + ///\param path the path to which the output should be written + void WriteHDF(const std::string& path, unsigned int compressionLevel=0) const; + + /// \brief Returns the minimum energy in [eV] + double GetEmin() const {return Emin;} + /// \brief Returns the maximum energy in [eV] + double GetEmax() const {return Emax;} }; /// \class NeutrinoGRCrossSection diff --git a/resources/build_template/Makefile b/resources/build_template/Makefile deleted file mode 100644 index 4e04990c..00000000 --- a/resources/build_template/Makefile +++ /dev/null @@ -1,74 +0,0 @@ -# Set this to the name you want for your compiled program -PROGRAM:= - -# Set this variable to a space-separated list of all C++ -# implementation files for your program, e.g.: -# IMPLEMENTATION_FILES=main.cpp functions.cpp -IMPLEMENTATION_FILES:= - -# Put in this variable the names of any header files you write -# which are used by your implementation files, e.g.: -# HEADERS:=functions.h -HEADERS:= - -# c++11 is the minimum version which works with nuSQuIDS. -# However, if you have a newer compiler and wish to use newer -# language features you can change this to more recent versions, -# e.g. c++14, c++17, etc. -CXX_VERSION:=c++11 - -# This is the file extension assumed for implementation files. -# E.g. if you name your files main.C, foo.C, etc., set this to C -CXX_SUFFIX:=cpp - -# Add here any additional flags you want to use when compiling, -# e.g. -O3 for maximum optimization, or -g to include debug info -CXXFLAGS+= - -# Add here any additional flags you want to use when linking, -# e.g. -lfftw3 to link against the 'FFTW' library -LDFLAGS+= - - - - -################################################################ -# DON"T CHANGE THE PARTS BELOW (UNLESS YOU REALLY NEED TO) # -################################################################ -CXX?=c++ - -OBJECTS=${IMPLEMENTATION_FILES:.${CXX_SUFFIX}=.o} - -CXXFLAGS+=-std=${CXX_VERSION} $$(cat .nusquids_cxxflags) -LDFLAGS+=$$(cat .nusquids_ldflags) - -all : ${PROGRAM} - @( [ "${PROGRAM}" ] || echo "Error: You have not set a program name in the Makefile") && [ "${PROGRAM}" ] - -${PROGRAM} : ${OBJECTS} Makefile .nusquids_ldflags - @( [ "${OBJECTS}" ] || echo "Error: You have not defined any implementation files in the Makefile") && [ "${OBJECTS}" ] - @( [ "${CXX_SUFFIX}" ] || echo "Error: CXX_SUFFIX is not set in the Makefile") && [ "${CXX_SUFFIX}" ] - @( echo "${OBJECTS}" | (! grep -q '\.[^o]') || echo "Error: At least one file in your IMPLEMENTATION_FILES does not have the suffix specified by CXX_SUFFIX") && (echo "${OBJECTS}" | (! grep -q '\.[^o]')) - ${CXX} ${OBJECTS} ${LDFLAGS} -o ${PROGRAM} - -# This pattern rule works for GNU make -%.o : %.${CXX_SUFFIX} Makefile ${HEADERS} .nusquids_cxxflags - @( [ "${CXX_VERSION}" ] || echo "Error: CXX_VERSION is not set in the Makefile") && [ "${CXX_VERSION}" ] - ${CXX} -c ${CXXFLAGS} $< -o $@ - -# This old-fashioned suffix rule works for BSD make -.SUFFIXES : .${CXX_SUFFIX} .o -.${CXX_SUFFIX}.o : Makefile ${HEADERS} .nusquids_cxxflags - @( [ "${CXX_VERSION}" ] || echo "Error: CXX_VERSION is not set in the Makefile") && [ "${CXX_VERSION}" ] - ${CXX} -c ${CXXFLAGS} $< -o $@ - -.nusquids_cxxflags : Makefile - pkg-config nusquids squids --cflags > .nusquids_cxxflags - -.nusquids_ldflags : Makefile - pkg-config nusquids squids --libs > .nusquids_ldflags - -.PHONY: all clean %.o -clean : - @( echo "${OBJECTS}" | (! grep -q '\.[^o]') || echo "Error: At least one file in your IMPLEMENTATION_FILES does not have the suffix specified by CXX_SUFFIX") && (echo "${OBJECTS}" | (! grep -q '\.[^o]')) - rm -rf ${PROGRAM} ${OBJECTS} .nusquids_cxxflags .nusquids_ldflags \ No newline at end of file diff --git a/resources/build_template/README.md b/resources/build_template/README.md deleted file mode 100644 index 306bba0d..00000000 --- a/resources/build_template/README.md +++ /dev/null @@ -1,141 +0,0 @@ -# Template for Building Simple C++ Programs - -Since nuSQuIDS is a library, to do calculations with it one must generally write a program linked against it. -One option is to use the python bindings, which allow use of the library either through a python script, or an interactive python interpreter session. -However, not all features of the library can be efficiently exposed to python, and the python interface has overheads. -It is often useful to program against the library's native C++ API, but preparing a C++ program for compilation is a task many people find tedious, so this template is provided for greater convenience. - -## Structure of the Template - -The template itself is the single `Makefile` in this directory. -It has two parts: -First, a set of variables with descriptions which the user should set to control what will be built and how. -Second, a set of variables and rules which form the implementation for compiling the user's program and ensuring that it is suitably linked with nuSQuIDS. -The template rules assume that the nuSQuIDS library has been compiled and installed so that the included `pkg-config` definition is available. -Note that, depending on your system and where you chose to install the library, this may require adding the install location to your `PKG_CONFIG_PATH` environment variable. -The two halves of the makefile are separated by a comment which advises against modifying the second half, as doing so should not be necessary in most circumstances. -The first half contains comments to guide usage, while the second half is only minimally commented. - -## Example Use - -Suppose that we want to write a program which will use nuSQuIDS to calculate the oscillation probability for a unit beam of muon neutrinos of a given energy through the Earth. One might write it as follows: - - #include - #include "nuSQuIDS/nuSQuIDS.h" - int main(int argc, char* argv[]){ - using namespace nusquids; - if(argc<2){ - std::cout << "Usage: earth_osc energy" << std::endl; - return 0; - } - nuSQUIDS nus(3,neutrino); - squids::Const units; - nus.Set_E(std::stod(argv[1])*units.GeV); - nus.Set_Body(std::make_shared()); - nus.Set_Track(std::make_shared(acos(-1.0))); - nus.Set_initial_state(marray({3},{0,1,0}),flavor); - nus.EvolveState(); - for(int i=0; i<3; i++) - std::cout << nus.EvalFlavor(i) << ' '; - std::cout << std::endl; - return 0; - } - -This program takes an energy, assumed to be in GeV, as its single argument, and propagates a suitable beam of neutrinos through the full diameter of the Earth. -It could be generalized and made more useful in myriad ways, but we will use this simple version for brevity. -Let us assume that we save this file as `earth_osc.cpp`, in some new directory where we wish to compile it. -Next, we would copy the template Makefile to the same directory: - - # In the directory containing earth_osc.cpp: - cp ${NUSQUIDS_SOURCE_PATH}/resources/build_template/Makefile ./ - -Assuming that NUSQUIDS_SOURCE_PATH is the path where the nuSQuIDS source code was placed. -Then, we edit the copied `Makefile` to set the necessary variables. - -First, we set `PROGRAM` to the name of our program, which will be `earth_osc` for this example: - - PROGRAM:=earth_osc - -Next, we specify the implementation files to be compiled. We have only one, `earth_osc.cpp`: - - IMPLEMENTATION_FILES:=earth_osc.cpp - -This is all that is required. It should now be sufficient to run `make` to compile the program, which we can then run. -Doing so might look something like this: - - $ make - pkg-config nusquids squids --cflags > .nusquids_cxxflags - /usr/local/bin/clang++ -c -std=c++11 $(cat .nusquids_cxxflags) earth_osc.cpp -o earth_osc.o - pkg-config nusquids squids --libs > .nusquids_ldflags - /usr/local/bin/clang++ earth_osc.o $(cat .nusquids_ldflags) -o earth_osc - $ ./earth_osc 10 - 0.0835682 0.507911 0.408521 - -To clean up automatically generated files, a `clean` target is also provided which will erase them: - - $ make clean - rm -rf earth_osc earth_osc.o .nusquids_cxxflags .nusquids_ldflags - -## More Advanced Programs - -Your program need not have only a single implementation file. -For example, you might implement a new type of `Body`, and for neatness place it in its own header and implementation file: - - /* NewBody.h */ - #ifndef NEWBODY_H - #define NEWBODY_H - #include - - class NewBody : public nusquids::Body{ - NewBody(double density); - //Declarations of other necessary functions and data types . . . - }; - #endif //NEWBODY_H - - /* NewBody.cpp */ - #include "NewBody.h" - - NewBody::NewBody(double density){ /* implementation. . . */ } - - // Implementations of other functions. . . - -Naturally, to use this new type of `Body` you would `#include "NewBody.h"` in your main implementation file. But how to ensure that it is properly compiled and dependencies are accounted for, etc.? -First, since you have a second implementation file, add it to `IMPLEMENTATION_FILES`: - - IMPLEMENTATION_FILES:=earth_osc.cpp NewBody.cpp - -Files in this variable are just separated by spaces. -Next, add your new header file to the `HEADERS` variable: - - HEADERS:=NewBody.h - -Like `IMPLEMENTATION_FILES`, this is just a space separated list, which can contain as many files as you need. - -With these changes, running `make` should compile both implementation files and link both into the program executable. -If the header file is changed, both implementation files will be recompiled, etc. - -## Other Variables and Settings - -The `CXX_VERSION` variable may be set if you want to compile your program with a different language standard. nuSQuIDS requires C++11, but should also work with C++14, C++17, C++20 and future versions. - -The `CXX_SUFFIX` variable may be changed if you prefer to name your C++ implementation files with a different file extension, such as `.cxx`, `.c++`, or `.C`. Note that no dot should be included in the value of the variable, so if you name your files lie `my_file.cxx`, just set it to `cxx`. - -`CXXFLAGS` can be set to include any additional compiler settings you want to use. -Common additions are the `-g` option for debug information, or `-O2`/`-O3` optimization options. - -`LDFLAGS` can be likewise set to add additional options to the linker; this is most commonly used to request linking against additional libraries besides nuSQuIDS. - -## Portability and Limitations - -The template makefile has been written and tested to work for both GNU make and BSD make, despite their differences in dialect. -It also assumes the availability of some standard unix programs (the test program `[`, `cat`, `echo`, `grep`) and Bourne shell features, as well as the `pkg-config` tool. -Naturally, a C++ compiler is required, whose name is obtained from the `CXX` environment variable, and is assumed to be `c++` if this is not set. - -The rules of the Makefile are written assuming that the compiler has a command line interface approximately like GNU `g++`. -As such, they have been tested with `g++` and `clang++`. -Broadly, they should also work with other Unix compilers, such as the Intel compiler (`icc`) and the Nvidia HPC C++ compiler (`nvc++`), however these have not been tested and may require additional, non-default flag settings. - -Due to a general limitation of `make`, the template makefile will not work correctly if any file name contains whitespace, or the paths to the working directory for building the program, or the install locations of any libraries, etc. contain whitespace. - -This simple build system does not encompass use of python, and as such will not build any bindings to expose custom code for use in python. -In future, it may be extended, or a separate template may be provided to handle this more complex task. \ No newline at end of file diff --git a/resources/paper/fig/cross_section_interpolation.pdf b/resources/paper/fig/cross_section_interpolation.pdf deleted file mode 100644 index f32aa4f7..00000000 Binary files a/resources/paper/fig/cross_section_interpolation.pdf and /dev/null differ diff --git a/resources/paper/fig/dsdy_tabulation.eps b/resources/paper/fig/dsdy_tabulation.eps deleted file mode 100644 index 6c8e0e1d..00000000 --- a/resources/paper/fig/dsdy_tabulation.eps +++ /dev/null @@ -1,162 +0,0 @@ -%!PS-Adobe-2.0 EPSF-2.0 -%%BoundingBox: 0 0 600 300 -%%EndComments -%%Page: 1 1 - -/SampleSpacing 16.66 def -/SampleRadius 4 def -/TableDim 12 def - -/drawSample { - /f exch def - /y exch def - /x exch def - - newpath - SampleRadius x add y moveto - x y SampleRadius 0 360 arc - closepath - - gsave % save path - f f f setrgbcolor - fill - grestore % restore path copy - stroke -} def - -/arrowhead { - /size exch def - /angle exch def - /y exch def - /x exch def - - /sfront 3.5 size mul def - /sback .05 size mul def - /side 2.3 size mul def - /dangle 120 def - - newpath - x sfront angle cos mul add y sfront angle sin mul add moveto - x side angle dangle add cos mul add y side angle dangle add sin mul add lineto - x sback angle 180 add cos mul add y sback angle 180 add sin mul add lineto - x side angle dangle sub cos mul add y side angle dangle sub sin mul add lineto - closepath - fill -} def - -/puttext { % (string) fontsize fontname x y angle - 5 1 roll % move angle before fontsize - gsave - moveto findfont exch scalefont setfont % s - rotate - gsave - dup false charpath flattenpath pathbbox % s x0 y0 x1 y1 - grestore - 3 -1 roll sub % s x0 x1 dy - 3 1 roll sub % s dy -dx - 2 div exch % s -dx/2 dy - -2 div % s -dx/2 -dy/2 - rmoveto show - grestore -} def - - -% Traditional table - -((a)) 14 /Helvetica 150 12 0 puttext - -0 1 TableDim{ - SampleSpacing mul 50 add - /x exch def - 0 1 TableDim{ - SampleSpacing mul 50 add - /y exch def - x y % put on stack for drawSample - x y gt { - 1 - } { - 0 - } ifelse - drawSample - } for -} for - -% E_in axis -newpath -40 40 moveto -40 260 lineto -stroke -40 255 90 2 arrowhead - -(E) 12 /Helvetica 28 142 90 puttext -(in) 8 /Helvetica 32 150 90 puttext - -% y axis -newpath -40 40 moveto -260 40 lineto -stroke -255 40 0 2 arrowhead - -(E) 12 /Helvetica 144 32 0 puttext -(out) 8 /Helvetica 154 28 0 puttext - - -% New-fangled table - -((b)) 14 /Helvetica 450 12 0 puttext - -0 1 TableDim{ - /col exch def - col SampleSpacing mul 350 add - /x exch def - 0 1 TableDim{ - /row exch def - row SampleSpacing mul 50 add - /y exch def - x y - 1 row gt { - 1 - } { - TableDim col eq { - 0.7 - } { - 0 - } ifelse - } ifelse - drawSample - } for -} for - -% E_in axis -newpath -340 40 moveto -340 260 lineto -stroke -340 255 90 2 arrowhead - -(E) 12 /Helvetica 328 142 90 puttext -(in) 8 /Helvetica 332 150 90 puttext - -% z axis -newpath -340 40 moveto -560 40 lineto -stroke -555 40 0 2 arrowhead - -(z) 12 /Helvetica 450 32 0 puttext - -% Key - -75 275 0 drawSample -(Regular Entry) 12 /Helvetica 125 277 0 puttext - -215 275 1 drawSample -(Unphysical/Unused) 12 /Helvetica 275 277 0 puttext - -375 275 0.7 drawSample -(Replaced w/ Approximation) 12 /Helvetica 460 277 0 puttext - -showpage -%%Trailer \ No newline at end of file diff --git a/resources/paper/fig/evaluation-concurrency-scaling.pdf b/resources/paper/fig/evaluation-concurrency-scaling.pdf deleted file mode 100644 index c9c969cf..00000000 Binary files a/resources/paper/fig/evaluation-concurrency-scaling.pdf and /dev/null differ diff --git a/resources/paper/fig/evaluation-scaling.pdf b/resources/paper/fig/evaluation-scaling.pdf deleted file mode 100644 index a45dd613..00000000 Binary files a/resources/paper/fig/evaluation-scaling.pdf and /dev/null differ diff --git a/resources/paper/fig/extended_sources.eps b/resources/paper/fig/extended_sources.eps deleted file mode 100644 index f5c450da..00000000 --- a/resources/paper/fig/extended_sources.eps +++ /dev/null @@ -1,2119 +0,0 @@ -%!PS-Adobe-2.0 EPSF-2.0 -%%Title: plot.eps -%%Creator: gnuplot 5.4 patchlevel 1 -%%CreationDate: Tue Mar 9 20:21:46 2021 -%%DocumentFonts: (atend) -%%BoundingBox: 50 50 410 302 -%%EndComments -%%BeginProlog -/gnudict 256 dict def -gnudict begin -% -% The following true/false flags may be edited by hand if desired. -% The unit line width and grayscale image gamma correction may also be changed. -% -/Color true def -/Blacktext false def -/Solid false def -/Dashlength 1 def -/Landscape false def -/Level1 false def -/Level3 false def -/Rounded false def -/ClipToBoundingBox false def -/SuppressPDFMark false def -/TransparentPatterns false def -/gnulinewidth 5.000 def -/userlinewidth gnulinewidth def -/Gamma 1.0 def -/BackgroundColor {-1.000 -1.000 -1.000} def -% -/vshift -46 def -/dl1 { - 10.0 Dashlength userlinewidth gnulinewidth div mul mul mul - Rounded { currentlinewidth 0.75 mul sub dup 0 le { pop 0.01 } if } if -} def -/dl2 { - 10.0 Dashlength userlinewidth gnulinewidth div mul mul mul - Rounded { currentlinewidth 0.75 mul add } if -} def -/hpt_ 31.5 def -/vpt_ 31.5 def -/hpt hpt_ def -/vpt vpt_ def -/doclip { - ClipToBoundingBox { - newpath 50 50 moveto 410 50 lineto 410 302 lineto 50 302 lineto closepath - clip - } if -} def -% -% Gnuplot Prolog Version 5.2 (Dec 2017) -% -%/SuppressPDFMark true def -% -/M {moveto} bind def -/L {lineto} bind def -/R {rmoveto} bind def -/V {rlineto} bind def -/N {newpath moveto} bind def -/Z {closepath} bind def -/C {setrgbcolor} bind def -/f {rlineto fill} bind def -/g {setgray} bind def -/Gshow {show} def % May be redefined later in the file to support UTF-8 -/vpt2 vpt 2 mul def -/hpt2 hpt 2 mul def -/Lshow {currentpoint stroke M 0 vshift R - Blacktext {gsave 0 setgray textshow grestore} {textshow} ifelse} def -/Rshow {currentpoint stroke M dup stringwidth pop neg vshift R - Blacktext {gsave 0 setgray textshow grestore} {textshow} ifelse} def -/Cshow {currentpoint stroke M dup stringwidth pop -2 div vshift R - Blacktext {gsave 0 setgray textshow grestore} {textshow} ifelse} def -/UP {dup vpt_ mul /vpt exch def hpt_ mul /hpt exch def - /hpt2 hpt 2 mul def /vpt2 vpt 2 mul def} def -/DL {Color {setrgbcolor Solid {pop []} if 0 setdash} - {pop pop pop 0 setgray Solid {pop []} if 0 setdash} ifelse} def -/BL {stroke userlinewidth 2 mul setlinewidth - Rounded {1 setlinejoin 1 setlinecap} if} def -/AL {stroke userlinewidth 2 div setlinewidth - Rounded {1 setlinejoin 1 setlinecap} if} def -/UL {dup gnulinewidth mul /userlinewidth exch def - dup 1 lt {pop 1} if 10 mul /udl exch def} def -/PL {stroke userlinewidth setlinewidth - Rounded {1 setlinejoin 1 setlinecap} if} def -3.8 setmiterlimit -% Classic Line colors (version 5.0) -/LCw {1 1 1} def -/LCb {0 0 0} def -/LCa {0 0 0} def -/LC0 {1 0 0} def -/LC1 {0 1 0} def -/LC2 {0 0 1} def -/LC3 {1 0 1} def -/LC4 {0 1 1} def -/LC5 {1 1 0} def -/LC6 {0 0 0} def -/LC7 {1 0.3 0} def -/LC8 {0.5 0.5 0.5} def -% Default dash patterns (version 5.0) -/LTB {BL [] LCb DL} def -/LTw {PL [] 1 setgray} def -/LTb {PL [] LCb DL} def -/LTa {AL [1 udl mul 2 udl mul] 0 setdash LCa setrgbcolor} def -/LT0 {PL [] LC0 DL} def -/LT1 {PL [2 dl1 3 dl2] LC1 DL} def -/LT2 {PL [1 dl1 1.5 dl2] LC2 DL} def -/LT3 {PL [6 dl1 2 dl2 1 dl1 2 dl2] LC3 DL} def -/LT4 {PL [1 dl1 2 dl2 6 dl1 2 dl2 1 dl1 2 dl2] LC4 DL} def -/LT5 {PL [4 dl1 2 dl2] LC5 DL} def -/LT6 {PL [1.5 dl1 1.5 dl2 1.5 dl1 1.5 dl2 1.5 dl1 6 dl2] LC6 DL} def -/LT7 {PL [3 dl1 3 dl2 1 dl1 3 dl2] LC7 DL} def -/LT8 {PL [2 dl1 2 dl2 2 dl1 6 dl2] LC8 DL} def -/SL {[] 0 setdash} def -/Pnt {stroke [] 0 setdash gsave 1 setlinecap M 0 0 V stroke grestore} def -/Dia {stroke [] 0 setdash 2 copy vpt add M - hpt neg vpt neg V hpt vpt neg V - hpt vpt V hpt neg vpt V closepath stroke - Pnt} def -/Pls {stroke [] 0 setdash vpt sub M 0 vpt2 V - currentpoint stroke M - hpt neg vpt neg R hpt2 0 V stroke - } def -/Box {stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M - 0 vpt2 neg V hpt2 0 V 0 vpt2 V - hpt2 neg 0 V closepath stroke - Pnt} def -/Crs {stroke [] 0 setdash exch hpt sub exch vpt add M - hpt2 vpt2 neg V currentpoint stroke M - hpt2 neg 0 R hpt2 vpt2 V stroke} def -/TriU {stroke [] 0 setdash 2 copy vpt 1.12 mul add M - hpt neg vpt -1.62 mul V - hpt 2 mul 0 V - hpt neg vpt 1.62 mul V closepath stroke - Pnt} def -/Star {2 copy Pls Crs} def -/BoxF {stroke [] 0 setdash exch hpt sub exch vpt add M - 0 vpt2 neg V hpt2 0 V 0 vpt2 V - hpt2 neg 0 V closepath fill} def -/TriUF {stroke [] 0 setdash vpt 1.12 mul add M - hpt neg vpt -1.62 mul V - hpt 2 mul 0 V - hpt neg vpt 1.62 mul V closepath fill} def -/TriD {stroke [] 0 setdash 2 copy vpt 1.12 mul sub M - hpt neg vpt 1.62 mul V - hpt 2 mul 0 V - hpt neg vpt -1.62 mul V closepath stroke - Pnt} def -/TriDF {stroke [] 0 setdash vpt 1.12 mul sub M - hpt neg vpt 1.62 mul V - hpt 2 mul 0 V - hpt neg vpt -1.62 mul V closepath fill} def -/DiaF {stroke [] 0 setdash vpt add M - hpt neg vpt neg V hpt vpt neg V - hpt vpt V hpt neg vpt V closepath fill} def -/Pent {stroke [] 0 setdash 2 copy gsave - translate 0 hpt M 4 {72 rotate 0 hpt L} repeat - closepath stroke grestore Pnt} def -/PentF {stroke [] 0 setdash gsave - translate 0 hpt M 4 {72 rotate 0 hpt L} repeat - closepath fill grestore} def -/Circle {stroke [] 0 setdash 2 copy - hpt 0 360 arc stroke Pnt} def -/CircleF {stroke [] 0 setdash hpt 0 360 arc fill} def -/C0 {BL [] 0 setdash 2 copy moveto vpt 90 450 arc} bind def -/C1 {BL [] 0 setdash 2 copy moveto - 2 copy vpt 0 90 arc closepath fill - vpt 0 360 arc closepath} bind def -/C2 {BL [] 0 setdash 2 copy moveto - 2 copy vpt 90 180 arc closepath fill - vpt 0 360 arc closepath} bind def -/C3 {BL [] 0 setdash 2 copy moveto - 2 copy vpt 0 180 arc closepath fill - vpt 0 360 arc closepath} bind def -/C4 {BL [] 0 setdash 2 copy moveto - 2 copy vpt 180 270 arc closepath fill - vpt 0 360 arc closepath} bind def -/C5 {BL [] 0 setdash 2 copy moveto - 2 copy vpt 0 90 arc - 2 copy moveto - 2 copy vpt 180 270 arc closepath fill - vpt 0 360 arc} bind def -/C6 {BL [] 0 setdash 2 copy moveto - 2 copy vpt 90 270 arc closepath fill - vpt 0 360 arc closepath} bind def -/C7 {BL [] 0 setdash 2 copy moveto - 2 copy vpt 0 270 arc closepath fill - vpt 0 360 arc closepath} bind def -/C8 {BL [] 0 setdash 2 copy moveto - 2 copy vpt 270 360 arc closepath fill - vpt 0 360 arc closepath} bind def -/C9 {BL [] 0 setdash 2 copy moveto - 2 copy vpt 270 450 arc closepath fill - vpt 0 360 arc closepath} bind def -/C10 {BL [] 0 setdash 2 copy 2 copy moveto vpt 270 360 arc closepath fill - 2 copy moveto - 2 copy vpt 90 180 arc closepath fill - vpt 0 360 arc closepath} bind def -/C11 {BL [] 0 setdash 2 copy moveto - 2 copy vpt 0 180 arc closepath fill - 2 copy moveto - 2 copy vpt 270 360 arc closepath fill - vpt 0 360 arc closepath} bind def -/C12 {BL [] 0 setdash 2 copy moveto - 2 copy vpt 180 360 arc closepath fill - vpt 0 360 arc closepath} bind def -/C13 {BL [] 0 setdash 2 copy moveto - 2 copy vpt 0 90 arc closepath fill - 2 copy moveto - 2 copy vpt 180 360 arc closepath fill - vpt 0 360 arc closepath} bind def -/C14 {BL [] 0 setdash 2 copy moveto - 2 copy vpt 90 360 arc closepath fill - vpt 0 360 arc} bind def -/C15 {BL [] 0 setdash 2 copy vpt 0 360 arc closepath fill - vpt 0 360 arc closepath} bind def -/Rec {newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto - neg 0 rlineto closepath} bind def -/Square {dup Rec} bind def -/Bsquare {vpt sub exch vpt sub exch vpt2 Square} bind def -/S0 {BL [] 0 setdash 2 copy moveto 0 vpt rlineto BL Bsquare} bind def -/S1 {BL [] 0 setdash 2 copy vpt Square fill Bsquare} bind def -/S2 {BL [] 0 setdash 2 copy exch vpt sub exch vpt Square fill Bsquare} bind def -/S3 {BL [] 0 setdash 2 copy exch vpt sub exch vpt2 vpt Rec fill Bsquare} bind def -/S4 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def -/S5 {BL [] 0 setdash 2 copy 2 copy vpt Square fill - exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def -/S6 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill Bsquare} bind def -/S7 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill - 2 copy vpt Square fill Bsquare} bind def -/S8 {BL [] 0 setdash 2 copy vpt sub vpt Square fill Bsquare} bind def -/S9 {BL [] 0 setdash 2 copy vpt sub vpt vpt2 Rec fill Bsquare} bind def -/S10 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt Square fill - Bsquare} bind def -/S11 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt2 vpt Rec fill - Bsquare} bind def -/S12 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill Bsquare} bind def -/S13 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill - 2 copy vpt Square fill Bsquare} bind def -/S14 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill - 2 copy exch vpt sub exch vpt Square fill Bsquare} bind def -/S15 {BL [] 0 setdash 2 copy Bsquare fill Bsquare} bind def -/D0 {gsave translate 45 rotate 0 0 S0 stroke grestore} bind def -/D1 {gsave translate 45 rotate 0 0 S1 stroke grestore} bind def -/D2 {gsave translate 45 rotate 0 0 S2 stroke grestore} bind def -/D3 {gsave translate 45 rotate 0 0 S3 stroke grestore} bind def -/D4 {gsave translate 45 rotate 0 0 S4 stroke grestore} bind def -/D5 {gsave translate 45 rotate 0 0 S5 stroke grestore} bind def -/D6 {gsave translate 45 rotate 0 0 S6 stroke grestore} bind def -/D7 {gsave translate 45 rotate 0 0 S7 stroke grestore} bind def -/D8 {gsave translate 45 rotate 0 0 S8 stroke grestore} bind def -/D9 {gsave translate 45 rotate 0 0 S9 stroke grestore} bind def -/D10 {gsave translate 45 rotate 0 0 S10 stroke grestore} bind def -/D11 {gsave translate 45 rotate 0 0 S11 stroke grestore} bind def -/D12 {gsave translate 45 rotate 0 0 S12 stroke grestore} bind def -/D13 {gsave translate 45 rotate 0 0 S13 stroke grestore} bind def -/D14 {gsave translate 45 rotate 0 0 S14 stroke grestore} bind def -/D15 {gsave translate 45 rotate 0 0 S15 stroke grestore} bind def -/DiaE {stroke [] 0 setdash vpt add M - hpt neg vpt neg V hpt vpt neg V - hpt vpt V hpt neg vpt V closepath stroke} def -/BoxE {stroke [] 0 setdash exch hpt sub exch vpt add M - 0 vpt2 neg V hpt2 0 V 0 vpt2 V - hpt2 neg 0 V closepath stroke} def -/TriUE {stroke [] 0 setdash vpt 1.12 mul add M - hpt neg vpt -1.62 mul V - hpt 2 mul 0 V - hpt neg vpt 1.62 mul V closepath stroke} def -/TriDE {stroke [] 0 setdash vpt 1.12 mul sub M - hpt neg vpt 1.62 mul V - hpt 2 mul 0 V - hpt neg vpt -1.62 mul V closepath stroke} def -/PentE {stroke [] 0 setdash gsave - translate 0 hpt M 4 {72 rotate 0 hpt L} repeat - closepath stroke grestore} def -/CircE {stroke [] 0 setdash - hpt 0 360 arc stroke} def -/Opaque {gsave closepath 1 setgray fill grestore 0 setgray closepath} def -/DiaW {stroke [] 0 setdash vpt add M - hpt neg vpt neg V hpt vpt neg V - hpt vpt V hpt neg vpt V Opaque stroke} def -/BoxW {stroke [] 0 setdash exch hpt sub exch vpt add M - 0 vpt2 neg V hpt2 0 V 0 vpt2 V - hpt2 neg 0 V Opaque stroke} def -/TriUW {stroke [] 0 setdash vpt 1.12 mul add M - hpt neg vpt -1.62 mul V - hpt 2 mul 0 V - hpt neg vpt 1.62 mul V Opaque stroke} def -/TriDW {stroke [] 0 setdash vpt 1.12 mul sub M - hpt neg vpt 1.62 mul V - hpt 2 mul 0 V - hpt neg vpt -1.62 mul V Opaque stroke} def -/PentW {stroke [] 0 setdash gsave - translate 0 hpt M 4 {72 rotate 0 hpt L} repeat - Opaque stroke grestore} def -/CircW {stroke [] 0 setdash - hpt 0 360 arc Opaque stroke} def -/BoxFill {gsave Rec 1 setgray fill grestore} def -/Density { - /Fillden exch def - currentrgbcolor - /ColB exch def /ColG exch def /ColR exch def - /ColR ColR Fillden mul Fillden sub 1 add def - /ColG ColG Fillden mul Fillden sub 1 add def - /ColB ColB Fillden mul Fillden sub 1 add def - ColR ColG ColB setrgbcolor} def -/BoxColFill {gsave Rec PolyFill} def -/PolyFill {gsave Density fill grestore grestore} def -/h {rlineto rlineto rlineto closepath gsave fill grestore stroke} bind def -% -% PostScript Level 1 Pattern Fill routine for rectangles -% Usage: x y w h s a XX PatternFill -% x,y = lower left corner of box to be filled -% w,h = width and height of box -% a = angle in degrees between lines and x-axis -% XX = 0/1 for no/yes cross-hatch -% -/PatternFill {gsave /PFa [ 9 2 roll ] def - PFa 0 get PFa 2 get 2 div add PFa 1 get PFa 3 get 2 div add translate - PFa 2 get -2 div PFa 3 get -2 div PFa 2 get PFa 3 get Rec - TransparentPatterns {} {gsave 1 setgray fill grestore} ifelse - clip - currentlinewidth 0.5 mul setlinewidth - /PFs PFa 2 get dup mul PFa 3 get dup mul add sqrt def - 0 0 M PFa 5 get rotate PFs -2 div dup translate - 0 1 PFs PFa 4 get div 1 add floor cvi - {PFa 4 get mul 0 M 0 PFs V} for - 0 PFa 6 get ne { - 0 1 PFs PFa 4 get div 1 add floor cvi - {PFa 4 get mul 0 2 1 roll M PFs 0 V} for - } if - stroke grestore} def -% -/languagelevel where - {pop languagelevel} {1} ifelse -dup 2 lt - {/InterpretLevel1 true def - /InterpretLevel3 false def} - {/InterpretLevel1 Level1 def - 2 gt - {/InterpretLevel3 Level3 def} - {/InterpretLevel3 false def} - ifelse } - ifelse -% -% PostScript level 2 pattern fill definitions -% -/Level2PatternFill { -/Tile8x8 {/PaintType 2 /PatternType 1 /TilingType 1 /BBox [0 0 8 8] /XStep 8 /YStep 8} - bind def -/KeepColor {currentrgbcolor [/Pattern /DeviceRGB] setcolorspace} bind def -<< Tile8x8 - /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke} ->> matrix makepattern -/Pat1 exch def -<< Tile8x8 - /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke - 0 4 M 4 8 L 8 4 L 4 0 L 0 4 L stroke} ->> matrix makepattern -/Pat2 exch def -<< Tile8x8 - /PaintProc {0.5 setlinewidth pop 0 0 M 0 8 L - 8 8 L 8 0 L 0 0 L fill} ->> matrix makepattern -/Pat3 exch def -<< Tile8x8 - /PaintProc {0.5 setlinewidth pop -4 8 M 8 -4 L - 0 12 M 12 0 L stroke} ->> matrix makepattern -/Pat4 exch def -<< Tile8x8 - /PaintProc {0.5 setlinewidth pop -4 0 M 8 12 L - 0 -4 M 12 8 L stroke} ->> matrix makepattern -/Pat5 exch def -<< Tile8x8 - /PaintProc {0.5 setlinewidth pop -2 8 M 4 -4 L - 0 12 M 8 -4 L 4 12 M 10 0 L stroke} ->> matrix makepattern -/Pat6 exch def -<< Tile8x8 - /PaintProc {0.5 setlinewidth pop -2 0 M 4 12 L - 0 -4 M 8 12 L 4 -4 M 10 8 L stroke} ->> matrix makepattern -/Pat7 exch def -<< Tile8x8 - /PaintProc {0.5 setlinewidth pop 8 -2 M -4 4 L - 12 0 M -4 8 L 12 4 M 0 10 L stroke} ->> matrix makepattern -/Pat8 exch def -<< Tile8x8 - /PaintProc {0.5 setlinewidth pop 0 -2 M 12 4 L - -4 0 M 12 8 L -4 4 M 8 10 L stroke} ->> matrix makepattern -/Pat9 exch def -/Pattern1 {PatternBgnd KeepColor Pat1 setpattern} bind def -/Pattern2 {PatternBgnd KeepColor Pat2 setpattern} bind def -/Pattern3 {PatternBgnd KeepColor Pat3 setpattern} bind def -/Pattern4 {PatternBgnd KeepColor Landscape {Pat5} {Pat4} ifelse setpattern} bind def -/Pattern5 {PatternBgnd KeepColor Landscape {Pat4} {Pat5} ifelse setpattern} bind def -/Pattern6 {PatternBgnd KeepColor Landscape {Pat9} {Pat6} ifelse setpattern} bind def -/Pattern7 {PatternBgnd KeepColor Landscape {Pat8} {Pat7} ifelse setpattern} bind def -} def -% -% -%End of PostScript Level 2 code -% -/PatternBgnd { - TransparentPatterns {} {gsave 1 setgray fill grestore} ifelse -} def -% -% Substitute for Level 2 pattern fill codes with -% grayscale if Level 2 support is not selected. -% -/Level1PatternFill { -/Pattern1 {0.250 Density} bind def -/Pattern2 {0.500 Density} bind def -/Pattern3 {0.750 Density} bind def -/Pattern4 {0.125 Density} bind def -/Pattern5 {0.375 Density} bind def -/Pattern6 {0.625 Density} bind def -/Pattern7 {0.875 Density} bind def -} def -% -% Now test for support of Level 2 code -% -Level1 {Level1PatternFill} {Level2PatternFill} ifelse -% -/Symbol-Oblique /Symbol findfont [1 0 .167 1 0 0] makefont -dup length dict begin {1 index /FID eq {pop pop} {def} ifelse} forall -currentdict end definefont pop -% -/Metrics {ExtendTextBox Gswidth} def -/Lwidth {currentpoint stroke M 0 vshift R Metrics} def -/Rwidth {currentpoint stroke M dup stringwidth pop neg vshift R Metrics} def -/Cwidth {currentpoint stroke M dup stringwidth pop -2 div vshift R Metrics} def -/GLwidth {currentpoint stroke M 0 vshift R {ExtendTextBox} forall} def -/GRwidth {currentpoint stroke M dup Gwidth vshift R {ExtendTextBox} forall} def -/GCwidth {currentpoint stroke M dup Gwidth 2 div vshift R {ExtendTextBox} forall} def -/GLwidth2 {0 Gwidth AddGlyphWidth} def -/GRwidth2 {Gwidth -1 mul 0 AddGlyphWidth} def -/GCwidth2 {Gwidth 2 div dup -1 mul AddGlyphWidth} def -/AddGlyphWidth { dup TBx2 gt {userdict /TBx2 3 -1 roll put} {pop} ifelse - dup TBx1 lt {userdict /TBx1 3 -1 roll put} {pop} ifelse } def -/MFshow { - { dup 5 get 3 ge - { 5 get 3 eq {gsave} {grestore} ifelse } - {dup dup 0 get findfont exch 1 get scalefont setfont - [ currentpoint ] exch dup 2 get 0 exch R dup 5 get 2 ne {dup dup 6 - get exch 4 get {textshow} {Metrics pop 0 R} ifelse }if dup 5 get 0 eq - {dup 3 get {2 get neg 0 exch R pop} {pop aload pop M} ifelse} {dup 5 - get 1 eq {dup 2 get exch dup 3 get exch 6 get Gswidth pop -2 div - dup 0 R} {dup 6 get Gswidth pop -2 div 0 R 6 get - textshow 2 index {aload pop M neg 3 -1 roll neg R pop pop} {pop pop pop - pop aload pop M} ifelse }ifelse }ifelse } - ifelse } - forall} def -/Gswidth {dup type /stringtype eq {stringwidth} {pop (n) stringwidth} ifelse} def -/MFwidth {0 exch { dup 5 get 3 ge { 5 get 3 eq { 0 } { pop } ifelse } - {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont - 6 get Gswidth pop add} {pop} ifelse} ifelse} forall} def -/MLshow { currentpoint stroke M - 0 exch R - Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def -/MRshow { currentpoint stroke M - exch dup MFwidth neg 3 -1 roll R - Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def -/MCshow { currentpoint stroke M - exch dup MFwidth -2 div 3 -1 roll R - Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def -/XYsave { [( ) 1 2 true false 3 ()] } bind def -/XYrestore { [( ) 1 2 true false 4 ()] } bind def -Level1 SuppressPDFMark or -{} { -/SDict 10 dict def -systemdict /pdfmark known not { - userdict /pdfmark systemdict /cleartomark get put -} if -SDict begin [ - /Title (plot.eps) - /Subject (gnuplot plot) - /Creator (gnuplot 5.4 patchlevel 1) -% /Producer (gnuplot) -% /Keywords () - /CreationDate (Tue Mar 9 20:21:46 2021) - /DOCINFO pdfmark -end -} ifelse -% -% Support for boxed text - Ethan A Merritt Sep 2016 -% -/InitTextBox { userdict /TBy2 3 -1 roll put userdict /TBx2 3 -1 roll put - userdict /TBy1 3 -1 roll put userdict /TBx1 3 -1 roll put - /Boxing true def } def -/ExtendTextBox { dup type /stringtype eq - { Boxing { gsave dup false charpath pathbbox - dup TBy2 gt {userdict /TBy2 3 -1 roll put} {pop} ifelse - dup TBx2 gt {userdict /TBx2 3 -1 roll put} {pop} ifelse - dup TBy1 lt {userdict /TBy1 3 -1 roll put} {pop} ifelse - dup TBx1 lt {userdict /TBx1 3 -1 roll put} {pop} ifelse - grestore } if } - {} ifelse} def -/PopTextBox { newpath TBx1 TBxmargin sub TBy1 TBymargin sub M - TBx1 TBxmargin sub TBy2 TBymargin add L - TBx2 TBxmargin add TBy2 TBymargin add L - TBx2 TBxmargin add TBy1 TBymargin sub L closepath } def -/DrawTextBox { PopTextBox stroke /Boxing false def} def -/FillTextBox { gsave PopTextBox fill grestore /Boxing false def} def -0 0 0 0 InitTextBox -/TBxmargin 20 def -/TBymargin 20 def -/Boxing false def -/textshow { ExtendTextBox Gshow } def -% -end -%%EndProlog -%%Page: 1 1 -gnudict begin -gsave -doclip -50 50 translate -0.050 0.050 scale -0 setgray -newpath -(Helvetica) findfont 140 scalefont setfont -BackgroundColor 0 lt 3 1 roll 0 lt exch 0 lt or or not {BackgroundColor C 1.000 0 0 7200.00 5040.00 BoxColFill} if -1.000 UL -LTb -LCb setrgbcolor -686 947 M -63 0 V -6198 0 R --63 0 V -stroke -602 947 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 0)] -] -46.7 MRshow -/Helvetica findfont 140 scalefont setfont -/vshift -46 def -1.000 UL -LTb -LCb setrgbcolor -686 1666 M -63 0 V -6198 0 R --63 0 V -stroke -602 1666 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 0.2)] -] -46.7 MRshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -686 2384 M -63 0 V -6198 0 R --63 0 V -stroke -602 2384 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 0.4)] -] -46.7 MRshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -686 3103 M -63 0 V -6198 0 R --63 0 V -stroke -602 3103 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 0.6)] -] -46.7 MRshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -686 3821 M -63 0 V -6198 0 R --63 0 V -stroke -602 3821 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 0.8)] -] -46.7 MRshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -686 4540 M -63 0 V -6198 0 R --63 0 V -stroke -602 4540 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 1)] -] -46.7 MRshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -686 588 M -0 63 V -0 4248 R -0 -63 V -stroke -686 448 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 0)] -] -46.7 MCshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -1469 588 M -0 63 V -0 4248 R -0 -63 V -stroke -1469 448 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 0.5)] -] -46.7 MCshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -2251 588 M -0 63 V -0 4248 R -0 -63 V -stroke -2251 448 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 1)] -] -46.7 MCshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -3034 588 M -0 63 V -0 4248 R -0 -63 V -stroke -3034 448 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 1.5)] -] -46.7 MCshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -3817 588 M -0 63 V -0 4248 R -0 -63 V -stroke -3817 448 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 2)] -] -46.7 MCshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -4599 588 M -0 63 V -0 4248 R -0 -63 V -stroke -4599 448 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 2.5)] -] -46.7 MCshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -5382 588 M -0 63 V -0 4248 R -0 -63 V -stroke -5382 448 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 3)] -] -46.7 MCshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -6164 588 M -0 63 V -0 4248 R -0 -63 V -stroke -6164 448 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 3.5)] -] -46.7 MCshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -6947 588 M -0 63 V -0 4248 R -0 -63 V -stroke -6947 448 M -[ [(Helvetica) 140.0 0.0 true true 0 ( 4)] -] -46.7 MCshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -LCb setrgbcolor -1.000 UL -LTB -LCb setrgbcolor -686 4899 N -686 588 L -6261 0 V -0 4311 V --6261 0 V -Z stroke -1.000 UP -1.000 UL -LTb -LCb setrgbcolor -LCb setrgbcolor -133 2743 M -currentpoint gsave translate -270 rotate 0 0 moveto -[ [(Helvetica) 140.0 0.0 true true 0 (Muon Flux Ratio)] -] -46.7 MCshow -grestore -/Helvetica findfont 140 scalefont setfont -LTb -LCb setrgbcolor -3816 238 M -[ [(Helvetica) 140.0 0.0 true true 0 (log)] -[(Helvetica) 112.0 -42.0 true true 0 (10)] -[(Helvetica) 140.0 0.0 true true 0 (\(E/GeV\))] -] -32.7 MCshow -/Helvetica findfont 140 scalefont setfont -LTb -1.000 UL -LTb -LCb setrgbcolor -5624 4416 N -0 420 V -1239 0 V -0 -420 V --1239 0 V -Z stroke -% Begin plot #1 -1.000 UL -LTb -0.58 0.00 0.83 C -2485 4899 M -4 -40 V -6 -72 V -7 -70 V -6 -68 V -6 -68 V -6 -66 V -7 -65 V -6 -64 V -6 -63 V -7 -62 V -6 -60 V -6 -60 V -6 -58 V -7 -57 V -6 -56 V -6 -55 V -6 -55 V -7 -53 V -6 -52 V -6 -51 V -6 -51 V -7 -49 V -6 -48 V -6 -48 V -6 -47 V -7 -46 V -6 -45 V -6 -44 V -6 -43 V -7 -43 V -6 -42 V -6 -41 V -7 -40 V -6 -40 V -6 -39 V -6 -38 V -7 -37 V -6 -37 V -6 -36 V -6 -36 V -7 -35 V -6 -34 V -6 -33 V -6 -33 V -7 -32 V -6 -32 V -6 -31 V -6 -31 V -7 -30 V -6 -29 V -6 -29 V -6 -29 V -7 -28 V -6 -27 V -6 -27 V -7 -27 V -6 -25 V -6 -26 V -6 -25 V -7 -24 V -6 -24 V -6 -24 V -6 -23 V -7 -23 V -6 -22 V -6 -22 V -6 -22 V -7 -21 V -6 -21 V -6 -20 V -6 -20 V -7 -20 V -6 -19 V -6 -19 V -6 -19 V -7 -18 V -6 -18 V -6 -18 V -7 -17 V -6 -17 V -6 -17 V -6 -16 V -7 -16 V -6 -16 V -6 -15 V -6 -15 V -7 -15 V -6 -15 V -6 -14 V -6 -14 V -7 -14 V -6 -14 V -6 -13 V -6 -13 V -7 -13 V -6 -13 V -6 -12 V -6 -13 V -7 -12 V -6 -11 V -6 -12 V -7 -11 V -6 -11 V -6 -11 V -6 -11 V -7 -10 V -6 -11 V -6 -10 V -6 -10 V -7 -9 V -6 -10 V -6 -10 V -6 -9 V -7 -9 V -6 -9 V -6 -8 V -6 -9 V -7 -8 V -6 -9 V -6 -8 V -6 -8 V -7 -8 V -6 -7 V -6 -8 V -7 -7 V -6 -8 V -6 -7 V -6 -7 V -7 -7 V -6 -6 V -6 -7 V -6 -7 V -7 -6 V -6 -6 V -6 -6 V -6 -6 V -7 -6 V -6 -6 V -6 -6 V -6 -5 V -7 -6 V -6 -5 V -6 -6 V -6 -5 V -7 -5 V -6 -5 V -6 -5 V -7 -5 V -6 -5 V -6 -4 V -6 -5 V -7 -4 V -6 -5 V -6 -4 V -6 -4 V -7 -5 V -6 -4 V -6 -4 V -6 -4 V -7 -4 V -6 -3 V -6 -4 V -6 -4 V -7 -3 V -6 -4 V -6 -4 V -6 -3 V -7 -3 V -6 -4 V -6 -3 V -7 -3 V -6 -3 V -6 -3 V -6 -3 V -7 -3 V -6 -3 V -6 -3 V -6 -3 V -7 -2 V -6 -3 V -6 -3 V -6 -2 V -7 -3 V -6 -2 V -6 -3 V -6 -2 V -7 -3 V -6 -2 V -6 -2 V -6 -2 V -7 -3 V -6 -2 V -6 -2 V -7 -2 V -6 -2 V -6 -2 V -6 -2 V -7 -2 V -6 -2 V -6 -2 V -6 -1 V -7 -2 V -6 -2 V -6 -2 V -6 -1 V -7 -2 V -6 -2 V -6 -1 V -6 -2 V -7 -2 V -6 -1 V -6 -2 V -7 -1 V -6 -1 V -6 -2 V -6 -1 V -7 -2 V -6 -1 V -6 -1 V -6 -2 V -7 -1 V -6 -1 V -6 -1 V -6 -1 V -7 -2 V -6 -1 V -6 -1 V -6 -1 V -7 -1 V -6 -1 V -6 -1 V -6 -1 V -7 -1 V -6 -1 V -6 -1 V -7 -1 V -6 -1 V -6 -1 V -6 -1 V -7 -1 V -6 -1 V -6 -1 V -6 0 V -7 -1 V -6 -1 V -6 -1 V -6 -1 V -7 0 V -6 -1 V -stroke 4042 988 M -6 -1 V -6 -1 V -7 0 V -6 -1 V -6 -1 V -6 0 V -7 -1 V -6 -1 V -6 0 V -7 -1 V -6 -1 V -6 0 V -6 -1 V -7 0 V -6 -1 V -6 -1 V -6 0 V -7 -1 V -6 0 V -6 -1 V -6 0 V -7 -1 V -6 0 V -6 -1 V -6 0 V -7 -1 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 -1 V -6 0 V -7 -1 V -6 0 V -6 0 V -6 -1 V -7 0 V -6 -1 V -6 0 V -6 0 V -7 -1 V -6 0 V -6 0 V -6 -1 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 -1 V -6 0 V -6 0 V -7 0 V -6 -1 V -6 0 V -7 0 V -6 -1 V -6 0 V -6 0 V -7 0 V -6 -1 V -6 0 V -6 0 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 0 V -6 -1 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 -1 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 -1 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 -1 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 -1 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -stroke 5601 948 M -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -% End plot #1 -% Begin plot #2 -stroke -LTb -0.00 0.62 0.45 C -% End plot #2 -% Begin plot #3 -1.000 UL -LTb -0.34 0.71 0.91 C -3446 4899 M -1 -3 V -6 -72 V -7 -71 V -6 -69 V -6 -68 V -6 -67 V -7 -66 V -6 -65 V -6 -63 V -6 -62 V -7 -61 V -6 -60 V -6 -59 V -6 -58 V -7 -57 V -6 -55 V -6 -55 V -7 -53 V -6 -53 V -6 -52 V -6 -51 V -7 -50 V -6 -49 V -6 -48 V -6 -47 V -7 -46 V -6 -46 V -6 -44 V -6 -44 V -7 -43 V -6 -42 V -6 -42 V -6 -41 V -7 -40 V -6 -39 V -6 -38 V -6 -38 V -7 -37 V -6 -37 V -6 -36 V -7 -35 V -6 -34 V -6 -34 V -6 -33 V -7 -33 V -6 -32 V -6 -31 V -6 -31 V -7 -31 V -6 -29 V -6 -30 V -6 -28 V -7 -28 V -6 -28 V -6 -27 V -6 -27 V -7 -26 V -6 -26 V -6 -25 V -7 -25 V -6 -24 V -6 -24 V -6 -23 V -7 -23 V -6 -23 V -6 -22 V -6 -22 V -7 -21 V -6 -21 V -6 -21 V -6 -20 V -7 -20 V -6 -19 V -6 -20 V -6 -18 V -7 -19 V -6 -18 V -6 -18 V -6 -17 V -7 -17 V -6 -17 V -6 -17 V -7 -16 V -6 -16 V -6 -15 V -6 -16 V -7 -15 V -6 -15 V -6 -14 V -6 -14 V -7 -14 V -6 -14 V -6 -13 V -6 -14 V -7 -13 V -6 -13 V -6 -12 V -6 -12 V -7 -12 V -6 -12 V -6 -12 V -6 -11 V -7 -12 V -6 -11 V -6 -10 V -7 -11 V -6 -10 V -6 -11 V -6 -10 V -7 -10 V -6 -9 V -6 -10 V -6 -9 V -7 -9 V -6 -9 V -6 -9 V -6 -9 V -7 -8 V -6 -9 V -6 -8 V -6 -8 V -7 -8 V -6 -7 V -6 -8 V -6 -8 V -7 -7 V -6 -7 V -6 -7 V -7 -7 V -6 -7 V -6 -7 V -6 -6 V -7 -7 V -6 -6 V -6 -6 V -6 -6 V -7 -6 V -6 -6 V -6 -6 V -6 -6 V -7 -5 V -6 -6 V -6 -5 V -6 -5 V -7 -5 V -6 -6 V -6 -5 V -6 -4 V -7 -5 V -6 -5 V -6 -5 V -7 -4 V -6 -5 V -6 -4 V -6 -4 V -7 -5 V -6 -4 V -6 -4 V -6 -4 V -7 -4 V -6 -4 V -6 -3 V -6 -4 V -7 -4 V -6 -3 V -6 -4 V -6 -3 V -7 -4 V -6 -3 V -6 -3 V -6 -3 V -7 -4 V -6 -3 V -6 -3 V -7 -3 V -6 -3 V -6 -2 V -6 -3 V -7 -3 V -6 -3 V -6 -2 V -6 -3 V -7 -3 V -6 -2 V -6 -3 V -6 -2 V -7 -2 V -6 -3 V -6 -2 V -6 -2 V -7 -2 V -6 -3 V -6 -2 V -6 -2 V -7 -2 V -6 -2 V -6 -2 V -7 -2 V -6 -2 V -6 -2 V -6 -2 V -7 -1 V -6 -2 V -6 -2 V -6 -2 V -7 -1 V -6 -2 V -6 -2 V -6 -1 V -7 -2 V -6 -1 V -6 -2 V -6 -1 V -7 -2 V -6 -1 V -6 -2 V -6 -1 V -7 -1 V -6 -2 V -6 -1 V -7 -1 V -6 -1 V -6 -2 V -6 -1 V -7 -1 V -6 -1 V -6 -1 V -6 -1 V -7 -2 V -6 -1 V -6 -1 V -6 -1 V -7 -1 V -6 -1 V -6 -1 V -6 -1 V -7 -1 V -6 -1 V -6 0 V -6 -1 V -7 -1 V -6 -1 V -6 -1 V -7 -1 V -6 -1 V -6 0 V -6 -1 V -7 -1 V -6 -1 V -stroke 5000 988 M -6 -1 V -6 0 V -7 -1 V -6 -1 V -6 0 V -6 -1 V -7 -1 V -6 0 V -6 -1 V -6 -1 V -7 0 V -6 -1 V -6 -1 V -6 0 V -7 -1 V -6 0 V -6 -1 V -7 0 V -6 -1 V -6 0 V -6 -1 V -7 0 V -6 -1 V -6 0 V -6 -1 V -7 0 V -6 -1 V -6 0 V -6 -1 V -7 0 V -6 -1 V -6 0 V -6 0 V -7 -1 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 -1 V -6 0 V -7 0 V -6 -1 V -6 0 V -6 -1 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 -1 V -6 0 V -6 0 V -7 0 V -6 -1 V -6 0 V -6 0 V -7 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 0 V -6 -1 V -7 0 V -6 0 V -6 0 V -6 0 V -7 -1 V -6 0 V -6 0 V -6 0 V -7 0 V -6 -1 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 -1 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 -1 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 -1 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 -1 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 -1 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -stroke 6559 948 M -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 -1 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -6 0 V -6 0 V -6 0 V -7 0 V -% End plot #3 -stroke -LCw setrgbcolor -1.000 5624 4416 1239 420 BoxColFill -1.000 UL -LTb -LCb setrgbcolor -5624 4416 N -0 420 V -1239 0 V -0 -420 V --1239 0 V -Z stroke -% Begin plot #4 -1.000 UL -LTb -0.58 0.00 0.83 C -LCb setrgbcolor -6296 4766 M -[ [(Helvetica) 140.0 0.0 true true 0 (Electron)] -] -46.7 MRshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -0.58 0.00 0.83 C -6380 4766 M -399 0 V -% End plot #4 -% Begin plot #5 -stroke -LTb -0.00 0.62 0.45 C -LCb setrgbcolor -6296 4626 M -[ [(Helvetica) 140.0 0.0 true true 0 (Muon)] -] -46.7 MRshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -0.00 0.62 0.45 C -6380 4626 M -399 0 V -% End plot #5 -% Begin plot #6 -stroke -LTb -0.34 0.71 0.91 C -LCb setrgbcolor -6296 4486 M -[ [(Helvetica) 140.0 0.0 true true 0 (Tau)] -] -46.7 MRshow -/Helvetica findfont 140 scalefont setfont -1.000 UL -LTb -0.34 0.71 0.91 C -6380 4486 M -399 0 V -% End plot #6 -stroke -2.000 UL -LTb -LCb setrgbcolor -1.000 UL -LTB -LCb setrgbcolor -686 4899 N -686 588 L -6261 0 V -0 4311 V --6261 0 V -Z stroke -1.000 UP -1.000 UL -LTb -LCb setrgbcolor -stroke -grestore -end -showpage -%%Trailer -%%DocumentFonts: Helvetica diff --git a/resources/paper/fig/propagation-scaling.pdf b/resources/paper/fig/propagation-scaling.pdf deleted file mode 100644 index 1a43e813..00000000 Binary files a/resources/paper/fig/propagation-scaling.pdf and /dev/null differ diff --git a/resources/paper/makefile b/resources/paper/makefile index bb899270..8d1b06e5 100644 --- a/resources/paper/makefile +++ b/resources/paper/makefile @@ -3,29 +3,11 @@ all: nusquids.pdf TEX_FILES:=nusquids.tex #body_track.tex cross_section_tau_decay.tex nusquids_class.tex nusquidsatm_class.tex -nusquids.pdf : $(TEX_FILES) nusquids.bib nusquids.bbl +nusquids.pdf : $(TEX_FILES) nusquids.bib pdflatex nusquids + bibtex nusquids pdflatex nusquids - -nusquids.bbl : nusquids.tex nusquids.bib pdflatex nusquids - bibtex nusquids - -nusquids_journal.bbl : nusquids_journal.tex nusquids.tex nusquids.bib - pdflatex nusquids_journal - bibtex nusquids_journal - -nusquids_journal.pdf : nusquids_journal.tex nusquids.tex nusquids_journal.bbl - pdflatex nusquids_journal - pdflatex nusquids_journal - -manual.bbl : manual.tex manual.bib - pdflatex manual - bibtex manual - -manual.pdf : manual.tex manual.bbl nusquids.tex - pdflatex manual - pdflatex manual fast : pdflatex nusquids @@ -33,16 +15,11 @@ fast : clean : rm -f nusquids.pdf rm -f nusquids.aux nusquids.bbl nusquids.blg nusquids.log nusquids.out nusquids.spl nusquids.toc - rm -f nusquids_journal.pdf - rm -f nusquids_journal.aux nusquids_journal.bbl nusquids_journal.blg nusquids_journal.log nusquids_journal.out nusquids_journal.spl nusquids_journal.toc - rm -f manual.pdf - rm -f manual.aux manual.bbl manual.blg manual.log manual.out manual.spl manual.toc rm -f arxiv.tar.bz2 arxiv : nusquids.pdf mkdir -p arxiv - cp -pr nusquids.bbl fig/* arxiv/ - sed 's|{fig/|{|' < nusquids.tex > arxiv/nusquids.tex + cp -pr nusquids.tex nusquids.bbl fig arxiv/ tar cjf arxiv.tar.bz2 arxiv rm -rf arxiv diff --git a/resources/paper/manual.bib b/resources/paper/manual.bib deleted file mode 120000 index 3779d19e..00000000 --- a/resources/paper/manual.bib +++ /dev/null @@ -1 +0,0 @@ -nusquids.bib \ No newline at end of file diff --git a/resources/paper/manual.tex b/resources/paper/manual.tex deleted file mode 100644 index 0b0990c2..00000000 --- a/resources/paper/manual.tex +++ /dev/null @@ -1,2 +0,0 @@ -\def\manualonly{} -\input{nusquids} \ No newline at end of file diff --git a/resources/paper/nusquids.bib b/resources/paper/nusquids.bib index e00b3707..44d3b9c6 100644 --- a/resources/paper/nusquids.bib +++ b/resources/paper/nusquids.bib @@ -1,874 +1,11 @@ %% This BibTeX bibliography file was created using BibDesk. %% http://bibdesk.sourceforge.net/ -%% Created for Carlos Arguelles at 2014-09-29 16:26:30 -0500 - - -%% Saved with string encoding Unicode (UTF-8) - -@article{Super-Kamiokande:2010tar, - author = "Abe, K. and others", - collaboration = "Super-Kamiokande", - title = "{Solar neutrino results in Super-Kamiokande-III}", - eprint = "1010.0118", - archivePrefix = "arXiv", - primaryClass = "hep-ex", - doi = "10.1103/PhysRevD.83.052010", - journal = "Phys. Rev. D", - volume = "83", - pages = "052010", - year = "2011" -} - -@article{Borexino:2013zhu, - author = "Bellini, G. and others", - collaboration = "Borexino", - title = "{Final results of Borexino Phase-I on low energy solar neutrino spectroscopy}", - eprint = "1308.0443", - archivePrefix = "arXiv", - primaryClass = "hep-ex", - doi = "10.1103/PhysRevD.89.112007", - journal = "Phys. Rev. D", - volume = "89", - number = "11", - pages = "112007", - year = "2014" -} - -@article{Super-Kamiokande:2015qek, - author = "Richard, E. and others", - collaboration = "Super-Kamiokande", - title = "{Measurements of the atmospheric neutrino flux by Super-Kamiokande: energy spectra, geomagnetic effects, and solar modulation}", - eprint = "1510.08127", - archivePrefix = "arXiv", - primaryClass = "hep-ex", - doi = "10.1103/PhysRevD.94.052001", - journal = "Phys. Rev. D", - volume = "94", - number = "5", - pages = "052001", - year = "2016" -} - -@article{Vincent:2017svp, - author = {Vincent, Aaron C. and Arg\"uelles, Carlos A. and Kheirandish, Ali}, - title = "{High-energy neutrino attenuation in the Earth and its associated uncertainties}", - eprint = "1706.09895", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1088/1475-7516/2017/11/012", - journal = "JCAP", - volume = "11", - pages = "012", - year = "2017" -} - -@article{Yoshida:2003js, - author = "Yoshida, Shigeru and Ishibashi, Rie and Miyamoto, Hiroko", - title = "{Propagation of extremely - high energy leptons in the earth: Implications to their detection by the IceCube Neutrino Telescope}", - eprint = "astro-ph/0312078", - archivePrefix = "arXiv", - doi = "10.1103/PhysRevD.69.103004", - journal = "Phys. Rev. D", - volume = "69", - pages = "103004", - year = "2004" -} - -@article{DeYoung:865626, - author = "De Young, T R", - title = "{IceTray: a Software Framework for IceCube}", - year = "2005", - url = "http://cds.cern.ch/record/865626", - doi = "10.5170/CERN-2005-002.463", -} - -@article{Akhmedov:1988kd, - author = "Akhmedov, Evgeny K.", - title = "{Neutrino oscillations in inhomogeneous matter. (In Russian)}", - journal = "Sov. J. Nucl. Phys.", - volume = "47", - pages = "301--302", - year = "1988" -} - -@article{Krastev:1989ix, - author = "Krastev, P. I. and Smirnov, A. Yu.", - title = "{Parametric Effects in Neutrino Oscillations}", - doi = "10.1016/0370-2693(89)91206-9", - journal = "Phys. Lett. B", - volume = "226", - pages = "341--346", - year = "1989" -} - -@article{Chizhov:1998ug, - author = "Chizhov, M. and Maris, M. and Petcov, S. T.", - title = "{On the oscillation length resonance in the transitions of solar and atmospheric neutrinos crossing the earth core}", - eprint = "hep-ph/9810501", - archivePrefix = "arXiv", - reportNumber = "SISSA-53-98-EP", - month = "7", - year = "1998" -} - -@article{Chizhov:1999az, - author = "Chizhov, M. V. and Petcov, S. T.", - title = "{New conditions for a total neutrino conversion in a medium}", - eprint = "hep-ph/9903399", - archivePrefix = "arXiv", - reportNumber = "SISSA-29-99-EP", - doi = "10.1103/PhysRevLett.83.1096", - journal = "Phys. Rev. Lett.", - volume = "83", - pages = "1096--1099", - year = "1999" -} - -@article{Akhmedov:1999va, - author = "Akhmedov, Evgeny K. and Smirnov, A. Yu.", - title = "{Comment on `New conditions for a total neutrino conversion in a medium'}", - eprint = "hep-ph/9910433", - archivePrefix = "arXiv", - reportNumber = "FISIST-17-99-CFIF", - doi = "10.1103/PhysRevLett.85.3978", - journal = "Phys. Rev. Lett.", - volume = "85", - pages = "3978", - year = "2000" -} - -@article{Nunokawa:2003ep, - author = "Nunokawa, H. and Peres, O. L. G. and Zukanovich Funchal, R.", - title = "{Probing the LSND mass scale and four neutrino scenarios with a neutrino telescope}", - eprint = "hep-ph/0302039", - archivePrefix = "arXiv", - reportNumber = "IFT-P-007-2003, IFUSP-DFN-03-079, NSF-ITP-03-09, IFT-P.007-2003", - doi = "10.1016/S0370-2693(03)00603-8", - journal = "Phys. Lett. B", - volume = "562", - pages = "279--290", - year = "2003" -} - -@article{Choubey:2007ji, - author = "Choubey, Sandhya", - title = "{Signature of sterile species in atmospheric neutrino data at neutrino telescopes}", - eprint = "0709.1937", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1088/1126-6708/2007/12/014", - journal = "JHEP", - volume = "12", - pages = "014", - year = "2007" -} - -@article{Barger:2011rc, - author = "Barger, V. and Gao, Y. and Marfatia, D.", - title = "{Is there evidence for sterile neutrinos in IceCube data?}", - eprint = "1109.5748", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1103/PhysRevD.85.011302", - journal = "Phys. Rev. D", - volume = "85", - pages = "011302", - year = "2012" -} - -@article{Esmaili:2012nz, - author = "Esmaili, Arman and Halzen, Francis and Peres, O. L. G.", - title = "{Constraining Sterile Neutrinos with AMANDA and IceCube Atmospheric Neutrino Data}", - eprint = "1206.6903", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1088/1475-7516/2012/11/041", - journal = "JCAP", - volume = "11", - pages = "041", - year = "2012" -} - -@article{Esmaili:2013vza, - author = "Esmaili, Arman and Smirnov, Alexei Yu.", - title = "{Restricting the LSND and MiniBooNE sterile neutrinos with the IceCube atmospheric neutrino data}", - eprint = "1307.6824", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1007/JHEP12(2013)014", - journal = "JHEP", - volume = "12", - pages = "014", - year = "2013" -} - -@article{Lindner:2015iaa, - author = "Lindner, Manfred and Rodejohann, Werner and Xu, Xun-Jie", - title = "{Sterile neutrinos in the light of IceCube}", - eprint = "1510.00666", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1007/JHEP01(2016)124", - journal = "JHEP", - volume = "01", - pages = "124", - year = "2016" -} - -@article{NuSpaceSim:2021hgs, - author = "Patel, Sameer and others", - collaboration = "NuSpaceSim", - title = "{Monte Carlo simulations of neutrino and charged lepton propagation in the Earth with nuPyProp}", - eprint = "2109.08198", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.22323/1.395.1203", - journal = "PoS", - volume = "ICRC2021", - pages = "1203", - year = "2021" -} - -@article{Gazizov:2004va, - author = "Gazizov, Askhat and Kowalski, Marek P.", - title = "{ANIS: High energy neutrino generator for neutrino telescopes}", - eprint = "astro-ph/0406439", - archivePrefix = "arXiv", - reportNumber = "DESY-04-101", - doi = "10.1016/j.cpc.2005.03.113", - journal = "Comput. Phys. Commun.", - volume = "172", - pages = "203--213", - year = "2005" -} - -@misc{shigeruyoshida_2020_4018117, - author = {Shigeru Yoshida and - Maximilian Meier}, - title = {{ShigeruYoshida/JULIeT: First official release with - a DOI}}, - month = sep, - year = 2020, - publisher = {Zenodo}, - version = {v5.2}, - doi = {10.5281/zenodo.4018117}, - url = {https://doi.org/10.5281/zenodo.4018117} -} - -@article{Alvarez-Muniz:2018owm, - author = "Alvarez-Mu\~niz, Jaime and Carvalho, Washington R. and Cummings, Austin L. and Payet, K\'evin and Romero-Wolf, Andr\'es and Schoorlemmer, Harm and Zas, Enrique", - title = "{Comprehensive approach to tau-lepton production by high-energy tau neutrinos propagating through the Earth}", - eprint = "1707.00334", - archivePrefix = "arXiv", - primaryClass = "astro-ph.HE", - doi = "10.1103/PhysRevD.97.023021", - journal = "Phys. Rev. D", - volume = "97", - number = "2", - pages = "023021", - year = "2018", - note = "[Erratum: Phys.Rev.D 99, 069902 (2019)]" -} - -@article{Liu:2020ckq, - author = {Liu, Qinrui and Lazar, Jeffrey and Arg\"uelles, Carlos A. and Kheirandish, Ali}, - title = "{$\chi$aro$\nu$: a tool for neutrino flux generation from WIMPs}", - eprint = "2007.15010", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1088/1475-7516/2020/10/043", - journal = "JCAP", - volume = "10", - pages = "043", - year = "2020" -} - -@article{IceCube:2021koo, - author = "Villarreal, Joshua and others", - collaboration = "IceCube", - title = "{Recent Progress in Solar Atmospheric Neutrino Searches with IceCube}", - eprint = "2107.13696", - archivePrefix = "arXiv", - primaryClass = "astro-ph.HE", - reportNumber = "PoS-ICRC2021-1174", - doi = "10.22323/1.395.1174", - journal = "PoS", - volume = "ICRC2021", - pages = "1174", - year = "2021" -} - -@article{Seckel:1991ffa, - author = "Seckel, D. and Stanev, Todor and Gaisser, T. K.", - title = "{Signatures of cosmic-ray interactions on the solar surface}", - doi = "10.1086/170753", - journal = "Astrophys. J.", - volume = "382", - pages = "652--666", - year = "1991" -} - -@article{Ingelman:1996mj, - author = "Ingelman, G. and Thunman, M.", - title = "{High-energy neutrino production by cosmic ray interactions in the sun}", - eprint = "hep-ph/9604288", - archivePrefix = "arXiv", - reportNumber = "TSL-ISV-96-0135", - doi = "10.1103/PhysRevD.54.4385", - journal = "Phys. Rev. D", - volume = "54", - pages = "4385--4392", - year = "1996" -} - -@article{Masip:2017gvw, - author = "Masip, M.", - title = "{High energy neutrinos from the Sun}", - eprint = "1706.01290", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1016/j.astropartphys.2017.11.003", - journal = "Astropart. Phys.", - volume = "97", - pages = "63--68", - year = "2018" -} - -@article{Moskalenko:1991hm, - author = "Moskalenko, I. V. and Karakula, S. and Tkaczyk, W.", - title = "{The Sun as the source of VHE neutrinos}", - journal = "Astron. Astrophys.", - volume = "248", - pages = "L5--L6", - year = "1991" -} - -@article{Ng:2017aur, - author = "Ng, Kenny C. Y. and Beacom, John F. and Peter, Annika H. G. and Rott, Carsten", - title = "{Solar Atmospheric Neutrinos: A New Neutrino Floor for Dark Matter Searches}", - eprint = "1703.10280", - archivePrefix = "arXiv", - primaryClass = "astro-ph.HE", - doi = "10.1103/PhysRevD.96.103006", - journal = "Phys. Rev. D", - volume = "96", - number = "10", - pages = "103006", - year = "2017" -} - -@article{Edsjo:2017kjk, - author = "Edsjo, Joakim and Elevant, Jessica and Enberg, Rikard and Niblaeus, Carl", - title = "{Neutrinos from cosmic ray interactions in the Sun}", - eprint = "1704.02892", - archivePrefix = "arXiv", - primaryClass = "astro-ph.HE", - doi = "10.1088/1475-7516/2017/06/033", - journal = "JCAP", - volume = "06", - pages = "033", - year = "2017" -} - -@article{Arguelles:2017eao, - author = {Arg\"uelles, C. A. and de Wasseige, G. and Fedynitch, A. and Jones, B. J. P.}, - title = "{Solar Atmospheric Neutrinos and the Sensitivity Floor for Solar Dark Matter Annihilation Searches}", - eprint = "1703.07798", - archivePrefix = "arXiv", - primaryClass = "astro-ph.HE", - doi = "10.1088/1475-7516/2017/07/024", - journal = "JCAP", - volume = "07", - pages = "024", - year = "2017" -} - -@article{Srednicki:1986vj, - author = "Srednicki, Mark and Olive, Keith A. and Silk, Joseph", - title = "{High-Energy Neutrinos from the Sun and Cold Dark Matter}", - reportNumber = "UMN-TH-553/86", - doi = "10.1016/0550-3213(87)90020-4", - journal = "Nucl. Phys. B", - volume = "279", - pages = "804--823", - year = "1987" -} - -@article{Kamionkowski:1991nj, - author = "Kamionkowski, Marc", - title = "{Energetic neutrinos from heavy neutralino annihilation in the sun}", - reportNumber = "FERMILAB-PUB-90-181-A", - doi = "10.1103/PhysRevD.44.3021", - journal = "Phys. Rev. D", - volume = "44", - pages = "3021--3042", - year = "1991" -} - -@article{Cirelli:2005gh, - author = "Cirelli, Marco and Fornengo, Nicolao and Montaruli, Teresa and Sokalski, Igor A. and Strumia, Alessandro and Vissani, Francesco", - title = "{Spectra of neutrinos from dark matter annihilations}", - eprint = "hep-ph/0506298", - archivePrefix = "arXiv", - reportNumber = "DFTT12-2005, IFUP-TH-2005-13", - doi = "10.1016/j.nuclphysb.2007.10.001", - journal = "Nucl. Phys. B", - volume = "727", - pages = "99--138", - year = "2005", - note = "[Erratum: Nucl.Phys.B 790, 338--344 (2008)]" -} - -@article{Barger:2007xf, - author = "Barger, Vernon and Keung, Wai-Yee and Shaughnessy, Gabe and Tregre, Adam", - title = "{High energy neutrinos from neutralino annihilations in the Sun}", - eprint = "0708.1325", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - reportNumber = "MADPH-07-1494", - doi = "10.1103/PhysRevD.76.095008", - journal = "Phys. Rev. D", - volume = "76", - pages = "095008", - year = "2007" -} - -@article{Glashow:1960zz, - author = "Glashow, Sheldon L.", - title = "{Resonant Scattering of Antineutrinos}", - doi = "10.1103/PhysRev.118.316", - journal = "Phys. Rev.", - volume = "118", - pages = "316--317", - year = "1960" -} - -@article{Seckel:1997kk, - author = "Seckel, D.", - title = "{Neutrino photon reactions in astrophysics and cosmology}", - eprint = "hep-ph/9709290", - archivePrefix = "arXiv", - reportNumber = "BA-97-32", - doi = "10.1103/PhysRevLett.80.900", - journal = "Phys. Rev. Lett.", - volume = "80", - pages = "900--903", - year = "1998" -} - -@article{Alikhanov:2014uja, - author = "Alikhanov, I.", - title = "{The Glashow resonance in neutrino\textendash{}photon scattering}", - eprint = "1402.6678", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1016/j.physletb.2014.12.056", - journal = "Phys. Lett. B", - volume = "741", - pages = "295--300", - year = "2015" -} - -@article{Alikhanov:2015kla, - author = "Alikhanov, I.", - title = "{Hidden Glashow resonance in neutrino\textendash{}nucleus collisions}", - eprint = "1503.08817", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1016/j.physletb.2016.03.009", - journal = "Phys. Lett. B", - volume = "756", - pages = "247--253", - year = "2016" -} - -@article{Palomares-Ruiz:2005zbh, - author = "Palomares-Ruiz, Sergio and Pascoli, Silvia and Schwetz, Thomas", - title = "{Explaining LSND by a decaying sterile neutrino}", - eprint = "hep-ph/0505216", - archivePrefix = "arXiv", - reportNumber = "CERN-PH-TH-2005-083, SISSA-34-2005-EP", - doi = "10.1088/1126-6708/2005/09/048", - journal = "JHEP", - volume = "09", - pages = "048", - year = "2005" -} - -@article{Gninenko:2009ks, - author = "Gninenko, S. N.", - title = "{The MiniBooNE anomaly and heavy neutrino decay}", - eprint = "0902.3802", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1103/PhysRevLett.103.241802", - journal = "Phys. Rev. Lett.", - volume = "103", - pages = "241802", - year = "2009" -} - -@article{Nelson:2010hz, - author = "Nelson, Ann E.", - title = "{Effects of CP Violation from Neutral Heavy Fermions on Neutrino Oscillations, and the LSND/MiniBooNE Anomalies}", - eprint = "1010.3970", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - reportNumber = "INT-PUB-10-057", - doi = "10.1103/PhysRevD.84.053001", - journal = "Phys. Rev. D", - volume = "84", - pages = "053001", - year = "2011" -} - -@article{Fan:2012ca, - author = "Fan, JiJi and Langacker, Paul", - title = "{Light Sterile Neutrinos and Short Baseline Neutrino Oscillation Anomalies}", - eprint = "1201.6662", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1007/JHEP04(2012)083", - journal = "JHEP", - volume = "04", - pages = "083", - year = "2012" -} - -@article{Bertuzzo:2018itn, - author = "Bertuzzo, Enrico and Jana, Sudip and Machado, Pedro A. N. and Zukanovich Funchal, Renata", - title = "{Dark Neutrino Portal to Explain MiniBooNE excess}", - eprint = "1807.09877", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - reportNumber = "FERMILAB-PUB-18-336-T, OSU-HEP-18-04", - doi = "10.1103/PhysRevLett.121.241801", - journal = "Phys. Rev. Lett.", - volume = "121", - number = "24", - pages = "241801", - year = "2018" -} - -@article{Ballett:2019pyw, - author = "Ballett, Peter and Hostert, Matheus and Pascoli, Silvia", - title = "{Dark Neutrinos and a Three Portal Connection to the Standard Model}", - eprint = "1903.07589", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - reportNumber = "IPPP/19/19/FTPI-MINN-20-17, IPPP/19/19", - doi = "10.1103/PhysRevD.101.115025", - journal = "Phys. Rev. D", - volume = "101", - number = "11", - pages = "115025", - year = "2020" -} - -@article{Arguelles:2018mtc, - author = {Arg\"uelles, Carlos A. and Hostert, Matheus and Tsai, Yu-Dai}, - title = "{Testing New Physics Explanations of the MiniBooNE Anomaly at Neutrino Scattering Experiments}", - eprint = "1812.08768", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - reportNumber = "IPPP/18/113, FERMILAB-PUB-18-686-A-ND-PPD-T", - doi = "10.1103/PhysRevLett.123.261801", - journal = "Phys. Rev. Lett.", - volume = "123", - number = "26", - pages = "261801", - year = "2019" -} - -@article{Dentler:2019dhz, - author = "Dentler, Mona and Esteban, Ivan and Kopp, Joachim and Machado, Pedro", - title = "{Decaying Sterile Neutrinos and the Short Baseline Oscillation Anomalies}", - eprint = "1911.01427", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - reportNumber = "FERMILAB-PUB-19-538-T", - doi = "10.1103/PhysRevD.101.115013", - journal = "Phys. Rev. D", - volume = "101", - number = "11", - pages = "115013", - year = "2020" -} - -@article{Ahn:2019jbm, - author = "Ahn, Y. H. and Kang, Sin Kyu", - title = "{A model for neutrino anomalies and IceCube data}", - eprint = "1903.09008", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1007/JHEP12(2019)133", - journal = "JHEP", - volume = "12", - pages = "133", - year = "2019" -} - -@article{deGouvea:2019qre, - author = "de Gouv\^ea, Andr\'e and Peres, O. L. G. and Prakash, Suprabh and Stenico, G. V.", - title = "{On The Decaying-Sterile Neutrino Solution to the Electron (Anti)Neutrino Appearance Anomalies}", - eprint = "1911.01447", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - reportNumber = "FERMILAB-PUB-19-611-T", - doi = "10.1007/JHEP07(2020)141", - journal = "JHEP", - volume = "07", - pages = "141", - year = "2020" -} - -@article{Abdallah:2020vgg, - author = "Abdallah, Waleed and Gandhi, Raj and Roy, Samiran", - title = "{Two-Higgs doublet solution to the LSND, MiniBooNE and muon g-2 anomalies}", - eprint = "2010.06159", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1103/PhysRevD.104.055028", - journal = "Phys. Rev. D", - volume = "104", - number = "5", - pages = "055028", - year = "2021" -} - -@article{Hostert:2020oui, - author = "Hostert, Matheus and Pospelov, Maxim", - title = "{Constraints on decaying sterile neutrinos from solar antineutrinos}", - eprint = "2008.11851", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - reportNumber = "FTPI-MINN-20-28", - doi = "10.1103/PhysRevD.104.055031", - journal = "Phys. Rev. D", - volume = "104", - number = "5", - pages = "055031", - year = "2021" -} - -@article{Brdar:2020tle, - author = "Brdar, Vedran and Fischer, Oliver and Smirnov, Alexei Yu.", - title = "{Model-independent bounds on the nonoscillatory explanations of the MiniBooNE excess}", - eprint = "2007.14411", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1103/PhysRevD.103.075008", - journal = "Phys. Rev. D", - volume = "103", - number = "7", - pages = "075008", - year = "2021" -} - -@article{Abdallah:2020biq, - author = "Abdallah, Waleed and Gandhi, Raj and Roy, Samiran", - title = "{Understanding the MiniBooNE and the muon and electron $g - 2$ anomalies with a light $Z'$ and a second Higgs doublet}", - eprint = "2006.01948", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1007/JHEP12(2020)188", - journal = "JHEP", - volume = "12", - pages = "188", - year = "2020" -} - -@article{Dutta:2021cip, - author = "Dutta, Bhaskar and Kim, Doojin and Thompson, Adrian and Thornton, Remington T. and Van de Water, Richard G.", - title = "{Solutions to the MiniBooNE Anomaly from New Physics in Charged Meson Decays}", - eprint = "2110.11944", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - reportNumber = "MI-HET-766, LA-UR-21-30532", - month = "10", - year = "2021" -} - -@article{Denton:2020igp, - author = "Denton, Peter B. and Pestes, Rebekah", - title = "{The impact of different parameterizations on the interpretation of CP violation in neutrino oscillations}", - eprint = "2006.09384", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1007/JHEP05(2021)139", - journal = "JHEP", - volume = "05", - pages = "139", - year = "2021" -} - -@article{Safa:2021ghs, - author = {Safa, Ibrahim and Lazar, Jeffrey and Pizzuto, Alex and Vasquez, Oswaldo and Arg\"uelles, Carlos A. and Vandenbroucke, Justin}, - title = "{TauRunner: A Public Python Program to Propagate Neutral and Charged Leptons}", - eprint = "2110.14662", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - month = "10", - year = "2021" -} - -@article{Bustamante:2017xuy, - author = "Bustamante, Mauricio and Connolly, Amy", - title = "{Extracting the Energy-Dependent Neutrino-Nucleon Cross Section above 10 TeV Using IceCube Showers}", - eprint = "1711.11043", - archivePrefix = "arXiv", - primaryClass = "astro-ph.HE", - doi = "10.1103/PhysRevLett.122.041101", - journal = "Phys. Rev. Lett.", - volume = "122", - number = "4", - pages = "041101", - year = "2019" -} -@article{Formaggio:2012cpf, - author = "Formaggio, J. A. and Zeller, G. P.", - title = "{From eV to EeV: Neutrino Cross Sections Across Energy Scales}", - eprint = "1305.7513", - archivePrefix = "arXiv", - primaryClass = "hep-ex", - reportNumber = "FERMILAB-PUB-12-785-E", - doi = "10.1103/RevModPhys.84.1307", - journal = "Rev. Mod. Phys.", - volume = "84", - pages = "1307--1341", - year = "2012" -} - -@article{Zhou:2019vxt, - author = "Zhou, Bei and Beacom, John F.", - title = "{Neutrino-nucleus cross sections for W-boson and trident production}", - eprint = "1910.08090", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1103/PhysRevD.101.036011", - journal = "Phys. Rev. D", - volume = "101", - number = "3", - pages = "036011", - year = "2020" -} -@article{Zhou:2019frk, - author = "Zhou, Bei and Beacom, John F.", - title = "{W-boson and trident production in TeV\textendash{}PeV neutrino observatories}", - eprint = "1910.10720", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1103/PhysRevD.101.036010", - journal = "Phys. Rev. D", - volume = "101", - number = "3", - pages = "036010", - year = "2020" -} - -@article{Esteban:2021tub, - author = "Esteban, Ivan and Pandey, Sujata and Brdar, Vedran and Beacom, John F.", - title = "{Probing Secret Interactions of Astrophysical Neutrinos in the High-Statistics Era}", - eprint = "2107.13568", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - reportNumber = "FERMILAB-PUB-21-328-T, nuhep-th/21-06", - month = "7", - year = "2021" -} - -@article{Vergani:2021tgc, - author = {Vergani, Stefano and Kamp, Nicholas W. and Diaz, Alejandro and Arg\"uelles, Carlos A. and Conrad, Janet M. and Shaevitz, Michael H. and Uchida, Melissa A.}, - title = "{Explaining the MiniBooNE Excess Through a Mixed Model of Oscillation and Decay}", - eprint = "2105.06470", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - month = "5", - year = "2021" -} - -@Article{Arguelles:2019rbn, - author = "Carlos A. Arguelles and Mauricio Bustamante and Ali Kheirandish and Sergio Palomares-Ruiz and Jordi Salvado and Aaron C. Vincent", - title = "Fundamental physics with high-energy cosmic neutrinos today and in the future", - journal = "PoS", - volume = "ICRC2019", - pages = "849", - year = "2020", - eprint = "1907.08690", - archivePrefix = "arXiv", - primaryClass = "astro-ph", - note = "36th International Cosmic Ray Conference (ICRC 2019), Madison, WI, U.S.A", -} - -@article{IceCube:2020rnc, - author = "Abbasi, R. and others", - collaboration = "IceCube", - title = "{Measurement of the high-energy all-flavor neutrino-nucleon cross section with IceCube}", - eprint = "2011.03560", - archivePrefix = "arXiv", - primaryClass = "hep-ex", - doi = "10.1103/PhysRevD.104.022001", - month = "11", - year = "2020" -} - -@article{deSalas:2020pgw, - author = "de Salas, P. F. and Forero, D. V. and Gariazzo, S. and Mart\'\i{}nez-Mirav\'e, P. and Mena, O. and Ternes, C. A. and T\'ortola, M. and Valle, J. W. F.", - title = "{2020 global reassessment of the neutrino oscillation picture}", - eprint = "2006.11237", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1007/JHEP02(2021)071", - journal = "JHEP", - volume = "02", - pages = "071", - year = "2021" -} - -@article{ANTARES:2018rtf, - author = "Albert, A. and others", - collaboration = "ANTARES", - title = "{Measuring the atmospheric neutrino oscillation parameters and constraining the 3+1 neutrino model with ten years of ANTARES data}", - eprint = "1812.08650", - archivePrefix = "arXiv", - primaryClass = "hep-ex", - doi = "10.1007/JHEP06(2019)113", - journal = "JHEP", - volume = "06", - pages = "113", - year = "2019" -} +%% Created for Carlos Arguelles at 2014-09-29 16:26:30 -0500 -@article{IceCube:2019dqi, - author = "Aartsen, M. G. and others", - collaboration = "IceCube", - title = "{Measurement of Atmospheric Tau Neutrino Appearance with IceCube DeepCore}", - eprint = "1901.05366", - archivePrefix = "arXiv", - primaryClass = "hep-ex", - doi = "10.1103/PhysRevD.99.032007", - journal = "Phys. Rev. D", - volume = "99", - number = "3", - pages = "032007", - year = "2019" -} -@article{IceCube:2020wum, - author = "Abbasi, R. and others", - collaboration = "IceCube", - title = "{The IceCube high-energy starting event sample: Description and flux characterization with 7.5 years of data}", - eprint = "2011.03545", - archivePrefix = "arXiv", - primaryClass = "astro-ph.HE", - doi = "10.1103/PhysRevD.104.022002", - journal = "Phys. Rev. D", - volume = "104", - pages = "022002", - year = "2021" -} +%% Saved with string encoding Unicode (UTF-8) @article{Chekanov:2002pv, author = "Chekanov, S. and others", @@ -1717,7 +854,7 @@ @article{Calland:2013vaa @misc{prob3pp, title = {{Prob3++} software for computing three flavor neutrino oscillation probabilities.}, - howpublished = {\url{https://github.com/rogerwendell/Prob3plusplus}}, + howpublished = {\url{http://www.phy.duke.edu/~raw22/public/Prob3++/}}, note = {2012} } @@ -1921,28 +1058,11 @@ @article{dziewonski1981preliminary Year = {1981}} @article{SQUIDS, - author = {Arg\"uelles Delgado, Carlos A. and Salvado, Jordi and Weaver, Christopher N.}, - title = "{A Simple Quantum Integro-Differential Solver (SQuIDS)}", - eprint = "1412.3832", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1016/j.cpc.2015.06.022", - journal = "Comput. Phys. Commun.", - volume = "196", - pages = "569--591", - year = "2015" -} - -@article{SQUIDSupdate, - author = {Arg\"uelles Delgado, Carlos A. and Salvado, Jordi and Weaver, Christopher N.}, - title = "{A Simple Quantum Integro-Differential Solver (SQuIDS)}", - journal = {Computer Physics Communications}, - volume = {255}, - pages = {107405}, - year = {2020}, - issn = {0010-4655}, - doi = {https://doi.org/10.1016/j.cpc.2020.107405}, -} + Author = {Arg\"uelles Delgado, Carlos Alberto and Salvado Serra, Jordi}, + Date-Added = {2014-09-08 22:56:32 +0000}, + Date-Modified = {2014-09-29 21:26:30 +0000}, + Title = {A Simple Quantum Integro Differential Solver (SQuIDS)}, + Year = {2014}} @book{gough2009gnu, Author = {Gough, Brian}, @@ -1953,9 +1073,10 @@ @book{gough2009gnu Year = {2009}} @misc{gsl2008scientific, + Author = {GSL, GNU}, Date-Added = {2014-09-08 05:18:22 +0000}, Date-Modified = {2014-09-08 05:18:22 +0000}, - Title = {GNU Scientific Library}, + Title = {Scientific Library}, Year = {2008}} @article{Dutta:2000jv, @@ -1991,46 +1112,6 @@ @article{Gonzalez-Garcia:2005xw Year = {2005}, Bdsk-Url-1 = {http://dx.doi.org/10.1103/PhysRevD.71.093010}} - @article{Garcia:2020jwr, - author = "Garcia, Alfonso and Gauld, Rhorry and Heijboer, Aart and Rojo, Juan", - title = "{Complete predictions for high-energy neutrino propagation in matter}", - eprint = "2004.04756", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1088/1475-7516/2020/09/025", - journal = "JCAP", - volume = "09", - pages = "025", - year = "2020" -} - -@article{Pospelov:2007mp, - author = "Pospelov, Maxim and Ritz, Adam and Voloshin, Mikhail B.", - title = "{Secluded WIMP Dark Matter}", - eprint = "0711.4866", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - doi = "10.1016/j.physletb.2008.02.052", - journal = "Phys. Lett. B", - volume = "662", - pages = "53--61", - year = "2008" -} - -@article{Niblaeus:2019gjk, - author = "Niblaeus, Carl and Beniwal, Ankit and Edsjo, Joakim", - title = "{Neutrinos and gamma rays from long-lived mediator decays in the Sun}", - eprint = "1903.11363", - archivePrefix = "arXiv", - primaryClass = "astro-ph.HE", - reportNumber = "CP3-19-09", - doi = "10.1088/1475-7516/2019/11/011", - journal = "JCAP", - volume = "11", - pages = "011", - year = "2019" -} - @article{Gonzalez-Garcia:2008vn, Abstract = {A measurement of the absorption of neutrinos with energies in excess of 10 TeV when traversing the Earth is capable of revealing its density distribution. Unfortunately, the existence of beams with sufficient luminosity for the task has been ruled out by the AMANDA South Pole neutrino telescope. In this Letter we point out that, with the advent of second-generation kilometer-scale neutrino detectors, the idea of studying the internal structure of Earth may be revived using atmospheric neutrinos instead.}, Author = {Gonzalez-Garcia, M C and Halzen, Francis and Maltoni, Michele and Tanaka, Hiroyuki K M}, @@ -2074,35 +1155,6 @@ @article{Esteban:2016qun SLACcitation = "%%CITATION = ARXIV:1611.01514;%%" } -@article{Esteban:2020cvm, - author = "Esteban, Ivan and Gonzalez-Garcia, M.C. and Maltoni, Michele and Schwetz, Thomas and Zhou, Albert", - title = "{The fate of hints: updated global analysis of three-flavor neutrino oscillations}", - eprint = "2007.14792", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - reportNumber = "IFT-UAM/CSIC-112, YITP-SB-2020-21", - doi = "10.1007/JHEP09(2020)178", - journal = "JHEP", - volume = "09", - pages = "178", - year = "2020" -} - -@article{Gonzalez-Garcia:2021dve, - author = "Gonzalez-Garcia, Maria Concepcion and Maltoni, Michele and Schwetz, Thomas", - title = "{NuFIT: Three-Flavour Global Analyses of Neutrino Oscillation Experiments}", - eprint = "2111.03086", - archivePrefix = "arXiv", - primaryClass = "hep-ph", - reportNumber = "IFT-UAM/CSIC-21-114", - doi = "10.3390/universe7120459", - journal = "Universe", - volume = "7", - number = "12", - pages = "459", - year = "2021" -} - @article{deSalas:2017kay, author = "de Salas, P. F. and Forero, D. V. and Ternes, C. A. and Tortola, M. and Valle, J. W. F.", @@ -2454,59 +1506,3 @@ @article{Parke:2019vbs pages = "351--360", year = "2019" } - -@article{ANIS, - title={ANIS: High energy neutrino generator for neutrino telescopes}, - volume={172}, - ISSN={0010-4655}, - url={http://dx.doi.org/10.1016/j.cpc.2005.03.113}, - DOI={10.1016/j.cpc.2005.03.113}, - number={3}, - journal={Computer Physics Communications}, - publisher={Elsevier BV}, - author={Gazizov, A. and Kowalski, M.}, - year={2005}, - month={Nov}, - pages={203–213} -} - -@article{nuPropEarth2020, - title={Complete predictions for high-energy neutrino propagation in matter}, - volume={2020}, - ISSN={1475-7516}, - url={http://dx.doi.org/10.1088/1475-7516/2020/09/025}, - DOI={10.1088/1475-7516/2020/09/025}, - number={09}, - journal={Journal of Cosmology and Astroparticle Physics}, - publisher={IOP Publishing}, - author={Garcia, Alfonso and Gauld, Rhorry and Heijboer, Aart and Rojo, Juan}, - year={2020}, - month={Sep}, - pages={025–025} -} - -@article{barger1980matter, - title={Matter effects on three-neutrino oscillations}, - author={Barger, V and Whisnant, K and Pakvasa, S and Phillips, RJN}, - journal={Physical Review D}, - volume={22}, - number={11}, - pages={2718}, - year={1980}, - publisher={APS} -} - -@article{nuFATE2017, - title={High-energy neutrino attenuation in the Earth and its associated uncertainties}, - volume={2017}, - ISSN={1475-7516}, - url={http://dx.doi.org/10.1088/1475-7516/2017/11/012}, - DOI={10.1088/1475-7516/2017/11/012}, - number={11}, - journal={Journal of Cosmology and Astroparticle Physics}, - publisher={IOP Publishing}, - author={Vincent, Aaron C. and Argüelles, Carlos A. and Kheirandish, Ali}, - year={2017}, - month={Nov}, - pages={012–012} -} diff --git a/resources/paper/nusquids.tex b/resources/paper/nusquids.tex index fc1277f8..186924af 100644 --- a/resources/paper/nusquids.tex +++ b/resources/paper/nusquids.tex @@ -11,7 +11,6 @@ \usepackage{cleveref} \usepackage{color} \usepackage{listings} -\usepackage{array} \usepackage{natbib} \biboptions{numbers,sort&compress} @@ -22,9 +21,9 @@ \setcounter{tocdepth}{4} \setcounter{secnumdepth}{4} + \usepackage{tikz} \usetikzlibrary{trees} -\usetikzlibrary{shapes.geometric} \tikzstyle{every node}=[draw=black,thick,anchor=west] \tikzstyle{selected}=[dashed,draw=red,fill=red!30] @@ -33,9 +32,6 @@ \usepackage{chngcntr} \counterwithin{figure}{section} -\usepackage{hyphenat} -\hyphenation{nu-Prop-Earth} - \titleclass{\subsubsubsection}{straight}[\subsection] \newcounter{subsubsubsection}[subsubsection] \renewcommand\thesubsubsubsection{\thesubsubsection.\arabic{subsubsubsection}} @@ -66,8 +62,6 @@ \end{lstlisting} } -\newcolumntype{C}[1]{>{\centering\arraybackslash}m{#1}} - \definecolor{mauve}{rgb}{1,0,1} \definecolor{dkgreen}{rgb}{0,0.6,0} @@ -100,59 +94,34 @@ \setcounter{secnumdepth}{4} \setcounter{tocdepth}{4} -%% This list environment is used for the references in the -%% Program Summary -%% -\newcounter{bla} -\newenvironment{refnummer}{% -\list{[\arabic{bla}]}% -{\usecounter{bla}% - \setlength{\itemindent}{0pt}% - \setlength{\topsep}{0pt}% - \setlength{\itemsep}{0pt}% - \setlength{\labelsep}{2pt}% - \setlength{\listparindent}{0pt}% - \settowidth{\labelwidth}{[9]}% - \setlength{\leftmargin}{\labelwidth}% - \addtolength{\leftmargin}{\labelsep}% - \setlength{\rightmargin}{0pt}}} - {\endlist} - \begin{document} \begin{frontmatter} -\title{\texttt{nuSQuIDS}: A toolbox for neutrino propagation\ifdefined\forjournal\else\tnoteref{t1}\fi} +\title{\texttt{$\nu$-SQuIDS}: A toolbox for neutrino oscillations\tnoteref{t1}} \author[HU]{Carlos A. Arg\"uelles} \ead{carguelles@fas.harvard.edu} \author[UB]{Jordi Salvado} \ead{jsalvado@icc.ub.edu} -\author[MSU]{Christopher N. Weaver} +\author[UC]{Christopher N. Weaver} \ead{chris.weaver@icecube.wisc.edu} - \address[HU]{Department of Physics \& Laboratory for Particle Physics and Cosmology, Harvard University, Cambridge, MA 02138, USA} +\address[UC]{Enrico Fermi Institute, University of Chicago, Chicago IL 60637, USA} \address[UB]{Departament de F\'isica Qu\`antica i Astrofísica and Institut de Ciencies del Cosmos, Universitat de Barcelona, Diagonal 647, E-08028 Barcelona, Spain} -\address[MSU]{Dept. of Physics and Astronomy, Michigan State University, East Lansing, MI 48824, USA} - -\ifdefined\manualonly -% omit most front matter -\else % not manualonly -\tnotetext[t1]{Code can be found at \url{https://github.com/arguelles/nuSQuIDS}} -\ifdefined\forjournal -\journal{Computer Physics Communications} -\else + +\tnotetext[t1]{The code can be found in \url{https://github.com/arguelles/nuSQuIDS}} \journal{arXiv} -\fi % forjournal +%\journal{Computer Physics Communications} \begin{abstract} -The Neutrino Simple Quantum Integro-Differential Solver (\texttt{nuSQuIDS}) +The Neutrino Simple Quantum Integro-Differential Solver ($\nu$-SQuIDS) is a C++ code based on SQuIDS that propagates an ensemble of neutrinos through given media. Neutrino oscillation calculations relevant to -current and next-generation experiments are implemented. +current and next generation experiments are implemented. This includes coherent and non-coherent neutrino interactions in -settings such as the Sun, Earth, or a vacuum. +settings such as the Sun, Earth, vacuum, and others. The code is designed to be accurate and flexible, while at the same time maintaining good performance. It has a modular design that allows the user to incorporate new physics in novel scenarios. @@ -161,90 +130,57 @@ \begin{keyword} Neutrino oscillation, phenomenology, collective neutrino behavior, numerical techniques \end{keyword} -\fi % manualonly \end{frontmatter} -\ifdefined\forjournal -{\bf PROGRAM SUMMARY} - -\begin{small} -\noindent -{\em Program Title:} Neutrino Simple Quantum Integro-Differential Solver \\ -{\em CPC Library link to program files:} (to be added by Technical Editor) \\ -{\em Developer's repository link:} \url{https://github.com/arguelles/nuSQuIDS} \\ -{\em Code Ocean capsule:} (to be added by Technical Editor)\\ -{\em Licensing provisions:} LGPL \\ -{\em Programming language:} C++ with optional Python interface \\ -{\em Supplementary material:} \\ -{\em Nature of problem:}\\ -The evolution of neutrino fluxes includes both coherent flavor changes (oscillations) and non-coherent scattering interactions with matter. Calculating both types of phenomena is necessary for some studies in neutrino physics, and even in cases where it is not required it is convenient to have a full physics description available in a single package. \\ -{\em Solution method:}\\ -The Simple Quantum Integro-Differential Solver (SQuIDS)~\cite{summary_squids, summary_squids_update} is used to decompose neutrino fields with SU(N) algebras and solve for their evolution with standard ODE solvers (via the GNU Scientific Library~\cite{summary_gsl}). The evolution of the flavor/mass eigenstate relationships are kept updated in parallel with the ODE solution, as are interaction effects with matter. Users may add new material profiles and physics effects. \\ -{\em Additional comments including restrictions and unusual features:}\\ -Vacuum oscillations are computed analytically, simplifying the ODE problem to be solved. This package supports additions to the neutrino flux over the full course of its evolution, allowing direct treatment of extended sources, and averaging of fast oscillations which cannot be experimentally resolved. The package does not currently implement the complex neutrino interactions relevant at low (O(10 GeV)) neutrino energies. - \\ - -\begin{thebibliography}{0} -\bibitem{summary_squids}C. A. Arg\"uelles Delgado, J. Salvado, C. N. Weaver, A Simple Quantum Integro-Differential Solver (SQuIDS), A Simple Quantum Integro-Differential Solver (SQuIDS), Comput. Phys. Commun. 196 (2015) 569–591. arXiv:1412.3832, doi:10.1016/j.cpc. 2015.06.022. -\bibitem{summary_squids_update}C. A. Arg\"uelles Delgado, J. Salvado, C. N. Weaver, A Simple Quantum Integro-Differential Solver (SQuIDS), Computer Physics Communications 255 (2020) 107405. doi:https://doi.org/10.1016/j.cpc.2020.107405 -\bibitem{summary_gsl}B. Gough, GNU scientific library reference manual, Network Theory Ltd., 2009. -\end{thebibliography} -\end{small} -\fi % forjournal - \hypersetup{linkcolor=black} \tableofcontents \hypersetup{linkcolor=blue} \newpage - -\ifdefined\manualonly -% omit paper body -\else % not manualonly \section{Introduction} \label{sec:intro} -In recent decades a large body of evidence that neutrinos change +In recent decades a plethora of evidence that neutrinos change flavor as they propagate macroscopic distances due to the non-alignment of their mass and flavor eigenstates has accumulated from -solar~\citep{Super-Kamiokande:2010tar, Borexino:2013zhu}, -atmospheric~\citep{PhysRevD.91.072004,Super-Kamiokande:2015qek,IceCube:2019dqi,ANTARES:2018rtf}, +solar~\citep{Abe:2010hy, Borexino2014}, +atmospheric~\citep{PhysRevD.91.072004,Richard:2015aua}, accelerator~\citep{PhysRevLett.112.181801, PhysRevD.93.051104,PhysRevLett.116.151806, PhysRevLett.110.251801}, and reactor~\citep{An:2013zwz,Abe:2015rcp, Kim:2016yvm} experiments. Thanks to these remarkable experimental results and related theoretical calculations, the - neutrino-mass-induced flavor oscillation paradigm~\citep{Pontecorvo:1967fh,Gribov:1968kq,fukugita2003physics, + neutrino-mass induced flavor oscillation paradigm~\citep{Pontecorvo:1967fh,Gribov:1968kq,fukugita2003physics, Akhmedov:1999uz,Balantekin:2013kc, GonzalezGarcia:2007ib,Mohapatra:qv, Gouvea:2013fj} has been firmly established and the three mixing angles, which -parametrize the lepton-mixing matrix, together with the two +parametrize the lepton mixing matrix, together with the two squared-mass differences, have been measured to good -precision~\citep{Esteban:2020cvm,deSalas:2017kay,Capozzi:2018ubv,deSalas:2020pgw}. It +precision~\citep{Esteban:2016qun,deSalas:2017kay,Capozzi:2018ubv}. It is the task of on-going -and future experiments to determine the neutrino-mass ordering +and future experiments to determine the neutrino mass ordering and the $CP$-violating phase~\citep{Hewett:2012et, Acciarri:2016crz,Aartsen:2014oha, Kouchner:2016pqa,DeRosa:2016ifc}. Also, the IceCube Neutrino Observatory has recently made precise measurements of the atmospheric spectrum above 100~GeV, where the Earth is no longer transparent to -neutrinos~\citep{Donini:2018tsg,Bustamante:2017xuy,IceCube:2020rnc}, allowing new physics +neutrinos~\citep{Donini:2018tsg}, allowing new physics models to be constrained~\citep{Aartsen:2014gkd,TheIceCube:2016oqi}. The identification of high-energy -extraterrestrial neutrinos~\citep{Aartsen:2014gkd,Aartsen:2015rwa,IceCube:2020wum} -has opened the possibility of exploring new physics at these energies as well~\citep{Arguelles:2015dca, Bustamante:2015waa, Baerwald:2012kc,Arguelles:2019rbn, Esteban:2021tub}. +extraterrestrial neutrinos~\citep{ Aartsen:2014gkd, Aartsen:2015rwa} +has opened the possibility of exploring new physics at these energies as well~\citep{Arguelles:2015dca, Bustamante:2015waa, Baerwald:2012kc}. Matter effects play a fundamental role in the explanation of solar -neutrinos~\citep{ Davis:1968cp,Bethe:1986ej}, which has motivated the study of new flavor-changing -neutrino interactions~\citep{Barger:1991ae, Roulet:1991sm, GonzalezGarcia:2011my, +neutrinos~\citep{ Davis:1968cp,Bethe:1986ej}, which has motivated the study of new flavor +changing neutrino interactions~\citep{Barger:1991ae, Roulet:1991sm, GonzalezGarcia:2011my, Gonzalez-Garcia:2013usa, Pospelov:2011dp, Kopp:2014nosterile, Maltoni:2015kca,Esteban:2018ppq}. -Even though most data can be explained in the standard three +Even though most of the data can be explained in the standard three neutrino framework, some puzzling anomalies still remain ~\citep{LSND,Mention:2011rr,MiniBoone:2012dn,Aguilar-Arevalo:2018gpe,Alekseev:2016llm, Ko:2016owz, Ashenfelter:2018iov, Abreu:2018pxg, Dentler:2018sju}. These may be explained by introducing new light neutrino states~\citep{kopp2013sterile, Collin:2016rao, Abazajian:2012rf,Blennow:2018hto, Dentler:2018sju, Diaz:2019fwt, Boser:2019rta} and other new physics -~\citep{Palomares-Ruiz:2005zbh,Gninenko:2009ks,Nelson:2010hz,Fan:2012ca,Bai:2015ztj,Bertuzzo:2018itn,Ballett:2019pyw,Arguelles:2018mtc,Dentler:2019dhz,Ahn:2019jbm,deGouvea:2019qre,Abdallah:2020vgg,Hostert:2020oui,Brdar:2020tle,Abdallah:2020biq,Dutta:2021cip,Vergani:2021tgc}. +~\citep{Bai:2015ztj,PalomaresRuiz:2005vf,Gninenko:2011xa}. Also, the interplay between cosmology and neutrino oscillation has been widely studied in the literature ~\citep{Bergstrom:2014fqa, Giusarma:2016phn, @@ -252,51 +188,37 @@ \section{Introduction} Generally, neutrinos are good probes to perform fundamental physics tests~\citep{Hewett:2012et,Aartsen:2017ibm,Mewes:2018cze,Barenboim:2017vlc}. -Tools are needed to compute neutrino -propagation accurately and reliably. -In classical computations, where the only effect of propagation is neutrino oscillation, libraries such as {\ttf GLoBES} +Tools are needed to accurately and reliably compute neutrino +propagation. +In classical computer when the only effect of propagation is neutrino oscillations libraries such as {\ttf GLoBES} ~\citep{Huber:2007ji}, {\ttf Prob3++}~\citep{prob3pp, Calland:2013vaa}, and {\ttf nuCRAFT}~\citep{Wallraff:2014vl} are available; for a recent comparison of oscillation calculations comparisons see~\cite{Parke:2019vbs}. On quantum computers, such as the IBM-Q systems, implementations using two entangled qubits have also been developed~\cite{Arguelles:2019phs}. -Unfortunately, when non-coherent interactions~\cite{Formaggio:2012cpf,Gandhi:1998ri,Zhou:2019frk,Zhou:2019vxt} are -important, these methods are no longer applicable. -In the high-energy regime, when oscillations can be neglected, tools have been developed -to propagate neutrinos taking into account non-coherent interactions; for example, \texttt{TauRunner}~\cite{Safa:2021ghs}, \texttt{NuPropEarth}~\cite{Garcia:2020jwr}, \texttt{nuFATE}~\cite{Vincent:2017svp}, \texttt{JuLiET}~\cite{Yoshida:2003js,shigeruyoshida_2020_4018117}, among others~\citep{Gazizov:2004va,DeYoung:865626}. -Beyond these general-purpose codes, packages have also been developed to propagate tau neutrinos specifically, \textit{e.g.} \texttt{NuTAuSim}~\cite{Alvarez-Muniz:2018owm} and \texttt{nuPyProp}~\cite{NuSpaceSim:2021hgs}. -However, none of the above-mentioned packages are able to take -coherent and non-coherent neutrino interactions into account simultaneously. -Furthermore, the ability to allow the user to incorporate new physics models or to change the -propagation medium is also limited in some of these packages. {\ttf nuSQuIDS} seeks to -address all of these limitations by providing a highly-customizable -package while at the same time remaining numerically efficient. - -In section~\ref{sec:theory} -we review neutrino oscillation and interaction theory, -in section~\ref{sec:features} we summarize the main features of the code, -in section~\ref{sec:short_examples} we show the use of the code in a few representative scenarios, -in section~\ref{sec:comparison} we discuss how this code compares to other software, -in section~\ref{sec:performance} we show the performance of -the library, and finally section~\ref{sec:conclu} presents concluding remarks. - -\ifdefined\forjournal -\else -Additionally, an extended appendix that provides -further useful information about the code. -In \ref{sec:tests} we describe the unit tests that -are provided with the library, in \ref{sec:code} we describe -the main classes and structure of the code; and finally, in \ref{sec:python} -we describe the library {\ttf Python} interface. -\fi %forjournal - -\section{Mathematical Framework} -\label{sec:theory} -\subsection{Neutrino Oscillations} +Unfortunately, when non-coherent interactions are +important they are no longer applicable. Furthermore, the ability to +allow the user to incorporate new physics models or to change the +propagation medium is also limited. {\ttf nuSQuIDS} seeks to +address all of these problems by providing a highly customizable +package, while at the same time remaining numerically efficient. + +The rest of the paper is organized as follows: in section~\ref{sec:theory} +we review neutrino oscillation theory; in section~\ref{sec:examples} +we show the use of the code in typical +scenarios; in section~\ref{sec:performance} we show the performance of +the library; in section~\ref{sec:tests} we describe the unit tests that +are provided with the library; in section~\ref{sec:code} we describe +the main classes and structure of the code; in section~\ref{sec:python} +we describe the library {\ttf Python} interface. Finally, section~\ref{sec:conclu} presents concluding remarks. + +\section{Neutrino Oscillations} +\subsection{Density Matrix Formalism} +\label{sec:theory} In this section we briefly review neutrino oscillations using the density matrix formalism. We can represent the state of a neutrino ensemble at an energy $E$ -and position $x$ using the density matrix. In the weak-interaction flavor-eigenstate basis, -$\{\ket{\nu_\alpha}\}$, it can be written as +and position $x$ using the density matrix. In the weak-interaction flavor-eigenstate basis +$\{\ket{\nu_\alpha}\}$ it can be written as \begin{equation} \rho(E,x) = \sum_\alpha \phi_\alpha(E,x) \ket{\nu_\alpha}\bra{\nu_\alpha} , \label{eq:state} @@ -308,7 +230,7 @@ \subsection{Neutrino Oscillations} \label{eq:changebasis} \end{equation} where $U$ is a unitary matrix known as the Pontecorvo-Maki-Nakagawa-Sakata (PMNS) -matrix, or neutral lepton mixing matrix. For antineutrinos, the relation +matrix or neutral lepton mixing matrix. For antineutrinos the relation is the same as in Eq.~\eqref{eq:changebasis} with $U \to U^*$. It is customary to parametrize $U$ as a product of complex rotations, @@ -318,8 +240,7 @@ \subsection{Neutrino Oscillations} R_{34} R_{24} R_{14} R_{23} R_{13} R_{12}, \end{equation} determined by angles, $\{\theta_{ij}\}$, and phases, $\{ \delta_{ij} -\}$~\cite{SQUIDS, SQUIDSupdate}; see~\cite{Denton:2020igp} for a recent discussion about parameterizations of the PMNS matrix. -When considering the standard three-flavor paradigm, +\}$~\cite{SQUIDS}. When considering the standard three flavor paradigm the following parametrization is often used: \begin{equation} U @@ -333,8 +254,8 @@ \subsection{Neutrino Oscillations} \label{eq:U} \end{equation} where $c_{ij} \equiv \cos \theta_{ij}$, $s_{ij} \equiv \sin \theta_{ij}$. In the -three-flavor scenario, we use this parametrization (with -values from \citep{Esteban:2020cvm} by default). +three flavor scenario we use this parametrization (with +values from \citep{Esteban:2016qun} by default). The neutrino ensemble propagation is described by the following quantum Von Neumann equation\footnote{In this equation and henceforth we set $c = \hbar = 1$.} \begin{equation} @@ -343,7 +264,7 @@ \subsection{Neutrino Oscillations} \end{equation} In general, the Hamiltonian, $H$, can always be split into -time-dependent and time-independent parts. For neutrino oscillations, +time-dependent and time-independent parts. For neutrino oscillations the following splitting is convenient: \begin{equation} H(E,x) = H_0(E) + H_{1}(E,x) , @@ -361,7 +282,7 @@ \subsection{Neutrino Oscillations} constant, $N_e(x)$ and $N_{nuc}(x)$ are the electron and nucleon number densities at position $x$, and $\Delta m^2_{i1}$ are the neutrino mass square differences. -In writing these equations, we have used the convention that the first +In writing these equations we have used the convention that the first three flavor eigenstates correspond to $\nu_e$, $\nu_\mu$, and $\nu_\tau$ respectively, while the rest are assumed to be sterile neutrinos. $H_0$ arises from the neutrino kinetic @@ -382,14 +303,13 @@ \subsection{Neutrino Oscillations} \label{eq:schrodinger_int} \end{equation} -\subsection{Non-coherent Interactions} -So far, we have only incorporated vacuum oscillations and matter +So far we have only incorporated vacuum oscillations and matter effects through coherent interactions, but we now wish to extend this formalism to incorporate non-coherent interactions and collective -neutrino behavior. In what follows, we will remove the subindex $I$ and +neutrino behavior. In what follows we will remove the subindex $I$ and assume that all operators, unless specified, are in the interaction picture. This problem has been extensively discussed in the literature,~\citep{Sigl:1992fn,Duan:2010tk,Strack:qd,Zhang:2013ay, - Cirelli:mw,Blennow:2007tw,Arguelles:2012cf}, for specificity we + Cirelli:mw,Blennow:2007tw,Arguelles:2012cf}, for definiteness we follow the formalism and notation given in~\citep{Gonzalez-Garcia:2005xw}. The neutrino (antineutrino), $\rho$ $(\bar\rho)$, kinetic equations are \begin{subequations} @@ -400,14 +320,13 @@ \subsection{Non-coherent Interactions} \pa{\bar\rho(E,x)}{x} &=& i [ H^*_1 (E,x), \bar\rho(E,x) ] - \left\{ \bar\Gamma(E,x), \rho(E,x) \right\} + \bar F\left[\rho,\bar\rho;E,x\right] , \end{eqnarray} -\label{eq:kinetic_equations} \end{subequations} where $\Gamma$ and $\bar\Gamma$ are functions that incorporate the effect of attenuation due to non-coherent interactions, and $F$ and $\bar F$ are functionals on $\rho$ and $\bar\rho$ that take into account interactions between different energies for neutrinos and antineutrinos. -In {\ttf nuSQuIDS}, the attenuation terms are +In {\ttf nuSQuIDS} the attenuation terms are \begin{subequations} \begin{eqnarray} \Gamma(E,x) &=& \frac{1}{2} \sum_\alpha \frac{\Pi_\alpha(E,x)}{ @@ -421,18 +340,18 @@ \subsection{Non-coherent Interactions} where $\Pi_\alpha(E,x)$ is the neutrino projector onto flavor $\alpha \in \{e,\mu,\tau\}$, $\lambda^\alpha_{\rm CC}$ ($\lambda^\alpha_{\rm NC}$) is the charged (neutral) current neutrino interaction length, -given by $(N_{nuc}(x)\sigma^\alpha_{\rm CC(NC)}(E))^{-1}$\citep{Formaggio:2012cpf,Gandhi:1998ri,Zhou:2019frk,Zhou:2019vxt,CooperSarkar:2011pa}, and +given by $(N_{nuc}(x)\sigma^\alpha_{\rm CC(NC)}(E))^{-1}$\citep{CooperSarkar:2011pa}, and $\bar\lambda^e_{\rm GR}$ is the mean free path due to the Glashow resonance $(N_{e}(x)\sigma^e_{\rm GR}(E))^{-1}$~\citep{Gandhi:1998ri}. Notice that we assume the matter only contains electrons, protons, and neutrons, -\textit{i.e.} $\bar\lambda^\mu_{\rm GR}=\bar\lambda^\tau_{\rm GR}=0$. +i.e. $\bar\lambda^\mu_{\rm GR}=\bar\lambda^\tau_{\rm GR}=0$. The other interaction terms are as follows: \begin{subequations} \begin{eqnarray} F\left[\rho,\bar\rho;E,x\right] &=& \sum_\alpha \Pi_\alpha(E,x) \int_E^\infty {\rm Tr}\left[\Pi_\alpha(E_{\nu_\alpha},x) \rho(E_{\nu_\alpha},x) \right] \frac{1}{\lambda^\alpha_{\rm NC}(E_{\nu_\alpha},x)} \pa{N^\alpha_{\rm - NC}(E_{\nu_\alpha},E)}{E} dE_{\nu_\alpha} \label{eq:intronu} \nonumber\\ + NC}(E_{\nu_\alpha},E)}{E} dE_{\nu_\alpha} \label{eq:intro} \nonumber\\ && + \Pi_\tau (E,x) \int_E^\infty\int_{E_\tau}^\infty {\rm Tr} \left[ \Pi_\tau(E_{\nu_\tau},x) \rho(E_{\nu_\tau},x)\right] \nonumber\\ @@ -456,7 +375,7 @@ \subsection{Non-coherent Interactions} \bar F\left[\rho,\bar\rho;E,x\right] &=& \sum_\alpha \bar\Pi_\alpha(E,x) \int_E^\infty {\rm Tr}\left[\bar\Pi_\alpha(E_{\bar\nu_\alpha},x) \bar\rho(E_{\bar\nu_\alpha},x) \right] \frac{1}{\bar\lambda^\alpha_{\rm NC}(E_{\bar\nu_\alpha},x)} \pa{\bar N^\alpha_{\rm - NC}(E_{\bar\nu_\alpha},E)}{E} dE_{\bar\nu_\alpha} \label{eq:intronubar} \nonumber\\ + NC}(E_{\bar\nu_\alpha},E)}{E} dE_{\bar\nu_\alpha} \label{eq:intro} \nonumber\\ && + \bar\Pi_\tau (E,x) \int_E^\infty\int_{E_\tau}^\infty {\rm Tr} \left[ \bar\Pi_\tau(E_{\bar\nu_\tau},x) \bar\rho(E_{\bar\nu_\tau},x)\right] \nonumber\\ @@ -494,7 +413,7 @@ \subsection{Non-coherent Interactions} GR} (E_{\bar\nu_e},E_e)}{E_e}, \end{eqnarray} \end{subequations} -are the charged-current, neutral-current, and Glashow resonance +are the charged current, neutral current, and Glashow resonance interaction. The $\tau$ decay distribution~\citep{Dutta:2000jv} in all modes and leptonic modes are \begin{eqnarray} @@ -512,10 +431,10 @@ \subsection{Non-coherent Interactions} The first term in Eqs.~\eqref{eq:Fterm} and \eqref{eq:antiFterm} accounts for neutrino re-injection at lower energies coming from -Eqs.~\eqref{eq:gammarhoa} and \eqref{eq:gammarhob} due to neutral-current +Eqs.~\eqref{eq:gammarhoa} and \eqref{eq:gammarhob} due to neutral current interaction. The second and third term is the injection due to the $\tau$ decay -into $\nu_\tau$ and into other flavors in the leptonic case: this +in to $\nu_\tau$ and in the other flavors in the leptonic case: this is known as tau-regeneration. It is important to note that the latter terms couple the propagation of neutrinos and antineutrinos. Finally, the last term in Eq.~\eqref{eq:antiFterm} accounts for the @@ -523,681 +442,57 @@ \subsection{Non-coherent Interactions} These equations are implemented by discretizing the problem in bins that the user specifies. The user should be aware that the discretization used can introduce errors due to -bin spill-over. Special care should be taken for hard spectra, +bin spill-over. Special care should be taken for hard spectrums, {\it e.g.} $\phi(E_\nu) = E^{-1}$, where this maybe more relevant and the user is encouraged -to check the effect of discretization by modifying the energy nodes spacing and cross sections' granularity. - -\section{Features} -\label{sec:features} - -\subsection{Standard oscillations in matter and vacuum} - -{\ttf nuSQuIDS} is able to compute the neutrino oscillation probabilities in the presence of matter. -Neutrino oscillations can be computed for up to six neutrino flavors out of the box, though this can be extended to an arbitrary number of -neutrino flavors by producing additional tables using the provided {\ttf Mathematica} files. -The calculation allows setting both the mixing angles and the $CP$-violating phases. -Using the {\ttf Body} and {\ttf Track} objects, {\ttf nuSQuIDS} can compute the oscillation probability in any media provided by the user. -Default media, such as the Earth, the Sun, a constant density slab, and others are provided for immediate use. -In general, no constraints exist in the trajectory of the neutrino oscillation, though in the provided implementations, all neutrinos are assumed -to travel in straight lines, which should cover most applications. - -Though some of this functionality is available in other neutrino oscillation -calculators~\citep{Huber:2007ji,prob3pp,Calland:2013vaa,Wallraff:2014vl}, the solution -implemented in {\ttf nuSQuIDS} is unique, and provides advantages over others. -By working in the neutrino interaction basis, the fast oscillations due the the vacuum part of the neutrino Hamiltonian are solved analytically. -This provides significant speed up in propagating neutrinos in dense environments, specially for slowly-changing or small matter densities. -An unusual feature of {\ttf nuSQuIDS} is that it solves the neutrino oscillation problem over a grid of energies; -though solving the problem (when considering only coherent effects) using an individual, fixed neutrino energy is also possible, as in other software. -In the multi-energy operating mode, {\ttf nuSQuIDS} can interpolate the interaction-picture solutions of the neutrino-evolution problem for energy values -that are in between the nodes where the calculation is performed. -This allows accurate and fast evaluation of the neutrino oscillation probability using a relatively coarse grid. -This is particularly important when evaluating the neutrino oscillation probability over a larger number of energies, which is often the case -when re-weighting large Monte Carlo data sets. - -\subsection{Extendability to new physics scenarios} - -{\ttf nuSQuIDS} implements the standard neutrino oscillation Hamiltonian with matter effects; -however, this can be extended to include additional terms that may appear in the Hamiltonian. -This can be achieved as illustrated in example~\ref{ssec:extphys}, where the user creates an inherited class of the main {\ttf nuSQuIDS} class and implements -the desired new physics operators. -In order to write the operators, the user needs to write in terms of the {\ttf SQuIDS} SU(N) vector type, which represents arbitrary hermitian matrices. -Additionally, {\ttf SQuIDS} implements operations between matrices and scalars that typically arise in writing these terms, -\textit{e.g.} matrix-scalar multiplication, commutator between matrices, \textit{etc}. -Once the new Hamiltonian is defined by the user no further change is needed. The user will be able to use all the functionality -of {\ttf nuSQuIDS} with the new physics. -Finally, {\ttf nuSQuIDS} allows for the serialization of user-defined values which allow for constants used by new physics operators to be serialized as -part of {\ttf nuSQuIDS} serialization. - -\subsection{Neutrino transport in dense media} - -{\ttf nuSQuIDS} implements non-coherent neutrino interactions that are relevant in very dense media or when neutrinos have high energies. -This functionality is comparable to other neutrino propagators used in neutrino telescopes~\cite{Safa:2021ghs,Garcia:2020jwr,Vincent:2017svp,Yoshida:2003js,shigeruyoshida_2020_4018117,Gazizov:2004va,DeYoung:865626,Alvarez-Muniz:2018owm,NuSpaceSim:2021hgs}. -At high energies, the neutrino interaction length is comparable to the size of the Earth, making the neutrino transport non-trivial. -{\ttf nuSQuIDS} takes into account charged-current and neutral-current interactions with nucleons through deep-inelastic scattering, which is the dominant interaction at the relevant energies~\citep{Formaggio:2012cpf,Gandhi:1998ri,Zhou:2019frk,Zhou:2019vxt,CooperSarkar:2011pa}. -Additionally, it takes into account neutrino-electron scattering, which is only relevant for resonant electron-antineutrino scattering at neutrino energies close to 6.4~PeV~\cite{Glashow:1960zz}. -A subdominant contribution from neutrino-photon scattering is not implemented~\cite{Seckel:1997kk,Alikhanov:2014uja,Alikhanov:2015kla,Zhou:2019frk,Zhou:2019vxt}, but can be easily extended in our framework; see~\cite{Garcia:2020jwr} for a publicly-available implementation of this cross section. -Finally, the production of neutrinos from lepton decay is neglected for all flavors, except for tau neutrinos. -In this case, we account for the contribution of neutrinos from tau decay in the approximation that the tau decays promptly, so it does not undergo significant energy losses. -This approximation is good below approximately 10~PeV and breaks down at higher energies; see~\cite{Safa:2021ghs,Garcia:2020jwr,NuSpaceSim:2021hgs} for recent work on implementing tau neutrino propagation at very high energies. - -\subsection{Scenarios with neutrino oscillations and interactions} - -{\ttf nuSQuIDS} is able to take into account simultaneously the presence of oscillations and non-coherent interactions in a consistent manner. -For neutrino transport in the Earth, and when standard neutrino oscillations are considered, this scenario is never an issue, since oscillations are important only below $\sim100$~GeV, while interactions appear above $\sim10$~TeV. -However, this is not the case for neutrino transport in larger astrophysical objects, \textit{e.g.} high-energy neutrinos produced in cosmic-ray collisions~\cite{Moskalenko:1991hm,Seckel:1991ffa,Ingelman:1996mj,Masip:2017gvw,Ng:2017aur,Edsjo:2017kjk,Arguelles:2017eao,IceCube:2021koo} or produced from dark matter decay or annihilation~\cite{Srednicki:1986vj,Kamionkowski:1991nj,Cirelli:2005gh,Blennow:2007tw,Barger:2007xf,Liu:2020ckq} in the Sun undergo oscillations and interactions simultaneously. -Additionally, this is not the case for non-standard neutrino oscillations, notably for light sterile neutrinos motivated by short-baseline anomalies, where flavor conversion can happen at high energies where interactions are relevant~\cite{Akhmedov:1988kd,Krastev:1989ix,Chizhov:1998ug,Chizhov:1999az,Akhmedov:1999va,Nunokawa:2003ep,Choubey:2007ji,Barger:2011rc,Esmaili:2012nz,Esmaili:2013vza,Lindner:2015iaa}. - -\subsection{Handling of extended sources} - -Neutrino emission does not happen as a physical point source, but rather there exist finite emission regions. -However, since the neutrino oscillation and interaction scales are much larger than the production region or detector size, in most scenarios, we can consider the neutrino emission to be point like to good approximation. -Nonetheless, there are scenarios where this approximation is not applicable. -For example, for neutrinos produced from dark matter decay through an intermediate mediator, a scenario known as secluded dark matter~\cite{Pospelov:2007mp}, the neutrinos are produced according to an exponential distribution that can be as large as the radius of the Earth or Sun depending on the model parameters~\cite{Niblaeus:2019gjk,Liu:2020ckq}. -This scenario can be implemented in nuSQuIDS~\cite{Liu:2020ckq} by introducing a source term that follows the exponential yield of neutrinos. -Another relevant scenario is that of production of neutrinos in pion or kaon decay in flight, \textit{e.g.} in accelerator neutrino experiments or in cosmic-ray air-showers. -Though for standard neutrino oscillation parameters the distribution of lengths induced by the varying decay position does not significantly impact the oscillation probability, this is not the case for new physics models that introduce small oscillations scales, \text{e.g.} when heavier neutrinos are introduced. -A similar scenario is that of experiments looking for fast oscillations close to cores of nuclear reactors where the size of the core is relevant. - -\subsection{Efficient fast oscillations and fully delocalized neutrino emission} - -Neutrino oscillations can vary extremely rapidly with neutrino energy, especially at small energies where the neutrino Hamiltonian in vacuum is large. -It is numerically expensive to solve the neutrino evolution on a very dense grid or for enough energies to be able to produce a meaningful oscillation pattern. -{\ttf nuSQuIDS} introduces a novel solution to this problem by permitting the evaluation of fast oscillations in a way that the oscillations due to vacuum are tracked analytically. -The evaluation of oscillations on a grid of nodes that has been already computed has been significantly optimized making it possible to evaluate the oscillation probability for large Monte Carlo data sets much faster than computing the individual oscillation probabilities at each of the Monte Carlo event energies. - -As noted in the previous point, the issue of fast oscillations and the localization of the neutrino emission is related. -Neutrinos emitted by an extended source smear out the neutrino oscillation probability statistically. -{\ttf nuSQuIDS} provides an option to analytically perform the smearing of the oscillation probability, in which the user provides the size of the oscillation length that they which to smear. -This can be -understood as the leading order of the Magnus expansion~\cite{Magnus:1954zz}, and can -speed up numerical calculations dramatically in some concrete physics setups, -such as oscillations in the early universe~\cite{Hernandez:2016kel}. -This calculation has no significant overhead and is much more efficient than performing integrals over the production region. -This feature is most useful in computing the oscillation expected from a nuclear reactor on a nearby detector, where one typically needs to smear over the reactor core size, or in computing the yield of atmospheric neutrino oscillations where one needs to smear over the production region in the atmosphere, which is several kilometers in size. - -\subsection{Serializable input and output} - -{\ttf nuSQuIDS} allows for the result of a calculation to be serialized into an \texttt{HDF5} file. -The serialization stores all the settings that were used to produce the {\ttf nuSQuIDS} object. -This can be advantageous in several scenarios. -For example, a calculation can be complex and lengthy, and the user may choose to perform it in steps. -In this scenario, the user can stop the calculation at a given point and then recover the {\ttf nuSQuIDS} object where it was left and continue. -Another scenario of interest is that related to not knowing at execution time which energies will need to be computed. -In this case, the user performs a calculation on a grid of energies and then stores the output of {\ttf nuSQuIDS} in a file. -Then, later, when the user wants to evaluate the result at specific energies, they can recover the object and perform the necessary evaluations. -This is also useful when the same calculation will be reused many times. - -\subsection{Techniques for high-performance Monte Carlo evaluation} -{\ttf nuSQuIDS} separates the calculation of a result flux from an input flux at the user's selected energy nodes from evaluating that result flux at arbitrary energies (provided those energies are within the span of energy nodes for which the propagation was performed). -As discussed previously, this latter step evaluates vacuum oscillations analytically, and interpolates all other effects between the nearest energy nodes. -As the final flux evaluation is often desired for very large numbers of energies (\textit{e.g.} for every event produced in a Monte-Carlo simulation), it has been optimized for speed, and furthermore to permit concurrent evaluation. -While the majority of the classes and functions in {\ttf nuSQuIDS} are not safe to access concurrently from multiple threads of execution, such use is specifically supported for all for the flux evaluation functions. -While not applicable in all cases, concurrent evaluation may provide considerable speed improvements for some users. - -\subsection{{\ttf C++} and {\ttf Python} interfaces} - -{\ttf nuSQuIDS} has been written in {\ttf C++} since this compiled language provides the best execution efficiency. -Extensive use is made internally of templating, inlining, and auto-vectorization to produce efficient machine code. -In particular, the algebra of SU(N) operators significantly benefits from these types of optimization. -All {\ttf nuSQuIDS} functions can be accessed in {\ttf C++}; however, recently, there has been great interest in designing particle physics software in interpreted languages such as {\ttf Python}. -To facilitate the usage of {\ttf nuSQuIDS} with {\ttf Python}-based physics software, an interface to {\ttf Python} is implemented by means of the Boost library. -Most of the functionality of {\ttf nuSQuIDS} is available through the {\ttf Python} interface, with the notable exception of new body objects and new physics operators. -These limitations arise because these types of extensions require user-provided functions which must be evaluated very frequently during the propagation calculation, which, if written in {\ttf Python}, would produce a significant amount of overhead. - -\section{Usage Examples} -\label{sec:short_examples} -Provided along with the code are a set of working examples demonstrating its use for various purposes. -Here, we discuss two illustrative use cases: computing neutrino oscillations for a range of energies simultaneously, and extending the base implementation in the library with new physics. - -\subsection{Multiple Energy Propagation} -In this section, we discuss an abbreviated version of the multiple energy propagation example found in the {\ttf examples/Multiple\_energy} subdirectory. - -Unit conversion factors and physical constants are provided by the supporting {\ttf SQuIDS} library's {\ttf Const} class. -It is typical to allocate an instance of this class to make these conveniently available: - -\begin{lstlisting}[frame=leftline, numbers = left,breaklines=true] -squids::Const units; -\end{lstlisting} - -Next, we construct the {\ttf nuSQUIDS} object itself. -For the multiple-energy mode, it requires an array of energies for which calculations will be carried out, which we choose here to be 200 values, spaced logarithmically from 1 GeV to 1,000 GeV. -We choose the number of neutrino flavors to consider to be four: three active flavors and one sterile. -These inputs are passed to the class constructor, along with the {\ttf neutrino} constant for the third argument to indicate that we will consider only neutrinos and not anti-neutrinos, and {\ttf false} for the fourth argument to disable the calculation of non-coherent interactions. -\begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,firstnumber=last] -auto energies = logspace(1.*units.GeV, 1.e4*units.GeV, 200); -unsigned int numneu = 4; -nuSQUIDS nus(energies, numneu, neutrino, false /*no interactions*/); -\end{lstlisting} - -Next, we choose the environment (matter profile) through which we will propagate the neutrino flux. -We choose here the Earth, with path passing through its full diameter, and apply these choices to the {\ttf nuSQUIDS} object: -\begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,firstnumber=last] -double phi = units.pi; // zenith angle for trajectory -auto earth_atm = std::make_shared(); -auto track_atm = std::make_shared(earth_atm->MakeTrack(phi)); -nus.Set_Body(earth_atm); -nus.Set_Track(track_atm); -\end{lstlisting} - -A variety of other {\ttf Body} classes are provided with the library for media such as vacuum, constant density material, material with user-specified variable density, and the Sun. -Additionally, users can create their own {\ttf Body} implementations for needs not covered by these. -Each {\ttf Body} type has an associated {\ttf Track} class, parameterizing paths through it in whatever manner is most appropriate. - -The parameters of the neutrino mixing matrix can be fully customized. -Here, we take a set of nominal values: - -\begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,firstnumber=last] -nus.Set_MixingAngle(0,1,0.563942); -nus.Set_MixingAngle(0,2,0.154085); -nus.Set_MixingAngle(1,2,0.785398); -nus.Set_SquareMassDifference(1,7.65e-05); -nus.Set_SquareMassDifference(2,0.00247); -nus.Set_SquareMassDifference(3,0.1); -nus.Set_MixingAngle(1,3,0.1); -\end{lstlisting} - -Mixing angles are expressed in radians, and are labeled by the lower an upper states they connect, with zero-based indexing. -Squared mass differences are specified in eV$^2$ and are always with respect to the lowest-mass eigenstate, so only the upper state index must be specified. -$CP$-violating phases can also be specified, again in radians and with two state indices. -If unspecified, they default to zero. - -Next, the initial neutrino flux before propagation must be configured. -Here, we will use a simple power-law spectrum, purely of the $\nu_\mu$ flavor (determined by the {\ttf k == 1} condition). -The flux is specified as a two-dimensional array, indexed by neutrino flavor and energy: -\begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,firstnumber=last] -marray inistate{energies.size(), numneu}; -double N0 = 1.0e18; -for(int i = 0 ; i < inistate.extent(0); i++){ - for(int k = 0; k < inistate.extent(1); k ++){ - inistate[i][k] = (k == 1) ? N0*pow(energies[i],-2) : 0.0; - } -} -nus.Set_initial_state(inistate,flavor); -\end{lstlisting} -If we choose to work with both neutrinos and anti-neutrinos at the same time, this array would be rank three, with an additional, middle index taking on values zero for neutrinos and one for anti-neutrinos. - -A number of settings are exposed which govern how the ODE solving process operates. -The most critical are the error tolerances, whose values should be chosen based on the precision needed and the difficulty of the propagation problem; see Sec~\ref{ssec:precision_parameters} for more detailed discussion. -\begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,firstnumber=last] -nus.Set_rel_error(1.0e-5); -nus.Set_abs_error(1.0e-5); -\end{lstlisting} - -After all settings are configured, the propagation itself can be performed: -\begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,firstnumber=last] -nus.EvolveState(); -\end{lstlisting} - -At this point, the propagated flux can be examined. -For simplicity, we evaluate it for all three flavors over a grid of energies, and write these results to a file, from which they can be plotted, etc.: -\begin{lstlisting}[frame=leftline, numbers=left, breaklines=true, firstnumber=last] -std::ofstream file("fluxes_flavor.txt"); -file << "# E flux-nu_e flux-nu_mu flux-nu_tau\n"; -for(double E : logspace(1.*units.GeV, 1.e4*units.GeV, 1000)){ - file << E << " "; - for(int fl=0; fl NSI_evol; - - void AddToPreDerive(double x); - squids::SU_vector HI(unsigned int ei,unsigned int index_rho) const; +In order to implement the evaluation of the vacuum oscillations in +this regime a generalized functions for the analytic evolution are included in +the SQuIDS~\cite{SQUIDS} versions 1.2 and later. +A low-level generalized version of the function {\ttf PrepareEvolve} is included: - public: - nuSQUIDSNSI(double epsilon_mutau, marray Erange, - int numneu, NeutrinoType NT, - bool iinteraction, double th01=0.563942, - double th02=0.154085, double th12=0.785398); -}; -\end{lstlisting} -We add three member variables: {\ttf epsilon\_mutau}--the sole NSI parameter we will support, {\ttf NSI}--the operator we construct from it, and {\ttf NSI\_evol} to hold time-evolved copies of {\ttf NSI} as an optimization. -We will add a new implementation of {\ttf HI} to update the Hamiltonian, as well as using {\ttf AddToPreDerive} to pre-calculate updates to {\ttf NSI\_evol}. -A new constructor will take the value of the NSI parameter, as well as the standard oscillation angles, which influence the value of the NSI operator. - -\begin{lstlisting}[frame=leftline, numbers=left, breaklines=true, firstnumber=last] -nuSQUIDSNSI(double epsilon_mutau, marray Erange, - int numneu, NeutrinoType NT, bool iinteraction, - double th01, double th02, double th12) - : nuSQUIDS(Erange,numneu,NT,iinteraction), - epsilon_mutau(epsilon_mutau) -{ - assert(numneu == 3); - // define the flavor structure as a complex matrix - gsl_matrix_complex* M = gsl_matrix_complex_calloc(3,3); - gsl_complex c {{ epsilon_mutau , 0.0 }}; - gsl_matrix_complex_set(M,2,1,c); - gsl_matrix_complex_set(M,1,2,gsl_complex_conjugate(c)); - NSI = squids::SU_vector(M); - gsl_matrix_complex_free(M); - - Set_MixingAngle(0,1,th01); - Set_MixingAngle(0,2,th02); - Set_MixingAngle(1,2,th12); - // rotate to mass representation - NSI.RotateToB1(params); - - NSI_evol.resize(ne); - for(int ei = 0; ei < ne; ei++) - NSI_evol[ei] = squids::SU_vector(nsun); -} -\end{lstlisting} -The constructor creates the NSI operator in the flavor basis from a matrix representation, then transforms it to the mass basis for later use. -Note that setting the mixing angles defines the effect of the {\ttf RotateToB1} basis-transformation function. -The {\ttf NSI\_evol} vector is filled with a set of correctly-sized operator vectors, but their values are not yet computed. -Due to the simplicity of the example, only three-neutrino scenarios are supported, with other settings being rejected. - -The implementation of {\ttf AddToPreDerive} is responsible for computing the time-evolved operator values, which depend on both the time/position of the system--{\ttf x} and on the time-independent Hamiltonian for each energy, accessed from the base class' {\ttf H0\_array}: -\begin{lstlisting}[frame=leftline, numbers=left, breaklines=true, firstnumber=last] -void AddToPreDerive(double x){ - for(int ei = 0; ei < ne; ei++) - NSI_evol[ei] = NSI.Evolve(H0_array[ei],(x-Get_t_initial())); -} -\end{lstlisting} -The implementation of {\ttf HI} can then make use of {\ttf NSI\_evol}, knowing that {\ttf AddToPreDerive} will be called to update it for each {\ttf x} before any calls to {\ttf HI} are made. - -The implementation of {\ttf HI} itself is concerned with adding the additional term to the Hamiltonian: -\begin{lstlisting}[frame=leftline, numbers=left, breaklines=true, firstnumber=last] -squids::SU_vector HI(unsigned int ei,unsigned int index_rho) const{ - static const double HI_prefactor=params.sqrt2*params.GF*params.Na*pow(params.cm,-3); - double CC = HI_prefactor*current_density*current_ye; - squids::SU_vector potential = (3.0*CC)*NSI_evol[ei]; - - if ((index_rho == 0 and NT==both) or NT==neutrino){ - // neutrino potential - return nuSQUIDS::HI(ei,index_rho) + potential; - } else if ((index_rho == 1 and NT==both) or NT==antineutrino){ - // antineutrino potential - return nuSQUIDS::HI(ei,index_rho) + -1*std::move(potential); - } - throw std::runtime_error("nuSQUIDS::HI : unknown particle or antiparticle"); -} +\begin{lstlisting}[frame=leftline, numbers = left,breaklines=true, label = ex:sin1,firstnumber=last] + void PrepareEvolve(double* buffer, double t, double scale, std::vector& avr) const \end{lstlisting} -A few details to note are that {\ttf current\_density} and {\ttf current\_ye} are member variables of the {\ttf nuSQUIDS} class which are used to obtain the matter properties (density and electron fraction) at the current position, the base {\ttf nuSQUIDS::HI} is invoked to obtain the original, standard model terms of the Hamiltonian, and that when the potential term must have the opposite sign for the anti-neutrino case, we apply the {\ttf std::move} function to it before performing the multiplication by $-1$ to indicate that the object's contents may be overwritten, eliminating the need for a temporary storage buffer. - -The full implementation of the class contains several other useful and convenient features, such as updating the serialization mechanism to save and restore the additional physics parameter; for the details we refer the reader to the file {\ttf examples/NSI/NSI.h} in the code. -With the {\ttf nuSQUIDSNSI} class fully defined, its usage is analogous to the original {\ttf nuSQUIDS}, with the only major difference being the extra parameters for the constructor; setting the initial state, running the evolution, and reading out the final state are the same. - -While this example makes only a very simple addition to the physics of {\ttf nuSQuIDS}, there are a wide variety possibilities of equal of greater complexity, such as new non-coherent interactions and additional, coupled scalar fields. - -\section{Comparison to Other Software} -\label{sec:comparison} - -A number of other software packages are available which perform related calculations. -In this section, we summarize how a number of these differ from {\ttf nuSQuIDS}. -Most neutrino propagation software can be divided into categories based on whether it was designed to handle neutrino oscillation physics or neutrino absorption physics. -{\ttf nuSQuIDS} is unusual in this regard, as it is designed to calculate both types of effect simultaneously. -Another important categorization is the calculation method used, which tends to have implications for the physics effects which can be readily calculated: -Three prevalent methods, each with different strengths and weaknesses, are algebraic matrix diagonalization, ordinary differential equation (ODE) integration, and Monte-Carlo (MC) sampling. -Matrix diagonalization is frequently used for coherent effects (\textit{e.g}. neutrino oscillation) in uniform media, for which the system of differential equations can be written down and solved analytically, as introduced in \cite{barger1980matter}. -This has the advantage of taking a small, constant time to solve, but loses efficiency when variations in the propagation medium must be approximated by repeating the calculation in many small steps, and is not normally applicable to physics effects which couple fluxes besides those of different flavors at the same energy (such as energy losses due to neural-current interactions). -ODE integration, the method used by {\ttf nuSQuIDS}, consists of writing down all physics effects in terms of their differential effects on neutrino fluxes and numerically solving the resulting system of equations. -This provides a quite natural framework for treating variable media and arbitrary coupling between fluxes, but requires care in discretizing the problem (e.g. in neutrino energy), in structuring the problem numerically for handling by a standard ODE integration routine, and in selecting the parameters of the integration routine to get precise results rapidly. -Monte Carlo sampling is in some sense the more literal method, consisting of simulating individual particles and randomly sampling the interactions they undergo. -This sampling has both the benefit and disadvantage that it discovers not only the average behavior but also the full distribution of variations from it. -This is indispensable when the full distribution is required, but has relatively slow convergence to precisely extract the mean behavior if that is all that is sought. -Monte Carlo sampling can not only naturally treat variable media, but requires no discretization. - -\begin{table} - \centering - \begin{tabular}{l | c | c | c | C{5em}} - \textbf{Package} & \textbf{Method} & \textbf{Oscillation} & \textbf{Absorption} & \textbf{Variable Density}\\ - \hline - GLoBES & AD & \checkmark & ~ & ~\\ - Prob3++ & AD & \checkmark & ~ & ~\\ - nuCraft & ODE & \checkmark & ~ & \checkmark\\ - nuFATE & ODE & ~ & \checkmark & \checkmark\\ - nuPropEarth & MC & ~ & \checkmark & \checkmark\\ - TauRunner & MC & ~ & \checkmark & \checkmark\\ - ANIS & MC & ~ & \checkmark & \checkmark\\ - nuSQuIDS & ODE & \checkmark & \checkmark & \checkmark\\ - \end{tabular} - \caption{Simple classification of neutrino evolution codes by calculation technique (analytic diagonalization--AD, differential equation integration--ODE, or Monte Carlo sampling--MC), whether they treat neutrino oscillation, absorption, or both, and whether they directly support propagation in variable density media.} -\end{table} - -The General Long Baseline Experiment Simulator (GLoBES)~\cite{Huber:2007ji} is a toolkit to enable analyzing the capabilities of neutrino oscillation experiments, and combinations of experiments. -Calculating neutrino flux evolutions is thus not the package's primary purpose, but is nonetheless one of its key components. -GLoBES calculates only oscillation effects, via the analytic diagonalization method. -Via its add-on system, the package can treat new physics effects, including sterile neutrinos, with the {\ttf snu} add-on. - -Prob3++~\cite{prob3pp} is designed specifically to calculate neutrino oscillation probabilities for the Super-Kamiokande collaboration. -As such, it calculates only oscillation effects, and only for up to three flavors, although Lorentz invariance-violating oscillations are also supported for searches for new physics. -As the package uses the analytic diagonalization method, only constant-density media are directly supported, although to support atmospheric neutrino measurements, the full Earth may be approximated as a set of spherically concentric shells of material, with a distinct density and electron fraction for each shell. - -nuCraft~\cite{Wallraff:2014vl} is a package created specifically to facilitate searches for sterile neutrino effects in the atmospheric neutrino flux, so it focuses on the computation of oscillation effects with support for four or more neutrino flavors, and has a continuous treatment of the density profile of the Earth. -Unlike the other pure oscillation calculators, nuCraft is an ODE integration-based system, which makes inclusion of the variable material density convenient. - -Turning to packages designed for higher energies with a focus on neutrino absorption, the All Neutrino Interaction Simulation (ANIS)~\cite{ANIS} is intended for use as an event generator for neutrino observatories. -For this reason it uses a Monte-Carlo sampling approach, and not only simulates neutrinos passing through the bulk of the Earth, with a continuously-parameterized density profile, but also includes forcing final interactions in a volume defined as the vicinity of a detector. (This volume is typically larger than the instrumented volume of the detector in order to fully sample muons produced by charge-current $\nu_\mu$ interactions entering the detector from outside.) -While ANIS treats all deep-inelastic scattering (DIS) and Glashow resonance (resonant $W^\pm$ production) processes as well as tau propagation and decay, it does not calculate oscillations. -The code requires DIS cross sections in the somewhat unusual form of Bjorken x, y pairs, pre-sampled at natural frequencies from the desired cross section. -While this enables the propagation code to run rapidly and without direct dependencies on other software, the user must beware that systematic biases will result if sufficiently large tables are not used. - -nuPropEarth~\cite{nuPropEarth2020} is a newer package which is similar to ANIS, but adds treatment of a number of subdominant interaction processes, such as nuclear effects. -It also uses a Monte-Carlo sampling method, and does not treat oscillations. -Choosing different tradeoffs than ANIS, nuPropEarth links directly to the GENIE/HEDIS, TAUOLA++, and TAUSIC packages to enable the use of recent and highly detailed cross sections treatments, but with the disadvantage of a considerable set of dependencies required to build the package. - -TauRunner~\cite{Safa:2021ghs} is a new {\ttf Python} package that provides similar functionality to nuPropEarth. -It has the advantage that it has less dependence on other software, and allows for arbitrary media and trajectories. -It also uses a Monte-Carlo sampling method, and does not treat oscillations. -It can use several built-in cross-section tables that can be extended by the user. -These tables only account for deep-inelastic scattering. -More importantly, TauRunner properly accounts for the tau energy losses at very high energies, where the on-spot decay approximation used in {\ttf nuSQuIDS} breaks down. - -Finally, nuFATE~\cite{nuFATE2017} is a tool for calculation of neutrino flux attenuations at high energies, which uses a particularly efficient differential equation solution method which avoids the need for using a general ODE-integration routine by applying an integrating factor transformation, so that only the material density profile must be integrated, rather than the coupled system of equations. -While this mechanism does support deep inelastic scattering, the Glashow resonance, and tau-regeneration all in a continuously variable medium, in its current form the package does not support distinct cross sections for different target species, either at the level of individual nucleon types, or different nuclei. - -\section{Performance and Precision} -\label{sec:performance} +where {\ttf buffer} will contain all of the pre-evaluated +trigonometric functions needed to evaluate the evolution give by the {\ttf +SU\_vector} to be used by any {\ttf Evolve()} function. +For frequencies, given by difference of the eigenvalues, +larger that the value given by {\ttf scale} the trigonometric evaluations are set to zero. +The time over which the evolution is to be evaluated is {\ttf double t} and the {\ttf avr} +vector is treated as an output parameter; its elements are set to +{\ttf true} when the corresponding frequency is set to zero due to the fast +oscillation approximation. -In the tests described in this section, Machine 1 is configured with an Intel Core\texttrademark~i7-6700K CPU, with a `base' frequency of 4.0 GHz. All tests were performed with the `Turbo Boost' feature disabled, preventing frequency scaling. - -The time evolution and basis transformations performed on \lstinline{squids::SU_vector} objects rely heavily on trigonometric functions, specifically sines and cosines, mostly in matched pairs. -These operations are in turn used by several of the key portions of {\ttf nuSQuIDs}, and for oscillation-only calculations evaluation of trigonometric functions can be the single largest part of time consumed by the library. -As a result, runtime is significantly dependent on the performance of the underlying math library, which is usually supplied by the operating system, or sometimes the compiler. -The differences are illustrated in Table~\ref{tab:trig_perf}, which shows measurements performed on Machine 1 with several combinations of operating system and compiler of the cost of computing a single sine function or the combination of sine and cosine for the same argument (which should ideally be performed by an efficient, fused calculation). -A measurement was also made of the time to run the pseudo-random number generator (PRNG) by itself. -The time spent for the PRNG varies somewhat, assumedly due to different optimization choices by the various compilers, but amounts to a small fraction of the time for the trigonometric calculation. -Broadly, it is apparent that the calculations using the math implementations from the older version of the GNU C library (glibc) are significantly slower than the versions using other math libraries. -The (approximately) factor of two difference in fused sine/cosine performance between glibc 2.17 and 2.28 translates into a 10-25\% difference in the overall runtime of {\ttf nuSQuIDs} oscillation calculations. -The user is therefore cautioned that the choice of compiler and runtime libraries can be important to maximizing the performance of {\ttf nuSQuIDs}. -The benchmarks shown in this section will use the GNU compiler, version 8.3.1 (Red Hat 8.3.1-5) on CentOS 8, as this is a combination with good performance which is likely to be relevant to many users. - -\begin{table*} - \begin{tabular}{ llcccl } - OS & Compiler & PRNG & Sine & Sine \& Cosine & Math Library \\ - CentOS 7 & gcc 4.8.5 & 6.0 ns & 40.5 ns & 63.5 ns & GNU C Library 2.17 \\ - CentOS 7 & gcc 7.3.1 & 2.7 ns & 37.1 ns & 63.3 ns & GNU C Library 2.17 \\ - CentOS 7 & clang 5.0.1 & 4.8 ns & 96.4 ns & 69.0 ns & GNU C Library 2.17 \\ - CentOS 7 & icc 18.0.3 & 4.0 ns & 20.9 ns & 22.2 ns & libimf 2018.3.222\\ - CentOS 8 & gcc 8.3.1 & 2.7 ns & 26.8 ns & 31.3 ns & GNU C Library 2.28\\ - Darwin 16.7.0 & clang 5.0.0 & 2.9 ns & 19.1 ns & 20.1 ns & libsystem\_m 3121.6.0 \\ - FreeBSD 11.2 & clang 6.0.1 & 2.9 ns & 22.3 ns & 30.8 ns & BSD libc - \end{tabular} - \caption{ - Measured time to compute trigonometric functions using different compilers and operating systems on Machine 1. In each case, the same stream of $10^8$ pseudo-random arguments in the domain [-100,100] was used, and the average time per call was computed, including the time necessary for the PRNG to compute the next argument value. - } - \label{tab:trig_perf} -\end{table*} +A set of higher level functions to evaluate the expectation values of +the system in this approximations are also added: -\subsection{Parameters Affecting Precision} -\label{ssec:precision_parameters} - -The primary quantity defining the size of the problem solved by {\ttf nuSQuIDS} in its multiple energy mode is the number of energy nodes included in the calculation. -It is important to note that the interpolation provided by {\ttf nuSQuIDS} allows arbitrary energies within the range of the energy nodes to be evaluated after propagating, so it is not necessary to calculate a node for every energy at which the final flux may be needed. -Rather, the minimum number of nodes should be chosen so that the calculation is suitably precise at each node and when interpolated between nodes. - -It is difficult to give specific guidance for all of the many types of problems to which {\ttf nuSQuIDs} is applied, so users are advised to be prepared to perform their own tests of how many nodes are needed to get good results for their use cases. -However, it can be noted that for most problems the authors have attempted to compute numbers of nodes in the range 100-300 have typically been found sufficient. -It is also important that, while it is often convenient to place nodes uniformly in energy or the logarithm of energy, this is by no means required by {\ttf nuSQuIDS}, so it can be advantageous to place nodes more densely in regions of particular interest or where sharp spectral features are expected, such as the vicinity of the Glashow resonance. - -A second key parameter is the requested error tolerance for the ODE integration, which effectively controls the number of steps the integrator must take, while the number of energy nodes causes the amount of work required to compute each step to vary. -As with the number of nodes, it is impossible to give one-size-fits-all advice on selecting the tolerance. -In general, problems which include greater variation in the magnitudes of the flux values at different energies (e.g. steep power law fluxes), or for different flavors, require more demanding tolerances in order for the small components to be computed precisely in the presence of the larger components. -Similar to selecting the number of energy nodes, the necessary tolerance may be found by incrementally tightening it until subsequent calculations produce results which are equivalent to within the desired precision. -While this process is manual and somewhat annoying, having been performed for one problem, the result can usually be applied to modified versions of the problem without retesting, as long as the changes are not drastic. - -\begin{lstlisting}[float=ht,frame=lines,label=lst:prec_comp,caption={A simple routine for comparing the precision of two different calculations with {\ttf nuSQuIDS}. Error checking, that numbers of energy ranges, number of flavors, etc. are compatible is advisable, but omitted here for brevity.}] -void compare_fluxes(const nuSQUIDS& nus1, const nuSQUIDS& nus2, - unsigned int oversampling, double tolerance){ - auto er1 = nus1.GetERange(), er2 = nus2.GetERange(); - marray samples = er1; - if(oversampling>1) - samples=logspace(er1.front(), er1.back(), - er1.size()*oversampling - 1); - double GeV=squids::Const().GeV; - double maxErr=0; - for(double e : samples){ - for(unsigned int fl=0; fl tolerance) - std::cout << "Disagreement: " << err << " for energy " - << e/GeV << " GeV flavor " << fl << " rho " << rho - << " (" << val1 << " vs. " << val2 << ")\n"; - if(err > maxErr) - maxErr = err; - } - } - } - if(maxErr > tolerance) - std::cout << "Maximum disagreement: " << maxErr << std::endl; -} +\begin{lstlisting}[frame=leftline, numbers = left,breaklines=true, label = ex:sin1,firstnumber=last] +double GetExpectationValue(SU_vector op, unsigned int nrh, unsigned int i, double scale, std::vector& avr) const; +double GetExpectationValueD(const SU_vector& op, unsigned int nrh, double x, double scale, std::vector& avr) const; \end{lstlisting} -A simple comparison function for guiding these selections is shown in Listing~\ref{lst:prec_comp}. -Two \lstinline{nuSQUIDS} objects are compared over the full energy range for which the first was calculated, with some oversampling factor which may be greater than 1 to check results for energies using interpolation, as well as at the energy nodes of the first object. -Any evaluation point at which the relative difference of the second \lstinline{nuSQUIDS} object's result from that of the first is greater than the specified tolerance is reported, and the greatest such discrepancy is reported at the end. -This generic routine may not be suitable in all situations, but gives a basis for users to begin assessing the parameter choices needed for their problems. -It was used to determine integration error tolerances and in relevant cases node counts for the test shown in the rest of this section. - -\subsection{Propagation Time Scaling with Problem Size} -\label{ssec:propagation_scaling} - -\begin{figure}[t] - \centering - \includegraphics[width=0.9\textwidth]{fig/propagation-scaling.pdf} - \caption{Propagation time scaling with problem size on Machine 1. Only the time to run \lstinline{EvolveState} is included, omitting cross-section preparation time for the cases with interactions. This initialization can be separated by calling \lstinline{InitializeInteractions} manually, and is shown as `Cross Section Initialization'. Propagation with only oscillation effects shows scaling which is very close to linear in the number of energies, while propagation with interactions takes time which is approximately quadratic in the number of energies.} - \label{fig:propagation_scaling} -\end{figure} - -Several tests were performed to demonstrate how the time to perform multi-energy propagations scales with the number of energy nodes included, depending on the use of some of the library's major features. -The results of these tests are shown in Fig.~\ref{fig:propagation_scaling}. - -The `Low-energy Oscillations' tests used a flat input spectrum over an energy range of 1~GeV - 10~GeV, initially consisting of $\nu_\mu$ only. -For these tests, non-coherent interactions were disabled. -The `Broad-energy Interactions' test used an $E^{-2}$ input spectrum over 10~GeV - $10^7$~GeV with an initially equal mixture of flavors. -All tests propagated the input flux through the full diameter of the Earth, using {\ttf nuSQuIDS} version of PREM for the density. -Each propagation was tested for various sets of energy nodes, distributed uniformly in the logarithm of energy, from 50 to 1000 nodes, in increments of 50. -Each measurement was repeated five times, and the median duration reported, unless the standard deviation of the distribution was greater than 1\% of the mean, which was taken to indicate an unstable set of measurements, in which case the entire set of measurements was repeated. - -The oscillation-only propagations are expected to scale linearly with the number of nodes, as the calculation performed for each integration step consists primarily of evolving the flavor projectors (needed to compute $H_1(E,x)$ and $H^*_1(E,x)$) and commutator forming the first terms on the right hand sides of Eqs.~\ref{eq:kinetic_equations}, which must be repeated for each energy node, neutrino flavor, and particle type (neutrino and anti-neutrino). -This is borne out quite well by the measurements. - -The oscillation calculation including a fourth, sterile neutrino flavor (`Low-energy Oscillations with Sterile') is significantly slower than the standard three-flavor calculation (`Low-energy Oscillations'), as is to be expected. -The representation of the four-flavor state for each component has sixteen components to the three-flavor state's nine, so a decrease in speed of at least $16/9 = 1.77$ times may be expected, to start with. -The addition of the sterile flavor also forces the ODE integrator to use a smaller step size for the integration, taking nearly eight times as many steps to complete the propagation. -The combination of these effects seems to plausibly account for the observed decrease in speed. - -The time for propagations, including non-coherent interactions (`Broad-energy Interactions'), can be expected to scale quadratically in the number of energy nodes, due to the need to calculate the cascading of particles at each node down to all lower energy nodes. -In addition, calculating the interactions requires an additional initialization step, in which the cross section data governing the cascading processes is gathered. -Since this extra step is needed only once for a \lstinline{nuSQUIDS} object to be able to perform multiple propagations with the same set of energy nodes, which is often relevant as various hypothesis input fluxes are tested, it is accounted separately in Fig.~\ref{fig:propagation_scaling} as `Cross Section Initialization'. -Both the cross section initialization and the propagations with interactions show approximately the expected quadratic scaling, and the calculation of both interactions and oscillations together (`Broad-energy Interactions with Oscillations') exhibits the additional cost of including both types of effects. -A brief departure from the expected power law form of the propagation time scaling is observed at intermediate numbers of energy nodes is also observed for the tests with interactions; in Fig.~\ref{fig:propagation_scaling}, this appears approximately between 200 and 300 energy nodes. -This is believed to be a result of the calculation's memory use growing comparable in size to the CPU's last-level cache (8 MB, for Machine 1). -It appears reliably, but moves to higher node counts for CPUs with larger cache sizes. -See Sec.~\ref{ssec:memory} for a discussion of memory use and some representative numbers which support this hypothesis. - -\subsection{Flux Evaluation Performance} - -\begin{figure}[t] - \centering - \includegraphics[width=0.9\textwidth]{fig/evaluation-scaling.pdf} - \caption{Flux evaluation speed scaling with problem size on Machine 1. As expected, only a weak dependence on the problem size is observed. } - \label{fig:evaluation_scaling} -\end{figure} - -The purpose of propagating a flux with {\ttf nuSQuIDS} is to determine the spectrum or composition after propagation, so the efficiency with which this information can be extracted is the second critical half of the library's performance. - -Evaluation of the propagated flux for a given energy, flavor, particle type combination consists of three parts: Mapping the physical energy to a logical position within the energy nodes of the propagated state, interpolating the state components from the nearest nodes to form the requested state, and application of the suitably evolved $H_0$ operator to that state. -Locating the nearest energy nodes for interpolation depends on the total number of such nodes, due to the allowance for arbitrary node distributions, and is performed using a binary search. -The interpolation of the state, computation and evolution of the $H_0$ operator, and application of the operator to the interpolated state do not depend on the number of nodes, but do depend on the size of each state component, determined by the number of neutrino flavors considered. - -Fig.~\ref{fig:evaluation_scaling} shows how the rate of flux evaluations scales with the number of energy nodes treated for the four example problems introduced in Sec.~\ref{ssec:propagation_scaling}. -As expected, due to the binary search for adjacent nodes, a weak dependence on number of nodes is observed. -A marked drop in performance also occurs between the three-flavor and four-flavor oscillation calculations, as expected from the corresponding increase in the complexity of both the states and operators. - -\subsubsection{Concurrent Evaluation} - -\begin{figure}[t] - \centering - \includegraphics[width=0.9\textwidth]{fig/evaluation-concurrency-scaling.pdf} - \caption{Flux evaluation speed scaling with number of threads. Fairly good linearity is observed on both machines until the number of physical CPU cores is exhausted, at 4 and 16 threads, respectively. Both processors tested support 2-way simultaneous multithreading, but using it for this task is not productive on Machine 1 as shown by the lack of significant increase in total throughput when the number of threads is increased from 4 to 8, while Machine 2 initially suffers a penalty (the drop in throughput from 16 to 17 threads), but recovers and shows increased throughput as all logical CPU cores are used. } - \label{fig:evaluation_threads} -\end{figure} - -The \lstinline{nuSQUIDS} object is not generally concurrency-safe for modification, but concurrent use of non-modifying member functions, including \lstinline{EvalFlavor}, is safe and supported. -This is potentially useful when computing large numbers of flux evaluations for tasks such as weighting large numbers of simulated neutrino interactions in a detector to form an expected observation. -Fig.~\ref{fig:evaluation_threads} shows an example of the application of this technique to evaluating the flux computed by the `Low Energy Oscillations' calculation introduced previously. -A problem size of 200 energy nodes was tested with a variable number of worker threads each being assigned to perform $10^7$ flux evaluations. -Due to the limited number of processor cores available to Machine 1, a second hardware configuration was introduced for this test. -Machine 2 used an AMD Ryzen\texttrademark~9 3950X CPU, having a `base' operating frequency of 3.5 GHz, with frequency scaling disabled. - -Scaling to many flux evaluation threads appears to work well until the number of physical CPU cores is saturated, in spite of memory allocations which are required by the internals of the calculation. -An important optimization to enable this result was thread-local reuse of memory buffers, avoiding the need to serialize execution between threads even when the system memory allocator might use globally shared state. -For numbers of evaluation threads beyond the available number of physical processor cores, simultaneous multithreading (SMT) is used, and produces mixed results which depend significantly on the CPU architecture. -SMT does not enable a useful increase in throughput for Machine 1, while on Machine 2, additional SMT threads provide less marginal benefit than full physical cores, but aside from a small loss in total throughput when a small number of physical cores are running multiple SMT threads, throughput generally benefits. -As this is not a thorough survey of available CPU models, users are advised to perform their own checks to determine whether use of SMT will be productive on their hardware. - -\subsection{Memory Requirements} -\label{ssec:memory} - -For a {\ttf nuSQuIDS} object configured with $M$ energy nodes, $N$ neutrino flavors, $P$ particle types, and $T$ target species for interactions (if non-coherent interactions are enabled), neglecting constant terms, the amount of memory used may be broken down as follows. -Essentially all data allocated by the {\ttf nuSQuIDS} object is either in the form of machine pointers or double-precision floating-point numbers, assuming that the non-pointer components of \lstinline{squids::SU_vector} are small enough that padding and alignment requirements fit them into space equivalent to two additional pointers, making the direct size of an \lstinline{SU_vector} three pointers. -The underlying {\ttf squids::SQuIDS} object then requires: - -\begin{subequations} -\label{eq:squids_memory} -\begin{align} -(PN^2 + 1)M &~\textrm{doubles}\\ -9(P+1)M &~\textrm{pointers} -\end{align} -\end{subequations} - -This omits some amount of memory which the GSL ODE integration library will allocate for its own internal state. -The size of this state will be proportional to $PN^2M$ doubles, with the constant of proportionality typically being around 10 (e.g. it is 12 when using the {\ttf nuSQuIDS} default Runge-Kutta-Fehlberg 4-5 stepper, RKF45). - -Without structures needed for non-coherent interactions, the {\ttf nuSQuIDS} object additionally allocates: - -\begin{subequations} -\label{eq:nusquids_memory} -\begin{align} -(2PN^3 + N^2 + 6PN + 5)M + (P+1)N^3 + 3(P+1)N &~\textrm{doubles}\\ -3(2PN + 1)M + 3(P+1)N &~\textrm{pointers} -\end{align} -\end{subequations} - -The data structures for computing non-coherent interactions (neglecting any memory allocated by the cross section and $\tau$ decay objects themselves) require: - -\begin{subequations} -\label{eq:intereaction_memory} -\begin{align} -(2(NT+1)P + 1)M^2 + (PN^2 + (2T + 3)PN + 12)M &~\textrm{doubles}\\ -3PM &~\textrm{pointers} -\end{align} -\end{subequations} - -If the external neutrino source feature is used, it requires a buffer of another $PNM$ doubles. - -It should be noted that $P$ can only take on the values 1 and 2, $T$ is typically 2, and $N$ is generally 3 or 4. - -As an example, a modestly-sized three-flavor neutrino oscillation calculation might use 100 energy nodes and not consider non-coherent interactions, so $M=100$, $N=3$, $P=2$ (if both neutrinos and anti-neutrinos are considered), and $T$ is irrelevant. -Assuming typical data sizes of 8 bytes for both pointers and double-precision floating-point numbers, such a calculation will then require $24435 * 8$ bytes or approximately 191 kilobytes of memory, plus approximately another 170 kilobytes allocated by GSL (for the RKF45 stepper). - -Due to the quadratic scaling with number of energy nodes (of the differential charged- and neutral-current interaction cross sections and $\tau$ decay spectra), memory requirements are much higher for calculations with non-coherent interactions. -An interaction calculation with 100 energy nodes and all interaction effects enabled would have $M=100$, $N=3$, $P=2$, and $T=2$, leading to a memory requirement of $322235 * 8$ bytes, or approximately 2.5 megabytes, and increasing to 300 nodes ($M=300$) would require $2706435 * 8$ bytes, or approximately 20.6 megabytes (with the size of the GSL state also increasing to 506 kilobytes). -Use of the external neutrino source feature, even with this larger problem size, would require only an additional $1800 * 8$ bytes or 14 kilobytes. - -\subsection{Efficient Use} -\label{ssec:efficient_use} - -Besides configuring the number of energy nodes and the error tolerance to the lowest and loosest values which will provide the desired precision, there are several other considerations for using {\ttf nuSQuIDS} with the best possible efficiency. - -One simple trick is to turn off features which are not needed for a given calculation. -If neutrino oscillations are not relevant in the regime covered by a given propagation problem, they can be disabled, and the same is true for non-coherent interactions. -With oscillations disabled, {\ttf nuSQuIDS} is able to skip computing the evolution of the flavor projection operators, and with interactions disabled it can omit obtaining interaction cross sections, updating interaction lengths for the matter density at each step, and computing the contribution to each energy node from the neutrinos cascading down from higher energy nodes. -Additionally, some particular types of interactions can be enabled or disabled as needed, in particular, tau regeneration and Glashow resonance effects. -For example, to propagate a high-energy atmospheric neutrino flux, not only are oscillations potentially unnecessary, but the flavor composition of the flux may mean the tau regeneration is irrelevant as well. -If a flux is being calculated which involves no anti-neutrinos, the effects of the Glashow resonance will not appear, and they may be turned off without changing the result. -In general, {\ttf nuSQuIDS} attempts to detect possibilities at runtime to minimize work performed, and this is fairly successful in the case of tau regeneration, so turning this feature off may not produce much change in computation time. -Handling of the Glashow resonance, though, requires additional interaction length updates which the existing structure of the code is unable to optimize away even when it turns out to be unused, so turning this capability off when it is not needed can have a useful impact. - -The cross-section data required to compute non-coherent interactions is dependent only on the placement of the energy nodes, not on the flux being propagated. -As a result, if many fluxes are to be calculated over the same set of nodes, it is most efficient to reuse the same \lstinline{nuSQUIDS} object, merely resetting the initial flux with \lstinline{Set_initial_state} before calling \lstinline{EvolveState} again, so that this initialization is not repeated. -As shown in \ref{fig:propagation_scaling} the initialization can take 5-15\% of the time for the propagation, so this can represent an important savings over many propagations. - -\section{Conclusions} -\label{sec:conclu} - -\nuSQUIDS~ provides a complete solution to neutrino propagation while accounting for neutrino oscillations and scattering. -We find that it is competitive with dedicated neutrino oscillation calculators, when the number of evaluations of the oscillation probability -is large, which is the typical case of interest in neutrino experiments. -The library also has a {\ttf Python} extension. Finally, the \nuSQUIDS~ library has been designed to be easily extendable -to both new media and new physics scenarios. User contributions to the project are encouraged and a number of additional -models have already been implemented and are linked in {\ttf resources/user\_contributions}. - -\section*{Acknowledgements} +where the two extra arguments, {\ttf scale} and {\ttf avr}, are included with the same meanings as in the generalized {\ttf PrepareEvolve}. +In section~\ref{sec:code} the functions to evaluate the the expectation values for the neutrinos, {\ttf EvalFlavor} in +{\ttf nuSQuIDS}, are described in detail. -We thank: Alexander Tretting for improving the fast oscillations treatment; -Jakob Van Santen for implementing the Glashow resonance cross sections; -Benjamin Jones for early adoption of this code onto the sterile analysis; -Melanie Day for early adoption of this code onto her analysis, carefully checking the non-standard interaction extension, and providing feedback; -Tianlu Yuan for comments on neutrino cross section utilities and testing the performance of the code in realistic analysis scenarios; -Subir Sarkar for providing the code to generate neutrino-nucleon cross section tables; -Kotoyo Hoshima and Aaron Vincent for dedicated comparisons and checks of this code; -Zander Moss for performing an independent check of several core features of the code; -Felix Kallenborn for carefully reading through the code, writing a GPU version of the algorithm, and pointing out an improve handling of the GSL ODE solver; -Jos\'e Carpio and Zander Moss for pointing out the need to improve the Earth density interpolation; -Mauricio Bustamante for testing the Python V3 support; -Austin Schneider for reading through this draft and testing the Ubuntu support; -Ibrahim Safa for reading through this draft; -Alejandro Diaz for reading through this draft; -Tom Studdard for providing feedback and contribution of neutrino decoherence; -Jos\'e Carpio, Alberto Gago, and Eduardo Massoni for providing feedback and implementing nuSQuIDS in GLoBES; -Zander Moss, Marjon Moulai, and Janet Conrad for providing feedback and contribution of neutrino decay extension; -Shivesh Mandalia and Teppei Katori for checking, providing feedback, and contribution on the Lorentz Violation model implementation; -Joshua Highnight and Jessie Micallef for providing a modified version of Prob3++ with NSI for detailed comparisons; and -Thomas Ehrhardt for performing detailed comparison between this code speed and accuracy versus Prob3++ CPU and GPU version. -Pedro Machado, Aaron Vincent, and Logan Wille for providing the Solar model files and useful discussion in the construction of the SolarTransition extension. -CAA is supported by the Faculty of Arts and Sciences of Harvard University, the Alfred P. Sloan Foundation, and was supported by U.S. National Science Foundation (NSF) grant PHY-1912764 through this work. -JS is supported by European ITN project H2020-MSCA-ITN-2019/860881-HIDDeN, the Spanish grants FPA2016-76005-C2-1-P, -PID2019-108122GB-C32, PID2019-105614GB-C21. +Besides using this approximation in the evaluation, essentially to set the states +from the interaction picture to the real picture, these approximate functions can be also used to compute the right hand side +terms of the differential equation when the oscillations are much +faster than the time scales of a given numerical system. This can be +understood as the leading order of the Magnus expansion~\cite{Magnus:1954zz} and can +speed up numerical calculations dramatically in some concrete physics setups +such as oscillations in the early universe~\cite{Hernandez:2016kel}. -\bibliographystyle{elsarticle-num} -\ifdefined\forjournal -\bibliography{nusquids_journal} -\else -\bibliography{nusquids} -\fi % forjournal -\fi % manualonly - -\ifdefined\forjournal -% no appendices -\else -\ifdefined\manualonly -% let appendices be main sections -\else -\appendix -\fi % manualonly \section{Examples} \label{sec:examples} @@ -1227,10 +522,10 @@ \subsection{Single energy \textnormal{({\ttf examples/Single\_energy})}} phase in radians. In order to do so we use the {\ttf Set\_MixingAngle} member function whose first two arguments are the indices of the rotation, starting -from zero. The $CP$ phase function is similar. +from zero. Similarly for the $CP$ phase function. In the case of the square mass difference, the first argument of the function is the mass eigenvalue index and the second argument the value. These -square mass differences are always with respect to the lightest mass state (whose index is zero). +square mass differences are always with respect to the lightest mass state. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true, label = ex:sin1,firstnumber=last] nus.Set_MixingAngle(0,1,0.563942); @@ -1262,18 +557,17 @@ \subsection{Single energy \textnormal{({\ttf examples/Single\_energy})}} \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true, label = ex:sin1,firstnumber=last] double phi = acos(-1.0); - auto earth_atm = std::make_shared(); - auto earth_atm_track = std::make_shared( - earth_atm->MakeTrackWithCosine(phi)); + std::shared_ptr earth_atm = std::make_shared(); + std::shared_ptr earth_atm_track = + std::make_shared(phi); nus.Set_Body(earth_atm); nus.Set_Track(earth_atm_track); \end{lstlisting} Now we set the initial neutrino flavor composition. In this example we start with -a pure muon neutrino state, represented by an {\ttf marray} (multi-dimensional array) of rank 1 and length {\ttf +a muon neutrino, which we represent represented by an {\ttf marray} of rank 1 and length {\ttf \{3\}}, corresponding to the number of flavors, and with value given by {\ttf\{0,1,0\}}. -We indicate that this state is described in the flavor basis when applying it to the {\ttf nuSQuIDS} object: \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true, label = ex:sin1,firstnumber=last] marray ini_state({3},{0,1,0}); @@ -1288,7 +582,7 @@ \subsection{Single energy \textnormal{({\ttf examples/Single\_energy})}} nus.Set_abs_error(1.0e-20); \end{lstlisting} -Finally, we show the result before and after propagation. The +Finally we show the result before and after propagation. The propagation is done by calling the function {\ttf nus.EvolveState()} \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true, label = ex:sin1,firstnumber=last] @@ -1317,17 +611,17 @@ \subsection{Single energy \textnormal{({\ttf examples/Single\_energy})}} \subsection{Multiple Energy \textnormal{({\ttf examples/Multiple\_energy})}} This is a more realistic example where we consider an ensemble of -neutrinos in an energy range. With this setup, -we can model the neutrino energy and flavor changes, -including the effects of charged and neutral current interactions. +neutrinos in an energy range. With this setup +we can model the neutrino energy and flavor changes. +For example interactions such as charged and neutral current. In the following we describe the code for the example. -As before, we construct the {\ttf Const} object to have a set of useful physical parameters. -\begin{lstlisting}[frame=leftline, numbers = left,breaklines=true, label = ex:sin1] +As before we construct the {\ttf Const} object to have a set of useful physical parameters. +\begin{lstlisting}[frame=leftline, numbers = left,breaklines=true, label = ex:sin1,firstnumber=last] squids::Const units; \end{lstlisting} -In the following, we allow the choice to compute +In the following we allow the possibility of choosing to compute the propagation for three active neutrinos or three active and one sterile. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true, label = ex:sin1,firstnumber=last] @@ -1339,33 +633,32 @@ \subsection{Multiple Energy \textnormal{({\ttf examples/Multiple\_energy})}} } \end{lstlisting} -In the next line, we construct the {\ttf nuSQUIDS} object. For the -multiple energy constructor, we need to provide the following arguments: -a list of neutrino energy nodes +In the next line, we construct the nuSQUIDS object. For the +multiple energy constructor we need to provide the following arguments: +list of neutrino energy nodes (\lstinline[columns=fixed,breaklines=true]{logspace(1.*units.GeV,1.e4*units.GeV,200)}), number of neutrino flavors ({\ttf numneu}= 3 or 4), neutrino or -anti-neutrino type ({\ttf neutrino}), and whether to compute non-coherent scattering +anti-neutrino type ({\ttf neutrino}), and non-coherent scattering interactions ({\ttf false}). \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true, - label = ex:sin1,firstnumber=8] + label = ex:sin1,firstnumber=last] nuSQUIDS nus(logspace(1.*units.GeV,1.e4*units.GeV,200),numneu,neutrino,false); \end{lstlisting} -As in the single energy mode, we must define the body and the path +As in the single energy mode we must define the body and the path where neutrinos will propagate. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true, label = ex:sin1,firstnumber=last] double phi = acos(-1.); - auto earth_atm = std::make_shared(); - auto track_atm = std::make_shared( - earth_atm->MakeTrackWithCosine(phi)); + std::shared_ptr earth_atm = std::make_shared(); + std::shared_ptr track_atm = std::make_shared(phi); nus.Set_Body(earth_atm); nus.Set_Track(track_atm); \end{lstlisting} -We set the neutrino oscillation parameters, and if a sterile -neutrino is considered, we set its parameters to $\theta_{24}=0.1$ and +We also set the neutrino oscillation parameters and if a sterile +neutrino is considered we set it's parameters to $\theta_{24}=0.1$ and $\Delta m_{41}^2=0.1{\rm eV}^2$. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] nus.Set_MixingAngle(0,1,0.563942); @@ -1374,15 +667,16 @@ \subsection{Multiple Energy \textnormal{({\ttf examples/Multiple\_energy})}} nus.Set_SquareMassDifference(1,7.65e-05); nus.Set_SquareMassDifference(2,0.00247); - if(numneu==4){ // sterile neutrino parameters + if(numneu==4){ + // sterile neutrino parameters nus.Set_SquareMassDifference(3,0.1); nus.Set_MixingAngle(1,3,0.1); } \end{lstlisting} Next we set some of the integration parameters: the maximum -step size for the evolution, the GSL stepper algorithm (all the steppers in -the GSL libraries can be used), and maximum relative and absolute error tolerances. +step for the evolution, the GSL stepper algorithm (all the steppers in +the GSL libraries can be used), maximum relative and absolute error. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] nus.Set_h_max( 500.0*units.km ); @@ -1398,11 +692,10 @@ \subsection{Multiple Energy \textnormal{({\ttf examples/Multiple\_energy})}} nus.Set_ProgressBar(true); \end{lstlisting} -We can ask {\ttf nuSQuIDS} to give back the array containing the values of -the energy nodes. We use this here to fill a multi-dimensional array with the initial +We can ask nuSQUIDS to give back the array containing the values of +the energy nodes. We use this here to fill a multiple array with the initial state of the system; in this case a $E^{-2}$ power-law for the muon -flavor and zero for the other flavors. -Unlike the single-energy example, the array now has rank 2, with dimensions for both energy and flavor. +flavor and zero for the others. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] marray E_range = nus.GetERange(); @@ -1416,13 +709,14 @@ \subsection{Multiple Energy \textnormal{({\ttf examples/Multiple\_energy})}} nus.Set_initial_state(inistate,flavor); \end{lstlisting} -We can then evolve the state: +Here we evolve the state. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] nus.EvolveState(); \end{lstlisting} -Finally, we write the propagated fluxes to a file and ask whether to run the plotting script: +Finally we write the propagated fluxes in a file called {\ttf + flux\_flavor.txt} and after that we ask to run the plotting script. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] std::ofstream file("fluxes_flavor.txt"); @@ -1449,85 +743,83 @@ \subsection{Multiple Energy \textnormal{({\ttf examples/Multiple\_energy})}} return system("./plot.plt"); \end{lstlisting} -Note that while we explicitly propagated 200 energies, we evaluate the resulting flux at 1000 energies, taking advantage of the automatic interpolation. \begin{figure}[h!] \label{fig:multimode} \centering \includegraphics[width=0.7\textwidth]{fig/Multiplot.eps} - \caption{Output for the multiple-energy mode with sterile neutrino (3+1)} + \caption{Output for the multiple energy mode with sterile neutrino (3+1)} \end{figure} -In Fig.~\ref{fig:multimode}, we show the results of running this example +In Fig.~\ref{fig:multimode} we show the results of running this example for the case with sterile neutrino. \subsection{Read and Write \textnormal{({\ttf examples/HDF5\_Write\_Read})}} \label{sec:readwrite} -In this example, we illustrate the use of the functions to +In this example we illustrate the use of the functions to read and write {\ttf HDF5} files. The file contains the full -information of the system: all settings, body, track (including the -current position along the track), and the density matrix at each node. -This serialization allows saving the system -in the middle of a complex propagation, and reading it later to continue -the calculation. Saving the system and then loading it from -the file restores the system to the saved state, allowing the user to -compute any quantum-mechanical observable. - -This example is based upon the multiple energy example, but -split into two parts. The first part computes the evolution and saves the +information of the system: all settings, body, track (including +current position in the track), and the density matrix at each node. +This serialization allows to save the system +in the middle of a complex propagation and read it later to continue +the calculation. Saving the system using this and loading it from +the file restores the system to the saved state allowing the user to +compute any quantum mechanical observable. + +This example is based upon the multiple energy example but +split in two parts. The first part computes the evolution and saves the state of the system ({\ttf write.cpp}). The second reads the -state, extracts the flavor fluxes, and prints them to a file ({\ttf read.cpp}). +state, extract the flavor fluxes, and prints them to a file ({\ttf + read.cpp}). -In the following, we describe lines that are relevant for reading and writing. +In the following we describe lines that are relevant for reading and writing. -In the file {\ttf write.cpp}, we save the system before and after the -evolution: +In the file {\ttf write.cpp} we save the system before and after the +evolution. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1] - nus.WriteStateHDF5("./initial_state.hdf5"); + nus.WriteStateHDF5(``./initial_state.hdf5''); nus.EvolveState(); - nus.WriteStateHDF5("./final_state.hdf5"); + nus.WriteStateHDF5(``./final_state.hdf5''); \end{lstlisting} -In order to recover that state in {\ttf read.cpp}, we use the -constructor that takes the name of the file as an argument: +And in order to recover that in the {\ttf read.cpp} file we use the +constructor that takes as an argument the name of the file. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1] - nuSQUIDS inus("./initial_state.hdf5"); - nuSQUIDS fnus("./final_state.hdf5"); + nuSQUIDS inus(``./initial_state.hdf5''); + nuSQUIDS fnus(``./final_state.hdf5''); \end{lstlisting} \subsection{Construction and use of bodies \textnormal{({\ttf examples/Bodies})}} \label{sec:body} -Two of the main classes in the {\ttf nuSQuIDS} library are the body and the -track. -These properties of the {\ttf nuSQuIDS} object itself do not have defaults, and always need to +One of the main classes in the nuSQUIDS library are the body and the +track. These two do not have defaults in the code and always need to be specified. -In this example, we show how to use the objects already implemented in -the library, and also how to create derived types from the classes +In this example we show how to use the objects already implemented in +the library and also how to create some objects from the classes already defined. -The folder {\ttf examples/Bodies/} contains new body and track definitions -in the files {\ttf exBody.h} and {\ttf exBody.cpp}. -It also contains the file {\ttf main.cpp}, whose main function +The folder {\ttf examples/Bodies/} contains a new body and track +definitions in the files {\ttf exBody.h} and {\ttf exBody.cpp}. +It also contains the file {\ttf main.cpp} whose main function uses all the pre-existing objects in nuSQUIDS and the new objects of these examples. \subsubsection{Construct a derived body} -Here is an example of how to define a derived class from the EarthAtm +Here is an example of how to define a derived object of the EarthAtm body. In this simple case the object is just an Earth model with some parameters that weight the relative densities in the different layers of the Earth's inner core, outer core, and mantle. -% TODO: Is this actually a good idea? Seems like a recipe for user code to be unnecessarily broken if we add things -The new classes may be placed inside the {\ttf nusquids} +In order to implement it we suggest to do it inside the {\ttf nusquids} namespace. We define a new class called {\ttf EarthMod}, which is a derived class of {\ttf - EarthAtm}. Because of this, the new class will have all the properties, + EarthAtm}. Because of this the new class will have all the properties, values, and functions of the parent class. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1] namespace nusquids{ @@ -1536,16 +828,17 @@ \subsubsection{Construct a derived body} public: \end{lstlisting} -Our object's constructors require the following inputs: -base Earth model file name ({\ttf earthmodel}), inner core weight -({\ttf frho1}), outer core weight ({\ttf frho2}), and mantle weight ({\ttf +Our object constructors require the following inputs: +based Earth model file name ({\ttf earthmodel}), inner core weight +({\ttf frho1}), outer core weight ({\ttf frho2}), mantle weight ({\ttf frho3}). \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] - EarthMod(std::string earthmodel, double frho1, double frho2, double frho3); + EarthMod(std::string earthmodel, double frho1, double frho2, double + frho3); \end{lstlisting} -The {\ttf Mod} function allows changing the parameters once the -object is already initialized. +The function {\ttf Mod} allows to change the parameters once the +object is already defined. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] void Mod(double frho1, double frho2, double frho3); @@ -1553,18 +846,20 @@ \subsubsection{Construct a derived body} \end{lstlisting} -The implementations of the functions that set the density arrays with -the modified values are given in the file {\ttf exBody.cpp}. +The implementation of the functions that set the density arrays with +the modified values are given in the files {\ttf exBody.cpp}. \subsubsection{Use of the bodies} -The {\ttf main.cpp} file defines a nuSQUIDS object and sets different bodies and -tracks. For each of these, it evolves the system and displays the resulting oscillation -probabilities. +In this part we will describe what is implemented in {\ttf + main.cpp}. +This file defines a nuSQUIDS object and sets different bodies and +tracks. For each of these it evolves the system and shows the +probabilities on the screen. For simplicity we use the single energy mode Sec.~\ref{sec:single}, but the use of the body and track would be the same for the multiple energy case. -First, we construct the nuSQUIDS object for three neutrinos, then we set the +First we construct the nuSQUIDS object for three neutrinos, then we set the oscillation parameters and the neutrino energy. \begin{lstlisting}[frame=leftline, numbers = @@ -1583,29 +878,30 @@ \subsubsection{Use of the bodies} \begin{enumerate} \item {\ttf Earth} -The first example is the {\ttf Earth} body. In this case, the track is -parametrized by the chord length through the Earth, which is useful for treating the baseline of an experiment with a fixed source and detector. -Here we define the body and track. For the track we need to specify the initial and final -position as well as the baseline: +The first example is the {\ttf Earth} body. In this case the track is +parametrized by the baseline of the experiment. Here we define the +body and track. For the track we need to specify the initial and final +position as well as the baseline. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] double baseline = 500.0*units.km; std::shared_ptr earth = std::make_shared(); std::shared_ptr earth_track = std::make_shared(0.0,baseline,baseline); \end{lstlisting} -We apply the Body and Track to the nuSQuIDS object: +And we set the Body and Track to the nuSQuIDS object. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] nus.Set_Body(earth); nus.Set_Track(earth_track); \end{lstlisting} -We then set the initial state of the system and print it: +We first set the initial state of the system and print the state on +the screen. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] marray ini_state({3},{0,1,0}); nus.Set_initial_state(ini_state,flavor); - + // Lets print out the initial state std::cout << "In state" << std::endl; for (double EE : nus.GetERange()){ std::cout << EE/units.GeV << " "; @@ -1615,7 +911,7 @@ \subsubsection{Use of the bodies} std::cout << std::endl; } \end{lstlisting} -We set the numerical error and maximum step for the GSL integrator: +We set the numerical error and maximum step for the GSL integrator. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] nus.Set_h_max( 200.0*units.km ); @@ -1623,7 +919,8 @@ \subsubsection{Use of the bodies} nus.Set_abs_error(1.0e-12); \end{lstlisting} -Finally, we evolve the state and print it: +Finally we evolve the state and print on the screen the final state of +the system. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] nus.EvolveState(); @@ -1636,19 +933,18 @@ \subsubsection{Use of the bodies} std::cout << std::endl; } \end{lstlisting} -These last steps in the code are the same in all the bodies examples and so are omitted for the following cases. +These last steps in the code are the same in all the bodies examples and we +are omitting this for the next cases. \item {\ttf EarthAtm} -In this example we use the {\ttf EarthAtm} body. -This body includes both the Earth and its atmosphere. -The track is defined by the zenith angle of the trajectory, and begins at the top of the atmosphere. -Because the track depends on the height of the atmosphere being treated, it is most conveniently constructed from the body, using the {\ttf MakeTrack} function, which takes a zenith angle and creates a track with the necessary details of the body automatically included. +In this example we use the {\ttf EarthAtm} body. The +track is defined by the zenith angle of the trajectory. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] double phi = acos(-1.0); - auto earth_atm = std::make_shared(); - auto earth_atm_track = std::make_shared(earth_atm->MakeTrack(phi)); + std::shared_ptr earth_atm = std::make_shared(); + std::shared_ptr earth_atm_track = std::make_shared(phi); nus.Set_Body(earth_atm); nus.Set_Track(earth_atm_track); @@ -1656,10 +952,10 @@ \subsubsection{Use of the bodies} \item {\ttf earth\_mod} - In this case, we use the modified Earth object. - As for the {\ttf EarthAtm} object, the track is defined by the zenith angle of + In this case we use the modified Earth object. + As before the track is defined by the zenith angle of the trajectory. In the constructor we set all the weights to $0.1$. - Finally, we set the body and track for the {\ttf nuSQUIDS} object. + Finally we set the body and track to nuSQUIDS. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] @@ -1674,8 +970,8 @@ \subsubsection{Use of the bodies} \item {\ttf VariableDensity} -In this case, we use the variable density body and a track of $200{\rm km}$. -First, we define the density, position, and electron fraction arrays +In this case we use the variable density body and a track of $200{\rm km}$ +First we define the density, position, and electron fraction arrays with the corresponding values. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] @@ -1695,7 +991,7 @@ \subsubsection{Use of the bodies} Now we construct the body and the track. The constructor for the variable density takes as an input the position, density, and electron -fraction vectors. Finally, like before, we set the body and the track on the {\ttf nuSQUIDS} object. +fraction vectors. Finally, like before, we set the body and the track in nuSQUIDS. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] @@ -1710,7 +1006,7 @@ \subsubsection{Use of the bodies} This is a trivial case where the density and electron fraction are zero. We only need to give the baseline as an argument to construct -the track. In this example, we set the baseline to $500{\rm km}$. +the track. In this example we set the baseline to $500{\rm km}$. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] @@ -1726,7 +1022,7 @@ \subsubsection{Use of the bodies} In the case of constant density an analytic approximation can be used to propagate the neutrinos if non-coherent interactions are -disabled in the construction of the {\ttf nuSQUIDS} object. The full +disabled in the construction of the nuSQuIDS object. The full Hamiltonian of the system is diagonalized and exponentiated. We set the density to $100{\rm g/cm}^3$, the electron fraction to $0.3$, and the @@ -1748,30 +1044,30 @@ \subsubsection{Use of the bodies} \subsection{Cross Sections \textnormal{({\ttf examples/Xsections})}} -One of the important features of {\ttf nuSQuIDS} is the possibility of consistently handling non-coherent interactions and oscillation +One of the important features of nuSQuIDS is the possibility of handling in a +consistent way the non-coherent interactions with the oscillation behavior. The physical quantity that encodes how often these scattering interactions happen between the neutrinos and the media is the cross section. -{\ttf nuSQuIDS} has implemented two kinds of deep inelastic scattering (DIS) interactions: charged- and -neutral-current, as well as resonant $W^-$ production on electrons (the Glashow resonance). It takes into account +nuSQuIDS has implemented two kind of interactions: charge and +neutral current. In the case of charge current we have taken into account the neutrinos produced by the decay of short lived charged particles -such as $\tau^\pm$ and $W^\pm$. For the neutral-current, we always include +such as $\tau$ and $W^\pm$. For the neutral current we always include the outgoing neutrino. -Other particles produced in the interactions, such as hadrons or long-lived -charged leptons, are ignored along the evolution. +Other particles produced in the interactions such as hadrons or long-lived +charged leptons are ignored along the evolution. This information is organized and stored in the cross-section class. -This class requires the user to provide the total cross-section for -each flavor and current in units of cm$^2$. It also requires -the singly-differential neutrino cross-sections with respect to +This class requires the user to provide the total cross section for +each flavor and current in units of cm$^2$. It also requires to +specify the single differential neutrino cross sections with respect to the outgoing neutrino energy in units of cm$^2$/GeV. -See ~\ref{sec:neutrino_cross_section_from_tables} for more details of how this data must be specified. -{\ttf nuSQuIDS} includes by default deep inelastic neutrino-nucleon -cross-sections as well as neutrino-electron -cross-sections~\citep{Gandhi:1998ri, CooperSarkar:2011pa}. +nuSQuIDS includes by default deep inelastic neutrino-nucleon +cross sections as well as neutrino-electron +cross sections~\citep{Gandhi:1998ri, CooperSarkar:2011pa}. In this example, we construct a new cross section object to be used by -{\ttf nuSQuIDS} instead of the default one. +nuSQuIDS instead of the default one. Every cross section must be a class of {\ttf NeutrinoCrossSections} and implement at least two member functions: {\ttf SingleDifferentialCrossSection} and {\ttf TotalCrossSection}. @@ -1797,22 +1093,19 @@ \subsection{Cross Sections \textnormal{({\ttf We use a toy total cross section that scales linearly with the neutrino energy and the corresponding differential cross sections linear in the outgoing neutrino energy; see implementation in {\ttf - exCross.cpp}. We also allow changing the proportion of charge-to-neutral + exCross.cpp}. We also allow to change the proportion of charge-to-neutral current at the construction of the object. -We construct two cross section libraries with the new cross section -associated with an isoscalar nucleon target: one with only charged-current interactions -{\ttf ncs\_cc} and another with only neutral-current {\ttf - ncs\_nc}. Then we construct the corresponding {\ttf nuSQUIDS} objects {\ttf nus\_cc} and {\ttf nus\_nc}. +We construct two cross section objects: one with only charge current interactions +{\ttf ncs\_cc} and another with only neutral current {\ttf + ncs\_nc}. Then we construct the corresponding nuSQuIDS objects {\ttf nus\_cc} and {\ttf nus\_nc}. We also disable neutrino oscillations in this example by means of the option {\ttf Set\_IncludeOscillations(false)}. \begin{lstlisting}[frame=leftline, numbers = - left,breaklines=true,label = ex:sin1] - auto ncs_cc=std::make_shared(CrossSectionLibrary::MapType{ - {isoscalar_nucleon, std::make_shared(0.0)}}); - auto ncs_nc=std::make_shared(CrossSectionLibrary::MapType{ - {isoscalar_nucleon, std::make_shared(1.0)}}); + left,breaklines=true,label = ex:sin1] + std::shared_ptr ncs_cc=std::make_shared(0.0); + std::shared_ptr ncs_nc=std::make_shared(1.0); nuSQUIDS nus_cc(logspace(Emin,Emax,200),numneu,neutrino,true,ncs_cc); nus_cc.Set_IncludeOscillations(false); @@ -1827,8 +1120,8 @@ \subsection{Cross Sections \textnormal{({\ttf \centering \includegraphics[width=0.7\textwidth]{fig/crossext.eps} \caption{Final to initial flux ratio as a function of the logarithm - of the neutrino energy for the example toy cross-sections with - only charged-current (CC) and only neutral-current (NC) interactions.} + of the neutrino energy for the example toy cross sections with + only charged current and only neutral current.} \end{figure} \subsection{Constant density multiple layers \textnormal{({\ttf @@ -1883,16 +1176,16 @@ \subsection{BSM extension: Non-Standard Interaction (NSI) \textnormal{({\ttf examples/NSI})}} \label{sec:NSI} In this example we illustrate how to construct a derived class of -{\ttf nuSQUIDS} including a new physics term. This procedure is similar to +nuSQuIDS including a new physics term. This procedure is similar to other new physics setups~\ref{sec:LV}. The implementation of {\ttf nuSQUIDSNSI} class is in {\ttf NSI.h}. -We will go through the implementation to see what needs to be +We will go trough the implementation to see what needs to be added to the base class. First, we declare the NSI matter potential as a {\ttf SU\_vector} -called {\ttf NSI}. By default {\ttf nuSQuIDS} works in the interaction -picture, thus every term we add to the Hamiltonian has to be properly +called {\ttf NSI}. By default nuSQuIDS works in the interaction +picture, thus every term we add to the hamiltonian has to be properly evolved with $H_0$. Since $H_0$ depends on the energy we do this in every node. For optimization we will compute and store the evolved NSI term in a vector of {\ttf SU\_vector} objects called {\ttf NSI\_evol}. @@ -1915,7 +1208,7 @@ \subsection{BSM extension: Non-Standard Interaction (NSI) \textnormal{({\ttf \end{lstlisting} -As previously noted, we need to compute the NSI operator in the +As we said before we need to compute the NSI operator in the interaction picture prior to adding it to the r.h.s. of the differential equation. We compute this for every energy node in the {\ttf AddToPreDerive} function. This function is called inside the @@ -1936,7 +1229,7 @@ \subsection{BSM extension: Non-Standard Interaction (NSI) \textnormal{({\ttf The following auxiliary member functions allow {\ttf nuSQUIDSNSI} to save the new physics parameters into the hdf5 files when the -{\ttf WriteStateHDF5} is called (See Sec.~\ref{sec:readwrite} for an overview of reading and writing). +{\ttf WriteStateHDF5} is called~\ref{sec:readwrite}. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] @@ -1954,13 +1247,13 @@ \subsection{BSM extension: Non-Standard Interaction (NSI) \textnormal{({\ttf } \end{lstlisting} -Here we overload the {\ttf HI} function where we return the original {\ttf nuSQUIDS} +Here we overload the {\ttf HI} function where we return the nuSQuIDS matter potential plus the new NSI contribution. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] squids::SU_vector HI(unsigned int ei,unsigned int index_rho) const{ - double CC=HI_prefactor*body->density(*track)*body->ye(*track); + double CC = HI_prefactor*body->density(*track)*body->ye(*track); squids::SU_vector potential(nsun,hiBuffer.get()); @@ -1977,8 +1270,8 @@ \subsection{BSM extension: Non-Standard Interaction (NSI) \textnormal{({\ttf \end{lstlisting} The constructor first calls the -{\ttf nuSQUIDS} constructor and then sets the oscillation -parameters and the NSI operator. +nuSQUIDS constructor and then sets the oscillation +paramters and the NSI operator. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] @@ -2019,7 +1312,7 @@ \subsection{BSM extension: Non-Standard Interaction (NSI) \textnormal{({\ttf The next function sets the value of {\ttf epsilon\_mutau} changing the {\ttf SU\_vector NSI} object accordingly. We construct the {\ttf SU\_vector} operator as a complex GSL matrix that represents the - operator in the flavor basis. Since {\ttf nuSQuIDS} solves the propagation + operator in the flavor basis. Since nuSQuIDS solves the propagation in the basis where $H_0$ is diagonal, i.e. the mass basis, we rotate the NSI operator to the mass basis by calling {\ttf RotateToB1}. @@ -2036,9 +1329,9 @@ \subsection{BSM extension: Non-Standard Interaction (NSI) \textnormal{({\ttf } \end{lstlisting} -In {\ttf main.cpp} we use the new NSI class in a +In {\ttf main.cpp} we use the new NSI in a multiple energy mode. In order to compare the oscillation -probabilities with and without NSI we construct two instances of {\ttf +probabilities with and without NSI we construct two instances {\ttf nuSQUIDSNSI} with {\ttf epsilon\_mutau=0} and {\ttf epsilon\_mutau=1e-2}. @@ -2050,7 +1343,7 @@ \subsection{BSM extension: Non-Standard Interaction (NSI) \textnormal{({\ttf \end{lstlisting} In the next lines we propagate both objects and print both -fluxes to a file. +fluxes in a file. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] @@ -2074,7 +1367,7 @@ \subsection{BSM extension: Non-Standard Interaction (NSI) \textnormal{({\ttf } \end{lstlisting} -In the folder there is a script that allows plotting the output text +In the folder there is a script that allows to plot the output text file. @@ -2082,17 +1375,16 @@ \subsection{BSM extension: Lorentz Violation \textnormal{({\ttf examples/LV})}} \label{sec:LV} The Lorentz symmetry is a well established property of space-time. -As a fundamental symmetry, it should be tested and neutrino +As a fundamental symmetry it should be tested and neutrino oscillations probe part of the parameter space. The example is technically the same as the non-standard interactions, but we add a couple of features to illustrate good practices. -As before, the new term is added in to {\ttf HI}. For this particular +As before the new term is added in to {\ttf HI}. For this particular physics case the effect is positive for neutrinos and negative for antineutrinos. This can be implemented using the integer {\ttf irho} -which labels neutrinos with $0$ and antineutrinos with $1$ when both particle types are being calculated. -Which particle types are under consideration is given by the {\ttf NT} member variable. +which labels neutrinos with $0$ and antineutrinos with $1$. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] @@ -2110,15 +1402,15 @@ \subsection{BSM extension: Lorentz Violation \textnormal{({\ttf } \end{lstlisting} -The parameters of the Lorentz violating term are set by the function -{\ttf Set\_LV\_OpMatrix}. In doing that, the oscillation parameters are -used to rotate to the mass basis. Therefore, any change to the +The parameters of the Lorentz violating term is set by the function +{\ttf Set\_LV\_OpMatrix}. In doing that the oscillation parameters are +used to rotate to the mass basis. Therefore any change done in the oscillation parameters after setting the LV term will be inconsistent. -In order to prevent inconsistencies, we overload the function that sets +In order to prevent inconsistencies we overload the function that sets the mixing parameters {\ttf Set\_MixingAngle} and the phases {\ttf Set\_CPPhase} turning the label {\ttf lv\_parameters\_set} to {\ttf false} and forcing the need to call {\ttf Set\_LV\_OpMatrix} again. -This enforces the order of the `Set' function calls. +This enforces the order of the set functions calls. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] @@ -2137,11 +1429,11 @@ \subsection{Decoherence or averaged oscillations\\ \textnormal{({\ttf examples/Astrophysical\_neutrino\_flavor\_ratio})}} This file demonstrates how to calculate the astrophysical flavor ratio by means -of using the `averaged out' approximation. We do this in two ways in this -example: first by means of nuSQuIDS fast averaging functionality, -and second explicitly using the PMNS matrix and the formula given in the literature. -For simplicity, we will do this example in the single energy mode, but it -can be performed in the multiple energy mode, as well. +of using the averaged out approximation. We do this in two ways in this +example: first explicitly using the PMNS matrix and the formula given +in the literature and second by means of nuSQuIDS fast averaging functionality. +For simplicity we will do this example in the single energy mode, but it +can be performed in the multiple energy mode too. In this example we set {\ttf N\_neutrino = 3} and {\ttf Type = "neutrino"}. @@ -2165,7 +1457,7 @@ \subsection{Decoherence or averaged oscillations\\ \textnormal{({\ttf nus.Set_CPPhase(0,2,0.0); \end{lstlisting} -We construct and set the body and the track; in this case we use vacuum +We construct and set the body and the track, in this case we use vacuum oscillations. \begin{lstlisting}[frame=leftline, numbers = @@ -2176,7 +1468,7 @@ \subsection{Decoherence or averaged oscillations\\ \textnormal{({\ttf nus.Set_Track(vacuum_track); \end{lstlisting} -Here we set the initial state for the flavor, a pion-produced flavor composition: +Here we set the initial state for the flavor, a pion-produced flavor composition \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1] @@ -2184,14 +1476,14 @@ \subsection{Decoherence or averaged oscillations\\ \textnormal{({\ttf nus.Set_initial_state(ini_state,flavor); \end{lstlisting} -We evolve the neutrinos: +We evolve the neutrinos. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1] nus.EvolveState(); \end{lstlisting} -{\ttf nuSQuIDS} can calculate the average oscillation probability +nuSQuIDS can calculate the average oscillation probability where the oscillation frequencies are larger than some value; we call this value {\ttf scale}. When this mode is used it is often valuable to know which frequencies have been averaged out. @@ -2246,18 +1538,18 @@ \subsection{Decoherence or averaged oscillations\\ \textnormal{({\ttf averaged out. -\subsection{Atmospheric mode: Standard \textnormal{({\ttf +\subsection{Atmospheric Mode: Standard \textnormal{({\ttf examples/Atm\_default})}} \label{sec:atmexample} In this example we show how to use the atmospheric mode. This mode is -a compact way to treat a set of {\ttf nuSQUIDS} objects distributed in -zenith angle. +a compact way to treat a set of nuSQUIDS objects distributed in +zenith. This allows us to propagate the energy-zenith dependent atmospheric neutrino flux through the Earth. -First, we construct the {\ttf nuSQUIDSAtm} object. The parameters of the +First, we construct the nuSQUIDSAtm object. The parameters of the constructors are the list of cosine of the zenith angle values ({\ttf - linspace(czmin,czmax,40)}) and the following arguments as for the {\ttf nuSQUIDS} + linspace(czmin,czmax,40)}) and the following arguments as the multiple energy constructor. \begin{lstlisting}[frame=leftline, numbers = @@ -2270,14 +1562,14 @@ \subsection{Atmospheric mode: Standard \textnormal{({\ttf nuSQUIDSAtm<> nus_atm(linspace(czmin,czmax,40),logspace(Emin,Emax,100),numneu,both,interactions); \end{lstlisting} -In this case the initial state is an {\ttf marray} of rank four with double values. -The first index is for the zenith angle, the second for the energy, the +In this case the initial state is marray of rank four with double values. +The first index is for the zenith, the second for the energy, the third for particle type (neutrino or antineutrino), and the last one for the neutrino flavor. In this example we fill the multi-dimensional array with the initial state of the system where the function {\ttf flux\_function} would be the corresponding -atmospheric flux in terms of energy and zenith angle. +atmospheric flux. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] @@ -2295,7 +1587,7 @@ \subsection{Atmospheric mode: Standard \textnormal{({\ttf nus_atm.Set_initial_state(inistate,flavor); \end{lstlisting} -To evolve the full state we call {\ttf EvolveState}, as usual. +To evolve the full state we call as always {\ttf EvolveState}. \begin{lstlisting}[frame=leftline, numbers = left,breaklines=true,label = ex:sin1,firstnumber=last] @@ -2303,8 +1595,8 @@ \subsection{Atmospheric mode: Standard \textnormal{({\ttf \end{lstlisting} Finally, we evaluate and print the flux in a file. The -atmospheric mode has an interpolation implemented that allows -evaluating the flux at any flavor, energy, and cosine-zenith. See~\ref{sec:nusquidsatm} +atmospheric mode has an interpolation implemented that allows to +evaluate the flux at any flavor, energy, and cosine-zenith. See~\ref{sec:nusquidsatm} for more details. \begin{lstlisting}[frame=leftline, numbers = @@ -2332,13 +1624,13 @@ \subsection{Atmospheric mode: Standard \textnormal{({\ttf \subsection{Atmospheric mode: BSM \textnormal{({\ttf examples/Atm\_BSM})}} \label{sec:atmBSM} The atmospheric mode is implemented such that it can be used with any -{\ttf nuSQUIDS} derived class. In this example, we use the atmospheric mode -with the NSI {\ttf nuSQUIDS} extension shown in the NSI example~\ref{sec:NSI}. +nuSQUIDS derived class. In this example we use the atmospheric mode +with the NSI nuSQUIDS extension shown in the NSI example~\ref{sec:NSI}. In the folder we include a copy of the NSI header file {\ttf NSI.h}. The main file is essentially the same as the atmospheric default mode example with the following changes. -The class type template argument is the {\ttf nuSQUIDS} derived class. The +The class type template argument is the nuSQuIDS derived class. The constructor takes a list of cosine zenith angle values and then the derived class constructor arguments. @@ -2348,95 +1640,140 @@ \subsection{Atmospheric mode: BSM \textnormal{({\ttf examples/Atm\_BSM})}} nuSQUIDSAtm nus_atm(linspace(czmin,czmax,40),epsilon_mutau,logspace(Emin,Emax,100),numneu,both,true); \end{lstlisting} -\subsection{Extended neutrino sources \textnormal{({\ttf - examples/Extended\_Source})}} -\label{sec:extended_source} +\section{Performance and precision} +\label{sec:performance} -Some neutrino evolution problems cannot be formulated as an starting flux -of neutrinos, as shown in the preceding examples. -For example, in the case of solar neutrinos the emission of neutrinos happens -over an extended region of the Sun; the same is true for atmospheric neutrinos -which are produced predominantly 20~km above the Earth surface, but which have varying production -height of tens of kilometers. -{\ttf nuSQuIDS} provides a way to handle these scenarios, which we will illustrate in this example. +Machine 1 is configured with an Intel 6700K CPU, with a `base' frequency of 4.0 GHz. All tests were performed with the `Turbo Boost' feature disabled. -A source term is added to the {\ttf nuSQuIDS} kinetic equations Eq.~\eqref{eq:kinetic_equations}, -which allows adding (or subtracting) neutrinos from the ensemble. -This term depends on the location of the ensemble in the traversed body. -For this reason it is in the body class where the user needs to implement this term, as it is -a property of the object being traversed rather than the ensemble. +The time evolution and basis transformations performed by SQuIDS on SU\_vector objects rely heavily on trigonometric functions, specifically sines and cosines, mostly in matched pairs. These operations are in turn used by several of the key portions of nuSQuIDS, and for oscillation-only calculations evaluation of trigonometric functions can be the single largest part of time consumed by the library. As a result, run time is strongly dependent on the performance of the underlying math library, which is usually supplied by the operating system, and sometimes the compiler. +The differences are illustrated in Table~\ref{tab:trig_perf}, which shows measurements performed on Machine 1 with several combinations of operating system and compiler of the cost of computing a single sine function or the combination of sine and cosine for the same argument (which should ideally be performed by an efficient, fused calculation). A measurement was also made of the time to run the pseudo-random number generator (PRNG) by itself. The time spent for the PRNG varies somewhat, assumedly due to different optimization choices by the various compilers, but amounts to a small fraction of the time for the trigonometric calculation. Broadly, it is apparent that the calculations using the math implementations from the GNU C library (glibc) are significantly slower than the versions using other math libraries. Furthermore, the glibc calculations appear to benefit only slightly from the opportunity to fuse sine and cosine calculations; while they are not as slow as might be expected from a simple doubling of the time to compute a single sine they are also not much better. +This is in contrast to the other implementations which are able to compute both functions in essentially the same time as a single function (or with relatively low overhead, in the case of BSD libc). In addition to this overhead, the glibc time to compute a single trigonometric function is approximately twice that of the other libraries (it is unclear why the result is far worse for clang 5.0.1 on CentOS 7, but this was deemed to have little practical relevance to this work and was not further investigated). Unfortunately, the conclusion is that the choice of compiler can be extremely important to maximizing the performance of nuSQuIDs. The benchmarks shown in this section will use the Intel compiler, version 18.0.3 on Cent OS 7, unless otherwise noted. -In this example, we will start with an empty neutrino ensemble that traverses a neutrino-emitting -vacuum. We define the following \texttt{EmittingVacuum} class that inherits from \texttt{Vacuum}: +\begin{table*} + \begin{tabular}{ llcccl } + OS & Compiler & PRNG & Sine & Sine \& Cosine & Math Library \\ + CentOS 7 & gcc 4.8.5 & 6.0 ns & 40.5 ns & 63.5 ns & GNU C Library 2.17 \\ + CentOS 7 & gcc 7.3.1 & 2.7 ns & 37.1 ns & 63.3 ns & GNU C Library 2.17 \\ + CentOS 7 & clang 5.0.1 & 4.8 ns & 96.4 ns & 69.0 ns & GNU C Library 2.17 \\ + CentOS 7 & icc 18.0.3 & 4.0 ns & 20.9 ns & 22.2 ns & libimf 2018.3.222\\ + Darwin 16.7.0 & clang 5.0.0 & 2.9 ns & 19.1 ns & 20.1 ns & libsystem\_m 3121.6.0 \\ + FreeBSD 11.2 & clang 6.0.1 & 2.9 ns & 22.3 ns & 30.8 ns & BSD libc + \end{tabular} + \caption{ + Measured time to compute trigonometric functions using different compilers and operating systems. In each case the same stream of $10^8$ pseudo-random arguments in the domain [-100,100] was used, and the average time per call was computed, including the time necessary for the PRNG to compute the next argument value. + } + \label{tab:trig_perf} +\end{table*} -\begin{lstlisting}[frame=leftline, numbers = - left,breaklines=true,label = ex:sin1,firstnumber=last] - double epsilon_mutau=1e-2; -class EmittingVacuum: public Vacuum { - private: - const unsigned int flavor; - const double decay_length; - public : - EmittingVacuum(unsigned int flavor, double decay_length): - flavor(flavor),decay_length(decay_length){} - void injected_neutrino_flux(marray& flux, const GenericTrack& track, const nuSQUIDS& nusquids) override { - double x_cur = track.GetX(); - for(unsigned int ei=0; ei& flux, const GenericTrack& track, const nuSQUIDS& nusquids) override -\end{lstlisting} -This function is given a container, \texttt{flux}, which has three indexes that correspond to the energy index, neutrino or antineutrino index, and flavor index. -Additionally, it is given constant references to the track being traversed and the nuSQUIDS object that is making the query of the body. -The implementation can use the track information to find the current position in the ensemble evolution and can use the nuSQUIDS object -to obtain additional information that may be needed to fill in the container. -A common need is to check the physical energies corresponding to the flavor indices, which can be obtained by calling the {\ttf GetERange} member function of the {\ttf nuSQUIDS} object. -It is important to note that the type of track that is passed by nuSQUIDS to the body object member function is a \texttt{GenericTrack}, which is necessaryto give this function a common signature for all the body types. If needed, the implementation of the member function can cast this to the specific track type for the body class. -Finally, we have added at the end of the signature above the optional keyword \texttt{override}, which ensures that this member function is overriding the correct signature used -internally by {\ttf nuSQuIDS}. This keyword will trigger a compile-time error, if the user accidentally declares a new member function and thus guarantees that the correct member function -is been overridden. - -Once your body has been constructed and passed to the {\ttf nuSQUIDS} object by means of the usual \texttt{Set\_Body} and \texttt{Set\_Track} member functions, it is also necessary to also indicate that continuous neutrino injection into the ensemble should be considered in the calculation. -This is not enabled by default, in order to avoid additional calls to virtual member functions that just add zero to the differential equation. -In order to enable this one needs to set -\begin{lstlisting}[frame=leftline, numbers = - left,breaklines=true,label = ex:sin1,firstnumber=last] - nus.Set_NeutrinoSources(true); -\end{lstlisting} -where \texttt{nus} is the {\ttf nuSQUIDS} object that we have created. -The result of running this code can be seen in Fig.~\ref{fig:extended_sources}, where the starting conditions are an empty -ensemble, and the injection is a muon-neutrino only source. The tau and electron contributions that appear are from oscillations. +\item {\ttf test/constant\_density\_osc\_prob.test} + + Tests that propagation with only oscillation of + neutrinos in constant density is equal to the analytic solution. -\begin{figure}[h!] - \centering - \includegraphics[width=0.6\textwidth]{fig/extended_sources.eps} - \caption{Final flux obtained from the extended source emission as a function of the neutrino energy.} - \label{fig:extended_sources} -\end{figure} +\item {\ttf test/constant\_opacity.test} + + Tests that propagation on a constant density with no oscillation and + neglecting regeneration from neutral current or tau decay matches + the expected exponential behavior. + +\item {\ttf test/constant\_opacity\_with\_nc.test} + + Tests that propagation on a constant density with no oscillation + matches an independent numerical solution. + +\item {\ttf test/atmospheric\_he.test} + + Tests that the high-energy propagation without oscillation of + neutrinos from the atmosphere does not give negative or {\ttf nan} values. + +\item {\ttf test/atmospheric\_osc.test} + + Tests that propagation with only oscillation of + neutrinos from the atmosphere does not give negative or {\ttf nan} + values. + +\item {\ttf test/body\_serialization.test} + + It checks that writing a body in to the hdf5 file and reading it + back does not alter the body. + +\item {\ttf test/cross\_section\_consistency.test} + + Checks that the differential cross section adds, within numerical error, + to the total cross section. + +\item {\ttf test/earth\_osc\_prob.test} + + Test that three and four neutrinos oscillation probability over a + 1000km baseline in multiple and single energy modes matches with the + numerical error to a reference independent calculation. + +\item {\ttf test/glashow\_resonance.test} + + Checks that Glashow resonance integrated differential cross-section + matches with the total cross-section and that is used while propagating. + +\item {\ttf test/hdf5\_atm\_in\_out.test} + + It checks that writing a nuSQuIDs atmospheric object into a hdf5 file and reading it + back does not alter the object and recovers all the properties. + + +\item {\ttf test/hdf5\_in\_out.test} + + It checks that writing a nuSQuIDs object into a hdf5 file and reading it + back does not alter the object and recovers all the properties. + +\item {\ttf test/move\_assig.test} + + Checks that constructor of a nuSQuIDS object from an rvalue nuSQuIDS object works. + +\item {\ttf test/mul\_energy\_constructor.test} + + Checks that the multiple energy constructor works. + +\item {\ttf test/time\_reversal.test} + + Checks that propagating a neutrino and propagating again backwards + in time returns to the original state. + +\item {\ttf test/tools\_integrator.test} + + Checks that the provided one dimensional integrate function works + within the numerical error. + +\item {\ttf test/track\_concatenate\_hdf5.test} + + Checks that propagating by concatenating a series of tracks in + vacuum and writing and reading that state at every step is the same + as propagating with a single track with the total length. + + +\item {\ttf test/track\_concatenate.test} + + Checks that propagating by concatenating a series of tracks in + vacuum is the same as propagating with a single track with the total length. + + +\end{itemize} \section{Description of the code} @@ -2768,7 +2105,7 @@ \subsubsection{Earth \label{sec:earth}} The {\ttf Earth} body specification is designed to propagate neutrinos in the Earth from two points on the surface. Since the Earth in the PREM model is assumed to be spherically symmetric the length of the -path is enough to determine the trajectory. {\ttfamily AkimaSpline} is used to interpolate $\rho$ and $y_e$ as a function of radius to the earth center. +path is enough to determine the trajectory. {\ttfamily AkimaSpline}~\ref{sec:tools} is used to interpolate $\rho$ and $y_e$ as a function of radius to the earth center. \begin{itemize} \item {\ttf Earth} \begin{lstlisting} @@ -2817,48 +2154,34 @@ \subsubsection{Earth \label{sec:earth}} \end{itemize} \subsubsection{EarthAtm\label{sec:earthatm}} -This body includes both the density profile of the Earth and a simple model of its atmosphere. -Paths end at the surface of the Earth, and are expressed in terms of their local zenith angle at the endpoint. -The deafult atmosphere height is 22 km, and a scale height of 7.594 km is used for its density. +This is to be used when the relevant parameter is the zenith angle of +the path. \begin{itemize} \item {\ttf EarthAtm} \begin{lstlisting} - EarthAtm(); + Earth(); \end{lstlisting} Initializes an {\ttf Earth} environment as defined by the PREM~\citep{dziewonski1981preliminary}. \begin{lstlisting} - EarthAtm(std::string earthmodel); + Earth(std::string earthmodel); \end{lstlisting} - Initializes an {\ttf EarthAtm} environment as defined by a table given in the file specified by {\ttf filepath}. The table should have three columns: relative radius (dimensionless, where 0 is the center and 1 the is surface), density (${\rm g}/{\rm cm}^3$), and electron fraction $y_e$ (dimensionless). + Initializes an {\ttf Earth} environment as defined by a table given in the file specified by {\ttf filepath}. The table should have three columns: radius (where 0 is center and 1 is surface), density (${\rm g}/{\rm cm}^3$), and $y_e$ (dimensionless). \begin{lstlisting} - EarthAtm(std::vector x,std::vector rho, + Earth(std::vector x,std::vector rho, std::vector ye); \end{lstlisting} - Initialize an {\ttf EarthAtm} whose radial density is specified by the + Initialize an {\ttf earth} whose radial density is specified by the values in the vector {\ttf rho} in ${\rm g}/{\rm cm}^3$, the - electron fraction in the vector {\ttf ye}, and the relative radial positions - in the vector {\ttf x}. - \begin{lstlisting} - void SetAtmosphereHeight(double height); - \end{lstlisting} - Change the height of the top of the atmosphere. - \begin{lstlisting} - EarthAtm::Track MakeTrack(double phi); - \end{lstlisting} - Create a track which arrives at the surface with the given zenith angle and an initial position at the top of the atmosphere. - \begin{lstlisting} - EarthAtm::Track MakeTrackWithCosine(double cosphi); - \end{lstlisting} - The same as {\ttf MakeTrack}, but takes the cosine of the zenith angle, which is a more convenient variable in many contexts. + electron fraction in the vector {\ttf ye}, and the radial positions + in the vector {\ttf x} in centimeters. \item {\ttf EarthAtm::Track} \begin{lstlisting} - Track(double x, double phi, - double earth_radius, double atmheight); - Track(double phi, double earth_radius, double atmheight); + Track(double x_,double phi):Track(phi){x=x_;}; + Track(double phi); \end{lstlisting} Initialize the corresponding {\ttf Track} by specifying the zenith - angle in radians ({\ttf phi}), radius of the Earth ({\ttf earth\_radius}) in eV$^{-1}$, height of the atmosphere ({\ttf atmheight}) in eV$^{-1}$, and the current position along the + angle in radians ({\ttf phi}) and the current position along the track ({\ttf x}) in eV$^{-1}$. \begin{lstlisting} @@ -2867,11 +2190,9 @@ \subsubsection{EarthAtm\label{sec:earthatm}} Returns the baseline in eV$^{-1}$. \begin{lstlisting} - static Track makeWithCosine(double cosphi, - double earth_radius, - double atmheight); + static Track makeWithCosine(double cosphi); \end{lstlisting} - Create a track with the cosine of the zenith angle ({\ttf cosphi}) instead of the angle. + Initialize the track with the cosine of the zenith angle ({\ttf cosphi}) instead. \end{itemize} @@ -3024,50 +2345,17 @@ \subsubsection{NeutrinoCrossSections\label{sec:neutrino_cross_section_class}} Bjorken-x ({\ttf x}), and y ({\ttf y}) should return the double differential cross section. Its implementation is not required to run {\ttf nuSQUIDS} and, by default, when evaluated, unless - overwritten, it will throw an error. - \item Averaged cross sections - \begin{lstlisting} - virtual double AverageTotalCrossSection(double EMin, - double EMax, NeutrinoFlavor flavor, NeutrinoType neutype, - Current current) const; - - virtual double AverageSingleDifferentialCrossSection(double E1, - double E2Min, double E2Max, NeutrinoFlavor flavor, - NeutrinoType neutype, Current current) const; - \end{lstlisting} - Averaged total and single differential cross section in energy - range {\ttf Emin}-{\ttf Emax} and {\ttf E2min}-{\ttf E2max} respectively. + overwritten, it will throw an error. \end{itemize} -\subsubsection{NullCrossSections\label{sec:null_cross_section}} -This class is a simple implementation of the a null cross section. -\begin{lstlisting} - NullCrossSections(){} - - double TotalCrossSection(double Enu, NeutrinoFlavor flavor, - NeutrinoType neutype, Current current) const override { return 0;} - - double SingleDifferentialCrossSection(double E1, double E2, - NeutrinoFlavor flavor, NeutrinoType neutype, Current current) - const override { return 0;} - - double DoubleDifferentialCrossSection(double E, double x, double y, - NeutrinoFlavor flavor, NeutrinoType neutype, Current current) - const override { return 0;} -\end{lstlisting} - - - \subsubsection{NeutrinoDISCrossSectionsFromTables\label{sec:neutrino_cross_section_from_tables}} -This class uses pre-calculated deep inelastic scattering (DIS) cross section tables -which are provided by {\ttf nuSQuIDS} or by the user. -In the code two different cross sections are available by default: -{\ttf csms.h5} is a perturbative QCD next-to-leading order calculation~\cite{CooperSarkar:2011pa} using the HERA -parton distribution functions~\cite{Chekanov:2002pv}, recalculated for proton and neutron targets, -and updated to account for the non-zero mass of the tau, reducing the $\nu_\tau$ -cross sections at low energies compared to the originally published version. -{\ttf nusigma}~\cite{nusigma} is a first order QCD +This class uses precalculated deep inelastic cross section tables +which are provided by {\ttf nuSQuIDS}. +In the code two different cross sections are available: +{\ttf csms.h5} is a perturbative QCD next-to-leading order calculation using the HERA +parton distribution functions~\cite{Chekanov:2002pv} on an iso-scalar +target~\cite{CooperSarkar:2011pa}. {\ttf nusigma}~\cite{nusigma} is a first order QCD calculation using the {\ttf CTEQ6} parton distribution functions on an iso-scalar target. In the {\ttf csms} calculation the mass of the tau is neglected, thus the neutrinos cross section is the same for all @@ -3076,70 +2364,42 @@ \subsubsection{NeutrinoDISCrossSectionsFromTables\label{sec:neutrino_cross_secti neutrino interaction with nucleons above $O({\rm 10~GeV})$. The cross sections are loaded from tables included in -{\ttfamily nuSQUIDS/data/xsections/}, or provided by the user. -The cross section object can be constructed from a single {\ttf HDF5} +{\ttfamily nuSQUIDS/data/xsections/}. +The cross section object can be constructed from a single {\ttf hdf5} file that contains both single and total cross sections or by a set of -twelve text files, containing all cross sections related to a single target species -(e.g. all cross sections for DIS neutrino interactions with protons). - -When an {\ttf HDF5} file is used, it must have an internal structure as shown -in Table~\ref{tab:hdf_cross_layout}. All cross sections must be tabulated with the same set of incident neutrino energies, and each singly-differential cross section must be tabulated for the same set of out-going lepton energies, expressed in the $z$ variable described in Sec.~\ref{sec:differential_tabulation}. -These common energy and $z$ values are stored in the one-dimensional {\ttf energies} and {\ttf zs} datasets. -For the energies, more specifically, the base-10 logarithms of the energies in GeV are stored. -All total cross section tables are one-dimensional datasets containing the base-10 logarithm of the cross section values in cm$^2$, and all singly-differential cross section tables are two-dimensional datasets with dimensions incident and out-going energy containing the base-10 logarithm of the cross section values in cm$^2$. - -When text files are used, they must be organized into three groups, -one for each active neutrino flavor, with a corresponding -filename component ({\ttf electron\_}, {\ttf muon\_}, or {\ttf tau\_}). -The four text files within each flavor set must end with the suffixes -{\ttf nu\_dsde\_CC.dat}, {\ttf nubar\_dsde\_NC.dat}, {\ttf nu\_sigma\_CC.dat}, and -{\ttf nubar\_sigma\_NC.dat} for the singly differential neutrino, singly differential -antineutrino, total neutrino, and total antineutrino cross sections, respectively. -Each total cross section file must contain two columns: -The incident neutrino energy in GeV and the total cross section in cm$^2$. -Each singly-differential cross section file must have three columns: -The incident neutrino energy in GeV, -outgoing neutrino energy encoded via the unitless $z$ variable described in the next section, -and the differential cross section in cm$^2$. - -\begin{figure}[] +four text files. The four text files have to end with the suffixes +{\ttf dsde\_CC.dat}, {\ttf dsde\_NC.dat}, {\ttf sigma\_CC.dat}, and +{\ttf sigma\_NC.dat}. +The text files contain the following columns: +For the total cross-sections neutrino energy in GeV, electron neutrino +cross sections, electron anti-neutrino cross-section, muon neutrino +cross sections, muon anti-neutrino cross-section, tau neutrino +cross sections, and tau anti-neutrino cross-section. All the cross +section values are in cm$^2$. +For the single differential cross-sections incident neutrino energy in +GeV, outgoing neutrino energy in GeV, electron neutrino +differential cross sections, differential electron anti-neutrino cross-section, muon neutrino +differential cross sections, muon anti-neutrino differential cross-section, tau neutrino +differential cross sections, and tau anti-neutrino differential +cross-section. All the differential cross-section values are in cm$^2/$GeV. +For the {\ttf HDF5} cross section format see Table~\ref{tab:cross}. + +\begin{figure}[htb!] + \label{tab:cross} \centering - \begin{tikzpicture}[ + \begin{tikzpicture}[% grow via three points={one child at (0.5,-0.7) and two children at (0.5,-0.7) and (0.5,-1.4)}, edge from parent path={(\tikzparentnode.south) |- (\tikzchildnode.west)}] - \node {{\ttf HDF5 root group}} - child { node [label=right:{Logarithm of incident neutrino energies for tabulated cross sections ($\log_{10}$ GeV)}] {\ttf energies}} - child { node [label=right:{Out-going lepton energies transformed into $z$ for tabulated cross sections}] {\ttf zs}} - child { node [label=right:{Electron flavor group}] {\ttf electron} - child { node [label=right:{Neutrino CC singly-differential cross sections (${\log_{10}\rm cm^2}$).}] {\ttf dsdy\_CC\_nu}} - child { node [label=right:{Antineutrino CC singly-differential cross sections (${\log_{10}\rm cm^2}$).}] {\ttf dsdy\_CC\_nubar}} - child { node [label=right:{Neutrino NC singly-differential cross sections (${\log_{10}\rm cm^2}$).}] {\ttf dsdy\_NC\_nu}} - child { node [label=right:{Antineutrino NC singly-differential cross sections (${\log_{10}\rm cm^2}$).}] {\ttf dsdy\_NC\_nubar}} - child { node [label=right:{Neutrino CC total cross sections (${\log_{10}\rm cm^2}$).}] {\ttf s\_CC\_nu}} - child { node [label=right:{Antineutrino CC total cross sections (${\log_{10}\rm cm^2}$).}] {\ttf s\_CC\_nubar}} - child { node [label=right:{Neutrino NC total cross sections (${\log_{10}\rm cm^2}$).}] {\ttf s\_NC\_nu}} - child { node [label=right:{Antineutrino NC total cross sections (${\log_{10}\rm cm^2}$).}] {\ttf s\_NC\_nubar}} - } - child [missing] {} - child [missing] {} - child [missing] {} - child [missing] {} - child [missing] {} - child [missing] {} - child [missing] {} - child [missing] {} - child { node [label=right:{Muon flavor group}] {\ttf muon} - child { node [label=right:{Analogous datasets to the electron group}] {\ttf .\ .\ .}} - } - child [missing] {} - child { node [label=right:{Tau flavor group}] {\ttf tau} - child { node [label=right:{Analogous datasets to the electron group}] {\ttf .\ .\ .}} - } + \node {{\ttf csms.h5}} + child { node [label=right:{Neutrino charge current differential spectrum (${\rm cm^2/GeV}$).}] {\ttf dsDE\_CC}} + child { node [label=right:{Neutrino neutral current differential spectrum (${\rm cm^2/GeV}$).}] {\ttf dsDE\_NC}} + child { node [label=right:{Total charge current neutrino cross section (${\rm cm^2}$).}]{\ttf s\_CC}} + child { node [label=right:{Total neutral current neutrino cross section (${\rm cm^2}$).}] {\ttf s\_NC}} ; \end{tikzpicture} - \caption{HDF5 cross section format. `CC' and `NC' are abbreviations for charged-current and neutral current, respectively. For the common case that two flavors (e.g. electron and muon) have indistinguishable cross section values, one group may be a link to the other within the file.} - \label{tab:hdf_cross_layout} + \caption{HDF5 cross section format.} + %\label{fig:nusquids_cross_section_hdf5} \end{figure} @@ -3190,7 +2450,7 @@ \subsubsection{Functions} \subsubsection{GlashowResonanceCrossSection\label{sec:neutrino_cross_section_glashow}} -This class implements the formulas in~\citep{Gandhi:1998ri} in order to calculate the electron antineutrino Glashow resonance cross section contribution. +This class implements the formulas in~\citep{GhandiReno} in order to calculate the electron antineutrino Glashow resonance cross section contribution. \subsubsection{Constructors} @@ -3394,7 +2654,7 @@ \subsubsection{Functions} by interpolating in the interaction basis. In each function, when considering {\ttf NT = both}, the parameter {\ttf rho} toggles between {\ttf neutrino (0)} and {\ttf antineutrino (1)}. -The last overload takes two additional arguments: a {\ttf scale}, such +The last function gets two additional arguments: a {\ttf scale}, such that all $H_0$ induced oscillation frequencies larger than this scale will be averaged, and a vector of booleans, which entries will be set to true if the corresponding oscillations frequencies have been averaged @@ -3933,6 +3193,8 @@ \subsubsection{Constructors} cosine zenith nodes. \end{itemize} +% TODO: section describing space and time complexity, benchmarks + \section{Python Interface} \label{sec:python} @@ -4175,7 +3437,7 @@ \subsubsection{Single-energy mode} \end{figure} nuSQuIDs has some predefined oscillation mixing angles ($\theta_{ij}$) and mass splittings ($\Delta m^2_{ij}$), -which we have taken from~\cite{Esteban:2020cvm}. +which we have taken from~\cite{nufit}. We can change the square mass differences by using the following function \begin{lstlisting}[language=Python, breaklines=true] nuSQ.Set_SquareMassDifference(1,2.0e-1) # sets dm^2_{21} in eV^2. @@ -4222,9 +3484,8 @@ \subsubsection{Multiple-energy mode} We can do that by setting the following Body and Track: \begin{lstlisting}[language=Python, frame=leftline, numbers=left, breaklines=true] -earth = nsq.EarthAtm() -nuSQ.Set_Body(earth) -nuSQ.Set_Track(earth.MakeTrackWithCosine(-1)) +nuSQ.Set_Body(nsq.EarthAtm()) +nuSQ.Set_Track(nsq.EarthAtm.Track(np.arccos(-1))) \end{lstlisting} For the initial flux we will assume that it's given by $\phi_\nu = N_0 E^{-2}$, @@ -4385,7 +3646,7 @@ \subsubsection{Multiple-energy mode} \end{figure} nuSQuIDs has some predefined oscillation mixing angles ($\theta_{ij}$) and mass splittings ($\Delta m^2_{ij}$), -which we have taken from~\cite{Esteban:2020cvm,Gonzalez-Garcia:2021dve}. +which we have taken from~\cite{nufit}. We can change the square mass differences by using the following function \begin{lstlisting}[language=Python, breaklines=true] nuSQ.Set_SquareMassDifference(1,2.0e-1) # sets dm^2_{21} in eV^2. @@ -4432,9 +3693,8 @@ \subsubsection{Multiple-energy mode} We can do that by setting the following Body and Track: \begin{lstlisting}[language=Python, frame=leftline, numbers=left, breaklines=true] -earth = nsq.EarthAtm() -nuSQ.Set_Body(earth) -nuSQ.Set_Track(earth.MakeTrackWithCosine(-1)) +nuSQ.Set_Body(nsq.EarthAtm()) +nuSQ.Set_Track(nsq.EarthAtm.Track(np.arccos(-1))) \end{lstlisting} For the initial flux we will assume that it's given by $\phi_\nu = N_0 E^{-2}$, @@ -4532,9 +3792,8 @@ \subsubsection{Multiple-energy mode} \begin{lstlisting}[language=Python, frame=leftline, numbers=left, breaklines=true] nuSQ.Set_MixingParametersToDefault() -earth = nsq.EarthAtm() -nuSQ.Set_Body(earth) -nuSQ.Set_Track(earth.MakeTrackWithCosine(-1)) +nuSQ.Set_Body(nsq.EarthAtm()) +nuSQ.Set_Track(nsq.EarthAtm.Track(np.arccos(-1.0))) nuSQ.Set_initial_state(InitialFlux,nsq.Basis.flavor) \end{lstlisting} An important phenomena in this scenario is that of tau-regeneration, which we can enable by @@ -4657,205 +3916,48 @@ \subsection{Extending the interface with user-defined classes~\label{sec:python_ to copy our Makefile and modify the name of the library to be generated to match the module name. As a final step the user should place the resulting shared object library in the system {\ttf PYTHONPATH}. -\section{Singly-Differential Cross-Section Tabulation} -\label{sec:differential_tabulation} -Efforts to precisely and consistently capture the physics of the singly-differential DIS cross sections have lead to using a slightly unusual tabulation scheme, the details of which we describe here. - -First, in order to interpolate cross section values for arbitrary incident and out-going energies, it is convenient that values be tabulated on some rectangular grid. -The natural choice is to use a common set of out-going energies energies for all incident energies. -Clearly, such a set of out-going energies should extend up to the maximum tabulated incident energy. -However, the cross section is meaningless for out-going energies greater than the incident energy, so for all table rows corresponding to incident energies less than the maximum tabulated, some of the higher out-going energy entries will be undefined, and must be filled with some dummy value (or a non-rectangular storage format must be used). -This layout is shown in the left panel of Fig.~\ref{fig:dsdy_tab}. -The presence of this diagonal boundary through the table between physical and unphysical regions frustrates simple interpolation schemes in the region near the boundary, as the method used must not allow the undefined or placeholder values to contribute to the calculation of the interpolated value. -This can be addressed by switching interpolation methods depending on location in the table (such as using linear interpolation via barycentric coordinates on a triangle for points in cells with only three physically allowed corner points but typical rectangular bilinear interpolation in other cells), but this adds complexity and is hostile to using higher-order interpolation methods. -As a more minor point, when typical rectangular storage formats are used, the unphysical region wastes storage space. - -\begin{figure} - \centering - \includegraphics[width=0.9\textwidth]{fig/dsdy_tabulation.eps} - \caption{Schematic depiction of the two tabulation schemes discussed for singly-differential cross sections. (a) shows simple tabulation in $E_{in}$ and $E_{out}$, while (b) shows the scheme introduced here using $E_{in}$ and the transformed $z$ variable, and indicates the $z = 1$ entries which are replaced by the values chosen to approximate the peak as a function of $E_{out}$ or $z$. It is assumed that $E_{out}$ ranges over the same set of values as $E_{in}$, and that $z$ ranges over [0, 1].} - \label{fig:dsdy_tab} -\end{figure} - -Second, the cross sections have considerable curvature, which leads to systematic errors when linear interpolation is used. -These errors are illustrated in the lower panel of Fig.~\ref{fig:cross_interp} where the relative error of the interpolated cross section grows periodically to between the tabulated cross section points. -It should be the case that the integral of the singly-differential cross section over out-going energy for a given incident energy should equal the total cross section (up to truncation effects due to the limited domain of tabulation). -If this is not the case, errors gradually accumulate when solving the evolution of a neutrino flux undergoing interactions with matter, producing non-physical artifacts in the final computed flux. -This effect is particularly pernicious because it is difficult to detect in calculations using a coarse energy node spacing, with its nature only becoming clearly evident for node spacings finer than the cross section tabulation spacing. -Importantly, neither calculation will be correct, but efforts to determine a suitably dense node spacing can be frustrated by the appearance of the unphysical artifacts when more dense spacing are tested for comparison. - -\begin{figure} - \centering - \includegraphics[width=0.9\textwidth]{fig/cross_section_interpolation.pdf} - \caption{Illustration of problems interpolating the singly-differential DIS cross section at high energies and the effects of different mitigations discussed in the text. The `Dense Tabulation' represents an essentially ideal treatment which unfortunately uses far too many samples for general practicality (10,000 samples per decade in $E_{out}$). The `Coarse Tabulation' uses are more normal 50 samples per decade. The tabulation points for the coarse table are visible as the points in the the lower panel where the error of the interpolation disappears, since the values tabulated in both tables are identical where they both exist. The linear interpolation of the coarse table is efficient to compute, but has problematically large errors in near the centers of the table bins due to being unable to represent curvature. Approximation with cubic splines greatly reduces this type of error. Simple interpolation with the final table entry (for $E_{out} = E_{in}$) being the formally correct zero value shows a very large error due to entirely missing the peak of the function. Replacing the final sample with a carefully chosen approximation eliminates this severe effect, although the true shape of the peak still cannot be captured.} - \label{fig:cross_interp} -\end{figure} - -Third, as incident neutrino energies increase, the cross section as a function of out-going energy develops a sharp peak structure for out-going energies close to the incident energy. -Inevitably this peak will at some energy become too narrow to be sampled accurately by the tabulation spacing, whatever it has been chosen to be. -This problem is greatly exacerbated by the additional fact that when the out-going energy is equal to the incident energy, the cross section must be zero. -Taken literally, this forces the final table entry in each row to be zero, which causes the interpolation between the last two table entries to fall sharply, even when one would wish for it to first rise to the peak. -Since a large portion of the integral of the differential cross section can be contained in this peak this causes a sizable discrepancy between the integral of the (interpolated) differential cross section and the total cross section. -This is illustrated in Fig.~\ref{fig:cross_interp} by the severe disagreement between the ideal sufficiently dense tabulation and the (practically realizable) coarse tabulation with linear interpolation over the latter's last table bin. - -To address the first and second problems, it is desirable to use a rectangular tabulation which has no unphysical entries and will permit simple use of higher order interpolation methods, such as cubic splines (or bicubic interpolation based on cubic splines, given the two-dimensional nature of the table). -It is therefore useful to introduce a variable $z$: - -\begin{equation} - z = {E_{out} - E_{out,min} \over E_{in} - E_{out,min}} -\end{equation} - -where $E_{in}$ is the incident neutrino energy, $E_{out}$ is the out-going lepton energy, and $E_{out,min}$ is the minimum tabulated out-going lepton energy. -This variable has the property that for $E_{out}$ ranging over $[E_{out,min}, E_{in}]$, $z$ takes on values from $[0, 1]$ for all $E_{in}$. -If one tabulates in some set of $z$ values distributed over $[0, 1]$, the range of $E_{out}$ values covered will differ for different $E_{in}$, but in a useful way, since all will be physically meaningful, and while no $E_{out}$ values except $E_{out,min}$ will generally be shared between different $E_{in}$ values, this does no particular harm, since interpolation can simply be performed in the $(E_{in}, z)$ space. -Tabulation in $z$ eliminates the first concern and significantly mitigates the second by enabling convenient use of higher order interpolation schemes, as shown in Fig.~\ref{fig:cross_interp}, where the spline interpolation shows greatly reduced errors for all except the last bin (which merits a separate discussion) compared to the linear interpolation. -It should be noted that $z$ is undefined for $E_{in} = E_{out,min}$, but there can be no non-zero cross section for this table row (shown in the right panel Fig.~\ref{fig:dsdy_tab} as white points) if it is included anyway, so {\ttf nuSQuIDS} will never explicitly refer to these entries and they can be safely set to any convenient values (such as values similar to the entries for the next row with greater $E_{out}$, in order to give well-behaved interpolation). - -Unfortunately, tabulation in $z$ does nothing useful to address the third concern. -More additional, valid tabulated values are added for lower incident energies, which have less need to resolve a sharp peak. -Instead, another approach is needed. -As previously mentioned, the $E_{out} = E_{in}$ (or $z = 1$) column of the table (shown as gray points in the right panel of Fig.~\ref{fig:dsdy_tab}) is known to always be formally zero, and so like the $E_{in} = E_{out,min}$ row it is not explicitly needed. -Since this column is also a major driver of the bad interpolation of the peak when it is unresolvable inside the final table bin, replacing it is doubly useful for changing the interpolation to be something more suitable. -Since the only strictly physically correct value to place in this column is zero, any other choice is an approximation, and which approximation is `best' is a matter of interpretation. -Since the shape of the peak itself cannot be represented faithfully, we choose to attempt to preserve its integral instead, and choose to replace the final entry in the row with one selected so that the average of the last two values is equal to the true average computed from a detailed integral of the cross section over the bin. -That is, if $T_i$ are the tabulated cross section values, of which there are $N$ in the table row, we set: - -\begin{equation} - T_{N} = {2 \over y(E_{out,N}) - y(E_{out,N-1})}\int^{y(E_{out,N})}_{y(E_{out,N-1})}{{d\sigma \over dy} dy} - T_{N-1} -\end{equation} - -where $y$ is the standard scaling variable $y = (E_{in} - E_{out}) / E_{in}$. -This choice gives the correct integral when the table is interpolated linearly, and gives similarly close results for common choices of higher-order interpolation, and can be interpreted as `smearing out' the contribution of the peak uniformly across the table bin in a cumulative sense. -The two curves shown in Fig.~\ref{fig:cross_interp} with `Peak Approximation' in their labels show this scheme in action. -While some residual error in the interpolated cross section remains due to the approximation cutting through the peak rather than following it exactly, the situation is vastly improved over the interpolation without approximation which drops rapidly to zero (extremely so, due to interpolation being done in the space of the logarithm of the cross section). -From the figure it is clear that this much more accurately captures the contribution of this bin to the integral. - - -\section{Test suite} -\label{sec:tests} -A test suite is provided with the library to guarantee the right -output in different systems or after any modification of the -code. All the tests are located in the folder {\ttf nuSQuIDS/test} -And they can be run using the provided script {\ttf test/run\_tests}. -A single test can be run by adding the name as an argument to the script -command. -In the following we list the tests that are provided with a brief -description of what they test. - -\begin{itemize} - -\item {\ttf test/vacuum\_osc\_prob.test} - - Tests that propagation with only oscillation of - neutrinos in vacuum is equal to the analytic solution. - -\item {\ttf test/constant\_density\_osc\_prob.test} - - Tests that propagation with only oscillation of - neutrinos in constant density is equal to the analytic solution. - -\item {\ttf test/constant\_opacity.test} - - Tests that propagation on a constant density with no oscillation and - neglecting regeneration from neutral current or tau decay matches - the expected exponential behavior. - -\item {\ttf test/constant\_opacity\_with\_nc.test} - - Tests that propagation on a constant density with no oscillation - matches an independent numerical solution. - -\item {\ttf test/atmospheric\_he.test} - - Tests that the high-energy propagation without oscillation of - neutrinos from the atmosphere does not give negative or {\ttf nan} values. - -\item {\ttf test/atmospheric\_osc.test} - - Tests that propagation with only oscillation of - neutrinos from the atmosphere does not give negative or {\ttf nan} - values. - -\item {\ttf test/body\_serialization.test} - - It checks that writing a body in to the hdf5 file and reading it - back does not alter the body. - -\item {\ttf test/cross\_section\_consistency.test} - - Checks that the differential cross section adds, within numerical error, - to the total cross section. - -\item {\ttf test/earth\_osc\_prob.test} - - Test that three and four neutrinos oscillation probability over a - 1000km baseline in multiple and single energy modes matches with the - numerical error to a reference independent calculation. - -\item {\ttf test/glashow\_resonance.test} - - Checks that Glashow resonance integrated differential cross-section - matches with the total cross-section and that is used while propagating. - -\item {\ttf test/hdf5\_atm\_in\_out.test} - - It checks that writing a nuSQuIDs atmospheric object into a hdf5 file and reading it - back does not alter the object and recovers all the properties. - - -\item {\ttf test/hdf5\_in\_out.test} - - It checks that writing a nuSQuIDs object into a hdf5 file and reading it - back does not alter the object and recovers all the properties. - -\item {\ttf test/move\_assig.test} - - Checks that constructor of a nuSQuIDS object from an rvalue nuSQuIDS object works. - -\item {\ttf test/mul\_energy\_constructor.test} - - Checks that the multiple energy constructor works. - -\item {\ttf test/time\_reversal.test} - - Checks that propagating a neutrino and propagating again backwards - in time returns to the original state. - -\item {\ttf test/tools\_integrator.test} - - Checks that the provided one dimensional integrate function works - within the numerical error. - -\item {\ttf test/track\_concatenate\_hdf5.test} - - Checks that propagating by concatenating a series of tracks in - vacuum and writing and reading that state at every step is the same - as propagating with a single track with the total length. - - -\item {\ttf test/track\_concatenate.test} - - Checks that propagating by concatenating a series of tracks in - vacuum is the same as propagating with a single track with the total length. - -\item {\ttf test/external\_flux.test} - - Checks that the emitting body feature works. This is done by propagating - an initially empty neutrino ensemble on a medium that emits neutrinos and comparing the - result with an analytical solution. +\section{Conclusions} +\label{sec:conclu} -\end{itemize} +In this article we have written in detail the equations that guide the evolution of an ensemble of neutrinos +in a dense medium. We have described the \nuSQUIDS~ library that solves these equations. We have provided examples +of the core features of the library. We also discussed its performance. +\nuSQUIDS~ provides a complete solution to neutrino propagation while accounting for neutrino oscillations and scattering. +We find that it is competitive with dedicated neutrino oscillation calculators, when the number of evaluations of the oscillation probability +is large; which is the typical case of interest in neutrino experiments. +The library also has a {\ttf Python} extension which we also discuss. Finally, the \nuSQUIDS~ library has been designed to be easily extendable +onto both new mediums and new physics scenarios. User contributions to the project are encouraged and a number of additional +models have already been implemented and are linked in {\ttf resources/user\_contributions}. -%\section{Additional resources} -%\label{sec:resources} +\section*{Acknowledgements} -\journal{arXiv} -\fi % forjournal +We thank: Jakob Van Santen for implementing the Glashow resonance cross sections; +Benjamin Jones for early adoption of this code onto the sterile analysis; +Melanie Day for early adoption of this code onto her analysis, carefully checking the non-standard interaction extension, and providing feedback; +Tianlu Yuan for comments on neutrino cross section utilities and testing the performance of the code in realistic analysis scenarios; +Subir Sarkar for providing the code to generate neutrino-nucleon cross section tables; +Kotoyo Hoshima and Aaron Vincent for dedicated comparisons and checks of this code; +Zander Moss for performing an independent check of several core features of the code; +Felix Kallenborn for carefully reading through the code, writing a GPU version of the algorithm, and pointing out an improve handling of the GSL ODE solver; +Jos\'e Carpio and Zander Moss for pointing out the need to improve the Earth density interpolation; +Mauricio Bustamante for testing the Python V3 support; +Austin Schneider for reading through this draft and testing the Ubuntu support; +Ibrahim Safa for reading through this draft; +Alejandro Diaz for reading through this draft; +Tom Studdard for providing feedback and contribution of neutrino decoherence; +Jos\'e Carpio, Alberto Gago, and Eduardo Massoni for providing feedback and implementing nuSQuIDS in GLoBES; +Zander Moss, Marjon Moulai, and Janet Conrad for providing feedback and contribution of neutrino decay extension; +Shivesh Mandalia and Teppei Katori for checking, providing feedback, and contribution on the Lorentz Violation model implementation; +Joshua Highnight and Jessie Micallef for providing a modified version of Prob3++ with NSI for detailed comparisons; and +Thomas Ehrhardt for performing detailed comparison between this code speed and accuracy versus Prob3++ CPU and GPU version. +Pedro Machado, Aaron Vincent, and Logan Wille for providing the Solar model files and useful discussion in the construction of the SolarTransition extension. +CAA is supported by U.S. National Science Foundation (NSF) grant PHY-1505858. +JS is supported by EU Networks FP10 ITN ELUSIVES (H2020-MSCA-ITN-2015-674896), INVISIBLES-PLUS (H2020-MSCA- +RISE-2015-690575), MINECO grant FPA2016-76005-C2-1-P and Maria de Maetzu grant MDM-2014-0367 of ICCUB. +CNW is supported by. -\ifdefined\manualonly \bibliographystyle{elsarticle-num} -\bibliography{manual} -\fi +\bibliography{nusquids} \end{document} diff --git a/resources/paper/nusquids_journal.bib b/resources/paper/nusquids_journal.bib deleted file mode 120000 index 3779d19e..00000000 --- a/resources/paper/nusquids_journal.bib +++ /dev/null @@ -1 +0,0 @@ -nusquids.bib \ No newline at end of file diff --git a/resources/paper/nusquids_journal.tex b/resources/paper/nusquids_journal.tex deleted file mode 100644 index c36aa304..00000000 --- a/resources/paper/nusquids_journal.tex +++ /dev/null @@ -1,2 +0,0 @@ -\def\forjournal{} -\input{nusquids} \ No newline at end of file diff --git a/resources/python/bindings/nuSQUIDSTools.py b/resources/python/bindings/nuSQUIDSTools.py index 441be74a..437f49ae 100644 --- a/resources/python/bindings/nuSQUIDSTools.py +++ b/resources/python/bindings/nuSQUIDSTools.py @@ -1,7 +1,7 @@ from __future__ import print_function import numpy as np import matplotlib.pyplot as plt -import nuSQuIDS as nsq +import nuSQUIDSpy as nsq # we will use the boost injector metaclass diff --git a/resources/python/example/nuSQUIDS-DEMO.ipynb b/resources/python/example/nuSQUIDS-DEMO.ipynb index 1ba47ff3..552cca76 100644 --- a/resources/python/example/nuSQUIDS-DEMO.ipynb +++ b/resources/python/example/nuSQUIDS-DEMO.ipynb @@ -15,9 +15,10 @@ "source": [ "%matplotlib inline\n", "import matplotlib as mpl\n", - "import nuSQuIDS as nsq\n", + "import nuSQUIDSpy as nsq\n", "import matplotlib.pyplot as plt\n", "\n", + "import nuSQUIDSTools\n", "import numpy as np" ] }, @@ -384,9 +385,8 @@ "outputs": [], "source": [ "nuSQ = nsq.nuSQUIDS(3,nsq.NeutrinoType.neutrino)\n", - "earth = nsq.EarthAtm()\n", - "nuSQ.Set_Body(earth)\n", - "nuSQ.Set_Track(earth.MakeTrackWithCosine(-1))\n", + "nuSQ.Set_Body(nsq.EarthAtm())\n", + "nuSQ.Set_Track(nsq.EarthAtm.Track(np.arccos(-1)))\n", "nuSQ.Set_rel_error(1.0e-17)\n", "nuSQ.Set_abs_error(1.0e-17)" ] @@ -472,7 +472,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Propagating in a constant density slab ####" + "#### Propagating in a constant density slap ####" ] }, { @@ -597,9 +597,8 @@ "metadata": {}, "outputs": [], "source": [ - "earth = nsq.EarthAtm()\n", - "nuSQ.Set_Body(earth)\n", - "nuSQ.Set_Track(earth.MakeTrackWithCosine(-1))" + "nuSQ.Set_Body(nsq.EarthAtm())\n", + "nuSQ.Set_Track(nsq.EarthAtm.Track(np.arccos(-1)))" ] }, { @@ -828,9 +827,8 @@ "metadata": {}, "outputs": [], "source": [ - "earth = nsq.EarthAtm()\n", - "nuSQ.Set_Body(earth)\n", - "nuSQ.Set_Track(earth.MakeTrackWithCosine(-1.0))\n", + "nuSQ.Set_Body(nsq.EarthAtm())\n", + "nuSQ.Set_Track(nsq.EarthAtm.Track(np.arccos(-1.0)))\n", "nuSQ.Set_initial_state(InitialFlux,nsq.Basis.flavor)" ] }, @@ -988,9 +986,8 @@ "metadata": {}, "outputs": [], "source": [ - "earth = nsq.EarthAtm()" - "nuSQ.Set_Body(earth)\n", - "nuSQ.Set_Track(earth.MakeTrackWithCosine(-1.0))\n", + "nuSQ.Set_Body(nsq.EarthAtm())\n", + "nuSQ.Set_Track(nsq.EarthAtm.Track(np.arccos(-1.0)))\n", "nuSQ.Set_initial_state(InitialFlux,nsq.Basis.flavor)\n", "nuSQ.Set_TauRegeneration(True)" ] @@ -1052,7 +1049,7 @@ "plt.grid()\n", "plt.loglog()\n", "plt.legend(loc = \"upper right\", fancybox = True, fontsize = 15)\n", - "plt.savefig(\"nusquids_python_with_interactions_both.pdf\",bbox_inches='tight')" + "plt.savefig(\"nusquids_python_with_interactions_both.eps\",bbox_inches='tight')" ] }, { @@ -1086,9 +1083,8 @@ "metadata": {}, "outputs": [], "source": [ - "earth = nsq.EarthAtm()\n", - "nuSQ.Set_Body(earth)\n", - "nuSQ.Set_Track(earth.MakeTrackWithCosine(-1))" + "nuSQ.Set_Body(nsq.EarthAtm())\n", + "nuSQ.Set_Track(nsq.EarthAtm.Track(np.arccos(-1)))" ] }, { @@ -1307,12 +1303,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# References\n", - "\n", - "- [1] *M.C. Gonzalez-Garcia, F. Halzen, and M. Maltoni*, **Physics Reach of High-Energy and High-Statistics IceCube Atmospheric Neutrino Data**, Phys.Rev. D71 (2005) 093010. http://arxiv.org/abs/hep-ph/0502223\n", - "- *C.A. Argüelles-Delgado, J. Salvado, and C. N. Weaver*, **SQuIDS: A Simple Quantum Integro Differential equation Solve.** On preparation.\n", - "- *C.A. Argüelles-Delgado, J. Salvado, and C. N. Weaver*, **$\\nu$-SQuIDS: A tool box for neutrino oscillation experiments.** On preparation.\n", - "- M. Galassi et al, GNU Scientific Library Reference Manual (3rd Ed.), ISBN 0954612078. http://www.gnu.org/software/gsl/" + "We can use the convenient python-only PlotFlavor member function to plot the nu mu flux as a function\n", + "of the energy and zenith." ] }, { @@ -1320,7 +1312,41 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "numu = 1\n", + "neutrino = 0\n", + "figure = nsq_atm.PlotFlavor(numu,neutrino)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly the muon antineutrino" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numu = 1\n", + "antineutrino = 1\n", + "figure = nsq_atm.PlotFlavor(numu,antineutrino)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# References\n", + "\n", + "- [1] *M.C. Gonzalez-Garcia, F. Halzen, and M. Maltoni*, **Physics Reach of High-Energy and High-Statistics IceCube Atmospheric Neutrino Data**, Phys.Rev. D71 (2005) 093010. http://arxiv.org/abs/hep-ph/0502223\n", + "- *C.A. Argüelles-Delgado, J. Salvado, and C. N. Weaver*, **SQuIDS: A Simple Quantum Integro Differential equation Solve.** On preparation.\n", + "- *C.A. Argüelles-Delgado, J. Salvado, and C. N. Weaver*, **$\\nu$-SQuIDS: A tool box for neutrino oscillation experiments.** On preparation.\n", + "- M. Galassi et al, GNU Scientific Library Reference Manual (3rd Ed.), ISBN 0954612078. http://www.gnu.org/software/gsl/" + ] }, { "cell_type": "code", @@ -1349,12 +1375,12 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.5" + "version": "3.7.4" }, "nteract": { "version": "0.2.0" } }, "nbformat": 4, - "nbformat_minor": 4 + "nbformat_minor": 1 } diff --git a/resources/python/example/nuSQUIDS-DEMO.py b/resources/python/example/nuSQUIDS-DEMO.py index 79e53130..62429555 100644 --- a/resources/python/example/nuSQUIDS-DEMO.py +++ b/resources/python/example/nuSQUIDS-DEMO.py @@ -1,20 +1,14 @@ # coding: utf-8 # # $\nu$-SQuIDS Demo: Welcome! -import nuSQuIDS as nsq - -try: - import matplotlib as mpl - import matplotlib.pyplot as plt - mpl.rc('font', family='serif', size=20) - if hasattr(plt, "style"): - plt.style.use('./paper.mplstyle') -except ImportError: - print("matplotlib not found, disabling plotting") - from unittest.mock import MagicMock - plt = MagicMock() +import matplotlib as mpl +import nuSQUIDSpy as nsq +import matplotlib.pyplot as plt +import nuSQUIDSTools import numpy as np +mpl.rc('font', family='serif', size=20) +plt.style.use('./paper.mplstyle') # Welcome to the $\nu$-SQuIDS demo. In @@ -143,9 +137,8 @@ # As in the C++ implementation we can change the `Body` by means of the `Set_Body` function and in similar way we can change the `Track`. Lets do an atmospheric oscillation example =). nuSQ = nsq.nuSQUIDS(3,nsq.NeutrinoType.neutrino) -earth = nsq.EarthAtm() -nuSQ.Set_Body(earth) -nuSQ.Set_Track(nsq.EarthAtm.Track(earth.MakeTrackWithCosine(-1))) +nuSQ.Set_Body(nsq.EarthAtm()) +nuSQ.Set_Track(nsq.EarthAtm.Track(np.arccos(-1))) nuSQ.Set_rel_error(1.0e-17) nuSQ.Set_abs_error(1.0e-17) @@ -192,7 +185,7 @@ plt.ylabel(r"$P(\nu_\mu \to \nu_\mu)$") plt.plot(energy_values,nu_mu_to_nu_e, lw = 2, color = 'blue') -# #### Propagating in a constant density slab #### +# #### Propagating in a constant density slap #### nuSQ = nsq.nuSQUIDS(3,nsq.NeutrinoType.neutrino) nuSQ.Set_Body(nsq.ConstantDensity(13.0,0.5)) @@ -243,9 +236,8 @@ # Lets propage this neutrino through the Earth in an atmospheric neutrino telescope setting. We can do that by setting the following `Body` and `Track`: -earth = nsq.EarthAtm() -nuSQ.Set_Body(earth) -nuSQ.Set_Track(earth.MakeTrackWithCosine(-1)) +nuSQ.Set_Body(nsq.EarthAtm()) +nuSQ.Set_Track(nsq.EarthAtm.Track(np.arccos(-1))) # Lets assume that $\phi_\nu = N_0 E^{-2}$, with flavor composition $\phi_e:\phi_\mu:\phi_\tau$ = $0:1:0$. $\nu$-SQuIDS input flux is a `numpy.ndarray` formatted in the following way : # @@ -348,9 +340,8 @@ nuSQ.Set_h_max(500.0*units.km) nuSQ.Set_MixingParametersToDefault() -earth = nsq.EarthAtm() -nuSQ.Set_Body(earth) -nuSQ.Set_Track(earth.MakeTrackWithCosine(-1.0)) +nuSQ.Set_Body(nsq.EarthAtm()) +nuSQ.Set_Track(nsq.EarthAtm.Track(np.arccos(-1.0))) nuSQ.Set_initial_state(InitialFlux,nsq.Basis.flavor) nuSQ.EvolveState() @@ -436,9 +427,9 @@ nuSQ.Set_h_max(500.0*units.km) nuSQ.Set_MixingParametersToDefault() -earth = nsq.EarthAtm() -nuSQ.Set_Body(earth) -nuSQ.Set_Track(earth.MakeTrackWithCosine(-1.0)) + +nuSQ.Set_Body(nsq.EarthAtm()) +nuSQ.Set_Track(nsq.EarthAtm.Track(np.arccos(-1.0))) nuSQ.Set_initial_state(InitialFlux,nsq.Basis.flavor) nuSQ.Set_TauRegeneration(True) @@ -491,9 +482,8 @@ nuSQ = nsq.nuSQUIDS(energy_nodes,neutrino_flavors,nsq.NeutrinoType.antineutrino,interactions) -earth = nsq.EarthAtm() -nuSQ.Set_Body(earth) -nuSQ.Set_Track(earth.MakeTrackWithCosine(-1)) +nuSQ.Set_Body(nsq.EarthAtm()) +nuSQ.Set_Track(nsq.EarthAtm.Track(np.arccos(-1))) nuSQ.Set_MixingParametersToDefault() nuSQ.Set_SquareMassDifference(3,1.) @@ -601,6 +591,21 @@ plt.legend(bbox_to_anchor=(1.05, 1), loc=2, fontsize = 14, fancybox = True) +# We can use the convenient python-only PlotFlavor member function to plot the nu mu flux as a function +# of the energy and zenith. + +numu = 1 +neutrino = 0 +figure = nsq_atm.PlotFlavor(numu,neutrino) + + +# Similarly the muon antineutrino + +numu = 1 +antineutrino = 1 +figure = nsq_atm.PlotFlavor(numu,antineutrino) + + # # References # # - [1] *M.C. Gonzalez-Garcia, F. Halzen, and M. Maltoni*, **Physics Reach of High-Energy and High-Statistics IceCube Atmospheric Neutrino Data**, Phys.Rev. D71 (2005) 093010. http://arxiv.org/abs/hep-ph/0502223 diff --git a/resources/python/src/nuSQUIDSpy.cpp b/resources/python/src/nuSQUIDSpy.cpp index 3b430d45..1f532017 100644 --- a/resources/python/src/nuSQUIDSpy.cpp +++ b/resources/python/src/nuSQUIDSpy.cpp @@ -22,6 +22,7 @@ ******************************************************************************/ #include "nuSQUIDSpy.h" +#include BOOST_PYTHON_MODULE(nuSQuIDS) { @@ -137,6 +138,15 @@ BOOST_PYTHON_MODULE(nuSQuIDS) RegisterBasicNuSQuIDSPythonBindings("nuSQUIDS"); RegisterBasicAtmNuSQuIDSPythonBindings("nuSQUIDSAtm"); + auto nusquids_lv = RegisterBasicNuSQuIDSPythonBindings("nuSQUIDSLV"); + auto nusquids_lv_atm = RegisterBasicAtmNuSQuIDSPythonBindingsHelper("nuSQUIDSLVAtm"); + void (nuSQUIDSLVAtm::*Set_LV_OpMatrix)(double lv_emu_re, double lv_emu_im, double lv_mutau_re, double lv_mutau_im, double lv_etau_re, double lv_etau_im, double lv_ee, double lv_mumu) = &nuSQUIDSLVAtm::Set_LV_OpMatrix; + void (nuSQUIDSLVAtm::*Set_LV_Operator)(squids::SU_vector op) = &nuSQUIDSLVAtm::Set_LV_Operator; + void (nuSQUIDSLVAtm::*Set_LV_EnergyPower)(int n) = &nuSQUIDSLVAtm::Set_LV_EnergyPower; + nusquids_lv_atm.GetClassObject()->def("Set_LV_OpMatrix", Set_LV_OpMatrix); + //nusquids_lv_atm.GetClassObject()->def("Set_LV_Operator", Set_LV_Operator); + nusquids_lv_atm.GetClassObject()->def("Set_LV_EnergyPower", Set_LV_EnergyPower); + class_, boost::noncopyable >("NeutrinoCrossSections", no_init); class_, std::shared_ptr, boost::noncopyable >("NullCrossSections") @@ -194,8 +204,6 @@ BOOST_PYTHON_MODULE(nuSQuIDS) ; class_("Const") - .def_readonly("GF",&squids::Const::GF) - .def_readonly("Na",&squids::Const::Na) .def_readonly("GF",&squids::Const::GF) .def_readonly("PeV",&squids::Const::PeV) .def_readonly("TeV",&squids::Const::TeV) @@ -340,7 +348,6 @@ BOOST_PYTHON_MODULE(nuSQuIDS) class_ >("Track", init()) .def(init()) - .def(init()) .def("GetInitialX",&SunASnu::Track::GetInitialX) .def("GetFinalX",&SunASnu::Track::GetFinalX) .def("GetX",&SunASnu::Track::GetX) @@ -356,16 +363,10 @@ BOOST_PYTHON_MODULE(nuSQuIDS) scope outer = class_, boost::noncopyable, std::shared_ptr >("EarthAtm") .def(init()) - .def("GetRadius",&EarthAtm::GetRadius) - .def("GetAtmosphereHeight",&EarthAtm::GetAtmosphereHeight) - .def("SetAtmosphereHeight",&EarthAtm::GetAtmosphereHeight) - .def("MakeTrack",&EarthAtm::MakeTrack) - .def("MakeTrackWithCosine",&EarthAtm::MakeTrackWithCosine) ; - class_ >("Track", init()) - .def(init()) - .def(init()) + class_ >("Track", init()) + .def(init()) .def("GetInitialX",&EarthAtm::Track::GetInitialX) .def("GetFinalX",&EarthAtm::Track::GetFinalX) .def("GetX",&EarthAtm::Track::GetX) diff --git a/resources/python/src/nuSQUIDSpy.h b/resources/python/src/nuSQUIDSpy.h index 3439a7c6..8cc95e8b 100644 --- a/resources/python/src/nuSQUIDSpy.h +++ b/resources/python/src/nuSQUIDSpy.h @@ -311,8 +311,10 @@ templatedef("GetHamiltonian",&BaseType::GetHamiltonian); class_object->def("GetState",(const squids::SU_vector&(BaseType::*)(unsigned int))&BaseType::GetState, return_value_policy()); class_object->def("GetState",(const squids::SU_vector&(BaseType::*)(unsigned int, unsigned int))&BaseType::GetState, return_value_policy()); - class_object->def("Set_EvolLowPassCutoff", &BaseType::Set_EvolLowPassCutoff); - class_object->def("Set_EvolLowPassScale", &BaseType::Set_EvolLowPassScale); + class_object->def("Set_EvolLowPassCutoff", (void(BaseType::*)(const marray&))&BaseType::Set_EvolLowPassCutoff); + class_object->def("Set_EvolLowPassCutoff", (void(BaseType::*)(double))&BaseType::Set_EvolLowPassCutoff); + class_object->def("Set_EvolLowPassScale", (void(BaseType::*)(const marray&))&BaseType::Set_EvolLowPassScale); + class_object->def("Set_EvolLowPassScale", (void(BaseType::*)(double))&BaseType::Set_EvolLowPassScale); class_object->def("Set_h_min",&BaseType::Set_h_min); class_object->def("Set_h_max",&BaseType::Set_h_max); class_object->def("Set_h",&BaseType::Set_h); @@ -351,8 +353,6 @@ templatedef("Set_Debug",&BaseType::Set_Debug); class_object->def("Set_IncludeOscillations",&BaseType::Set_IncludeOscillations); class_object->def("Set_GlashowResonance",&BaseType::Set_GlashowResonance); - class_object->def("Set_NeutrinoSources",&BaseType::Set_NeutrinoSources); - class_object->def("Get_NeutrinoSources",&BaseType::Get_NeutrinoSources); } std::shared_ptr>> GetClassObject() { return class_object; @@ -363,77 +363,85 @@ template::value>::type > - struct RegisterBasicAtmNuSQuIDSPythonBindings { +template::value>::type> + struct RegisterBasicAtmNuSQuIDSPythonBindingsHelper { const std::string class_label; - std::shared_ptr, boost::noncopyable, std::shared_ptr>>> class_object; - RegisterBasicAtmNuSQuIDSPythonBindings(std::string class_label){ - class_object = std::make_shared, boost::noncopyable, std::shared_ptr>>>(class_label.c_str(), no_init); + std::shared_ptr>> class_object; + RegisterBasicAtmNuSQuIDSPythonBindingsHelper(std::string class_label){ + class_object = std::make_shared>>(class_label.c_str(), no_init); class_object->def(init,marray,unsigned int,NeutrinoType>(args("CosZenith_vector","E_vector","numneu","NT"))); class_object->def(init,marray,unsigned int,NeutrinoType,bool>(args("CosZenith_vector","E_vector","numneu","NT","iinteraction"))); class_object->def(init,marray,unsigned int,NeutrinoType,bool,std::shared_ptr>(args("CosZenith_vector","E_vector","numneu","NT","iinteraction","ncs"))); class_object->def(init(args("filename"))); - class_object->def("EvolveState",&nuSQUIDSAtm::EvolveState); - class_object->def("Set_TauRegeneration",&nuSQUIDSAtm::Set_TauRegeneration); - class_object->def("EvalFlavor",(double(nuSQUIDSAtm::*)(unsigned int,double,double,unsigned int,bool) const)&nuSQUIDSAtm::EvalFlavor, - nuSQUIDSAtm_EvalFlavor_overload>(args("Flavor","cos(theta)","Neutrino Energy","NeuType","BoolToRandomzeProdutionHeight"), + class_object->def("EvolveState",&AtmType::EvolveState); + class_object->def("Set_TauRegeneration",&AtmType::Set_TauRegeneration); + class_object->def("EvalFlavor",(double(AtmType::*)(unsigned int,double,double,unsigned int,bool) const)&AtmType::EvalFlavor, + nuSQUIDSAtm_EvalFlavor_overload(args("Flavor","cos(theta)","Neutrino Energy","NeuType","BoolToRandomzeProdutionHeight"), "nuSQuIDSAtm evaluate flux..")); - class_object->def("Set_EvalThreads",&nuSQUIDSAtm::Set_EvalThreads); - class_object->def("Get_EvalThreads",&nuSQUIDSAtm::Get_EvalThreads); - class_object->def("Set_EarthModel",&nuSQUIDSAtm::Set_EarthModel); - class_object->def("WriteStateHDF5",&nuSQUIDSAtm::WriteStateHDF5); - class_object->def("ReadStateHDF5",&nuSQUIDSAtm::ReadStateHDF5); - class_object->def("Set_MixingAngle",&nuSQUIDSAtm::Set_MixingAngle); - class_object->def("Get_MixingAngle",&nuSQUIDSAtm::Get_MixingAngle); - class_object->def("Set_CPPhase",&nuSQUIDSAtm::Set_CPPhase); - class_object->def("Get_CPPhase",&nuSQUIDSAtm::Get_CPPhase); - class_object->def("Set_SquareMassDifference",&nuSQUIDSAtm::Set_SquareMassDifference); - class_object->def("Get_SquareMassDifference",&nuSQUIDSAtm::Get_SquareMassDifference); - class_object->def("Set_h",(void(nuSQUIDSAtm::*)(double))&nuSQUIDSAtm::Set_h); - class_object->def("Set_h",(void(nuSQUIDSAtm::*)(double,unsigned int))&nuSQUIDSAtm::Set_h); - class_object->def("Set_h_max",(void(nuSQUIDSAtm::*)(double))&nuSQUIDSAtm::Set_h_max); - class_object->def("Set_h_max",(void(nuSQUIDSAtm::*)(double,unsigned int))&nuSQUIDSAtm::Set_h_max); - class_object->def("Set_h_min",(void(nuSQUIDSAtm::*)(double))&nuSQUIDSAtm::Set_h_min); - class_object->def("Set_h_min",(void(nuSQUIDSAtm::*)(double,unsigned int))&nuSQUIDSAtm::Set_h_min); - class_object->def("Set_ProgressBar",&nuSQUIDSAtm::Set_ProgressBar); - class_object->def("Set_MixingParametersToDefault",&nuSQUIDSAtm::Set_MixingParametersToDefault); + class_object->def("Set_EvalThreads",&AtmType::Set_EvalThreads); + class_object->def("Get_EvalThreads",&AtmType::Get_EvalThreads); + class_object->def("Set_EarthModel",&AtmType::Set_EarthModel); + class_object->def("WriteStateHDF5",&AtmType::WriteStateHDF5); + class_object->def("ReadStateHDF5",&AtmType::ReadStateHDF5); + class_object->def("Set_MixingAngle",&AtmType::Set_MixingAngle); + class_object->def("Get_MixingAngle",&AtmType::Get_MixingAngle); + class_object->def("Set_CPPhase",&AtmType::Set_CPPhase); + class_object->def("Get_CPPhase",&AtmType::Get_CPPhase); + class_object->def("Set_SquareMassDifference",&AtmType::Set_SquareMassDifference); + class_object->def("Get_SquareMassDifference",&AtmType::Get_SquareMassDifference); + class_object->def("Set_h",(void(AtmType::*)(double))&AtmType::Set_h); + class_object->def("Set_h",(void(AtmType::*)(double,unsigned int))&AtmType::Set_h); + class_object->def("Set_h_max",(void(AtmType::*)(double))&AtmType::Set_h_max); + class_object->def("Set_h_max",(void(AtmType::*)(double,unsigned int))&AtmType::Set_h_max); + class_object->def("Set_h_min",(void(AtmType::*)(double))&AtmType::Set_h_min); + class_object->def("Set_h_min",(void(AtmType::*)(double,unsigned int))&AtmType::Set_h_min); + class_object->def("Set_ProgressBar",&AtmType::Set_ProgressBar); + class_object->def("Set_MixingParametersToDefault",&AtmType::Set_MixingParametersToDefault); class_object->def("Set_GSL_step",wrap_nusqatm_Set_GSL_STEP); - class_object->def("Set_rel_error",(void(nuSQUIDSAtm::*)(double))&nuSQUIDSAtm::Set_rel_error); - class_object->def("Set_rel_error",(void(nuSQUIDSAtm::*)(double, unsigned int))&nuSQUIDSAtm::Set_rel_error); - class_object->def("Set_abs_error",(void(nuSQUIDSAtm::*)(double))&nuSQUIDSAtm::Set_abs_error); - class_object->def("Set_abs_error",(void(nuSQUIDSAtm::*)(double, unsigned int))&nuSQUIDSAtm::Set_abs_error); - class_object->def("Set_EvolLowPassCutoff",&nuSQUIDSAtm::Set_EvolLowPassCutoff); - class_object->def("Set_EvolLowPassScale",&nuSQUIDSAtm::Set_EvolLowPassScale); - class_object->def("GetNumE",&nuSQUIDSAtm::GetNumE); - class_object->def("GetNumCos",&nuSQUIDSAtm::GetNumCos); - class_object->def("GetNumNeu",&nuSQUIDSAtm::GetNumNeu); - class_object->def("GetNumRho",&nuSQUIDSAtm::GetNumRho); - class_object->def("GetnuSQuIDS",(std::vector&(nuSQUIDSAtm::*)())&nuSQUIDSAtm::GetnuSQuIDS,boost::python::return_internal_reference<>()); - class_object->def("GetnuSQuIDS",(BaseType&(nuSQUIDSAtm::*)(unsigned int))&nuSQUIDSAtm::GetnuSQuIDS,boost::python::return_internal_reference<>()); - class_object->def("Set_initial_state",(void(nuSQUIDSAtm::*)(const marray&, Basis))&nuSQUIDSAtm::Set_initial_state,nuSQUIDSAtm_Set_initial_state>()); - class_object->def("Set_initial_state",(void(nuSQUIDSAtm::*)(const marray&, Basis))&nuSQUIDSAtm::Set_initial_state,nuSQUIDSAtm_Set_initial_state>()); - class_object->def("GetStates", (marray(nuSQUIDSAtm::*)(unsigned int))&nuSQUIDSAtm::GetStates, - nuSQUIDSAtm_GetStates_overload>(args("rho"), "Get evolved states of all nodes")); - class_object->def("GetERange",&nuSQUIDSAtm::GetERange); - class_object->def("GetCosthRange",&nuSQUIDSAtm::GetCosthRange); - class_object->def("Set_IncludeOscillations",&nuSQUIDSAtm::Set_IncludeOscillations); - class_object->def("Set_GlashowResonance",&nuSQUIDSAtm::Set_GlashowResonance); - class_object->def("Set_TauRegeneration",&nuSQUIDSAtm::Set_TauRegeneration); - class_object->def("Set_AllowConstantDensityOscillationOnlyEvolution",&nuSQUIDSAtm::Set_AllowConstantDensityOscillationOnlyEvolution); - class_object->def("Set_PositivyConstrain",&nuSQUIDSAtm::Set_PositivityConstrain); - class_object->def("Set_PositivyConstrainStep",&nuSQUIDSAtm::Set_PositivityConstrainStep); - class_object->def("Get_EvalThreads",&nuSQUIDSAtm::Get_EvalThreads); - class_object->def("Set_EvalThreads",&nuSQUIDSAtm::Set_EvalThreads); - class_object->def("Set_EarthModel",&nuSQUIDSAtm::Set_EarthModel); - class_object->def("SetNeutrinoCrossSections",&nuSQUIDSAtm::SetNeutrinoCrossSections); - class_object->def("GetNeutrinoCrossSections",&nuSQUIDSAtm::GetNeutrinoCrossSections); + class_object->def("Set_rel_error",(void(AtmType::*)(double))&AtmType::Set_rel_error); + class_object->def("Set_rel_error",(void(AtmType::*)(double, unsigned int))&AtmType::Set_rel_error); + class_object->def("Set_abs_error",(void(AtmType::*)(double))&AtmType::Set_abs_error); + class_object->def("Set_abs_error",(void(AtmType::*)(double, unsigned int))&AtmType::Set_abs_error); + class_object->def("Set_EvolLowPassCutoff",&AtmType::Set_EvolLowPassCutoff); + class_object->def("Set_EvolLowPassScale",&AtmType::Set_EvolLowPassScale); + class_object->def("Set_AutoEvolLowPass", &AtmType::Set_AutoEvolLowPass); + class_object->def("GetNumE",&AtmType::GetNumE); + class_object->def("GetNumCos",&AtmType::GetNumCos); + class_object->def("GetNumNeu",&AtmType::GetNumNeu); + class_object->def("GetNumRho",&AtmType::GetNumRho); + class_object->def("GetnuSQuIDS",(std::vector&(AtmType::*)())&AtmType::GetnuSQuIDS,boost::python::return_internal_reference<>()); + class_object->def("GetnuSQuIDS",(BaseType&(AtmType::*)(unsigned int))&AtmType::GetnuSQuIDS,boost::python::return_internal_reference<>()); + class_object->def("Set_initial_state",(void(AtmType::*)(const marray&, Basis))&AtmType::Set_initial_state,nuSQUIDSAtm_Set_initial_state()); + class_object->def("Set_initial_state",(void(AtmType::*)(const marray&, Basis))&AtmType::Set_initial_state,nuSQUIDSAtm_Set_initial_state()); + class_object->def("GetStates", (marray(AtmType::*)(unsigned int))&AtmType::GetStates, + nuSQUIDSAtm_GetStates_overload(args("rho"), "Get evolved states of all nodes")); + class_object->def("GetERange",&AtmType::GetERange); + class_object->def("GetCosthRange",&AtmType::GetCosthRange); + class_object->def("Set_IncludeOscillations",&AtmType::Set_IncludeOscillations); + class_object->def("Set_GlashowResonance",&AtmType::Set_GlashowResonance); + class_object->def("Set_TauRegeneration",&AtmType::Set_TauRegeneration); + class_object->def("Set_AllowConstantDensityOscillationOnlyEvolution",&AtmType::Set_AllowConstantDensityOscillationOnlyEvolution); + class_object->def("Set_PositivyConstrain",&AtmType::Set_PositivityConstrain); + class_object->def("Set_PositivyConstrainStep",&AtmType::Set_PositivityConstrainStep); + class_object->def("Get_EvalThreads",&AtmType::Get_EvalThreads); + class_object->def("Set_EvalThreads",&AtmType::Set_EvalThreads); + class_object->def("Set_EarthModel",&AtmType::Set_EarthModel); + class_object->def("SetNeutrinoCrossSections",&AtmType::SetNeutrinoCrossSections); + class_object->def("GetNeutrinoCrossSections",&AtmType::GetNeutrinoCrossSections); } - std::shared_ptr, boost::noncopyable, std::shared_ptr>>> GetClassObject() { + std::shared_ptr>> GetClassObject() { return class_object; } }; +template::value>::type> + struct RegisterBasicAtmNuSQuIDSPythonBindings : RegisterBasicAtmNuSQuIDSPythonBindingsHelper, BaseType> { + RegisterBasicAtmNuSQuIDSPythonBindings(std::string class_label) : RegisterBasicAtmNuSQuIDSPythonBindingsHelper, BaseType>(class_label) { + } +}; + #endif diff --git a/src/body.cpp b/src/body.cpp index b56ad5bb..0dc8257e 100644 --- a/src/body.cpp +++ b/src/body.cpp @@ -683,15 +683,18 @@ EarthAtm::EarthAtm():EarthAtm(getResourcePath()+"/astro/EARTH_MODEL_PREM.dat") {} // track constructor -EarthAtm::Track::Track(double phi_input,double earth_radius_,double atmheight_):Body::Track(0,0) +EarthAtm::Track::Track(double phi_input):Body::Track(0,0) { - earth_radius = earth_radius_; - atmheight = atmheight_; + radius_nu = 6371.0*param.km; + atmheight = 22.*param.km; cosphi = cos(phi_input); double sinsqphi = 1-cosphi*cosphi; - L = sqrt(SQR(earth_radius+atmheight)-earth_radius*earth_radius*sinsqphi)-earth_radius*cosphi; + double R = radius_nu; + double r = atmheight; + + L = sqrt(SQR(R+r)-R*R*sinsqphi)-R*cosphi; x = 0.0; xini = 0.0; @@ -707,30 +710,17 @@ EarthAtm::Track::Track(double phi_input,double earth_radius_,double atmheight_): } void EarthAtm::Track::Serialize(hid_t group) const { - addH5Attribute(group,"name", GetName()); - addH5Attribute(group,"x",x); - addH5Attribute(group,"xini",xini); - addH5Attribute(group,"xend",xend); - addH5Attribute(group,"cosphi",cosphi); - addH5Attribute(group,"earth_radius",earth_radius); - addH5Attribute(group,"atmheight",atmheight); + addStringAttribute(group,"name", GetName().c_str()); + addDoubleAttribute(group,"x",x); + addDoubleAttribute(group,"xini",xini); + addDoubleAttribute(group,"xend",xend); + addDoubleAttribute(group,"cosphi",cosphi); } std::shared_ptr EarthAtm::Track::Deserialize(hid_t group){ - double x, cosphi; - readH5Attribute(group,"x", x); - readH5Attribute(group,"cosphi",cosphi); - // these parameters were originally not serialized, so give them default values equal to what - // was originally hard-coded - double earth_radius = 6371.0*param.km; - double atmheight = 22.*param.km; - if(H5Aexists(group,"earth_radius")) - readH5Attribute(group,"earth_radius", earth_radius); - if(H5Aexists(group,"atmheight")) - readH5Attribute(group,"atmheight", atmheight); - auto track=std::make_shared(EarthAtm::Track::MakeWithCosine(cosphi,earth_radius,atmheight)); - track->SetX(x); - return track; + double x_ =readDoubleAttribute(group,"x"); + double cosphi_ =readDoubleAttribute(group,"cosphi"); + return std::make_shared(x_,acos(cosphi_)); } void EarthAtm::Serialize(hid_t group) const { @@ -740,8 +730,6 @@ void EarthAtm::Serialize(hid_t group) const { H5LTmake_dataset_double(group, "earth_radius", 1, dims.data(), earth_radius.data()); H5LTmake_dataset_double(group, "earth_density", 1, dims.data(), earth_density.data()); H5LTmake_dataset_double(group, "earth_ye", 1, dims.data(), earth_ye.data()); - addH5Attribute(group,"radius",radius); - addH5Attribute(group,"atm_height",atm_height); } std::shared_ptr EarthAtm::Deserialize(hid_t group){ @@ -750,31 +738,21 @@ std::shared_ptr EarthAtm::Deserialize(hid_t group){ H5LTread_dataset_double(group,"earth_radius",x_vec.data()); H5LTread_dataset_double(group,"earth_density",rho_vec.data()); H5LTread_dataset_double(group,"earth_ye",ye_vec.data()); - // these parameters were originally not serialized, so give them default values equal to what - // was originally hard-coded - double radius = 6371.0; - double atm_height = 22.; - if(H5Aexists(group,"radius")) - readH5Attribute(group,"radius", radius); - if(H5Aexists(group,"atm_height")) - readH5Attribute(group,"atm_height", atm_height); - auto earthAtm = std::make_shared(x_vec,rho_vec,ye_vec); - earthAtm->radius = radius; - earthAtm->SetAtmosphereHeight(atm_height); - return earthAtm; + return std::make_shared(x_vec,rho_vec,ye_vec); } EarthAtm::Track::Track(): -Body::Track(0,0),earth_radius(6371.0*param.km),atmheight(22.*param.km){} +Body::Track(0,0),radius_nu(6371.0*param.km),atmheight(22.*param.km){} EarthAtm::Track -EarthAtm::Track::MakeWithCosine(double cosphi, double earth_radius_, double atmheight_){ +EarthAtm::Track::makeWithCosine(double cosphi){ Track track; track.cosphi = cosphi; double sinsqphi = 1-track.cosphi*track.cosphi; + double R = track.radius_nu; - track.L = sqrt(SQR(earth_radius_+atmheight_)-earth_radius_*earth_radius_*sinsqphi)-earth_radius_*cosphi; + track.L = sqrt(SQR(R+track.atmheight)-R*R*sinsqphi)-R*cosphi; track.x = 0.0; track.xini = 0.0; track.xend = track.L; @@ -783,28 +761,18 @@ EarthAtm::Track::MakeWithCosine(double cosphi, double earth_radius_, double atmh } void EarthAtm::Track::FillDerivedParams(std::vector& TrackParams) const{ - TrackParams.push_back(acos(cosphi)); - TrackParams.push_back(earth_radius); - TrackParams.push_back(atmheight); -} - -EarthAtm::Track EarthAtm::MakeTrack(double phi){ - return Track(phi, GetRadius()*param.km, GetAtmosphereHeight()*param.km); + TrackParams.push_back(acos(cosphi)); } - -EarthAtm::Track EarthAtm::MakeTrackWithCosine(double cosphi){ - return Track::MakeWithCosine(cosphi, GetRadius()*param.km, GetAtmosphereHeight()*param.km); -} - + double EarthAtm::density(const GenericTrack& track_input) const { const EarthAtm::Track& track_earthatm = static_cast(track_input); double xkm = track_earthatm.GetX()/param.km; double sinsqphi = 1-track_earthatm.cosphi*track_earthatm.cosphi; - double dL = sqrt(SQR(earth_with_atm_radius)-radius*radius*sinsqphi)+radius*track_earthatm.cosphi; + double dL = sqrt(SQR(radius+atm_height)-radius*radius*sinsqphi)+radius*track_earthatm.cosphi; double r2 = SQR(earth_with_atm_radius) + SQR(xkm) - (track_earthatm.L/param.km+dL)*xkm; double r = (r2>0 ? sqrt(r2) : 0); - + double rel_r = r/earth_with_atm_radius; if ( rel_r < x_radius_min ){ return x_rho_min; @@ -827,7 +795,7 @@ double EarthAtm::ye(const GenericTrack& track_input) const const EarthAtm::Track& track_earthatm = static_cast(track_input); double xkm = track_earthatm.GetX()/param.km; double sinsqphi = 1-track_earthatm.cosphi*track_earthatm.cosphi; - double dL = sqrt(SQR(earth_with_atm_radius)-radius*radius*sinsqphi)+radius*track_earthatm.cosphi; + double dL = sqrt(SQR(radius+atm_height)-radius*radius*sinsqphi)+radius*track_earthatm.cosphi; double r2 = SQR(earth_with_atm_radius) + SQR(xkm) - (track_earthatm.L/param.km+dL)*xkm; double r = (r2>0 ? sqrt(r2) : 0); @@ -896,11 +864,6 @@ inter_density(earth_radius,earth_density),inter_ye(earth_radius,earth_ye) } EarthAtm::~EarthAtm(){} - -void EarthAtm::SetAtmosphereHeight(double height){ - atm_height = height; - earth_with_atm_radius = radius + atm_height; -} // body registration stuff diff --git a/src/nuSQuIDS.cpp b/src/nuSQuIDS.cpp index 948f0379..01e24cfb 100644 --- a/src/nuSQuIDS.cpp +++ b/src/nuSQuIDS.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +72,10 @@ std::string getStringAttribute(hid_t loc_id, const char* obj_name, const char* a throw std::runtime_error("Failed to read attribute "+std::string(attr_name)+" of object "+std::string(obj_name)); return(std::string(buffer.get(),type_size)); } + +bool objectExists(hid_t loc_id, const char* name){ + return H5Lexists(loc_id,name,H5P_DEFAULT)>0 && H5Oexists_by_name(loc_id,name,H5P_DEFAULT)>0; +}; } // close unnamed namespace @@ -141,7 +146,7 @@ void nuSQUIDS::init(double xini){ void nuSQUIDS::Set_E(double Enu){ if( ne != 1 ) - throw std::runtime_error("nuSQUIDS::Error:Can only use Set_E in single energy mode."); + throw std::runtime_error("nuSQUIDS::Error:Cannot use Set_E in single energy mode."); E_range = marray{1}; E_range[0] = Enu; Set_xrange(std::vector{Enu}); @@ -279,10 +284,6 @@ void nuSQUIDS::PreDerive(double x){ track->SetX(x-time_offset); current_ye = body->ye(*track); current_density = body->density(*track); - if(enable_neutrino_sources){ - body->injected_neutrino_flux(current_external_flux,*track,*this); - assert(current_external_flux.extent(0) == ne && current_external_flux.extent(1) == nrhos && current_external_flux.extent(2) == numneu); - } if( basis != mass and ioscillations){ EvolveProjectors(x); } @@ -300,13 +301,13 @@ void nuSQUIDS::EvolveProjectors(double x){ std::unique_ptr evol_buf(new double[H0_array[0].GetEvolveBufferSize()]); for(unsigned int ei = 0; ei < ne; ei++){ H0_array[ei].PrepareEvolve(evol_buf.get(),x-Get_t_initial()); - if (evol_lowpass_cutoff > 0){ + if (evol_lowpass_cutoff.extent(0) > ei and evol_lowpass_scale.extent(0) > ei and evol_lowpass_cutoff[ei] > 0){ // std::cout << "evol_buf: "; // for (unsigned int i = 0; i < H0_array[ei].GetEvolveBufferSize(); i++){ // std::cout << evol_buf.get()[i] << " "; // } // std::cout << std::endl; - H0_array[ei].LowPassFilter(evol_buf.get(), evol_lowpass_cutoff, evol_lowpass_scale); + H0_array[ei].LowPassFilter(evol_buf.get(), evol_lowpass_cutoff[ei], evol_lowpass_scale[ei]); // std::cout << "evol_buf after filter: "; // for (unsigned int i = 0; i < H0_array[ei].GetEvolveBufferSize(); i++){ // std::cout << evol_buf.get()[i] << " "; @@ -321,7 +322,9 @@ void nuSQUIDS::EvolveProjectors(double x){ (b1_proj[rho][flv].Evolve(evol_buf.get())); } } + AddToEvolveProjectors(x,ei,evol_buf.get()); } + AddToEvolveProjectors(x); return; } @@ -375,16 +378,8 @@ squids::SU_vector nuSQUIDS::InteractionsRho(unsigned int e1,unsigned int index_r if(iinteraction && !ioscillations) //can use precomputed result from UpdateInteractions return(interaction_cache[index_rho][e1]); - if (not iinteraction and not enable_neutrino_sources) + if (not iinteraction) return squids::SU_vector(nsun); - else if (not iinteraction) { - squids::SU_vector external_flux_contribution(current_external_flux[e1][index_rho][0]*evol_b1_proj[index_rho][0][e1]); - for(unsigned int i = 1; i < numneu; i++) - external_flux_contribution+=squids::detail::guarantee - - (current_external_flux[e1][index_rho][i]*evol_b1_proj[index_rho][i][e1]); - return external_flux_contribution; - } // NC interactions double factor_e =nc_factors[index_rho][0][e1]; @@ -402,14 +397,6 @@ squids::SU_vector nuSQUIDS::InteractionsRho(unsigned int e1,unsigned int index_r factor_mu +=gr_factors[e1]; factor_tau+=gr_factors[e1]; } - - // add explicitly - if(enable_neutrino_sources){ - factor_e +=current_external_flux[e1][index_rho][0]; - factor_mu +=current_external_flux[e1][index_rho][1]; - factor_tau+=current_external_flux[e1][index_rho][2]; - } - // Add the weighted projectors squids::SU_vector interaction_term(factor_e*evol_b1_proj[index_rho][0][e1]); interaction_term+=squids::detail::guarantee @@ -418,15 +405,7 @@ squids::SU_vector nuSQUIDS::InteractionsRho(unsigned int e1,unsigned int index_r interaction_term+=squids::detail::guarantee (factor_tau*evol_b1_proj[index_rho][2][e1]); - - if(enable_neutrino_sources){ - for(unsigned int i = 3; i < numneu; i++){ - interaction_term+=squids::detail::guarantee - - (current_external_flux[e1][index_rho][i]*evol_b1_proj[index_rho][i][e1]); - } - } - + return interaction_term; } @@ -839,19 +818,6 @@ void nuSQUIDS::UpdateInteractions(){ (factors_nu_tau[e1]*projector_tau); } - - if(enable_neutrino_sources){ - for(unsigned int rho = 0; rho < nrhos; rho++){ - for(unsigned int e1=0; e1 - (current_external_flux[e1][rho][i]*evol_b1_proj[rho][i][e1]); - } - } - } - } - } } //end of no oscillation handling @@ -1092,27 +1058,25 @@ void nuSQUIDS::GetCrossSections(){ for(unsigned int flv = 0; flv < numneu; flv++){ for(unsigned int e1 = 0; e1 < ne; e1++){ // differential cross sections - dsignudE_NC[neutype][flv][e1][0] = xs->SingleDifferentialCrossSection(E_range[e1],E_range[0],(NeutrinoCrossSections::NeutrinoFlavor)flv,neutype_xs_dict[neutype],NeutrinoCrossSections::NC)*cm2GeV; - validateCrossSection(dsignudE_NC[neutype][flv][e1][0],cm2GeV,"NC",true,E_range[e1],E_range[0],flv); - dsignudE_CC[neutype][flv][e1][0] = xs->SingleDifferentialCrossSection(E_range[e1],E_range[0],(NeutrinoCrossSections::NeutrinoFlavor)flv,neutype_xs_dict[neutype],NeutrinoCrossSections::CC)*cm2GeV; - validateCrossSection(dsignudE_CC[neutype][flv][e1][0],cm2GeV,"CC",true,E_range[e1],E_range[0],flv); - for(unsigned int e2 = 1; e2 < e1; e2++){ - dsignudE_NC[neutype][flv][e1][e2] = xs->AverageSingleDifferentialCrossSection(E_range[e1],E_range[e2-1],E_range[e2],(NeutrinoCrossSections::NeutrinoFlavor)flv,neutype_xs_dict[neutype],NeutrinoCrossSections::NC)*cm2GeV; + for(unsigned int e2 = 0; e2 < e1; e2++){ + dsignudE_NC[neutype][flv][e1][e2] = xs->AverageSingleDifferentialCrossSection(E_range[e1],E_range[e2],E_range[e2+1],(NeutrinoCrossSections::NeutrinoFlavor)flv,neutype_xs_dict[neutype],NeutrinoCrossSections::NC)*cm2GeV; validateCrossSection(dsignudE_NC[neutype][flv][e1][e2],cm2GeV,"NC",true,E_range[e1],E_range[e2],flv); - dsignudE_CC[neutype][flv][e1][e2] = xs->AverageSingleDifferentialCrossSection(E_range[e1],E_range[e2-1],E_range[e2],(NeutrinoCrossSections::NeutrinoFlavor)flv,neutype_xs_dict[neutype],NeutrinoCrossSections::CC)*cm2GeV; + dsignudE_CC[neutype][flv][e1][e2] = xs->AverageSingleDifferentialCrossSection(E_range[e1],E_range[e2],E_range[e2+1],(NeutrinoCrossSections::NeutrinoFlavor)flv,neutype_xs_dict[neutype],NeutrinoCrossSections::CC)*cm2GeV; validateCrossSection(dsignudE_CC[neutype][flv][e1][e2],cm2GeV,"CC",true,E_range[e1],E_range[e2],flv); } // total cross sections - if(e1>0) { - int_struct->sigma_CC[target][neutype][flv][e1] = xs->AverageTotalCrossSection(E_range[e1-1],E_range[e1],(NeutrinoCrossSections::NeutrinoFlavor)flv,neutype_xs_dict[neutype],NeutrinoCrossSections::CC)*cm2; - int_struct->sigma_NC[target][neutype][flv][e1] = xs->AverageTotalCrossSection(E_range[e1-1],E_range[e1],(NeutrinoCrossSections::NeutrinoFlavor)flv,neutype_xs_dict[neutype],NeutrinoCrossSections::NC)*cm2; - } - else { + if(e1sigma_CC[target][neutype][flv][e1] = xs->AverageTotalCrossSection(E_range[e1],E_range[e1+1],(NeutrinoCrossSections::NeutrinoFlavor)flv,neutype_xs_dict[neutype],NeutrinoCrossSections::CC)*cm2; + } else { int_struct->sigma_CC[target][neutype][flv][e1] = xs->TotalCrossSection(E_range[e1],static_cast(flv),neutype_xs_dict[neutype],NeutrinoCrossSections::CC)*cm2; + validateCrossSection(int_struct->sigma_CC[target][neutype][flv][e1],cm2,"CC",false,E_range[e1],0,flv); + } + if(e1sigma_NC[target][neutype][flv][e1] = xs->AverageTotalCrossSection(E_range[e1],E_range[e1+1],(NeutrinoCrossSections::NeutrinoFlavor)flv,neutype_xs_dict[neutype],NeutrinoCrossSections::NC)*cm2; + } else { int_struct->sigma_NC[target][neutype][flv][e1] = xs->TotalCrossSection(E_range[e1],static_cast(flv),neutype_xs_dict[neutype],NeutrinoCrossSections::NC)*cm2; + validateCrossSection(int_struct->sigma_NC[target][neutype][flv][e1],cm2,"NC",false,E_range[e1],0,flv); } - validateCrossSection(int_struct->sigma_CC[target][neutype][flv][e1],cm2,"CC",false,E_range[e1],0,flv); - validateCrossSection(int_struct->sigma_NC[target][neutype][flv][e1],cm2,"NC",false,E_range[e1],0,flv); } } } @@ -1151,13 +1115,14 @@ void nuSQUIDS::GetCrossSections(){ throw std::runtime_error("Glashow Resonance handling is active, but the supplied cross sections do not include a cross section for electrons"); marray dsignudE_GR{ne,ne}; for(unsigned int e1 = 0; e1 < ne; e1++){ - if(e1>0) - int_struct->sigma_GR[e1] = gr_cs->AverageTotalCrossSection(E_range[e1-1],E_range[e1],NeutrinoCrossSections::electron,NeutrinoCrossSections::antineutrino,NeutrinoCrossSections::GR)*cm2; - else + if(e1sigma_GR[e1] = gr_cs->AverageTotalCrossSection(E_range[e1],E_range[e1+1],NeutrinoCrossSections::electron,NeutrinoCrossSections::antineutrino,NeutrinoCrossSections::GR)*cm2; + } else { int_struct->sigma_GR[e1] = gr_cs->TotalCrossSection(E_range[e1],NeutrinoCrossSections::electron,NeutrinoCrossSections::antineutrino,NeutrinoCrossSections::GR)*cm2; - dsignudE_GR[e1][0] = gr_cs->SingleDifferentialCrossSection(E_range[e1],E_range[0],NeutrinoCrossSections::electron,NeutrinoCrossSections::antineutrino,NeutrinoCrossSections::GR)*cm2GeV; - for(unsigned int e2 = 1; e2 < e1; e2++) - dsignudE_GR[e1][e2] = gr_cs->AverageSingleDifferentialCrossSection(E_range[e1],E_range[e2-1],E_range[e2],NeutrinoCrossSections::electron,NeutrinoCrossSections::antineutrino,NeutrinoCrossSections::GR)*cm2GeV; + } + for(unsigned int e2 = 0; e2 < e1; e2++){ + dsignudE_GR[e1][e2] = gr_cs->AverageSingleDifferentialCrossSection(E_range[e1],E_range[e2],E_range[e2+1],NeutrinoCrossSections::electron,NeutrinoCrossSections::antineutrino,NeutrinoCrossSections::GR)*cm2GeV; + } } for(unsigned int e1 = 0; e1 < ne; e1++){ for(unsigned int e2 = 0; e2 < e1; e2++){ @@ -1477,6 +1442,32 @@ double nuSQUIDS::EvalFlavor(unsigned int flv,double EE,unsigned int rho) const{ return GetExpectationValueD(b1_proj[rho][flv], rho, EE); } +double nuSQUIDS::EvalFlavorLowPass(unsigned int flv,double EE,unsigned int rho) const{ + if ( not ienergy ) + throw std::runtime_error("nuSQUIDS::Error::Energy not set."); + if ( rho != 0 and NT != both ) + throw std::runtime_error("nuSQUIDS::Error::Cannot evaluate rho != 0 in this NT mode."); + if ( EE < *E_range.begin() || EE > *E_range.rbegin() ) + throw std::runtime_error("nuSQUIDS::Error::Energy "+std::to_string(EE)+" outside of propagated energy range, [" + +std::to_string(*E_range.begin())+","+std::to_string(*E_range.rbegin())+"]."); + if(evol_lowpass_cutoff.extent(0) != ne or evol_lowpass_scale.extent(0) != ne) + throw std::runtime_error("nuSQUIDS::Error::Cannot apply LowPassFilter because LowPassCutoff or LowPassScale are not initialized."); + if ( basis == mass ) + return b1_proj[rho][flv]*GetIntermediateState(rho,EE); + + auto xit=std::lower_bound(E_range.begin(),E_range.end(),EE); + if(xit==E_range.end()) + throw std::runtime_error("SQUIDS::GetExpectationValueD : x value not in the array."); + if(xit!=E_range.begin()) + xit--; + size_t xid=std::distance(E_range.begin(),xit); + double f2=((EE-E_range[xid])/(E_range[xid+1]-E_range[xid])); + double f1=1-f2; + double scale = evol_lowpass_scale[xid]*f1 + evol_lowpass_scale[xid+1]*f2; + double cutoff = evol_lowpass_cutoff[xid]*f1 + evol_lowpass_cutoff[xid+1]*f2; + return GetExpectationValueD(b1_proj[rho][flv], rho, EE, scale, cutoff); +} + double nuSQUIDS::EvalMass(unsigned int flv,double EE, unsigned int rho, double scale, std::vector& avr) const{ if ( not ienergy ) throw std::runtime_error("nuSQUIDS::Error::Energy not set."); @@ -1685,6 +1676,41 @@ squids::SU_vector nuSQUIDS::GetHamiltonian(unsigned int ei, unsigned int rho){ return H0(E_range[ei],rho)+HI(ei,rho,Get_t()); } +struct H5Handle{ + H5Handle():id(-1),deleter(nullptr){} + H5Handle(hid_t id, herr_t(*deleter)(hid_t), const char* desc): + id(id),deleter(deleter){ + if(id<0){ + if(desc) + throw std::runtime_error(std::string("Failed to ")+desc); + else + throw std::runtime_error("Failed to get HDF5 object"); + } + } + H5Handle(const H5Handle&)=delete; + H5Handle(H5Handle&& other): + id(other.id),deleter(other.deleter){ + other.id=-1; + } + ~H5Handle(){ + if(id>=0) + (*deleter)(id); + } + H5Handle& operator=(H5Handle&)=delete; + H5Handle& operator=(H5Handle&& other){ + if(&other!=this){ + std::swap(id,other.id); + std::swap(deleter,other.deleter); + } + return *this; + } + hid_t get() const{ return id; } + operator hid_t() const{ return id; } +private: + hid_t id; + herr_t(*deleter)(hid_t); +}; + void nuSQUIDS::WriteStateHDF5(std::string str,std::string grp,bool save_cross_section, std::string cross_section_grp_loc, bool overwrite) const{ if ( body == nullptr ) throw std::runtime_error("nuSQUIDS::Error::BODY is a NULL pointer"); @@ -1752,6 +1778,10 @@ void nuSQUIDS::WriteStateHDF5(std::string str,std::string grp,bool save_cross_se H5LTset_attribute_int(group, "basic", "tau_regeneration", &auxint, 1); auxint = static_cast(iglashow); H5LTset_attribute_int(group, "basic", "glashow_resonance", &auxint, 1); + auxint = static_cast(average); + H5LTset_attribute_int(group, "basic", "average", &auxint, 1); + auxint = static_cast(lowpass); + H5LTset_attribute_int(group, "basic", "lowpass", &auxint, 1); double auxt = Get_t(); H5LTset_attribute_double(group, "basic", "squids_time", &auxt,1); double auxt_ini = Get_t_initial(); @@ -1825,7 +1855,7 @@ void nuSQUIDS::WriteStateHDF5(std::string str,std::string grp,bool save_cross_se xs_group = H5Handle(H5Gcreate(group, "crosssections", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT),H5Gclose," create HDF5 group"); } else { //this location is shared, so the group may already exist - if(h5ObjectExists(rootGroup, cross_section_grp_loc.c_str())){ + if(objectExists(rootGroup, cross_section_grp_loc.c_str())){ xs_group = H5Handle(H5Gopen(rootGroup, cross_section_grp_loc.c_str(), H5P_DEFAULT), H5Gclose, "open HDF5 shared crosssection group"); } else{ //but if it does not exist, just create it @@ -2076,88 +2106,99 @@ void nuSQUIDS::AddToReadHDF5(hid_t hdf5_loc_id){ } void nuSQUIDS::ReadStateHDF5Internal(std::string str,std::string grp,std::shared_ptr iis){ + hid_t file_id,group_id,root_id; // open HDF5 file //std::cout << "reading from hdf5 file" << std::endl; - H5File file(H5Fopen(str.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT)); - if (file < 0) + file_id = H5Fopen(str.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); + if (file_id < 0) throw std::runtime_error("nuSQUIDS::Error::file not found : " + str + "."); - H5Handle rootGroup(H5Gopen(file, "/", H5P_DEFAULT), H5Gclose, "open HDF5 group"); + root_id = H5Gopen(file_id, "/", H5P_DEFAULT); if (strncmp(grp.c_str(),"/",1)!=0){ std::cout << "nuSQUIDS::ReadStateHDF5::Warning::group location name did not start with '/'. '/' was prepend to " + grp << std::endl; grp = "/"+grp; } - H5Handle group(H5Gopen(rootGroup, grp.c_str(), H5P_DEFAULT),H5Gclose,"open HDF5 group"); - if ( group < 0 ) + group_id = H5Gopen(root_id, grp.c_str(), H5P_DEFAULT); + if ( group_id < 0 ) throw std::runtime_error("nuSQUIDS::Error::Group '" + grp + "' does not exist in HDF5."); // read number of neutrinos - H5LTget_attribute_uint(group, "basic", "numneu", static_cast(&numneu)); + H5LTget_attribute_uint(group_id, "basic", "numneu", static_cast(&numneu)); // neutrino/antineutrino/both int auxint; char auxchar[20]; herr_t err; - H5LTget_attribute_int(group, "basic", "NT", &auxint); + H5LTget_attribute_int(group_id, "basic", "NT", &auxint); NT = static_cast(auxint); // interactions - H5LTget_attribute_string(group,"basic","interactions", auxchar); + H5LTget_attribute_string(group_id,"basic","interactions", auxchar); std::string aux = auxchar; if ( aux == "True") iinteraction = true; else iinteraction = false; - err=H5LTget_attribute_int(group, "basic", "oscillations", &auxint); + err=H5LTget_attribute_int(group_id, "basic", "oscillations", &auxint); if(err>=0) ioscillations=auxint; - err=H5LTget_attribute_int(group, "basic", "tau_regeneration", &auxint); + err=H5LTget_attribute_int(group_id, "basic", "tau_regeneration", &auxint); if(err>=0) tauregeneration=auxint; - err=H5LTget_attribute_int(group, "basic", "glashow_resonance", &auxint); + err=H5LTget_attribute_int(group_id, "basic", "glashow_resonance", &auxint); if(err>=0) iglashow=auxint; + err=H5LTget_attribute_int(group_id, "basic", "average", &auxint); + if(err>=0) average=auxint; + err=H5LTget_attribute_int(group_id, "basic", "lowpass", &auxint); + if(err>=0) lowpass=auxint; double squids_time; - H5LTget_attribute_double(group, "basic", "squids_time", &squids_time); + H5LTget_attribute_double(group_id, "basic", "squids_time", &squids_time); double squids_time_initial; - H5LTget_attribute_double(group, "basic", "squids_time_initial", &squids_time_initial); + H5LTget_attribute_double(group_id, "basic", "squids_time_initial", &squids_time_initial); // check version numbers unsigned int squids_version; - H5LTget_attribute_uint(group, "basic", "squids_version_number", &squids_version); + H5LTget_attribute_uint(group_id, "basic", "squids_version_number", &squids_version); if ( squids_version > SQUIDS_VERSION ) throw std::runtime_error("nuSQUIDS::ReadStateHDF5::Error: File was written using SQuIDS version " + std::to_string(squids_version) + " current version is " + std::to_string(SQUIDS_VERSION)); unsigned int nusquids_version; - H5LTget_attribute_uint(group, "basic", "nusquids_version_number", &nusquids_version); + H5LTget_attribute_uint(group_id, "basic", "nusquids_version_number", &nusquids_version); if ( nusquids_version > NUSQUIDS_VERSION ) throw std::runtime_error("nuSQUIDS::ReadStateHDF5::Error: File was written using nuSQuIDS version " + std::to_string(nusquids_version) + " current version is " + std::to_string(NUSQUIDS_VERSION)); // reading body and track if(nusquids_version>100000){ - std::string body_name = getStringAttribute(group,"body","name"); - H5Handle body_group(H5Gopen(group, "body", H5P_DEFAULT), H5Gclose, "open body group"); - body=GetBodyDeserializer(body_name)(body_group); - - H5Handle track_group(H5Gopen(group, "track", H5P_DEFAULT), H5Gclose, "open track group"); - std::string track_name = getStringAttribute(group,"track","name"); - track=GetTrackDeserializer(track_name)(track_group); + std::string body_name = getStringAttribute(group_id,"body","name"); + hid_t body_group_id = H5Gopen(group_id, "body", H5P_DEFAULT); + if(body_group_id<0) + throw std::runtime_error("nuSQuIDS::Error opening body group"); + body=GetBodyDeserializer(body_name)(body_group_id); + H5Gclose(body_group_id); + + hid_t track_group_id = H5Gopen(group_id, "track", H5P_DEFAULT); + if(track_group_id<0) + throw std::runtime_error("nuSQuIDS::Error opening track group"); + std::string track_name = getStringAttribute(group_id,"track","name"); + track=GetTrackDeserializer(track_name)(track_group_id); + H5Gclose(track_group_id); } else { unsigned int body_id; hsize_t dimbody[1]; - H5LTget_attribute_uint(group,"body","ID",&body_id); + H5LTget_attribute_uint(group_id,"body","ID",&body_id); - H5LTget_dataset_info(group,"body", dimbody,nullptr,nullptr); + H5LTget_dataset_info(group_id,"body", dimbody,nullptr,nullptr); double body_params[dimbody[0]]; - H5LTread_dataset_double(group,"body", body_params); + H5LTread_dataset_double(group_id,"body", body_params); hsize_t dimtrack[1]; - H5LTget_dataset_info(group,"track", dimtrack ,nullptr,nullptr); + H5LTget_dataset_info(group_id,"track", dimtrack ,nullptr,nullptr); std::unique_ptr track_params(new double[dimtrack[0]]); - H5LTread_dataset_double(group,"track", track_params.get()); + H5LTread_dataset_double(group_id,"track", track_params.get()); double x_current; - H5LTget_attribute_double(group,"track","X",&x_current); + H5LTget_attribute_double(group_id,"track","X",&x_current); // setting body and track SetBodyTrack(body_id,dimbody[0],body_params,dimtrack[0],track_params.get()); @@ -2167,11 +2208,11 @@ void nuSQUIDS::ReadStateHDF5Internal(std::string str,std::string grp,std::shared // reading energy hsize_t dims[2]; - H5LTget_dataset_info(group, "energies", dims, nullptr, nullptr); + H5LTget_dataset_info(group_id, "energies", dims, nullptr, nullptr); ne = static_cast(dims[0]); std::unique_ptr energy_data(new double[ne]); - H5LTread_dataset_double(group, "energies", energy_data.get()); + H5LTread_dataset_double(group_id, "energies", energy_data.get()); E_range = marray{ne}; for (unsigned int ie = 0; ie < ne; ie++) E_range[ie] = energy_data[ie]; @@ -2192,12 +2233,12 @@ void nuSQUIDS::ReadStateHDF5Internal(std::string str,std::string grp,std::shared for( unsigned int j = i+1; j < numneu; j++ ){ double th_value; std::string th_label = "th"+std::to_string(i+1)+std::to_string(j+1); - H5LTget_attribute_double(group,"mixingangles", th_label.c_str(), &th_value); + H5LTget_attribute_double(group_id,"mixingangles", th_label.c_str(), &th_value); Set_MixingAngle(i,j,th_value); double delta_value; std::string delta_label = "delta"+std::to_string(i+1)+std::to_string(j+1); - H5LTget_attribute_double(group,"CPphases", delta_label.c_str(), &delta_value); + H5LTget_attribute_double(group_id,"CPphases", delta_label.c_str(), &delta_value); Set_CPPhase(i,j,delta_value); } } @@ -2205,7 +2246,7 @@ void nuSQUIDS::ReadStateHDF5Internal(std::string str,std::string grp,std::shared for( unsigned int i = 1; i < numneu; i++ ){ double dm2_value; std::string dm2_label = "dm"+std::to_string(i+1)+"1sq"; - H5LTget_attribute_double(group,"massdifferences", dm2_label.c_str(), &dm2_value); + H5LTget_attribute_double(group_id,"massdifferences", dm2_label.c_str(), &dm2_value); Set_SquareMassDifference(i, dm2_value); } @@ -2228,13 +2269,13 @@ void nuSQUIDS::ReadStateHDF5Internal(std::string str,std::string grp,std::shared EvolveProjectors(squids_time); // reading state - H5LTget_dataset_info(group,"neustate", dims,nullptr,nullptr); + H5LTget_dataset_info(group_id,"neustate", dims,nullptr,nullptr); std::unique_ptr neudata(new double[dims[0]*dims[1]]); - H5LTread_dataset_double(group,"neustate", neudata.get()); + H5LTread_dataset_double(group_id,"neustate", neudata.get()); - H5LTget_dataset_info(group,"aneustate", dims,nullptr,nullptr); + H5LTget_dataset_info(group_id,"aneustate", dims,nullptr,nullptr); std::unique_ptr aneudata(new double[dims[0]*dims[1]]); - H5LTread_dataset_double(group,"aneustate", aneudata.get()); + H5LTread_dataset_double(group_id,"aneustate", aneudata.get()); for(unsigned int ie = 0; ie < dims[0]; ie++){ for (unsigned int j = 0; j < dims[1]; j ++){ @@ -2267,12 +2308,20 @@ void nuSQUIDS::ReadStateHDF5Internal(std::string str,std::string grp,std::shared } // read from user parameters - hid_t user_parameters_id = H5Gopen(group, "user_parameters", H5P_DEFAULT); + hid_t user_parameters_id = H5Gopen(group_id, "user_parameters", H5P_DEFAULT); //H5Eset_auto (H5E_DEFAULT,(H5E_auto_t) H5Eprint,stderr); AddToReadHDF5(user_parameters_id); //H5Eset_auto (H5E_DEFAULT,nullptr,nullptr); H5Gclose(user_parameters_id); + // close HDF5 file + H5Gclose ( group_id ); + // close root and file + H5Gclose ( root_id ); + H5Fclose (file_id); + // close all HDF5 variables/memory + H5close(); + // we assume that this was created with the writer and got to this point! istate = true; ienergy = true; @@ -2320,6 +2369,10 @@ void nuSQUIDS::ReadStateHDF5(std::string str,std::string grp,std::string cross_s if(err>=0) tauregeneration=auxint; err=H5LTget_attribute_int(group, "basic", "glashow_resonance", &auxint); if(err>=0) iglashow=auxint; + err=H5LTget_attribute_int(group, "basic", "average", &auxint); + if(err>=0) average=auxint; + err=H5LTget_attribute_int(group, "basic", "lowpass", &auxint); + if(err>=0) lowpass=auxint; double squids_time; H5LTget_attribute_double(group, "basic", "squids_time", &squids_time); @@ -2344,12 +2397,20 @@ void nuSQUIDS::ReadStateHDF5(std::string str,std::string grp,std::string cross_s // reading body and track if(nusquids_version>100000){ H5Handle body_group(H5Gopen(group, "body", H5P_DEFAULT), H5Gclose, "open body group"); - std::string body_name = getStringAttribute(group,"body","name"); - body=GetBodyDeserializer(body_name)(body_group); - - H5Handle track_group(H5Gopen(group, "track", H5P_DEFAULT), H5Gclose, "open track group"); + std::string body_name = getStringAttribute(group,"body","name"); + //hid_t body_group_id = H5Gopen(group_id, "body", H5P_DEFAULT); + //if(body_group_id<0) + // throw std::runtime_error("nuSQuIDS::Error opening body group"); + //body=GetBodyDeserializer(body_name)(body_group_id); + //H5Gclose(body_group_id); + body=GetBodyDeserializer(body_name)(body_group); + + hid_t track_group_id = H5Gopen(group, "track", H5P_DEFAULT); + if(track_group_id<0) + throw std::runtime_error("nuSQuIDS::Error opening track group"); std::string track_name = getStringAttribute(group,"track","name"); - track=GetTrackDeserializer(track_name)(track_group); + track=GetTrackDeserializer(track_name)(track_group_id); + H5Gclose(track_group_id); } else { unsigned int body_id; hsize_t dimbody[1]; @@ -2762,10 +2823,9 @@ void nuSQUIDS::SetBodyTrack(unsigned int body_id, unsigned int body_params_len, } case 7: { - auto earth = std::make_shared(); - body = earth; + body = std::make_shared(); // track_param[2] corresponds to the zenith angle - track = std::make_shared(earth->MakeTrack(track_params[2])); + track = std::make_shared(track_params[2]); break; } default: @@ -2819,12 +2879,37 @@ void nuSQUIDS::Set_ProgressBar(bool opt){ } void nuSQUIDS::Set_EvolLowPassCutoff(double val){ + if(evol_lowpass_cutoff.extent(0) != ne) { + evol_lowpass_cutoff = marray({ne}); + } + for(unsigned int ie=0; ie < ne; ++ie) { + evol_lowpass_cutoff[ie] = val; + } +} + +void nuSQUIDS::Set_EvolLowPassCutoff(const marray& val){ + if(val.extent(0) != ne) { + throw std::runtime_error("nuSQUIDS::Error::LowPassCutoff extents must match the number of energy nodes, thus LowPassCutoff cannot be set to the specified value."); + } evol_lowpass_cutoff = val; } void nuSQUIDS::Set_EvolLowPassScale(double val){ + if(evol_lowpass_scale.extent(0) != ne) { + evol_lowpass_scale = marray({ne}); + } + for(unsigned int ie=0; ie < ne; ++ie) { + evol_lowpass_scale[ie] = val; + } +} + +void nuSQUIDS::Set_EvolLowPassScale(const marray& val){ + if(val.extent(0) != ne) { + throw std::runtime_error("nuSQUIDS::Error::LowPassScale extents must match the number of energy nodes, thus LowPassScale cannot be set to the specified value."); + } evol_lowpass_scale = val; } + void nuSQUIDS::Set_IncludeOscillations(bool opt){ ioscillations = opt; } diff --git a/src/taudecay.cpp b/src/taudecay.cpp index 9c230414..3088fd7d 100644 --- a/src/taudecay.cpp +++ b/src/taudecay.cpp @@ -120,7 +120,10 @@ double TauDecaySpectra::TauDecayToAll(double E_tau, double E_nu) const{ // define tau decay object void TauDecaySpectra::SetParameters(bool neutrino_type){ - TauPolarization = -1.0; // due to CP symmetry both tau and antitau spectra are the same + if(neutrino_type) + TauPolarization = -1.0; + else + TauPolarization = 1.0; RPion = SQR(0.07856); RRho = SQR(0.43335); RA1 = SQR(0.70913); BrLepton = 0.18; BrPion = 0.12; BrRho = 0.26; BrRA1 = 0.13; BrHadron = 0.13; } @@ -141,7 +144,10 @@ void TauDecaySpectra::Init(marray E_range){ dNdEle_Lep_tbl.resize(std::vector{neutrino_number,e_size,e_size}); for(unsigned int neutype = 0; neutype < neutrino_number; neutype++){ - TauPolarization = -1.0; // due to CP symmetry both tau and antitau spectra are the same + if(neutype == 0) + TauPolarization = -1.0; + else + TauPolarization = 1.0; for(unsigned int e1 = 0 ; e1 < e_size ; e1 ++){ double Enu1 = E_range[e1]/GeV; // tau energy for(unsigned int e2 = 0 ; e2 < e_size ; e2 ++){ diff --git a/src/tools.cpp b/src/tools.cpp index fc8ade31..b1701944 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -475,10 +475,6 @@ double BiCubicInterpolator::operator()(double x, double y) const{ result=result*t + ((c0[3]*u+c0[2])*u+c0[1])*u+c0[0]; return result; } - -bool h5ObjectExists(hid_t loc_id, const char* name){ - return H5Lexists(loc_id,name,H5P_DEFAULT)>0 && H5Oexists_by_name(loc_id,name,H5P_DEFAULT)>0; -}; template<> void addH5Attribute(hid_t object, std::string name, const std::string& contents){ diff --git a/src/xsections.cpp b/src/xsections.cpp index 0c3ed7c5..16439813 100644 --- a/src/xsections.cpp +++ b/src/xsections.cpp @@ -25,9 +25,6 @@ #include #include -#include -#include - #include "nuSQuIDS/AdaptiveQuad.h" #include "nuSQuIDS/resources.h" @@ -55,7 +52,7 @@ namespace{ double a1=std::abs(est1); double a2=std::abs(est2); if(a1(a1/a2)-1) || (a1==a2)); + return((a2 && tol>(a1/a2)-1) || (!a2 && a1second) - throw std::runtime_error("No cross sections for flavor "+std::to_string(flavor)); - return *it->second; -} NeutrinoDISCrossSectionsFromTables::NeutrinoDISCrossSectionsFromTables(): NeutrinoDISCrossSectionsFromTables(getResourcePath()+"/xsections/csms_square.h5"){} @@ -212,10 +201,9 @@ double NeutrinoDISCrossSectionsFromTables::TotalCrossSection(double Enu, Neutrin return TotalCrossSection(Emin, flavor, neutype, current)*(Enu/Emin); } - const auto& flavorData=getFlavor(flavor); const AkimaSpline& sigma= - (neutype==neutrino ? (current==CC ? flavorData.s_CC_nu : flavorData.s_NC_nu) - : (current==CC ? flavorData.s_CC_nubar : flavorData.s_NC_nubar)); + (neutype==neutrino ? (current==CC ? s_CC_nu : s_NC_nu) + : (current==CC ? s_CC_nubar : s_NC_nubar)); return pow(10.,sigma(log10(Enu))); } @@ -230,10 +218,9 @@ double NeutrinoDISCrossSectionsFromTables::SingleDifferentialCrossSection(double if (E1 <= Emin) return std::numeric_limits::min(); - const auto& flavorData=getFlavor(flavor); const BiCubicInterpolator& dsdy= - (neutype==neutrino ? (current==CC ? flavorData.dsdy_CC_nu : flavorData.dsdy_NC_nu) - : (current==CC ? flavorData.dsdy_CC_nubar : flavorData.dsdy_NC_nubar)); + (neutype==neutrino ? (current==CC ? dsdy_CC_nu : dsdy_NC_nu) + : (current==CC ? dsdy_CC_nubar : dsdy_NC_nubar)); double z=(E2-Emin)/(E1-Emin); double val=dsdy(log10(E1),z); if(E2<=Emin){ //if extrapolating, make sure no blow-up happens @@ -265,73 +252,34 @@ double NeutrinoDISCrossSectionsFromTables::AverageSingleDifferentialCrossSection }; return fastInt(integrand,E2Min,E2Max,1e-3)/(E2Max-E2Min); } - -std::shared_ptr -NeutrinoDISCrossSectionsFromTables::readFlavorText(const std::string& prefix, - std::string& erangeSrc){ - auto data=std::make_shared(); - + +void NeutrinoDISCrossSectionsFromTables::ReadText(const std::string& prefix){ double eMinTmp, eMaxTmp; - std::tie(data->s_CC_nu,eMinTmp,eMaxTmp)=read1DInterpolationFromText(prefix+"nu_sigma_CC.dat"); - //if the global energy minimum and maximum have not yet been set, set them - if(!(Emin>0 && Emax>0)){ - Emin=eMinTmp; - Emax=eMaxTmp; - erangeSrc=prefix+"nu_sigma_CC.dat"; - } - std::tie(data->s_NC_nu,eMinTmp,eMaxTmp)=read1DInterpolationFromText(prefix+"nu_sigma_NC.dat"); + std::tie(s_CC_nu,eMinTmp,eMaxTmp)=read1DInterpolationFromText(prefix+"nu_sigma_CC.dat"); + Emin=eMinTmp; + Emax=eMaxTmp; + std::tie(s_NC_nu,eMinTmp,eMaxTmp)=read1DInterpolationFromText(prefix+"nu_sigma_NC.dat"); if(eMinTmp!=Emin || eMaxTmp!=Emax) - throw std::runtime_error(prefix+"nu_sigma_NC.dat has different energy domain than "+erangeSrc); - std::tie(data->s_CC_nubar,eMinTmp,eMaxTmp)=read1DInterpolationFromText(prefix+"nubar_sigma_CC.dat"); + throw std::runtime_error(prefix+"nu_sigma_NC.dat has different energy domain than "+prefix+"nu_sigma_CC.dat"); + std::tie(s_CC_nubar,eMinTmp,eMaxTmp)=read1DInterpolationFromText(prefix+"nubar_sigma_CC.dat"); if(eMinTmp!=Emin || eMaxTmp!=Emax) - throw std::runtime_error(prefix+"nubar_sigma_CC.dat has different energy domain than "+erangeSrc); - std::tie(data->s_NC_nubar,eMinTmp,eMaxTmp)=read1DInterpolationFromText(prefix+"nubar_sigma_NC.dat"); + throw std::runtime_error(prefix+"nubar_sigma_CC.dat has different energy domain than "+prefix+"nu_sigma_CC.dat"); + std::tie(s_NC_nubar,eMinTmp,eMaxTmp)=read1DInterpolationFromText(prefix+"nubar_sigma_NC.dat"); if(eMinTmp!=Emin || eMaxTmp!=Emax) - throw std::runtime_error(prefix+"nubar_sigma_NC.dat has different energy domain than "+erangeSrc); + throw std::runtime_error(prefix+"nubar_sigma_NC.dat has different energy domain than "+prefix+"nu_sigma_CC.dat"); - std::tie(data->dsdy_CC_nu,eMinTmp,eMaxTmp)=read2DInterpolationFromText(prefix+"nu_dsde_CC.dat"); + std::tie(dsdy_CC_nu,eMinTmp,eMaxTmp)=read2DInterpolationFromText(prefix+"nu_dsde_CC.dat"); if(eMinTmp!=Emin || eMaxTmp!=Emax) - throw std::runtime_error(prefix+"nu_dsde_CC.dat has different energy domain than "+erangeSrc); - std::tie(data->dsdy_NC_nu,eMinTmp,eMaxTmp)=read2DInterpolationFromText(prefix+"nu_dsde_NC.dat"); + throw std::runtime_error(prefix+"nu_dsde_CC.dat has different energy domain than "+prefix+"nu_sigma_CC.dat"); + std::tie(dsdy_NC_nu,eMinTmp,eMaxTmp)=read2DInterpolationFromText(prefix+"nu_dsde_NC.dat"); if(eMinTmp!=Emin || eMaxTmp!=Emax) - throw std::runtime_error(prefix+"nu_dsde_NC.dat has different energy domain than "+erangeSrc); - std::tie(data->dsdy_CC_nubar,eMinTmp,eMaxTmp)=read2DInterpolationFromText(prefix+"nubar_dsde_CC.dat"); + throw std::runtime_error(prefix+"nu_dsde_NC.dat has different energy domain than "+prefix+"nu_sigma_CC.dat"); + std::tie(dsdy_CC_nubar,eMinTmp,eMaxTmp)=read2DInterpolationFromText(prefix+"nubar_dsde_CC.dat"); if(eMinTmp!=Emin || eMaxTmp!=Emax) - throw std::runtime_error(prefix+"nubar_dsde_CC.dat has different energy domain than "+erangeSrc); - std::tie(data->dsdy_NC_nubar,eMinTmp,eMaxTmp)=read2DInterpolationFromText(prefix+"nubar_dsde_NC.dat"); + throw std::runtime_error(prefix+"nubar_dsde_CC.dat has different energy domain than "+prefix+"nu_sigma_CC.dat"); + std::tie(dsdy_NC_nubar,eMinTmp,eMaxTmp)=read2DInterpolationFromText(prefix+"nubar_dsde_NC.dat"); if(eMinTmp!=Emin || eMaxTmp!=Emax) - throw std::runtime_error(prefix+"nubar_dsde_NC.dat has different energy domain than "+erangeSrc); - - return data; -} - -void NeutrinoDISCrossSectionsFromTables::ReadText(const std::string& prefix){ - auto expectedFilesExist=[](const std::string& prefix)->bool{ - return fexists(prefix+"nu_sigma_CC.dat") && fexists(prefix+"nu_sigma_NC.dat") && - fexists(prefix+"nubar_sigma_CC.dat") && fexists(prefix+"nubar_sigma_NC.dat") && - fexists(prefix+"nu_dsde_CC.dat") && fexists(prefix+"nu_dsde_NC.dat") && - fexists(prefix+"nubar_dsde_CC.dat") && fexists(prefix+"nubar_dsde_NC.dat"); - }; - std::string erangeSrc=""; - //check for old-style files with common data for all flavors - if(expectedFilesExist(prefix)){ - Emin=Emax=std::numeric_limits::quiet_NaN(); - std::shared_ptr data=readFlavorText(prefix,erangeSrc); - xsData[electron]=data; - xsData[muon]=data; - xsData[tau]=data; - } - //new style files with distinct per-flavor data - else if(expectedFilesExist(prefix+"electron_") && - expectedFilesExist(prefix+"muon_") && - expectedFilesExist(prefix+"tau_")){ - Emin=Emax=std::numeric_limits::quiet_NaN(); - xsData[electron]=readFlavorText(prefix+"electron_",erangeSrc); - xsData[muon]=readFlavorText(prefix+"muon_",erangeSrc); - xsData[tau]=readFlavorText(prefix+"tau_",erangeSrc); - } - else - throw std::runtime_error("Unrecognized text file layout in "+prefix); + throw std::runtime_error(prefix+"nubar_dsde_NC.dat has different energy domain than "+prefix+"nu_sigma_CC.dat"); } void NeutrinoDISCrossSectionsFromTables::WriteText(const std::string& prefix) const{ @@ -358,231 +306,70 @@ void NeutrinoDISCrossSectionsFromTables::WriteText(const std::string& prefix) co outfile << en << ' ' << y[j] << ' ' << pow(10.,z[i][j]) << '\n'; } }; - NeutrinoFlavor flavor; - std::string name; - for(auto item : std::unordered_map{{electron,"electron"}, - {muon,"muon"}, - {tau,"tau"}}){ - std::tie(flavor, name) = item; - std::string flavor_prefix=prefix+name+"_"; - const auto& data=getFlavor(flavor); - write1D(data.s_CC_nu,flavor_prefix+"nu_sigma_CC.dat"); - write1D(data.s_NC_nu,flavor_prefix+"nu_sigma_NC.dat"); - write1D(data.s_CC_nubar,flavor_prefix+"nubar_sigma_CC.dat"); - write1D(data.s_NC_nubar,flavor_prefix+"nubar_sigma_NC.dat"); - write2D(data.dsdy_CC_nu,flavor_prefix+"nu_dsde_CC.dat"); - write2D(data.dsdy_NC_nu,flavor_prefix+"nu_dsde_NC.dat"); - write2D(data.dsdy_CC_nubar,flavor_prefix+"nubar_dsde_CC.dat"); - write2D(data.dsdy_NC_nubar,flavor_prefix+"nubar_dsde_NC.dat"); - } + write1D(s_CC_nu,prefix+"nu_sigma_CC.dat"); + write1D(s_NC_nu,prefix+"nu_sigma_NC.dat"); + write1D(s_CC_nubar,prefix+"nubar_sigma_CC.dat"); + write1D(s_NC_nubar,prefix+"nubar_sigma_NC.dat"); + write2D(dsdy_CC_nu,prefix+"nu_dsde_CC.dat"); + write2D(dsdy_NC_nu,prefix+"nu_dsde_NC.dat"); + write2D(dsdy_CC_nubar,prefix+"nubar_dsde_CC.dat"); + write2D(dsdy_NC_nubar,prefix+"nubar_dsde_NC.dat"); } - -std::shared_ptr -NeutrinoDISCrossSectionsFromTables::readFlavorHDF5(hid_t sourceLoc, - const marray& energies, - const marray& zs){ - auto data=std::make_shared(); + +void NeutrinoDISCrossSectionsFromTables::ReadHDF(const std::string& path){ + try{ + H5File h5file(H5Fopen(path.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT)); + + marray energies,zs; + readArrayH5(h5file, "energies", energies); + readArrayH5(h5file, "zs", zs); + Emin=pow(10.,energies.front()); + Emax=pow(10.,energies.back()); marray buffer1; auto readTotal=[&](AkimaSpline& dest, const std::string& tableName){ - readArrayH5(sourceLoc, tableName, buffer1); + readArrayH5(h5file, tableName, buffer1); if(buffer1.extent(0)!=energies.extent(0)) throw std::runtime_error(tableName+" does not have the same dimensions as energies"); dest=AkimaSpline(energies.get_data(),buffer1.get_data(),energies.size()); }; - readTotal(data->s_CC_nu,"s_CC_nu"); - readTotal(data->s_NC_nu,"s_NC_nu"); - readTotal(data->s_CC_nubar,"s_CC_nubar"); - readTotal(data->s_NC_nubar,"s_NC_nubar"); + readTotal(s_CC_nu,"s_CC_nu"); + readTotal(s_NC_nu,"s_NC_nu"); + readTotal(s_CC_nubar,"s_CC_nubar"); + readTotal(s_NC_nubar,"s_NC_nubar"); marray buffer2; auto readDifferential=[&](BiCubicInterpolator& dest, const std::string& tableName){ - readArrayH5(sourceLoc, tableName, buffer2); //reallocates the target array + readArrayH5(h5file, tableName, buffer2); //reallocates the target array if(buffer2.extent(0)!=energies.extent(0)) throw std::runtime_error(tableName+" does not have the same first dimension as energies"); if(buffer2.extent(1)!=zs.extent(0)) throw std::runtime_error(tableName+"'s second dimension does not have the same size as zs"); dest=BiCubicInterpolator(std::move(buffer2),energies,zs); }; - readDifferential(data->dsdy_CC_nu,"dsdy_CC_nu"); - readDifferential(data->dsdy_NC_nu,"dsdy_NC_nu"); - readDifferential(data->dsdy_CC_nubar,"dsdy_CC_nubar"); - readDifferential(data->dsdy_NC_nubar,"dsdy_NC_nubar"); - - return data; -} - -namespace{ -#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 12 - #define H5Lget_info_compat 1 -#else - #define H5Lget_info_compat 2 -#endif - ///A helper class for determining whether different HDF5 names refer to the - ///same underlying object - struct h5HardLinkID{ - hid_t loc; -#if H5Lget_info_compat == 1 - haddr_t addr; -#elif H5Lget_info_compat == 2 - H5O_token_t addr; -#endif - h5HardLinkID(hid_t loc, const std::string& name):loc(loc){ - herr_t err=0; - -#if H5Lget_info_compat == 1 - H5L_info_t linfo; - err=H5Lget_info(loc, name.c_str(), &linfo, H5P_DEFAULT); - if(err<0) - throw std::runtime_error("Failed to get link info for object named "+name); - if(linfo.type!=H5L_TYPE_HARD) - throw std::runtime_error("Object named "+name+" is not a hard link"); - addr=linfo.u.address; -#elif H5Lget_info_compat == 2 - H5L_info2_t linfo; - err=H5Lget_info2(loc, name.c_str(), &linfo, H5P_DEFAULT); - if(err<0) - throw std::runtime_error("Failed to get link info for object named "+name); - if(linfo.type!=H5L_TYPE_HARD) - throw std::runtime_error("Object named "+name+" is not a hard link"); - addr=linfo.u.token; -#endif - } - - bool operator==(const h5HardLinkID& other){ -#if H5Lget_info_compat == 1 - return addr==other.addr; -#elif H5Lget_info_compat == 2 - int val; - herr_t err=H5Otoken_cmp(loc, &addr, &other.addr, &val); - if(err<0) - throw std::runtime_error("Unable to compare HDF5 tokens"); - return val==0; -#endif - } - - bool operator!=(const h5HardLinkID& other){ - return !(*this==other); - } - }; -#undef H5Lget_info_compat -} - -void NeutrinoDISCrossSectionsFromTables::ReadHDF(const std::string& path){ - try{ - H5File h5file(H5Fopen(path.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT)); - - marray energies,zs; - readArrayH5(h5file, "energies", energies); - readArrayH5(h5file, "zs", zs); - Emin=pow(10.,energies.front()); - Emax=pow(10.,energies.back()); - - //check for old-style files with common data for all flavors - if(h5ObjectExists(h5file,"s_CC_nu") && h5ObjectExists(h5file,"s_CC_nubar") && - h5ObjectExists(h5file,"s_NC_nu") && h5ObjectExists(h5file,"s_NC_nubar") && - h5ObjectExists(h5file,"dsdy_CC_nu") && h5ObjectExists(h5file,"dsdy_CC_nubar") && - h5ObjectExists(h5file,"dsdy_NC_nu") && h5ObjectExists(h5file,"dsdy_NC_nubar")){ - std::shared_ptr data=readFlavorHDF5(h5file,energies,zs); - xsData[electron]=data; - xsData[muon]=data; - xsData[tau]=data; - } - //new style files with distinct per-flavor data - else if(h5ObjectExists(h5file,"electron") && - h5ObjectExists(h5file,"muon") && - h5ObjectExists(h5file,"tau")){ - h5HardLinkID eID(h5file,"electron"); - h5HardLinkID mID(h5file,"muon"); - h5HardLinkID tID(h5file,"tau"); - - H5Handle nueGrp(H5Gopen(h5file,"electron",H5P_DEFAULT), H5Gclose,"open HDF5 group for nu_e cross sections"); - std::shared_ptr nueData=readFlavorHDF5(nueGrp,energies,zs); - xsData[electron]=nueData; - - if(mID==eID) //if the data is an alias, don't read it again - xsData[muon]=xsData[electron]; - else{ - H5Handle numuGrp(H5Gopen(h5file,"muon",H5P_DEFAULT), H5Gclose,"open HDF5 group for nu_mu cross sections"); - std::shared_ptr numuData=readFlavorHDF5(numuGrp,energies,zs); - xsData[muon]=numuData; - } - - if(tID==eID) - xsData[tau]=xsData[electron]; - else if(tID==mID) - xsData[tau]=xsData[muon]; - else{ - H5Handle nutauGrp(H5Gopen(h5file,"tau",H5P_DEFAULT), H5Gclose,"open HDF5 group for nu_tau cross sections"); - std::shared_ptr nutauData=readFlavorHDF5(nutauGrp,energies,zs); - xsData[tau]=nutauData; - } - } - else - throw std::runtime_error("Unrecognized HDF5 data object layout in "+path); + readDifferential(dsdy_CC_nu,"dsdy_CC_nu"); + readDifferential(dsdy_NC_nu,"dsdy_NC_nu"); + readDifferential(dsdy_CC_nubar,"dsdy_CC_nubar"); + readDifferential(dsdy_NC_nubar,"dsdy_NC_nubar"); } catch(std::runtime_error& err){ throw std::runtime_error("Failed to read cross sections from "+path+": "+err.what()); } } - -void NeutrinoDISCrossSectionsFromTables::writeFlavorHDF5(hid_t destLoc, const perFlavorData& data, unsigned int compressionLevel) const{ - using StoreType=float; - writeArrayH5(destLoc, "s_CC_nu", data.s_CC_nu.getOrdinates(), compressionLevel); - writeArrayH5(destLoc, "s_NC_nu", data.s_NC_nu.getOrdinates(), compressionLevel); - writeArrayH5(destLoc, "s_CC_nubar", data.s_CC_nubar.getOrdinates(), compressionLevel); - writeArrayH5(destLoc, "s_NC_nubar", data.s_NC_nubar.getOrdinates(), compressionLevel); - writeArrayH5(destLoc, "dsdy_CC_nu", data.dsdy_CC_nu.getData(), compressionLevel); - writeArrayH5(destLoc, "dsdy_NC_nu", data.dsdy_NC_nu.getData(), compressionLevel); - writeArrayH5(destLoc, "dsdy_CC_nubar", data.dsdy_CC_nubar.getData(), compressionLevel); - writeArrayH5(destLoc, "dsdy_NC_nubar", data.dsdy_NC_nubar.getData(), compressionLevel); -} void NeutrinoDISCrossSectionsFromTables::WriteHDF(const std::string& path, unsigned int compressionLevel) const{ + using StoreType=float; H5File h5file(H5Fcreate(path.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)); - - { - using StoreType=float; - assert(xsData.size()>0); - const perFlavorData& data=*xsData.begin()->second; - writeArrayH5(h5file, "energies", data.dsdy_CC_nu.getXCoords(), compressionLevel); - writeArrayH5(h5file, "zs", data.dsdy_CC_nu.getYCoords(), compressionLevel); - } - - auto flavorsSame=[this](NeutrinoFlavor f1, NeutrinoFlavor f2)->bool{ - auto it1=xsData.find(f1); - auto it2=xsData.find(f2); - return it1->second == it2->second; - }; - - auto makeAlias=[&h5file](const std::string& srcName, const std::string& destName){ - H5Handle create_plist(H5Pcreate(H5P_LINK_CREATE),&H5Pclose,"create a link creation property list"); - H5Handle access_plist(H5Pcreate(H5P_LINK_ACCESS),&H5Pclose,"create a link access property list"); - herr_t err=H5Lcreate_hard(h5file, srcName.c_str(), h5file, destName.c_str(), create_plist, access_plist); - if(err<0) - throw std::runtime_error("Failed to create HDF5 hardlink from "+srcName+" to "+destName); - }; - - { - H5Handle nueGrp(H5Gcreate(h5file, "electron", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT),H5Gclose,"create HDF5 group for nu_e cross sections"); - writeFlavorHDF5(nueGrp, getFlavor(electron), compressionLevel); - } - - if(true || flavorsSame(electron,muon)) - makeAlias("electron","muon"); - else{ - H5Handle numuGrp(H5Gcreate(h5file, "muon", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT),H5Gclose,"create HDF5 group for nu_mu cross sections"); - writeFlavorHDF5(numuGrp, getFlavor(muon), compressionLevel); - } - - if(flavorsSame(electron,tau)) - makeAlias("electron","tau"); - else if(flavorsSame(muon,tau)) - makeAlias("muon","tau"); - else{ - H5Handle nutauGrp(H5Gcreate(h5file, "tau", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT),H5Gclose,"create HDF5 group for nu_tau cross sections"); - writeFlavorHDF5(nutauGrp, getFlavor(tau), compressionLevel); - } + writeArrayH5(h5file, "energies", dsdy_CC_nu.getXCoords(), compressionLevel); + writeArrayH5(h5file, "zs", dsdy_CC_nu.getYCoords(), compressionLevel); + writeArrayH5(h5file, "s_CC_nu", s_CC_nu.getOrdinates(), compressionLevel); + writeArrayH5(h5file, "s_NC_nu", s_NC_nu.getOrdinates(), compressionLevel); + writeArrayH5(h5file, "s_CC_nubar", s_CC_nubar.getOrdinates(), compressionLevel); + writeArrayH5(h5file, "s_NC_nubar", s_NC_nubar.getOrdinates(), compressionLevel); + writeArrayH5(h5file, "dsdy_CC_nu", dsdy_CC_nu.getData(), compressionLevel); + writeArrayH5(h5file, "dsdy_NC_nu", dsdy_NC_nu.getData(), compressionLevel); + writeArrayH5(h5file, "dsdy_CC_nubar", dsdy_CC_nubar.getData(), compressionLevel); + writeArrayH5(h5file, "dsdy_NC_nubar", dsdy_NC_nubar.getData(), compressionLevel); } double NeutrinoDISCrossSectionsFromTables_V1::LinInter(double x,double xM, double xP,double yM,double yP) const{ diff --git a/test/Expected_Failures.txt b/test/Expected_Failures.txt index e69de29b..b402eb53 100644 --- a/test/Expected_Failures.txt +++ b/test/Expected_Failures.txt @@ -0,0 +1,3 @@ +cross_section_consistency.test.cpp +earth_osc_prob.test.cpp +glashow_resonance.test.cpp diff --git a/test/body_serialization.test.cpp b/test/body_serialization.test.cpp index efbf05b8..b0e9c638 100644 --- a/test/body_serialization.test.cpp +++ b/test/body_serialization.test.cpp @@ -69,7 +69,7 @@ int main(){ auto ctr = ConstantDensity::Track::Deserialize(track_group_id); if ( fabs(cr->density(*ctr) - c.density(ct)) >1.0e-5 ) - std::cout << "densities are different after serializing for constant_density: Before = " << c.density(ct) << " After = " << cr->density(*ctr) << std::endl; + std::cout << "densities are different after serializing for constant_density" << std::endl; if ( fabs(cr->ye(*ctr) - c.ye(ct)) >1.0e-5 ) std::cout << "ye are different after serializing for constant_density" << std::endl; @@ -97,10 +97,10 @@ int main(){ auto varr = VariableDensity::Deserialize(body_group_id); auto vartr = VariableDensity::Track::Deserialize(track_group_id); - if ( fabs(varr->density(*vartr) - var.density(vart)) >1.0e-5 ) - std::cout << "densities are different after serializing for variable_density: Before = " << var.density(vart) << " After = " << cr->density(*ctr) << std::endl; + if ( fabs(varr->density(*ctr) - var.density(vart)) >1.0e-5 ) + std::cout << "densities are different after serializing for constant_density" << std::endl; if ( fabs(varr->ye(*vartr) - var.ye(vart)) >1.0e-5 ) - std::cout << "ye are different after serializing for variable_density" << std::endl; + std::cout << "ye are different after serializing for constant_density" << std::endl; // close hdf5 groups H5Gclose(body_group_id); @@ -124,9 +124,9 @@ int main(){ auto earthtr = Earth::Track::Deserialize(track_group_id); if ( fabs(earthr->density(*earthtr) - earth.density(eartht)) >1.0e-5 ) - std::cout << "densities are different after serializing for Earth: Before = " << earth.density(eartht) << " After = " << earthr->density(*earthtr) << std::endl; + std::cout << "densities are different after serializing for constant_density" << std::endl; if ( fabs(earthr->ye(*earthtr) - earth.ye(eartht)) >1.0e-5 ) - std::cout << "ye are different after serializing for Earth" << std::endl; + std::cout << "ye are different after serializing for constant_density" << std::endl; // close hdf5 groups H5Gclose(body_group_id); @@ -150,9 +150,9 @@ int main(){ auto suntr = Sun::Track::Deserialize(track_group_id); if ( fabs(sunr->density(*suntr) - sun.density(sunt)) >1.0e-5 ) - std::cout << "densities are different after serializing for Sun: Before = " << sun.density(sunt) << " After = " << sunr->density(*suntr) << std::endl; + std::cout << "densities are different after serializing for constant_density" << std::endl; if ( fabs(sunr->ye(*suntr) - sun.ye(sunt)) >1.0e-5 ) - std::cout << "ye are different after serializing for Sun" << std::endl; + std::cout << "ye are different after serializing for constant_density" << std::endl; // close hdf5 groups H5Gclose(body_group_id); @@ -176,9 +176,9 @@ int main(){ auto sunasnutr = SunASnu::Track::Deserialize(track_group_id); if ( fabs(sunasnur->density(*sunasnutr) - sunasnu.density(sunasnut)) >1.0e-5 ) - std::cout << "densities are different after serializing for SunASnu: Before = " << sunasnu.density(sunasnut) << " After = " << sunasnur->density(*sunasnutr) << std::endl; + std::cout << "densities are different after serializing for constant_density" << std::endl; if ( fabs(sunasnur->ye(*sunasnutr) - sunasnu.ye(sunasnut)) >1.0e-5 ) - std::cout << "ye are different after serializing for SunASnu" << std::endl; + std::cout << "ye are different after serializing for constant_density" << std::endl; // close hdf5 groups H5Gclose(body_group_id); @@ -189,8 +189,7 @@ int main(){ // testing earthatm // ************************************ EarthAtm earthatm; - earthatm.SetAtmosphereHeight(50/*km*/); - EarthAtm::Track earthatmt(10.*units.km,acos(-1.0),earthatm.GetRadius()*units.km,earthatm.GetAtmosphereHeight()*units.km); + EarthAtm::Track earthatmt(10.*units.km,acos(-1.0)); // open groups hid_t earthatm_group_id = H5Gcreate(file_id, "earthatm", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); @@ -202,16 +201,10 @@ int main(){ auto earthatmr = EarthAtm::Deserialize(body_group_id); auto earthatmtr = EarthAtm::Track::Deserialize(track_group_id); - if (earthatmtr->GetX() != earthatmt.GetX()) - std::cout << "track positions are different after serializing for EarthAtm: Before = " << earthatmt.GetX() << " After = " << earthatmtr->GetX() << std::endl; - if (earthatmtr->GetInitialX() != earthatmt.GetInitialX()) - std::cout << "track initial positions are different after serializing for EarthAtm: Before = " << earthatmt.GetInitialX() << " After = " << earthatmtr->GetInitialX() << std::endl; - if (earthatmtr->GetFinalX() != earthatmt.GetFinalX()) - std::cout << "track final positions are different after serializing for EarthAtm: Before = " << earthatmt.GetFinalX() << " After = " << earthatmtr->GetFinalX() << std::endl; if ( fabs(earthatmr->density(*earthatmtr) - earthatm.density(earthatmt)) >1.0e-5 ) - std::cout << "densities are different after serializing for EarthAtm: Before = " << earthatm.density(earthatmt) << " After = " << earthatmr->density(*earthatmtr) << std::endl; + std::cout << "densities are different after serializing for constant_density" << std::endl; if ( fabs(earthatmr->ye(*earthatmtr) - earthatm.ye(earthatmt)) >1.0e-5 ) - std::cout << "ye are different after serializing for EarthAtm" << std::endl; + std::cout << "ye are different after serializing for constant_density" << std::endl; // close hdf5 groups H5Gclose(body_group_id); diff --git a/test/cross_section_consistency.output.txt b/test/cross_section_consistency.output.txt new file mode 100644 index 00000000..e69de29b diff --git a/test/cross_section_consistency.test.cpp b/test/cross_section_consistency.test.cpp new file mode 100644 index 00000000..1b15eacd --- /dev/null +++ b/test/cross_section_consistency.test.cpp @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace nusquids; + +int main(){ + // units + const unsigned int numneu = 3; + squids::Const units; + double Emin = 1.0e2*units.GeV; + double Emax = 1.0e6*units.GeV; + unsigned int Esize = 100; + nuSQUIDS nus(logspace(Emin,Emax,Esize),numneu,both,true); + + auto energies = nus.GetERange(); + nus.InitializeInteractions(); + auto is = nus.GetInteractionStructure(); + + for(unsigned int rho = 0; rho < 2; rho++){ + for(unsigned int flv = 0; flv < numneu; flv++){ + for(unsigned int ei = 1; ei < nus.GetNumE(); ei++){ + // initialze muon state + double total_CC_xs = is->sigma_CC[rho][flv][ei]; + if(total_CC_xs < 0.) + std::cout << "Error: negative cross sections." << std::endl; + double total_NC_xs = is->sigma_NC[rho][flv][ei]; + if(total_NC_xs < 0.) + std::cout << "Error: negative cross sections." << std::endl; + /* + double total_dNdECC = 0; + double begincap_dNdECC = energies[0]*is->dNdE_CC[rho][flv][ei][0]; + for(unsigned int ef = 0; ef < ei; ef++){ + total_dNdECC += (is->dNdE_CC[rho][flv][ei][ef+1]+is->dNdE_CC[rho][flv][ei][ef])*(energies[ef+1]-energies[ef])/2.; + } + if(std::abs(total_dNdECC + begincap_dNdECC - 1.0) > 1.0e-2) + std::cout << "Error: CC cross sectiosn are not unitarity: "<< ei << " " << total_dNdECC + begincap_dNdECC << std::endl; + */ + double total_dNdENC = 0; + double begincap_dNdENC = energies[0]*is->dNdE_NC[rho][flv][ei][0]; + double m = 0; + for(unsigned int ef = 0; ef < ei; ef++){ + //total_dNdENC += is->dNdE_NC[rho][flv][ei][ef]*(energies[ef+1]-energies[ef]); + //total_dNdENC += (is->dNdE_NC[rho][flv][ei][ef+1]+is->dNdE_NC[rho][flv][ei][ef])*(energies[ef+1]-energies[ef])/2.; + if(ef + 1 == ei) + total_dNdENC += (is->dNdE_NC[rho][flv][ei][ef])*(energies[ef+1]-energies[ef]) + m*(energies[ef+1]-energies[ef])*(energies[ef+1]-energies[ef]); + else + total_dNdENC += (is->dNdE_NC[rho][flv][ei][ef+1] + is->dNdE_NC[rho][flv][ei][ef])*(energies[ef+1]-energies[ef])/2.; + m = (is->dNdE_NC[rho][flv][ei][ef+1]-is->dNdE_NC[rho][flv][ei][ef])/(energies[ef+1]-energies[ef]); + //std::cout << ef << " " << std::endl; + //total_dNdENC += (is->dNdE_NC[rho][flv][ei][ef])*(energies[ef+1]-energies[ef]); + } + if(std::abs(total_dNdENC + begincap_dNdENC - 1.0) > 1.0e-2) + std::cout << "Error: NC cross sectiosn are not unitarity: "<< rho << " " << flv << " " << ei << " " << total_dNdENC + begincap_dNdENC << std::endl; + } + } + } + + return 0; +} diff --git a/test/earth_osc_prob.output.txt b/test/earth_osc_prob.output.txt index 9de9ac01..eaad4fbe 100644 --- a/test/earth_osc_prob.output.txt +++ b/test/earth_osc_prob.output.txt @@ -1,98 +1,98 @@ -Body 0 [flv] 1.000e-02 [GeV] 9.222e-01 3.376e-02 4.402e-02 +Body 0 [flv] 1.000e-02 [GeV] 9.227e-01 3.355e-02 4.374e-02 Body 0 [flv] 1.000e-01 [GeV] 4.043e-01 4.044e-01 1.913e-01 Body 0 [flv] 1.000e+00 [GeV] 9.901e-01 2.607e-03 7.295e-03 Body 0 [flv] 1.000e+01 [GeV] 9.911e-01 4.660e-03 4.259e-03 Body 0 [flv] 1.000e+02 [GeV] 9.999e-01 4.443e-05 4.372e-05 Body 0 [flv] 1.000e+03 [GeV] 1.000e+00 4.406e-07 4.372e-07 Body 0 [flv] 1.000e+04 [GeV] 1.000e+00 0.000e+00 0.000e+00 -Body 1 [flv] 1.000e-02 [GeV] 3.727e-02 1.005e-01 8.622e-01 +Body 1 [flv] 1.000e-02 [GeV] 3.783e-02 1.007e-01 8.615e-01 Body 1 [flv] 1.000e-01 [GeV] 3.667e-01 4.593e-01 1.739e-01 -Body 1 [flv] 1.000e+00 [GeV] 3.088e-03 9.937e-01 3.209e-03 +Body 1 [flv] 1.000e+00 [GeV] 3.087e-03 9.937e-01 3.209e-03 Body 1 [flv] 1.000e+01 [GeV] 4.238e-03 9.026e-01 9.314e-02 Body 1 [flv] 1.000e+02 [GeV] 4.400e-05 9.990e-01 9.634e-04 Body 1 [flv] 1.000e+03 [GeV] 4.402e-07 1.000e+00 9.638e-06 Body 1 [flv] 1.000e+04 [GeV] 0.000e+00 1.000e+00 9.638e-08 -Body 2 [flv] 1.000e-02 [GeV] 4.051e-02 8.657e-01 9.378e-02 -Body 2 [flv] 1.000e-01 [GeV] 2.289e-01 1.363e-01 6.347e-01 -Body 2 [flv] 1.000e+00 [GeV] 6.814e-03 3.690e-03 9.895e-01 +Body 2 [flv] 1.000e-02 [GeV] 4.049e-02 8.656e-01 9.394e-02 +Body 2 [flv] 1.000e-01 [GeV] 2.290e-01 1.363e-01 6.347e-01 +Body 2 [flv] 1.000e+00 [GeV] 6.814e-03 3.689e-03 9.895e-01 Body 2 [flv] 1.000e+01 [GeV] 4.681e-03 9.272e-02 9.026e-01 Body 2 [flv] 1.000e+02 [GeV] 4.415e-05 9.630e-04 9.990e-01 Body 2 [flv] 1.000e+03 [GeV] 4.376e-07 9.637e-06 1.000e+00 Body 2 [flv] 1.000e+04 [GeV] 0.000e+00 9.638e-08 1.000e+00 -Body 0 [flv] 1.000e-02 [GeV] 9.155e-01 3.150e-03 8.133e-02 +Body 0 [flv] 1.000e-02 [GeV] 9.147e-01 3.269e-03 8.199e-02 Body 0 [flv] 1.000e-01 [GeV] 4.455e-01 3.411e-01 2.134e-01 -Body 0 [flv] 1.000e+00 [GeV] 9.845e-01 1.161e-02 3.876e-03 +Body 0 [flv] 1.000e+00 [GeV] 9.845e-01 1.161e-02 3.875e-03 Body 0 [flv] 1.000e+01 [GeV] 9.920e-01 3.834e-03 4.213e-03 Body 0 [flv] 1.000e+02 [GeV] 9.999e-01 4.358e-05 4.368e-05 Body 0 [flv] 1.000e+03 [GeV] 1.000e+00 4.398e-07 4.371e-07 Body 0 [flv] 1.000e+04 [GeV] 1.000e+00 0.000e+00 0.000e+00 -Body 1 [flv] 1.000e-02 [GeV] 5.877e-02 2.307e-01 7.105e-01 +Body 1 [flv] 1.000e-02 [GeV] 5.857e-02 2.303e-01 7.111e-01 Body 1 [flv] 1.000e-01 [GeV] 4.225e-01 5.049e-01 7.259e-02 -Body 1 [flv] 1.000e+00 [GeV] 1.209e-02 9.868e-01 1.137e-03 +Body 1 [flv] 1.000e+00 [GeV] 1.210e-02 9.868e-01 1.137e-03 Body 1 [flv] 1.000e+01 [GeV] 4.236e-03 9.026e-01 9.317e-02 Body 1 [flv] 1.000e+02 [GeV] 4.400e-05 9.990e-01 9.635e-04 Body 1 [flv] 1.000e+03 [GeV] 4.402e-07 1.000e+00 9.638e-06 Body 1 [flv] 1.000e+04 [GeV] 0.000e+00 1.000e+00 9.638e-08 -Body 2 [flv] 1.000e-02 [GeV] 2.571e-02 7.661e-01 2.082e-01 +Body 2 [flv] 1.000e-02 [GeV] 2.550e-02 7.662e-01 2.083e-01 Body 2 [flv] 1.000e-01 [GeV] 1.320e-01 1.539e-01 7.141e-01 -Body 2 [flv] 1.000e+00 [GeV] 3.393e-03 1.621e-03 9.950e-01 +Body 2 [flv] 1.000e+00 [GeV] 3.391e-03 1.620e-03 9.950e-01 Body 2 [flv] 1.000e+01 [GeV] 3.812e-03 9.357e-02 9.026e-01 Body 2 [flv] 1.000e+02 [GeV] 4.326e-05 9.639e-04 9.990e-01 Body 2 [flv] 1.000e+03 [GeV] 4.367e-07 9.638e-06 1.000e+00 Body 2 [flv] 1.000e+04 [GeV] 0.000e+00 9.638e-08 1.000e+00 -Body 0 [flv] 1.000e-02 [GeV] 8.844e-01 6.755e-02 4.777e-02 2.597e-04 -Body 0 [flv] 1.000e-01 [GeV] 3.695e-01 3.313e-01 2.363e-01 6.295e-02 -Body 0 [flv] 1.000e+00 [GeV] 9.377e-01 1.655e-02 1.635e-02 2.939e-02 -Body 0 [flv] 1.000e+01 [GeV] 9.292e-01 1.065e-02 2.278e-03 5.790e-02 -Body 0 [flv] 1.000e+02 [GeV] 9.614e-01 7.865e-03 2.061e-03 2.864e-02 +Body 0 [flv] 1.000e-02 [GeV] 8.847e-01 6.741e-02 4.763e-02 2.145e-04 +Body 0 [flv] 1.000e-01 [GeV] 3.698e-01 3.314e-01 2.363e-01 6.260e-02 +Body 0 [flv] 1.000e+00 [GeV] 9.384e-01 1.628e-02 1.624e-02 2.906e-02 +Body 0 [flv] 1.000e+01 [GeV] 9.292e-01 1.064e-02 2.275e-03 5.785e-02 +Body 0 [flv] 1.000e+02 [GeV] 9.614e-01 7.867e-03 2.061e-03 2.865e-02 Body 0 [flv] 1.000e+03 [GeV] 9.593e-01 8.455e-03 2.389e-03 2.988e-02 Body 0 [flv] 1.000e+04 [GeV] 9.964e-01 9.456e-04 2.693e-04 2.376e-03 -Body 1 [flv] 1.000e-02 [GeV] 2.841e-02 7.154e-03 6.017e-01 3.628e-01 -Body 1 [flv] 1.000e-01 [GeV] 2.950e-01 9.557e-02 2.442e-01 3.653e-01 -Body 1 [flv] 1.000e+00 [GeV] 6.464e-03 3.874e-01 5.503e-02 5.511e-01 -Body 1 [flv] 1.000e+01 [GeV] 3.058e-02 1.912e-01 1.347e-01 6.435e-01 -Body 1 [flv] 1.000e+02 [GeV] 8.987e-03 6.523e-01 2.283e-02 3.159e-01 -Body 1 [flv] 1.000e+03 [GeV] 8.557e-03 7.281e-01 1.738e-02 2.460e-01 +Body 1 [flv] 1.000e-02 [GeV] 2.857e-02 6.375e-03 6.046e-01 3.605e-01 +Body 1 [flv] 1.000e-01 [GeV] 2.947e-01 9.842e-02 2.414e-01 3.655e-01 +Body 1 [flv] 1.000e+00 [GeV] 6.419e-03 3.869e-01 5.511e-02 5.516e-01 +Body 1 [flv] 1.000e+01 [GeV] 3.063e-02 1.915e-01 1.346e-01 6.432e-01 +Body 1 [flv] 1.000e+02 [GeV] 8.988e-03 6.523e-01 2.284e-02 3.159e-01 +Body 1 [flv] 1.000e+03 [GeV] 8.558e-03 7.281e-01 1.737e-02 2.460e-01 Body 1 [flv] 1.000e+04 [GeV] 9.467e-04 9.553e-01 4.554e-03 3.916e-02 -Body 2 [flv] 1.000e-02 [GeV] 2.368e-02 6.061e-01 1.109e-01 2.593e-01 -Body 2 [flv] 1.000e-01 [GeV] 3.123e-01 1.352e-01 4.174e-01 1.351e-01 -Body 2 [flv] 1.000e+00 [GeV] 1.447e-02 4.599e-02 7.664e-01 1.731e-01 -Body 2 [flv] 1.000e+01 [GeV] 1.434e-02 1.321e-01 6.447e-01 2.088e-01 -Body 2 [flv] 1.000e+02 [GeV] 2.683e-03 2.272e-02 8.800e-01 9.459e-02 +Body 2 [flv] 1.000e-02 [GeV] 2.383e-02 6.098e-01 1.104e-01 2.560e-01 +Body 2 [flv] 1.000e-01 [GeV] 3.117e-01 1.355e-01 4.184e-01 1.344e-01 +Body 2 [flv] 1.000e+00 [GeV] 1.388e-02 4.418e-02 7.730e-01 1.689e-01 +Body 2 [flv] 1.000e+01 [GeV] 1.431e-02 1.326e-01 6.438e-01 2.092e-01 +Body 2 [flv] 1.000e+02 [GeV] 2.684e-03 2.272e-02 8.800e-01 9.459e-02 Body 2 [flv] 1.000e+03 [GeV] 2.445e-03 1.737e-02 9.097e-01 7.046e-02 Body 2 [flv] 1.000e+04 [GeV] 2.700e-04 4.554e-03 9.840e-01 1.113e-02 -Body 3 [flv] 1.000e-02 [GeV] 6.349e-02 3.192e-01 2.397e-01 3.776e-01 -Body 3 [flv] 1.000e-01 [GeV] 2.324e-02 4.379e-01 1.021e-01 4.367e-01 -Body 3 [flv] 1.000e+00 [GeV] 4.135e-02 5.501e-01 1.622e-01 2.464e-01 -Body 3 [flv] 1.000e+01 [GeV] 2.591e-02 6.660e-01 2.183e-01 8.977e-02 -Body 3 [flv] 1.000e+02 [GeV] 2.689e-02 3.171e-01 9.510e-02 5.609e-01 +Body 3 [flv] 1.000e-02 [GeV] 6.288e-02 3.159e-01 2.342e-01 3.871e-01 +Body 3 [flv] 1.000e-01 [GeV] 2.343e-02 4.374e-01 1.021e-01 4.371e-01 +Body 3 [flv] 1.000e+00 [GeV] 4.102e-02 5.514e-01 1.622e-01 2.454e-01 +Body 3 [flv] 1.000e+01 [GeV] 2.625e-02 6.649e-01 2.178e-01 9.100e-02 +Body 3 [flv] 1.000e+02 [GeV] 2.690e-02 3.171e-01 9.510e-02 5.609e-01 Body 3 [flv] 1.000e+03 [GeV] 2.972e-02 2.461e-01 7.050e-02 6.537e-01 Body 3 [flv] 1.000e+04 [GeV] 2.374e-03 3.917e-02 1.113e-02 9.473e-01 -Body 0 [flv] 1.000e-02 [GeV] 8.693e-01 1.396e-02 5.960e-02 5.711e-02 -Body 0 [flv] 1.000e-01 [GeV] 4.187e-01 3.019e-01 2.660e-01 1.340e-02 -Body 0 [flv] 1.000e+00 [GeV] 9.468e-01 1.757e-02 1.153e-02 2.411e-02 -Body 0 [flv] 1.000e+01 [GeV] 9.397e-01 2.655e-02 1.218e-02 2.156e-02 -Body 0 [flv] 1.000e+02 [GeV] 9.795e-01 6.527e-03 1.951e-03 1.198e-02 -Body 0 [flv] 1.000e+03 [GeV] 9.858e-01 5.125e-03 1.465e-03 7.582e-03 -Body 0 [flv] 1.000e+04 [GeV] 9.966e-01 9.228e-04 2.632e-04 2.221e-03 -Body 1 [flv] 1.000e-02 [GeV] 1.011e-01 9.911e-03 5.244e-01 3.646e-01 -Body 1 [flv] 1.000e-01 [GeV] 3.414e-01 1.732e-01 7.953e-02 4.058e-01 -Body 1 [flv] 1.000e+00 [GeV] 6.543e-03 3.212e-01 6.534e-02 6.070e-01 -Body 1 [flv] 1.000e+01 [GeV] 8.468e-03 1.936e-01 1.273e-01 6.706e-01 -Body 1 [flv] 1.000e+02 [GeV] 5.660e-03 5.761e-01 4.512e-02 3.731e-01 +Body 0 [flv] 1.000e-02 [GeV] 8.683e-01 1.444e-02 5.997e-02 5.726e-02 +Body 0 [flv] 1.000e-01 [GeV] 4.196e-01 3.016e-01 2.657e-01 1.316e-02 +Body 0 [flv] 1.000e+00 [GeV] 9.470e-01 1.771e-02 1.149e-02 2.384e-02 +Body 0 [flv] 1.000e+01 [GeV] 9.392e-01 2.669e-02 1.224e-02 2.189e-02 +Body 0 [flv] 1.000e+02 [GeV] 9.795e-01 6.528e-03 1.952e-03 1.198e-02 +Body 0 [flv] 1.000e+03 [GeV] 9.858e-01 5.125e-03 1.465e-03 7.581e-03 +Body 0 [flv] 1.000e+04 [GeV] 9.966e-01 9.227e-04 2.632e-04 2.221e-03 +Body 1 [flv] 1.000e-02 [GeV] 1.013e-01 9.366e-03 5.285e-01 3.609e-01 +Body 1 [flv] 1.000e-01 [GeV] 3.424e-01 1.738e-01 7.916e-02 4.047e-01 +Body 1 [flv] 1.000e+00 [GeV] 6.425e-03 3.186e-01 6.626e-02 6.087e-01 +Body 1 [flv] 1.000e+01 [GeV] 8.439e-03 1.931e-01 1.275e-01 6.710e-01 +Body 1 [flv] 1.000e+02 [GeV] 5.661e-03 5.761e-01 4.511e-02 3.731e-01 Body 1 [flv] 1.000e+03 [GeV] 5.058e-03 6.130e-01 5.416e-02 3.278e-01 Body 1 [flv] 1.000e+04 [GeV] 9.216e-04 9.545e-01 4.813e-03 3.974e-02 -Body 2 [flv] 1.000e-02 [GeV] 2.924e-02 5.695e-01 1.470e-01 2.542e-01 -Body 2 [flv] 1.000e-01 [GeV] 1.731e-01 1.901e-01 5.540e-01 8.282e-02 -Body 2 [flv] 1.000e+00 [GeV] 2.865e-03 7.341e-02 7.554e-01 1.683e-01 -Body 2 [flv] 1.000e+01 [GeV] 1.651e-03 1.301e-01 6.614e-01 2.068e-01 -Body 2 [flv] 1.000e+02 [GeV] 1.450e-03 4.525e-02 8.425e-01 1.108e-01 -Body 2 [flv] 1.000e+03 [GeV] 1.425e-03 5.417e-02 8.506e-01 9.380e-02 +Body 2 [flv] 1.000e-02 [GeV] 2.933e-02 5.716e-01 1.451e-01 2.540e-01 +Body 2 [flv] 1.000e-01 [GeV] 1.728e-01 1.906e-01 5.526e-01 8.402e-02 +Body 2 [flv] 1.000e+00 [GeV] 2.850e-03 7.340e-02 7.553e-01 1.684e-01 +Body 2 [flv] 1.000e+01 [GeV] 1.680e-03 1.301e-01 6.615e-01 2.067e-01 +Body 2 [flv] 1.000e+02 [GeV] 1.451e-03 4.524e-02 8.425e-01 1.108e-01 +Body 2 [flv] 1.000e+03 [GeV] 1.426e-03 5.417e-02 8.506e-01 9.380e-02 Body 2 [flv] 1.000e+04 [GeV] 2.625e-04 4.813e-03 9.836e-01 1.129e-02 -Body 3 [flv] 1.000e-02 [GeV] 3.338e-04 4.066e-01 2.690e-01 3.241e-01 -Body 3 [flv] 1.000e-01 [GeV] 6.685e-02 3.347e-01 1.005e-01 4.979e-01 -Body 3 [flv] 1.000e+00 [GeV] 4.380e-02 5.879e-01 1.677e-01 2.006e-01 -Body 3 [flv] 1.000e+01 [GeV] 5.018e-02 6.498e-01 1.991e-01 1.010e-01 +Body 3 [flv] 1.000e-02 [GeV] 4.117e-04 4.098e-01 2.649e-01 3.249e-01 +Body 3 [flv] 1.000e-01 [GeV] 6.699e-02 3.351e-01 1.003e-01 4.977e-01 +Body 3 [flv] 1.000e+00 [GeV] 4.330e-02 5.884e-01 1.664e-01 2.019e-01 +Body 3 [flv] 1.000e+01 [GeV] 4.983e-02 6.513e-01 1.995e-01 9.935e-02 Body 3 [flv] 1.000e+02 [GeV] 1.335e-02 3.722e-01 1.104e-01 5.041e-01 Body 3 [flv] 1.000e+03 [GeV] 7.687e-03 3.277e-01 9.377e-02 5.708e-01 Body 3 [flv] 1.000e+04 [GeV] 2.223e-03 3.973e-02 1.129e-02 9.467e-01 diff --git a/test/earth_osc_prob.test.cpp b/test/earth_osc_prob.test.cpp index c5bd874c..24192d02 100644 --- a/test/earth_osc_prob.test.cpp +++ b/test/earth_osc_prob.test.cpp @@ -34,8 +34,8 @@ void exercise_se_mode(unsigned int numneu,NeutrinoType NT, std::shared_ptr nus.Set_Body(body); squids::Const units; - nus.Set_rel_error(1.0e-10); - nus.Set_abs_error(1.0e-10); + nus.Set_rel_error(1.0e-5); + nus.Set_abs_error(1.0e-5); nus.Set_Basis(interaction); nus.Set_h(units.km); nus.Set_h_max(300.0*units.km); diff --git a/test/external_flux.output.txt b/test/external_flux.output.txt deleted file mode 100644 index ea7c8701..00000000 --- a/test/external_flux.output.txt +++ /dev/null @@ -1,6 +0,0 @@ -Interactions true, oscillations true, vacuum -Interactions true, oscillations false, vacuum -Interactions false, oscillations false, vacuum -Interactions false, oscillations true, vacuum -Interactions true, oscillations false, matter -Interactions true, oscillations true, matter diff --git a/test/external_flux.test.cpp b/test/external_flux.test.cpp deleted file mode 100644 index 1cc59e8b..00000000 --- a/test/external_flux.test.cpp +++ /dev/null @@ -1,264 +0,0 @@ -#include -#include -#include - -#include -#include - -using namespace nusquids; - -// Exponential source -// The assumption will be that it will be a all flavor neutrino source -// with an exponential decay profile. -class EmittingSlab: public ConstantDensity{ - private: - const double decay_length; - public : - EmittingSlab(double decay_length, double density, double ye): - ConstantDensity(density,ye),decay_length(decay_length){} - void injected_neutrino_flux(marray& flux, const GenericTrack& track, const nuSQUIDS& nusquids) override { - double x_cur = track.GetX(); - for(unsigned int ei=0; ei < nusquids.GetNumE(); ei++){ - for(unsigned int rhoi = 0; rhoi < nusquids.GetNumRho(); rhoi++){ - for(unsigned int flv = 0; flv < nusquids.GetNumNeu(); flv++){ - flux[ei][rhoi][flv] = exp(-x_cur/decay_length); - } - } - } - } -}; - -// Analytical solution -// Solution of a differential equation of the form -// dphi(t)/dt = - phi(t)/lambda_1 + exp(-t/lambda_2) -// with phi(0) = 0 and where -// lambda_1 : interaction_length -// lambda_2 : decay_length -double analytical_solution(double t, double interaction_length, double decay_length){ - if(interaction_length>=std::numeric_limits::max()){ - //when lambda_1 -> infinity the phi(t) term can be ignored - return decay_length*(1-exp(-t/decay_length)); - } - double c=(interaction_length*decay_length)/(decay_length-interaction_length); - return -c*exp(-t/interaction_length)+c*exp(-t/decay_length); -} - -void test(const nuSQUIDS& nus, - unsigned int Nen, double lEmin, double lEmax,double interaction_length, double decay_length, - std::shared_ptr track){ - squids::Const units; - for(double lE=lEmin; lEGetFinalX(),interaction_length,decay_length); - double del = nus.EvalFlavor(fl, E) - exact; - double rel = del/exact; - if(std::abs(rel) > 1.e-5 or std::isnan(del)) - std::cout << fl << ' ' << del << '\n'; - } - } -} - -int main(){ - squids::Const units; - const double integration_tol=1e-8; - - {// interactions true and osc true, vac - std::cout << "Interactions true, oscillations true, vacuum" << std::endl; - nuSQUIDS nus(logspace(1.e2*units.GeV,1.e6*units.GeV,60),3,neutrino,true); - double decay_length = 100.0*units.meter; - std::shared_ptr emit = std::make_shared(decay_length,0.0,0.5); - std::shared_ptr track = std::make_shared(1.0*units.km); - nus.Set_Body(emit); - nus.Set_Track(track); - nus.Set_rel_error(integration_tol); - nus.Set_abs_error(integration_tol); - nus.Set_NeutrinoSources(true); - nus.Set_IncludeOscillations(true); - - marray E_range = nus.GetERange(); - marray inistate{E_range.size(),nus.GetNumNeu()}; - std::fill(inistate.begin(),inistate.end(),0.0); - nus.Set_initial_state(inistate,flavor); - nus.EvolveState(); - - test(nus,1000,2,6,std::numeric_limits::max(),decay_length,track); - } - - {// interactions true and osc false, vac - std::cout << "Interactions true, oscillations false, vacuum" << std::endl; - nuSQUIDS nus(logspace(1.e2*units.GeV,1.e6*units.GeV,60),3,neutrino,true); - double decay_length = 100.0*units.meter; - std::shared_ptr emit = std::make_shared(decay_length,0.0,0.5); - std::shared_ptr track = std::make_shared(1.0*units.km); - nus.Set_Body(emit); - nus.Set_Track(track); - nus.Set_rel_error(integration_tol); - nus.Set_abs_error(integration_tol); - nus.Set_NeutrinoSources(true); - nus.Set_IncludeOscillations(false); - - marray E_range = nus.GetERange(); - marray inistate{E_range.size(),nus.GetNumNeu()}; - std::fill(inistate.begin(),inistate.end(),0.0); - nus.Set_initial_state(inistate,flavor); - nus.EvolveState(); - - test(nus,1000,2,6,std::numeric_limits::max(),decay_length,track); - } - - {// interactions false and osc false, vac - std::cout << "Interactions false, oscillations false, vacuum" << std::endl; - nuSQUIDS nus(logspace(1.e2*units.GeV,1.e6*units.GeV,60),3,neutrino,false); - double decay_length = 100.0*units.meter; - std::shared_ptr emit = std::make_shared(decay_length,0.0,0.5); - std::shared_ptr track = std::make_shared(1.0*units.km); - nus.Set_Body(emit); - nus.Set_Track(track); - nus.Set_rel_error(integration_tol); - nus.Set_abs_error(integration_tol); - nus.Set_NeutrinoSources(true); - nus.Set_IncludeOscillations(false); - - marray E_range = nus.GetERange(); - marray inistate{E_range.size(),nus.GetNumNeu()}; - std::fill(inistate.begin(),inistate.end(),0.0); - nus.Set_initial_state(inistate,flavor); - nus.EvolveState(); - - test(nus,1000,2,6,std::numeric_limits::max(),decay_length,track); - } - - {// interactions false and osc true, vac - std::cout << "Interactions false, oscillations true, vacuum" << std::endl; - nuSQUIDS nus(logspace(1.e2*units.GeV,1.e6*units.GeV,60),3,neutrino,false); - double decay_length = 100.0*units.meter; - std::shared_ptr emit = std::make_shared(decay_length,0.0,0.5); - std::shared_ptr track = std::make_shared(1.0*units.km); - nus.Set_Body(emit); - nus.Set_Track(track); - nus.Set_rel_error(integration_tol); - nus.Set_abs_error(integration_tol); - nus.Set_NeutrinoSources(true); - nus.Set_IncludeOscillations(true); - - marray E_range = nus.GetERange(); - marray inistate{E_range.size(),nus.GetNumNeu()}; - std::fill(inistate.begin(),inistate.end(),0.0); - nus.Set_initial_state(inistate,flavor); - nus.EvolveState(); - - test(nus,1000,2,6,std::numeric_limits::max(),decay_length,track); - } - - // We can't write down a convenient analytical solution to the differential - // equation for the neutrino flux when NC cascading is taking effect, so to - // test that we do the right thing in the presence of absorption we use a - // trick cross section which is only non-zero for charged current interactions - // (which purely remove neutrinos in our treatment) - class CCOnlyCrossSections : public nusquids::NeutrinoDISCrossSectionsFromTables{ - using Parent=nusquids::NeutrinoDISCrossSectionsFromTables; - public: - CCOnlyCrossSections(std::string p):Parent(p){} - double TotalCrossSection(double Enu, NeutrinoFlavor flavor, NeutrinoType neutype, Current current) const override{ - if(current!=CC) - return 0; - return Parent::TotalCrossSection(Enu, flavor, neutype, current); - } - double SingleDifferentialCrossSection(double E1, double E2, NeutrinoFlavor flavor, NeutrinoType neutype, Current current) const override{ - if(current!=CC) - return 0; - return Parent::SingleDifferentialCrossSection(E1, E2, flavor, neutype, current); - } - }; - std::shared_ptr ccOnlyXS(new CrossSectionLibrary); - { - std::string xsdir = nusquids::getResourcePath()+"/xsections/"; - ccOnlyXS->addTarget(nusquids::proton, CCOnlyCrossSections(xsdir+"csms_proton.h5")); - ccOnlyXS->addTarget(nusquids::neutron,CCOnlyCrossSections(xsdir+"csms_neutron.h5")); - } - - {// interactions true and osc false, matter - std::cout << "Interactions true, oscillations false, matter" << std::endl; - nuSQUIDS nus(logspace(1.e2*units.GeV,1.e6*units.GeV,60),3,neutrino,true); - nus.SetNeutrinoCrossSections(ccOnlyXS); - double decay_length = 100.0*units.meter; - double density = 5.0; - //use a material which has no neutrons to reduce the number of cross sections we need to deal with - std::shared_ptr emit = std::make_shared(decay_length,density,1.0); - std::shared_ptr track = std::make_shared(100*units.km); - nus.Set_Body(emit); - nus.Set_Track(track); - nus.Set_rel_error(integration_tol); - nus.Set_abs_error(integration_tol); - nus.Set_NeutrinoSources(true); - nus.Set_IncludeOscillations(false); - - marray E_range = nus.GetERange(); - marray inistate{E_range.size(),nus.GetNumNeu()}; - std::fill(inistate.begin(),inistate.end(),0.0); - nus.Set_initial_state(inistate,flavor); - nus.EvolveState(); - - auto int_struct = nus.GetInteractionStructure(); - double target_number_density = density*units.gr*pow(units.cm,-3)/(units.proton_mass + units.electron_mass); - - for(unsigned int ie = 0; ie < E_range.size(); ie++){ - double E=E_range[ie]; - for(unsigned int fl=0; flsigma_CC[0][0][fl][ie]*target_number_density; - double interaction_length = 1./invlen; - double exact = analytical_solution(track->GetFinalX(),interaction_length,decay_length); - double computed = nus.EvalFlavor(fl, E); - double del = computed - exact; - double rel = del/exact; - if(std::abs(rel) > 1.e-5 or std::isnan(del)) - std::cout << ie << ' ' << fl << ' ' << del << ' ' << rel << ' ' << exact << ' ' << computed << '\n'; - } - } - } - - {// interactions true and osc true, matter - std::cout << "Interactions true, oscillations true, matter" << std::endl; - nuSQUIDS nus(logspace(1.e2*units.GeV,1.e6*units.GeV,60),3,neutrino,true); - nus.SetNeutrinoCrossSections(ccOnlyXS); - double decay_length = 100.0*units.meter; - double density = 5.0; - //use a material which has no neutrons to reduce the number of cross sections we need to deal with - std::shared_ptr emit = std::make_shared(decay_length,density,1.0); - std::shared_ptr track = std::make_shared(100*units.km); - nus.Set_Body(emit); - nus.Set_Track(track); - nus.Set_rel_error(integration_tol); - nus.Set_abs_error(integration_tol); - nus.Set_NeutrinoSources(true); - nus.Set_IncludeOscillations(true); - - marray E_range = nus.GetERange(); - marray inistate{E_range.size(),nus.GetNumNeu()}; - std::fill(inistate.begin(),inistate.end(),0.0); - nus.Set_initial_state(inistate,flavor); - nus.EvolveState(); - - auto int_struct = nus.GetInteractionStructure(); - double target_number_density = density*units.gr*pow(units.cm,-3)/(units.proton_mass + units.electron_mass); - - for(unsigned int ie = 0; ie < E_range.size(); ie++){ - double E=E_range[ie]; - for(unsigned int fl=0; flsigma_CC[0][0][fl][ie]*target_number_density; - double interaction_length = 1./invlen; - double exact = analytical_solution(track->GetFinalX(),interaction_length,decay_length); - double computed = nus.EvalFlavor(fl, E); - double del = computed - exact; - double rel = del/exact; - if(std::abs(rel) > 1.e-5 or std::isnan(del)) - std::cout << ie << ' ' << fl << ' ' << del << ' ' << rel << ' ' << exact << ' ' << computed << '\n'; - } - } - } - - return 0; -} diff --git a/test/glashow_resonance.output.txt b/test/glashow_resonance.output.txt index e533d849..3318eccb 100644 --- a/test/glashow_resonance.output.txt +++ b/test/glashow_resonance.output.txt @@ -3,203 +3,153 @@ Checking single-differential cross-section Evolving a nue_bar line spectrum at the Glashow resonance Propagating. . . Propagation done -0 1e+04 0 0 0 0.999 0.000245 0.000245 -1 1.04e+04 0 0 0 0.999 0.000245 0.000245 -2 1.07e+04 0 0 0 0.999 0.000254 0.000254 -3 1.11e+04 0 0 0 0.999 0.000263 0.000263 -4 1.15e+04 0 0 0 0.998 0.000272 0.000272 -5 1.19e+04 0 0 0 0.998 0.000282 0.000282 -6 1.23e+04 0 0 0 0.998 0.000292 0.000292 -7 1.27e+04 0 0 0 0.998 0.000302 0.000302 -8 1.32e+04 0 0 0 0.998 0.000313 0.000313 -9 1.36e+04 0 0 0 0.998 0.000324 0.000324 -10 1.41e+04 0 0 0 0.998 0.000335 0.000335 -11 1.46e+04 0 0 0 0.998 0.000347 0.000347 -12 1.51e+04 0 0 0 0.998 0.00036 0.00036 -13 1.57e+04 0 0 0 0.998 0.000372 0.000372 -14 1.62e+04 0 0 0 0.998 0.000385 0.000385 -15 1.68e+04 0 0 0 0.998 0.000399 0.000399 -16 1.74e+04 0 0 0 0.998 0.000413 0.000413 -17 1.8e+04 0 0 0 0.998 0.000428 0.000428 -18 1.86e+04 0 0 0 0.997 0.000443 0.000443 -19 1.93e+04 0 0 0 0.997 0.000459 0.000459 -20 2e+04 0 0 0 0.997 0.000475 0.000475 -21 2.07e+04 0 0 0 0.997 0.000492 0.000492 -22 2.14e+04 0 0 0 0.997 0.00051 0.00051 -23 2.21e+04 0 0 0 0.997 0.000528 0.000528 -24 2.29e+04 0 0 0 0.997 0.000547 0.000547 -25 2.37e+04 0 0 0 0.997 0.000566 0.000566 -26 2.45e+04 0 0 0 0.997 0.000586 0.000586 -27 2.54e+04 0 0 0 0.997 0.000607 0.000607 -28 2.63e+04 0 0 0 0.996 0.000629 0.000629 -29 2.72e+04 0 0 0 0.996 0.000651 0.000651 -30 2.82e+04 0 0 0 0.996 0.000674 0.000674 -31 2.92e+04 0 0 0 0.996 0.000698 0.000698 -32 3.02e+04 0 0 0 0.996 0.000723 0.000723 -33 3.13e+04 0 0 0 0.996 0.000749 0.000749 -34 3.24e+04 0 0 0 0.996 0.000776 0.000776 -35 3.35e+04 0 0 0 0.995 0.000804 0.000804 -36 3.47e+04 0 0 0 0.995 0.000832 0.000832 -37 3.59e+04 0 0 0 0.995 0.000862 0.000862 -38 3.72e+04 0 0 0 0.995 0.000893 0.000893 -39 3.85e+04 0 0 0 0.995 0.000925 0.000925 -40 3.98e+04 0 0 0 0.995 0.000958 0.000958 -41 4.12e+04 0 0 0 0.994 0.000993 0.000993 -42 4.27e+04 0 0 0 0.994 0.00103 0.00103 -43 4.42e+04 0 0 0 0.994 0.00107 0.00107 -44 4.57e+04 0 0 0 0.994 0.0011 0.0011 -45 4.73e+04 0 0 0 0.994 0.00114 0.00114 -46 4.9e+04 0 0 0 0.993 0.00118 0.00118 -47 5.07e+04 0 0 0 0.993 0.00123 0.00123 -48 5.25e+04 0 0 0 0.993 0.00127 0.00127 -49 5.43e+04 0 0 0 0.993 0.00132 0.00132 -50 5.62e+04 0 0 0 0.992 0.00137 0.00137 -51 5.82e+04 0 0 0 0.992 0.00141 0.00141 -52 6.03e+04 0 0 0 0.992 0.00147 0.00147 -53 6.24e+04 0 0 0 0.991 0.00152 0.00152 -54 6.46e+04 0 0 0 0.991 0.00157 0.00157 -55 6.68e+04 0 0 0 0.991 0.00163 0.00163 -56 6.92e+04 0 0 0 0.991 0.00169 0.00169 -57 7.16e+04 0 0 0 0.99 0.00175 0.00175 -58 7.41e+04 0 0 0 0.99 0.00182 0.00182 -59 7.67e+04 0 0 0 0.989 0.00188 0.00188 -60 7.94e+04 0 0 0 0.989 0.00195 0.00195 -61 8.22e+04 0 0 0 0.989 0.00202 0.00202 -62 8.51e+04 0 0 0 0.988 0.0021 0.0021 -63 8.81e+04 0 0 0 0.988 0.00217 0.00217 -64 9.12e+04 0 0 0 0.987 0.00225 0.00225 -65 9.44e+04 0 0 0 0.987 0.00234 0.00234 -66 9.77e+04 0 0 0 0.987 0.00242 0.00242 -67 1.01e+05 0 0 0 0.986 0.00251 0.00251 -68 1.05e+05 0 0 0 0.986 0.00261 0.00261 -69 1.08e+05 0 0 0 0.985 0.0027 0.0027 -70 1.12e+05 0 0 0 0.985 0.0028 0.0028 -71 1.16e+05 0 0 0 0.984 0.00291 0.00291 -72 1.2e+05 0 0 0 0.983 0.00301 0.00301 -73 1.24e+05 0 0 0 0.983 0.00313 0.00313 -74 1.29e+05 0 0 0 0.982 0.00324 0.00324 -75 1.33e+05 0 0 0 0.982 0.00337 0.00337 -76 1.38e+05 0 0 0 0.981 0.00349 0.00349 -77 1.43e+05 0 0 0 0.98 0.00362 0.00362 -78 1.48e+05 0 0 0 0.979 0.00376 0.00376 -79 1.53e+05 0 0 0 0.979 0.0039 0.0039 -80 1.58e+05 0 0 0 0.978 0.00405 0.00405 -81 1.64e+05 0 0 0 0.977 0.0042 0.0042 -82 1.7e+05 0 0 0 0.976 0.00436 0.00436 -83 1.76e+05 0 0 0 0.975 0.00453 0.00453 -84 1.82e+05 0 0 0 0.975 0.0047 0.0047 -85 1.88e+05 0 0 0 0.974 0.00488 0.00488 -86 1.95e+05 0 0 0 0.973 0.00507 0.00507 -87 2.02e+05 0 0 0 0.972 0.00527 0.00527 -88 2.09e+05 0 0 0 0.971 0.00547 0.00547 -89 2.16e+05 0 0 0 0.97 0.00568 0.00568 -90 2.24e+05 0 0 0 0.968 0.0059 0.0059 -91 2.32e+05 0 0 0 0.967 0.00613 0.00613 -92 2.4e+05 0 0 0 0.966 0.00637 0.00637 -93 2.48e+05 0 0 0 0.965 0.00663 0.00663 -94 2.57e+05 0 0 0 0.963 0.00689 0.00689 -95 2.66e+05 0 0 0 0.962 0.00716 0.00716 -96 2.75e+05 0 0 0 0.961 0.00744 0.00744 -97 2.85e+05 0 0 0 0.959 0.00774 0.00774 -98 2.95e+05 0 0 0 0.958 0.00805 0.00805 -99 3.05e+05 0 0 0 0.956 0.00837 0.00837 -100 3.16e+05 0 0 0 0.955 0.0087 0.0087 -101 3.27e+05 0 0 0 0.953 0.00905 0.00905 -102 3.39e+05 0 0 0 0.951 0.00942 0.00942 -103 3.51e+05 0 0 0 0.949 0.0098 0.0098 -104 3.63e+05 0 0 0 0.947 0.0102 0.0102 -105 3.76e+05 0 0 0 0.945 0.0106 0.0106 -106 3.89e+05 0 0 0 0.943 0.0111 0.0111 -107 4.03e+05 0 0 0 0.941 0.0115 0.0115 -108 4.17e+05 0 0 0 0.939 0.012 0.012 -109 4.32e+05 0 0 0 0.936 0.0125 0.0125 -110 4.47e+05 0 0 0 0.934 0.013 0.013 -111 4.62e+05 0 0 0 0.931 0.0135 0.0135 -112 4.79e+05 0 0 0 0.929 0.0141 0.0141 -113 4.95e+05 0 0 0 0.926 0.0147 0.0147 -114 5.13e+05 0 0 0 0.923 0.0153 0.0153 -115 5.31e+05 0 0 0 0.92 0.016 0.016 -116 5.5e+05 0 0 0 0.917 0.0166 0.0166 -117 5.69e+05 0 0 0 0.914 0.0173 0.0173 -118 5.89e+05 0 0 0 0.91 0.0181 0.0181 -119 6.1e+05 0 0 0 0.907 0.0189 0.0189 -120 6.31e+05 0 0 0 0.903 0.0197 0.0197 -121 6.53e+05 0 0 0 0.899 0.0205 0.0205 -122 6.76e+05 0 0 0 0.895 0.0214 0.0214 -123 7e+05 0 0 0 0.89 0.0223 0.0223 -124 7.24e+05 0 0 0 0.886 0.0233 0.0233 -125 7.5e+05 0 0 0 0.881 0.0243 0.0243 -126 7.76e+05 0 0 0 0.876 0.0254 0.0254 -127 8.04e+05 0 0 0 0.871 0.0265 0.0265 -128 8.32e+05 0 0 0 0.866 0.0276 0.0276 -129 8.61e+05 0 0 0 0.86 0.0288 0.0288 -130 8.91e+05 0 0 0 0.854 0.0301 0.0301 -131 9.23e+05 0 0 0 0.847 0.0314 0.0314 -132 9.55e+05 0 0 0 0.841 0.0328 0.0328 -133 9.89e+05 0 0 0 0.834 0.0342 0.0342 -134 1.02e+06 0 0 0 0.827 0.0357 0.0357 -135 1.06e+06 0 0 0 0.819 0.0373 0.0373 -136 1.1e+06 0 0 0 0.811 0.0389 0.0389 -137 1.14e+06 0 0 0 0.802 0.0406 0.0406 -138 1.17e+06 0 0 0 0.793 0.0424 0.0424 -139 1.22e+06 0 0 0 0.783 0.0442 0.0442 -140 1.26e+06 0 0 0 0.773 0.0461 0.0461 -141 1.3e+06 0 0 0 0.763 0.0481 0.0481 -142 1.35e+06 0 0 0 0.751 0.0501 0.0501 -143 1.4e+06 0 0 0 0.739 0.0522 0.0522 -144 1.45e+06 0 0 0 0.727 0.0544 0.0544 -145 1.5e+06 0 0 0 0.713 0.0566 0.0566 -146 1.55e+06 0 0 0 0.699 0.0589 0.0589 -147 1.6e+06 0 0 0 0.684 0.0613 0.0613 -148 1.66e+06 0 0 0 0.668 0.0637 0.0637 -149 1.72e+06 0 0 0 0.651 0.0662 0.0662 -150 1.78e+06 0 0 0 0.633 0.0687 0.0687 -151 1.84e+06 0 0 0 0.614 0.0713 0.0713 -152 1.91e+06 0 0 0 0.594 0.0739 0.0739 -153 1.97e+06 0 0 0 0.573 0.0765 0.0765 -154 2.04e+06 0 0 0 0.55 0.0792 0.0792 -155 2.11e+06 0 0 0 0.527 0.0818 0.0818 -156 2.19e+06 0 0 0 0.501 0.0844 0.0844 -157 2.26e+06 0 0 0 0.475 0.087 0.087 -158 2.34e+06 0 0 0 0.447 0.0895 0.0895 -159 2.43e+06 0 0 0 0.418 0.092 0.092 -160 2.51e+06 0 0 0 0.388 0.0943 0.0943 -161 2.6e+06 0 0 0 0.357 0.0966 0.0966 -162 2.69e+06 0 0 0 0.324 0.0987 0.0987 -163 2.79e+06 0 0 0 0.291 0.101 0.101 -164 2.88e+06 0 0 0 0.258 0.102 0.102 -165 2.99e+06 0 0 0 0.224 0.104 0.104 -166 3.09e+06 0 0 0 0.191 0.105 0.105 -167 3.2e+06 0 0 0 0.158 0.106 0.106 -168 3.31e+06 0 0 0 0.127 0.107 0.107 -169 3.43e+06 0 0 0 0.0985 0.108 0.108 -170 3.55e+06 0 0 0 0.0728 0.108 0.108 -171 3.67e+06 0 0 0 0.0508 0.108 0.108 -172 3.8e+06 0 0 0 0.0329 0.108 0.108 -173 3.94e+06 0 0 0 0.0193 0.107 0.107 -174 4.07e+06 0 0 0 0.01 0.106 0.106 -175 4.22e+06 0 0 0 0.00441 0.105 0.105 -176 4.37e+06 0 0 0 0.00155 0.104 0.104 -177 4.52e+06 0 0 0 0.000406 0.103 0.103 -178 4.68e+06 0 0 0 7.73e-05 0.101 0.101 -179 4.84e+06 0 0 0 1.66e-05 0.0995 0.0995 -180 5.01e+06 0 0 0 8.46e-06 0.0972 0.0972 -181 5.19e+06 0 0 0 5.88e-06 0.0944 0.0944 -182 5.37e+06 0 0 0 4.09e-06 0.0909 0.0909 -183 5.56e+06 0 0 0 2.72e-06 0.0866 0.0866 -184 5.75e+06 0 0 0 1.66e-06 0.0809 0.0809 -185 5.96e+06 0 0 0 8.62e-07 0.073 0.073 -186 6.17e+06 0 0 0 3.32e-07 0.0615 0.0615 -187 6.38e+06 0 0 0 1.26e-07 0.0565 0.0565 -188 6.61e+06 0 0 0 2.23e-07 0.0571 0.0571 -189 6.84e+06 0 0 0 8.08e-07 0.0566 0.0566 -190 7.08e+06 0 0 0 2.1e-06 0.0549 0.0549 -191 7.33e+06 0 0 0 4.41e-06 0.0524 0.0524 -192 7.59e+06 0 0 0 8.22e-06 0.0491 0.0491 -193 7.85e+06 0 0 0 1.44e-05 0.0453 0.0453 -194 8.13e+06 0 0 0 2.45e-05 0.0408 0.0408 -195 8.41e+06 0 0 0 4.23e-05 0.0357 0.0357 -196 8.71e+06 0 0 0 8.8e-05 0.03 0.03 -197 9.02e+06 0 0 0 0.000262 0.0236 0.0236 -198 9.33e+06 0 0 0 0.000864 0.0165 0.0165 -199 9.66e+06 0 0 0 0.00246 0.00867 0.00867 +0 10000 0 0 0 3.58079e-07 7.93637e-07 7.98956e-07 +1 10471.3 0 0 0 3.72298e-07 8.25507e-07 8.31084e-07 +2 10964.8 0 0 0 3.87358e-07 8.59249e-07 8.651e-07 +3 11481.5 0 0 0 4.02546e-07 8.93353e-07 8.99484e-07 +4 12022.6 0 0 0 4.18561e-07 9.2931e-07 9.35738e-07 +5 12589.3 0 0 0 4.34882e-07 9.66016e-07 9.72753e-07 +6 13182.6 0 0 0 4.51525e-07 1.00351e-06 1.01057e-06 +7 13803.8 0 0 0 4.69064e-07 1.04302e-06 1.05041e-06 +8 14454.4 0 0 0 4.86587e-07 1.0826e-06 1.09034e-06 +9 15135.6 0 0 0 5.05271e-07 1.12478e-06 1.13288e-06 +10 15848.9 0 0 0 5.23834e-07 1.16682e-06 1.1753e-06 +11 16595.9 0 0 0 5.43513e-07 1.21137e-06 1.22025e-06 +12 17378 0 0 0 5.63361e-07 1.25641e-06 1.2657e-06 +13 18197 0 0 0 5.83415e-07 1.30204e-06 1.31174e-06 +14 19054.6 0 0 0 6.04655e-07 1.35034e-06 1.36049e-06 +15 19952.6 0 0 0 6.25478e-07 1.3979e-06 1.4085e-06 +16 20893 0 0 0 6.47929e-07 1.4491e-06 1.46019e-06 +17 21877.6 0 0 0 6.69761e-07 1.49914e-06 1.51071e-06 +18 22908.7 0 0 0 6.9312e-07 1.55263e-06 1.56471e-06 +19 23988.3 0 0 0 7.16337e-07 1.60598e-06 1.61859e-06 +20 25118.9 0 0 0 7.39497e-07 1.6594e-06 1.67255e-06 +21 26302.7 0 0 0 7.64245e-07 1.71642e-06 1.73014e-06 +22 27542.3 0 0 0 7.87847e-07 1.77118e-06 1.78547e-06 +23 28840.3 0 0 0 8.13776e-07 1.83115e-06 1.84605e-06 +24 30199.5 0 0 0 8.38194e-07 1.88808e-06 1.90359e-06 +25 31622.8 0 0 0 8.64749e-07 1.94984e-06 1.966e-06 +26 33113.1 0 0 0 8.90582e-07 2.01027e-06 2.02708e-06 +27 34673.7 0 0 0 9.1589e-07 2.06981e-06 2.08728e-06 +28 36307.8 0 0 0 9.43363e-07 2.13427e-06 2.15245e-06 +29 38018.9 0 0 0 9.68479e-07 2.19389e-06 2.21275e-06 +30 39810.7 0 0 0 9.96974e-07 2.26108e-06 2.2807e-06 +31 41686.9 0 0 0 1.0225e-06 2.32212e-06 2.34246e-06 +32 43651.6 0 0 0 1.0511e-06 2.39009e-06 2.41122e-06 +33 45708.8 0 0 0 1.07801e-06 2.45468e-06 2.47659e-06 +34 47863 0 0 0 1.10367e-06 2.51685e-06 2.53954e-06 +35 50118.7 0 0 0 1.13233e-06 2.58587e-06 2.6094e-06 +36 52480.7 0 0 0 1.15679e-06 2.64602e-06 2.67032e-06 +37 54954.1 0 0 0 1.18621e-06 2.71731e-06 2.74251e-06 +38 57544 0 0 0 1.21045e-06 2.77761e-06 2.80363e-06 +39 60256 0 0 0 1.23916e-06 2.84804e-06 2.87496e-06 +40 63095.7 0 0 0 1.26475e-06 2.91194e-06 2.93973e-06 +41 66069.3 0 0 0 1.28809e-06 2.97124e-06 2.99988e-06 +42 69183.1 0 0 0 1.31564e-06 3.04018e-06 3.06977e-06 +43 72443.6 0 0 0 1.33638e-06 3.0944e-06 3.12482e-06 +44 75857.8 0 0 0 1.36436e-06 3.165e-06 3.19642e-06 +45 79432.8 0 0 0 1.38411e-06 3.21773e-06 3.24999e-06 +46 83176.4 0 0 0 1.41033e-06 3.2852e-06 3.31845e-06 +47 87096.4 0 0 0 1.43147e-06 3.34174e-06 3.3759e-06 +48 91201.1 0 0 0 1.44913e-06 3.39087e-06 3.42589e-06 +49 95499.3 0 0 0 1.4727e-06 3.45358e-06 3.48959e-06 +50 100000 0 0 0 1.48607e-06 3.49379e-06 3.5306e-06 +51 104713 0 0 0 1.50979e-06 3.55761e-06 3.59547e-06 +52 109648 0 0 0 1.52137e-06 3.59447e-06 3.63311e-06 +53 114815 0 0 0 1.54216e-06 3.65249e-06 3.69214e-06 +54 120226 0 0 0 1.55546e-06 3.69394e-06 3.73444e-06 +55 125893 0 0 0 1.56394e-06 3.72479e-06 3.76605e-06 +56 131826 0 0 0 1.58053e-06 3.77443e-06 3.81665e-06 +57 138038 0 0 0 1.58295e-06 3.79207e-06 3.83495e-06 +58 144544 0 0 0 1.59963e-06 3.84267e-06 3.88655e-06 +59 151356 0 0 0 1.59966e-06 3.85542e-06 3.89989e-06 +60 158489 0 0 0 1.61229e-06 3.89744e-06 3.94287e-06 +61 165959 0 0 0 1.61478e-06 3.91646e-06 3.96257e-06 +62 173780 0 0 0 1.61118e-06 3.92161e-06 3.96826e-06 +63 181970 0 0 0 1.61832e-06 3.95199e-06 3.99947e-06 +64 190546 0 0 0 1.60713e-06 3.93996e-06 3.98779e-06 +65 199526 0 0 0 1.61463e-06 3.9718e-06 4.02049e-06 +66 208930 0 0 0 1.60086e-06 3.9541e-06 4.0031e-06 +67 218776 0 0 0 1.60344e-06 3.97504e-06 4.02479e-06 +68 229087 0 0 0 1.59335e-06 3.96642e-06 4.01657e-06 +69 239883 0 0 0 1.5762e-06 3.94124e-06 3.9916e-06 +70 251189 0 0 0 1.57251e-06 3.94823e-06 3.99919e-06 +71 263027 0 0 0 1.54681e-06 3.90293e-06 3.95386e-06 +72 275423 0 0 0 1.54406e-06 3.91271e-06 3.96426e-06 +73 288403 0 0 0 1.51614e-06 3.86225e-06 3.91368e-06 +74 301995 0 0 0 1.50799e-06 3.85967e-06 3.91156e-06 +75 316228 0 0 0 1.48522e-06 3.82197e-06 3.87389e-06 +76 331131 0 0 0 1.45493e-06 3.76603e-06 3.81774e-06 +77 346737 0 0 0 1.4404e-06 3.74879e-06 3.80079e-06 +78 363078 0 0 0 1.40138e-06 3.67156e-06 3.72301e-06 +79 380189 0 0 0 1.3885e-06 3.65903e-06 3.71082e-06 +80 398107 0 0 0 1.3481e-06 3.57844e-06 3.62963e-06 +81 416869 0 0 0 1.32977e-06 3.55314e-06 3.60447e-06 +82 436516 0 0 0 1.29593e-06 3.48931e-06 3.54024e-06 +83 457088 0 0 0 1.25472e-06 3.40686e-06 3.4571e-06 +84 478630 0 0 0 1.23051e-06 3.36791e-06 3.41807e-06 +85 501187 0 0 0 1.18127e-06 3.265e-06 3.31415e-06 +86 524807 0 0 0 1.15938e-06 3.23286e-06 3.28202e-06 +87 549541 0 0 0 1.10992e-06 3.12932e-06 3.1774e-06 +88 575440 0 0 0 1.083e-06 3.08512e-06 3.13299e-06 +89 602560 0 0 0 1.04109e-06 3.00169e-06 3.04874e-06 +90 630957 0 0 0 9.9266e-07 2.90073e-06 2.94668e-06 +91 660693 0 0 0 9.60996e-07 2.84518e-06 2.89073e-06 +92 691831 0 0 0 9.06276e-07 2.72653e-06 2.77062e-06 +93 724436 0 0 0 8.77431e-07 2.67952e-06 2.72328e-06 +94 758578 0 0 0 8.23928e-07 2.56326e-06 2.60556e-06 +95 794328 0 0 0 7.91145e-07 2.50586e-06 2.54764e-06 +96 831764 0 0 0 7.45624e-07 2.4116e-06 2.45221e-06 +97 870964 0 0 0 6.95354e-07 2.30235e-06 2.34153e-06 +98 912011 0 0 0 6.59883e-07 2.23683e-06 2.27528e-06 +99 954993 0 0 0 6.06203e-07 2.11413e-06 2.15087e-06 +100 1e+06 0 0 0 5.74126e-07 2.05819e-06 2.09431e-06 +101 1.04713e+06 0 0 0 5.23513e-07 1.94081e-06 1.97524e-06 +102 1.09648e+06 0 0 0 4.89563e-07 1.87701e-06 1.91064e-06 +103 1.14815e+06 0 0 0 4.47012e-07 1.78177e-06 1.81405e-06 +104 1.20226e+06 0 0 0 4.02304e-07 1.67525e-06 1.7059e-06 +105 1.25893e+06 0 0 0 3.69006e-07 1.60731e-06 1.63704e-06 +106 1.31826e+06 0 0 0 3.24806e-07 1.49277e-06 1.52068e-06 +107 1.38038e+06 0 0 0 2.95774e-07 1.43482e-06 1.46192e-06 +108 1.44544e+06 0 0 0 2.56651e-07 1.32815e-06 1.35352e-06 +109 1.51356e+06 0 0 0 2.28721e-07 1.26574e-06 1.29017e-06 +110 1.58489e+06 0 0 0 1.97356e-07 1.17973e-06 1.20275e-06 +111 1.65959e+06 0 0 0 1.66612e-07 1.0869e-06 1.10835e-06 +112 1.7378e+06 0 0 0 1.43181e-07 1.02487e-06 1.0453e-06 +113 1.8197e+06 0 0 0 1.16437e-07 9.2988e-07 9.48635e-07 +114 1.90546e+06 0 0 0 9.79201e-08 8.77712e-07 8.95602e-07 +115 1.99526e+06 0 0 0 7.71216e-08 7.92388e-07 8.08724e-07 +116 2.0893e+06 0 0 0 6.20637e-08 7.39527e-07 7.54939e-07 +117 2.18776e+06 0 0 0 4.7518e-08 6.71997e-07 6.86162e-07 +118 2.29087e+06 0 0 0 3.49354e-08 6.01966e-07 6.14799e-07 +119 2.39883e+06 0 0 0 2.57927e-08 5.53623e-07 5.6556e-07 +120 2.51189e+06 0 0 0 1.74683e-08 4.86336e-07 4.96946e-07 +121 2.63027e+06 0 0 0 1.19821e-08 4.47006e-07 4.56858e-07 +122 2.75423e+06 0 0 0 7.37013e-09 3.8958e-07 3.98278e-07 +123 2.88403e+06 0 0 0 4.44931e-09 3.5254e-07 3.60487e-07 +124 3.01995e+06 0 0 0 2.40411e-09 3.08732e-07 3.15782e-07 +125 3.16228e+06 0 0 0 1.15441e-09 2.65438e-07 2.71572e-07 +126 3.31131e+06 0 0 0 5.05862e-10 2.35025e-07 2.40512e-07 +127 3.46737e+06 0 0 0 1.77679e-10 1.96725e-07 2.01373e-07 +128 3.63078e+06 0 0 0 5.25302e-11 1.73304e-07 1.77449e-07 +129 3.80189e+06 0 0 0 1.08106e-11 1.42925e-07 1.46384e-07 +130 3.98107e+06 0 0 0 1.48269e-12 1.22787e-07 1.25791e-07 +131 4.16869e+06 0 0 0 1.03767e-13 1.0098e-07 1.0348e-07 +132 4.36516e+06 0 0 0 2.63171e-15 8.07251e-08 8.27439e-08 +133 4.57088e+06 0 0 0 1.33797e-17 6.64014e-08 6.80818e-08 +134 4.7863e+06 0 0 0 3.26655e-19 5.04541e-08 5.1745e-08 +135 5.01187e+06 0 0 0 2.35582e-19 4.02775e-08 4.13193e-08 +136 5.24807e+06 0 0 0 1.54616e-19 2.89765e-08 2.97354e-08 +137 5.49541e+06 0 0 0 1.03184e-19 2.12008e-08 2.1762e-08 +138 5.7544e+06 0 0 0 6.11995e-20 1.3785e-08 1.4154e-08 +139 6.0256e+06 0 0 0 3.01762e-20 7.45129e-09 7.65359e-09 +140 6.30957e+06 0 0 0 1.87192e-31 4.36614e-20 3.90425e-20 +141 6.60693e+06 0 0 0 0 0 0 +142 6.91831e+06 0 0 0 0 0 0 +143 7.24436e+06 0 0 0 0 0 0 +144 7.58578e+06 0 0 0 0 0 0 +145 7.94328e+06 0 0 0 0 0 0 +146 8.31764e+06 0 0 0 0 0 0 +147 8.70964e+06 0 0 0 0 0 0 +148 9.12011e+06 0 0 0 0 0 0 +149 9.54993e+06 0 0 0 0 0 0 diff --git a/test/glashow_resonance.test.cpp b/test/glashow_resonance.test.cpp index 6fb67091..71edb4e0 100644 --- a/test/glashow_resonance.test.cpp +++ b/test/glashow_resonance.test.cpp @@ -52,10 +52,8 @@ int main (int argc, char const *argv[]) const unsigned int numneu = 3; const unsigned int num_steps = 201; squids::Const units; - auto gr_only = std::make_shared(); - gr_only->addTarget(electron,GlashowResonanceCrossSection()); - gr_only->addTarget(isoscalar_nucleon, NullCrossSections()); - nuSQUIDS squid(logspace(1e4*units.GeV,1e7*units.GeV,num_steps),numneu,both,true,gr_only); + std::shared_ptr ndcs = std::make_shared(); + nuSQUIDS squid(logspace(1e4*units.GeV,1e7*units.GeV,num_steps),numneu,both,true,ndcs); std::shared_ptr const_dens = std::make_shared(10.,0.5); std::shared_ptr const_dens_track = std::make_shared(10000.*units.km); @@ -90,9 +88,6 @@ int main (int argc, char const *argv[]) squid.EvolveState(); std::cout << "Propagation done" << std::endl; std::ostream &output = std::cout; - // One part in a thousand is a somewhat loose tolerance, but this is necessary because the key area - // around the resonance has such a suppression of the (nuebar) flux that it has much higher relative error. - output.precision(3); for (auto i=0; i < num_steps-1; i++) { double ee = E_range[i]; double de = (E_range[i+1]-E_range[i])/units.GeV; @@ -105,6 +100,21 @@ int main (int argc, char const *argv[]) output << squid.EvalFlavorAtNode(1,i,1)*ee << " "; output << squid.EvalFlavorAtNode(2,i,1)*ee << " "; output << std::endl; + /* + for (auto flav=0; flav<3; flav++) { + assert(squid.EvalFlavorAtNode(flav,i,0) == 0); + // Extra interaction channel suppresses nue_bar more than other flavors + //assert(squid.EvalFlavorAtNode(flav,i,1) >= squid.EvalFlavorAtNode(0,i,1)); + if(squid.EvalFlavorAtNode(flav,i,1) < squid.EvalFlavorAtNode(0,i,1)) + output << "nu_e bar not smaller than other flavors: " << flav << ' ' << i << ' ' + << squid.EvalFlavorAtNode(flav,i,1) << ' ' << squid.EvalFlavorAtNode(0,i,1) << std::endl;; + // If there is some nue_bar flux left over, there must also be some other flavors + if (flav!=0 && squid.EvalFlavorAtNode(0,i,1)>0 && squid.EvalFlavorAtNode(flav,i,1)<=0){ + output << "Unexpected lack of flux: " << flav << ' ' << i + << ' ' << squid.EvalFlavorAtNode(0,i,1) << ' ' << squid.EvalFlavorAtNode(flav,i,1) << std::endl; + } + } + */ } return 0; diff --git a/test/hdf5_atm_in_out.test.cpp b/test/hdf5_atm_in_out.test.cpp index 378b69b7..ebad5500 100644 --- a/test/hdf5_atm_in_out.test.cpp +++ b/test/hdf5_atm_in_out.test.cpp @@ -12,6 +12,7 @@ int main(){ double phi = acos(-0.5); std::shared_ptr earth_atm = std::make_shared(); + std::shared_ptr track_atm = std::make_shared(phi); // set mixing angles and masses nus.Set_MixingParametersToDefault(); @@ -169,8 +170,7 @@ int main(){ for ( int i = 0 ; i < nsq.GetTrack()->GetTrackParams().size(); i++){ double track_params_diff = nsq.GetTrack()->GetTrackParams()[i] - nsq_read.GetTrack()->GetTrackParams()[i]; if (std::abs(track_params_diff) > 1.0e-15) - std::cout << "TP " << i << ' ' << nsq.GetTrack()->GetTrackParams()[i] << ' ' - << nsq_read.GetTrack()->GetTrackParams()[i] << std::endl; + std::cout << "TP " << track_params_diff << std::endl; } counter++; } diff --git a/test/hdf5_in_out.test.cpp b/test/hdf5_in_out.test.cpp index 44b64f25..35a4fc12 100644 --- a/test/hdf5_in_out.test.cpp +++ b/test/hdf5_in_out.test.cpp @@ -28,7 +28,7 @@ int main(){ double phi = acos(-0.5); std::shared_ptr earth_atm = std::make_shared(); - std::shared_ptr track_atm = std::make_shared(earth_atm->MakeTrack(phi)); + std::shared_ptr track_atm = std::make_shared(phi); nus.Set_Body(earth_atm); nus.Set_Track(track_atm); diff --git a/test/mul_energy_constructor.test.cpp b/test/mul_energy_constructor.test.cpp index 238e7531..1a1075c5 100644 --- a/test/mul_energy_constructor.test.cpp +++ b/test/mul_energy_constructor.test.cpp @@ -20,7 +20,7 @@ int main(){ // i need to put some things inside in order to write it out double phi = acos(-0.5); std::shared_ptr earth_atm = std::make_shared(); - std::shared_ptr track_atm = std::make_shared(earth_atm->MakeTrack(phi)); + std::shared_ptr track_atm = std::make_shared(phi); nus1.Set_Body(earth_atm); nus1.Set_Track(track_atm); marray inistate{60,3}; diff --git a/test/time_reversal.test.cpp b/test/time_reversal.test.cpp index 1c5abd20..3b5dab7f 100644 --- a/test/time_reversal.test.cpp +++ b/test/time_reversal.test.cpp @@ -12,7 +12,7 @@ int main(){ nuSQUIDS nus(logspace(1.e2*units.GeV,1.e6*units.GeV,60),3,both,true); std::shared_ptr earth_atm = std::make_shared(); - std::shared_ptr track_atm = std::make_shared(earth_atm->MakeTrackWithCosine(-1)); + std::shared_ptr track_atm = std::make_shared(acos(-1.)); nus.Set_Body(earth_atm); nus.Set_Track(track_atm);