diff --git a/CHANGELOG.md b/CHANGELOG.md index b3bbdf771..6eb5e7d1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,25 +1,51 @@ -# CRPropa vNext +## CRPropa vNext + +### Bug fixes: + +### New features: + +### Interface changes: + +### Features that are deprecated and will be removed after this release + +### Removed features + +### New plugins and resources linked on the webpages + + +## CRPropa 3.2.1 ### Bug fixes: * Re-added ToroidalHaloField and LogarithmicSpiralField models. Note, that the class name was also corrected in spelling: TorroidalHaloField --> ToroidalHaloField * Synchronized signature of ParticleSplitting constructor ### New features: -* new candidate property tagOrigin to trace back which source or which interaction created the candidate -* new interace for massdistributions given on a Grid1f -* grids can be restricted to the volume without repetition -* sourceFeature to sample the source position from a given massdistribution +* New candidate property tagOrigin to trace back which source or which interaction created the candidate +* New interface for massdistributions given on a Grid1f +* Grids can be restricted to the volume without repetition (clipVolume parameter) +* SourceFeature to sample the source position from a given massdistribution +* EBL model from Saldana-Lopez et al. 2021 +* New module CandidateSplitting for better statistics at high energies for e.g. diffusive shock acceleration +* New advection fields for modeling diffusive shock acceleration at 1D planar, oblique and spherical shocks ### Interface changes: * Weight column in hdf-Output is now called "W", which is the same as for TextOutput. ### Features that are deprecated and will be removed after this release * ObserverPoint will be renamed into Observer1D. -* AMRMagenticField - underlying library (saga) is no longer supported. - -### New plugins and resources linked on the webpages: +* AMRMagneticField - underlying library (saga) is no longer supported. +### Removed features +* External extensions DINT and Eleca, which can be replaced with the + EM*-modules combined with the thinning option for reasonable computation + times. +### New plugins and resources linked on the webpages: +* FieldlineIntegrator +* grplinst +* monopole +* ROOTOutputPlugin + ## CRPropa 3.2 diff --git a/CITATION.bib b/CITATION.bib new file mode 100644 index 000000000..34fc33d43 --- /dev/null +++ b/CITATION.bib @@ -0,0 +1,12 @@ +@ARTICLE{crpropa3.2, + author = {{Alves Batista}, Rafael and {Becker Tjus}, Julia and {D{\"o}rner}, Julien and {Dundovic}, Andrej and {Eichmann}, Bj{\"o}rn and {Frie}, Antonius and {Heiter}, Christopher and {Hoerbe}, Mario R. and {Kampert}, Karl-Heinz and {Merten}, Lukas and {M{\"u}ller}, Gero and {Reichherzer}, Patrick and {Saveliev}, Andrey and {Schlegel}, Leander and {Sigl}, G{\"u}nter and {van Vliet}, Arjen and {Winchen}, Tobias}, + title = "{CRPropa 3.2 - an advanced framework for high-energy particle propagation in extragalactic and galactic spaces}", + journal = {Journal of Cosmology and Astroparticle Physics}, + year = 2022, + volume = {9}, + eid = {035}, + pages = {035}, + doi = {10.1088/1475-7516/2022/09/035}, + eprint = {2208.00107} +} + diff --git a/CMakeLists.txt b/CMakeLists.txt index db9f05abb..4a969f792 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ else(APPLE) endif(APPLE) project(CRPropa Fortran C CXX) -set(CRPROPA_RELEASE_VERSION 3.2+) # Update for new release +set(CRPROPA_RELEASE_VERSION 3.2.1+) # Update for new release set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) @@ -164,16 +164,6 @@ add_subdirectory(libs/sophia) list(APPEND CRPROPA_EXTRA_LIBRARIES sophia gfortran) list(APPEND CRPROPA_EXTRA_INCLUDES libs/sophia) -# DINT (provided) -add_subdirectory(libs/dint) -list(APPEND CRPROPA_EXTRA_LIBRARIES dint) -list(APPEND CRPROPA_EXTRA_INCLUDES libs/dint/include) - -# EleCa (provided) -add_subdirectory(libs/EleCa) -list(APPEND CRPROPA_EXTRA_LIBRARIES eleca) -list(APPEND CRPROPA_EXTRA_INCLUDES libs/EleCa/include) - # GlacticMagneticLenses option(ENABLE_GALACTICMAGETICLENS "Galactic Magnetic Lens" ON) option(INSTALL_EIGEN "Install provided EIGEN headers" OFF) @@ -242,7 +232,7 @@ if(FFTW3F_FOUND) endif(FFTW3F_FOUND) # Quimby (optional for SPH magnetic fields) -option(ENABLE_QUIMBY "Quimby Support" ON) +option(ENABLE_QUIMBY "Quimby Support" OFF) if(ENABLE_QUIMBY) find_package(Quimby) if(QUIMBY_FOUND) @@ -336,16 +326,18 @@ endif(APPLE) # Download data files (interaction data, masses, decay data ...) # ---------------------------------------------------------------------------- OPTION(DOWNLOAD_DATA "Download CRPropa data files" ON) -set(CRPROPA_DATAFILE_VER "2022-07-06") +set(CRPROPA_DATAFILE_VER "2023-10-20") if(DOWNLOAD_DATA) - message("-- Downloading data file from crpropa.desy.de ~ 65 MB") + message("-- Downloading data files from sciebo ~ 73 MB") file(DOWNLOAD - https://www.desy.de/~crpropa/data/interaction_data/data-${CRPROPA_DATAFILE_VER}.tar.gz-CHECKSUM - ${CMAKE_BINARY_DIR}/data-${CRPROPA_DATAFILE_VER}.tar.gz-CHECKSUM) + https://ruhr-uni-bochum.sciebo.de/public.php/webdav/data-${CRPROPA_DATAFILE_VER}.tar.gz-CHECKSUM + ${CMAKE_BINARY_DIR}/data-${CRPROPA_DATAFILE_VER}.tar.gz-CHECKSUM + USERPWD "3juW9sntQX2IWBS") file(STRINGS ${CMAKE_BINARY_DIR}/data-${CRPROPA_DATAFILE_VER}.tar.gz-CHECKSUM DATA_CHECKSUM LIMIT_COUNT 1 LENGTH_MINIMUM 32 LENGTH_MAXIMUM 32) file(DOWNLOAD - https://www.desy.de/~crpropa/data/interaction_data/data-${CRPROPA_DATAFILE_VER}.tar.gz + https://ruhr-uni-bochum.sciebo.de/public.php/webdav/data-${CRPROPA_DATAFILE_VER}.tar.gz ${CMAKE_BINARY_DIR}/data-${CRPROPA_DATAFILE_VER}.tar.gz + USERPWD "3juW9sntQX2IWBS" EXPECTED_MD5 "${DATA_CHECKSUM}") message("-- Extracting data file") else() @@ -381,7 +373,6 @@ add_library(crpropa SHARED src/ParticleMass.cpp src/ParticleState.cpp src/PhotonBackground.cpp - src/PhotonPropagation.cpp src/ProgressBar.cpp src/Random.cpp src/Source.cpp @@ -391,8 +382,8 @@ add_library(crpropa SHARED src/module/Acceleration.cpp src/module/Boundary.cpp src/module/BreakCondition.cpp + src/module/CandidateSplitting.cpp src/module/DiffusionSDE.cpp - src/module/EMCascade.cpp src/module/EMDoublePairProduction.cpp src/module/EMInverseComptonScattering.cpp src/module/EMPairProduction.cpp @@ -400,6 +391,7 @@ add_library(crpropa SHARED src/module/ElasticScattering.cpp src/module/ElectronPairProduction.cpp src/module/HDF5Output.cpp + src/module/MomentumDiffusion.cpp src/module/NuclearDecay.cpp src/module/Observer.cpp src/module/Output.cpp @@ -407,7 +399,6 @@ add_library(crpropa SHARED src/module/ParticleCollector.cpp src/module/PhotoDisintegration.cpp src/module/PhotoPionProduction.cpp - src/module/PhotonEleCa.cpp src/module/PhotonOutput1D.cpp src/module/PropagationBP.cpp src/module/PropagationCK.cpp @@ -625,10 +616,6 @@ if(ENABLE_TESTING) target_link_libraries(testDensity crpropa gtest gtest_main pthread ${COVERAGE_LIBS}) add_test(testDensity testDensity) - add_executable(testDINT test/testDINT.cpp) - target_link_libraries(testDINT crpropa gtest gtest_main pthread ${COVERAGE_LIBS}) - add_test(testDINT testDINT) - add_executable(testPropagation test/testPropagation.cpp) target_link_libraries(testPropagation crpropa gtest gtest_main pthread ${COVERAGE_LIBS}) add_test(testPropagation testPropagation) @@ -657,6 +644,9 @@ if(ENABLE_TESTING) target_link_libraries(testAdiabaticCooling crpropa gtest gtest_main pthread ${COVERAGE_LIBS}) add_test(testAdiabaticCooling testAdiabaticCooling) + add_executable(testCandidateSplitting test/testCandidateSplitting.cpp) + target_link_libraries(testCandidateSplitting crpropa gtest gtest_main pthread ${COVERAGE_LIBS}) + add_test(testCandidateSplitting testCandidateSplitting) if(WITH_GALACTIC_LENSES) add_executable(testGalacticMagneticLens test/testMagneticLens.cpp) @@ -677,6 +667,9 @@ if(ENABLE_TESTING) CONFIGURE_FILE(test/testDiffusionSDE.py testDiffusionSDE.py COPYONLY) add_test(testDiffusionSDE ${PYTHON_EXECUTABLE} testDiffusionSDE.py) + CONFIGURE_FILE(test/testMomentumDiffusion.py testMomentumDiffusion.py COPYONLY) + add_test(testMomentumDiffusion ${PYTHON_EXECUTABLE} testMomentumDiffusion.py) + CONFIGURE_FILE(test/testPythonExtension.py testPythonExtension.py COPYONLY) add_test(testPythonExtension ${PYTHON_EXECUTABLE} testPythonExtension.py) endif(ENABLE_PYTHON AND PYTHONLIBS_FOUND) diff --git a/README.md b/README.md index a85e3431e..b89e9cf81 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,15 @@ -CRPropa3 +CRPropa ======== +![stable release](https://img.shields.io/badge/stable\_release-3.2.0-darkblue) [![Build status](https://github.com/crpropa/crpropa3/actions/workflows/testing.yml/badge.svg)](https://github.com/crpropa/crpropa3/actions/) [![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/CRPropa/CRPropa3.svg)](https://isitmaintained.com/project/CRPropa/CRPropa3) [![Percentage of issues still open](https://isitmaintained.com/badge/open/CRPropa/CRPropa3.svg)](https://isitmaintained.com/project/CRPropa/CRPropa3) +[![DOI:10.1088/1475-7516/2022/09/035](http://img.shields.io/badge/DOI-10.1088/1475-7516/2022/09/035.svg)]() +[![arXiv](https://img.shields.io/badge/arXiv-2208.00107-b31b1b.svg)](https://arxiv.org/abs/2208.00107) +[![ascl:2208.016](https://img.shields.io/badge/ascl-2208.016-blue.svg?colorB=262255)](https://ascl.net/2208.016) + CRPropa is a publicly available simulation framework to study the propagation of ultra-high-energy nuclei up to iron on their voyage through an (extra)galactic environment. It takes into account: pion production, @@ -61,3 +66,15 @@ as well as [additional publications](https://crpropa.github.io/CRPropa3/pages/ho An extensive list of publications using CRPropa can be found via [inSPIRE](https://inspirehep.net/search?ln=en&ln=en&p=refersto%3Arecid%3A1322902+or+refersto%3Arecid%3A1432676+or+refersto%3Arecid%3A1242078&of=hb&action_search=Search&sf=earliestdate&so=d&rm=&rg=25&sc=0). + +## Plugins +Plugins are extensions of the core CRPropa framework, but they are not maintained by the CRPropa developer team. Instructions to install plugins can be found in the [documentation](https://crpropa.github.io/CRPropa3/pages/example_notebooks/extending-CRPropa/extending-CRPropa.html#Plugins:-Integrate-Custom-C++-Code-to-CRPropa%E2%80%99s-Python-Steering). + +Make sure to correctly cite the plugins when using them. + +| Name | Purpose | Link | +| ---- | ------- | ---- | +| FieldlineIntegrator | Magnetic Field Analysis | | +| grplinst | Plasma Instabilities | | +| monopole | Magnetic Monopole Studies | https://github.com/chchristie/monopole/tree/main | +| ROOTOutputPlugin | Output into root file format | https://github.com/CRPropa/ROOTOutputPlugin | diff --git a/doc/pages/AdditionalResources.rst b/doc/pages/AdditionalResources.rst index f95c69733..97bd3f6cb 100644 --- a/doc/pages/AdditionalResources.rst +++ b/doc/pages/AdditionalResources.rst @@ -20,6 +20,8 @@ Additional Resources - Data for the strong extragalactic magnetic fields by `Alves Batista et al. `__ can be downloaded `here `__. +- Data for the Galactic mass distribution by `Mertsch et al. (2020) `__ can be found + `here `__. Note that these resources are completely external to CRPropa. We cannot supply any kind of additional information nor can we offer support on how to use them. diff --git a/doc/pages/example_notebooks/Diffusion/MomentumDiffusion.ipynb b/doc/pages/example_notebooks/Diffusion/MomentumDiffusion.ipynb new file mode 100644 index 000000000..e830b6781 --- /dev/null +++ b/doc/pages/example_notebooks/Diffusion/MomentumDiffusion.ipynb @@ -0,0 +1,606 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Momentum Diffusion\n", + "\n", + "This notebooks gives an overview about the *MomentumDiffusion* module and shortly explains the theoretical background. Momentum diffusion or Second Order Fermi Acceleration is a process in which the particle ensemble gains energy on average due to scattering in magnetic turbulence. In contrast to diffusive shock acceleration (DSA - First Order Fermi Acceleration) individual particles can however loose significant amounts of energy.\n", + "\n", + "\n", + "The stationary transport equation ($\\partial_t f = 0$) for pure momenetum diffusion - neglecting all other terms - can be written as:\n", + "\n", + "$0 = \\frac{\\partial}{\\partial p}\\left[p^2 D_{pp} \\frac{\\partial}{\\partial p}\\left(\\frac{n}{p^2}\\right) \\right]$, \n", + "\n", + "where $n$ is the particle density, $p$ is the absolute momentum and $D_{pp}$ is the momentum diffusion scalar. For a constant momentum diffusion coefficient $D_{pp}=\\mathrm{const.}$, the stationary solution can be solved analytically and we get a simple momentum dependence for the particle density: $n \\propto p^1$. So, momentum diffusion (with a constant diffusion coefficient) can lead to much harder spectra than DSA. However, the acceleration time scales are usually much larger than for DSA.\n", + "\n", + "Further information can be found, e.g., in [Stawarz and Petrosian, ApJ **681** (2008) 1725-1744](https://iopscience.iop.org/article/10.1086/588813).\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib widget\n", + "\n", + "import crpropa as crp\n", + "from crpropa import c_light, meter, second\n", + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "from scipy.optimize import curve_fit" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Functionality to run the simulation and analyse the data" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "def loadData(filename: str) -> pd.DataFrame:\n", + " \"\"\"Loading CRPropa data file into a pandas DataFrame\n", + " The columns are derived from reading the header.\n", + " Args:\n", + " filename (str): CRPropa textout to be loaded\n", + " Returns:\n", + " pd.DataFrame: CRPropa simulation results\n", + " \"\"\"\n", + "\n", + " with open(filename, 'r') as f:\n", + " names = (f.readline()[:-1]).split('\\t')[1:]\n", + " df = pd.read_csv(filename, delimiter='\\t', comment='#', names=names, low_memory=False)\n", + " return df\n", + "\n", + "def TimeIntegrateSpectrum(df : pd.DataFrame, time : float, bins : np.array, weighted : bool=False) -> tuple:\n", + " \"\"\"Time integrated spectrum\n", + "\n", + " Sums all snapshots until simulation time 'time' to calculate the energy spectrum J including \n", + " its standard deviation dJ, central energy of the histogram binCenters, and the mean energy of\n", + " the full particle ensemble meanE.\n", + "\n", + " Args:\n", + " df (pd.DataFrame): Simulation data, e.g., loaded with 'loadData'.\n", + " time (float): maximal integration time\n", + " bins (np.array): binning used for the energy spectrum\n", + " weighted (bool, optional): Flag to include weights, e.g., from particle splitting. Defaults to False.\n", + "\n", + " Returns:\n", + " tuple(J, dJ, binCenter, meanE)\n", + " \"\"\"\n", + "\n", + " E = df.loc[df[\"T\"] <= time, \"E\"]\n", + " meanE = E.mean()\n", + "\n", + " if weighted:\n", + " HW = np.histogram(E, bins = bins, weights = df.loc[df[\"T\"] <= time, \"W\"])\n", + " H = np.histogram(E, bins = bins)\n", + "\n", + " bin_edges = H[1]\n", + " bin_width = bin_edges[1:] - bin_edges[:-1]\n", + " bin_center = bin_edges[:-1] + 0.5 * bin_width\n", + "\n", + " if weighted:\n", + " J = HW[0]/bin_width\n", + " dJ = J/np.sqrt(H[0])\n", + " else:\n", + " J = H[0]/bin_width\n", + " dJ = np.sqrt(H[0])/bin_width\n", + "\n", + " return J, dJ, bin_center, meanE\n", + "\n", + "\n", + "def linFit(x: np.array, a: float, b: float) -> np.array:\n", + " \"\"\"Linear Function\n", + " f(x) -> a*x + b\n", + "\n", + " Args:\n", + " x (np.array): input values\n", + " a (float): gradient\n", + " b (float): offset\n", + "\n", + " Returns:\n", + " np.array: solution\n", + " \"\"\"\n", + "\n", + " return a*x+b\n", + "\n", + "\n", + "def logFit(x: np.array, alpha: float, x_0: float=1.) -> np.array:\n", + " \"\"\"Linear Function\n", + " f(x) -> a*x + b\n", + "\n", + " Args:\n", + " x (np.array): input values\n", + " alpha (float): spectral index\n", + " x_0 (float=1.): normalization\n", + "\n", + " Returns:\n", + " np.array: solution\n", + " \"\"\"\n", + "\n", + " return x_0*x**alpha\n", + "\n", + "def Run_MomentumDiffusion(dpp : float=1, dxx : float=1, alpha : float=0., \n", + " p_0 : float=1., mono : bool=True, N_obs : int=10000, N_cand : int=1000, \n", + " B0 : crp.Vector3d=crp.Vector3d(1,0,0), epsilon : float=0., step : float=1e-3*c_light, \n", + " src_pos : crp.Vector3d=crp.Vector3d(0.), src_ID : crp.nucleusId=crp.nucleusId(1, 1)) -> None:\n", + " \"\"\"Simulation of momentum diffusion\n", + "\n", + " Args:\n", + " dpp (float, optional): Momentum diffusion scalar. Defaults to 1.\n", + " dxx (float, optional): Spatial diffusion scalar. Defaults to 1.\n", + " alpha (float, optional): Power law index of spatial diffusion energy dependence. Defaults to 0..\n", + " p_0 (float, optional): Injection Momentum. Defaults to 1..\n", + " mono (bool, optional): Flag for mono-energetic source spectrum. Defaults to True.\n", + " N_obs (int, optional): Number of observation points in time. Defaults to 10000.\n", + " N_cand (int, optional): Number of injected candidates. Defaults to 1000.\n", + " B0 (crp.Vector3d, optional): Background magnetic field direction - sets diffusion direction, too. Defaults to crp.Vector3d(1,0,0).\n", + " epsilon (float, optional): Ratio between perpendicular and parallel diffusion scalars. Defaults to 0..\n", + " step (float, optional): Integration step size. Defaults to 1e-3*c_light.\n", + " src_pos (crp.Vector3d, optional): Source position. Defaults to crp.Vector3d(0.).\n", + " src_ID (crp.nucleusId, optional): Particle type. Defaults to crp.nucleusId(1, 1).\n", + " \"\"\"\n", + " \n", + "\n", + " scale = dxx / (6.1*1e24 * meter**2. / second)\n", + " E_0 = p_0 * c_light\n", + " E_min = E_0/10\n", + " D_min = 100 * step\n", + " deltaD = 100 * step\n", + " maxD = (N_obs) * deltaD\n", + "\n", + "\n", + " Bfield = crp.UniformMagneticField(B0)\n", + "\n", + " spatialDiff = crp.DiffusionSDE(Bfield, 1e-4, step, step)\n", + " spatialDiff.setEpsilon(epsilon)\n", + " spatialDiff.setScale(scale)\n", + " spatialDiff.setAlpha(alpha)\n", + "\n", + " momentumDiff = crp.ConstantMomentumDiffusion(dpp)\n", + "\n", + " out = crp.TextOutput('MomentumDiffusion_p0-{}_dpp-{}_dxx-{}_delT-{}_Nobs-{}_delTobs-{}_mono-{}.txt'.format(p_0, dpp, dxx, step/c_light, N_obs, deltaD/c_light, mono))\n", + " out.disableAll()\n", + " out.enable(crp.Output.CurrentPositionColumn)\n", + " out.enable(crp.Output.CurrentEnergyColumn)\n", + " out.enable(crp.Output.TrajectoryLengthColumn)\n", + " out.setLengthScale(meter) \n", + " out.setEnergyScale(E_0)\n", + "\n", + " obs = crp.Observer()\n", + " obs.add(crp.ObserverTimeEvolution(D_min, deltaD, N_obs))\n", + " obs.onDetection(out)\n", + " obs.setDeactivateOnDetection(False)\n", + "\n", + " maxTra = crp.MaximumTrajectoryLength(maxD)\n", + " minEnergy = crp.MinimumEnergy(0.) #Seems to be needed, otherwise infs can appear\n", + "\n", + " src = crp.Source()\n", + " src.add(crp.SourceIsotropicEmission())\n", + " src.add(crp.SourceParticleType(src_ID))\n", + "\n", + " if mono:\n", + " src.add(crp.SourceEnergy(E_0))\n", + " else:\n", + " src.add(crp.SourcePowerLawSpectrum(E_min, E_0, -1))\n", + " src.add(crp.SourcePosition(src_pos))\n", + "\n", + " sim = crp.ModuleList()\n", + "\n", + " sim.add(spatialDiff)\n", + " sim.add(momentumDiff)\n", + " sim.add(obs)\n", + " sim.add(maxTra)\n", + " sim.add(minEnergy)\n", + "\n", + " sim.setShowProgress(True)\n", + " sim.run(src, N_cand)\n", + "\n", + " out.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Slow time evolution setup \n", + "\n", + "Here, a momentum diffusion coefficient of $D_{pp}=1$ is used." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# settings\n", + "\n", + "dpp_1 = 1\n", + "dxx_1 = 1\n", + "alpha_1 = 0.\n", + "p_0_1 = 1\n", + "mono_1 = True #switch for monoenergetic or power law injection.\n", + "\n", + "N_obs_1 = 10000\n", + "N_cand_1 = 1000\n", + "\n", + "step_1 = 1e-3 * c_light\n", + "deltaD_1 = 100 * step_1" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "crpropa::ModuleList: Number of Threads: 8\n", + "Run ModuleList\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Started Mon Oct 16 15:28:27 2023 : [\u001b[1;32m Finished \u001b[0m] 100% Needed: 00:02:59 - Finished at Mon Oct 16 15:31:26 2023\n", + "\r" + ] + } + ], + "source": [ + "# Run the simulation\n", + "Run_MomentumDiffusion(dpp =dpp_1, dxx=dxx_1, alpha=alpha_1, p_0=p_0_1, mono=mono_1, N_obs=N_obs_1, N_cand=N_cand_1, step=step_1)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# Load data\n", + "df_1 = loadData('MomentumDiffusion_p0-{}_dpp-{}_dxx-{}_delT-{}_Nobs-{}_delTobs-{}_mono-{}.txt'.format(p_0_1, dpp_1, dxx_1, step_1/c_light, N_obs_1, deltaD_1/c_light, mono_1))\n", + "df_1[\"T\"] = df_1[\"D\"]/c_light\n", + "del (df_1[\"D\"])\n", + "del (df_1[\"Y\"])\n", + "del (df_1[\"Z\"])\n", + "\n", + "times_1 = df_1[\"T\"].unique()\n", + "\n", + "groups_1 = df_1.groupby(df_1[\"T\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "9c35f3cce6a946699c7cb0f365cf00a3", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAABdfUlEQVR4nO3dd1gUV9sG8HuXDkrvCPYYEQXFXiHYsMWSiC0SNSZGjAWNJYk1BhPbh4XEkhg1bxKJGk0swYK9giI2jAYlNqTYQFDa7nx/EFbXpZdZYO7fdXHpnjlzzjO7Azycc2ZGJgiCACIiIiKSDLm2AyAiIiIicTEBJCIiIpIYJoBEREREEsMEkIiIiEhimAASERERSQwTQCIiIiKJYQJIREREJDFMAImIiIgkhgkgERERkcQwASQiIiKSGCaARERERBLDBJCIiIhIYpgAEhEREUkME0AiIiIiiWECSERERCQxTACJiIiIJIYJIBEREZHEMAEkIiIikhgmgEREREQSwwSQiIiISGKYABIRERFJDBNAIiIiIolhAkhEREQkMUwAiYiIiCSGCSARERGRxDABJCIiIpIYJoBEREREEsMEkIiIiEhimAASERERSQwTQCIiIiKJYQJIREREJDFMAImIiIgkhgkgERERkcQwASQiIiKSGCaARERERBLDBJCIiIhIYpgAEhEREUkME0AiIiIiiWECSERERCQxTACJiIiIJIYJIBEREZHEMAEkIiIikhgmgEREREQSwwSQiIiISGKYABIRERFJDBNAIiIiIolhAkhEREQkMUwAiYiIiCSGCSARERGRxDABJCIiIpIYJoBEREREEsMEkIiIiEhimAASERERSQwTQCIiIiKJYQJIREREJDFMAImIiIgkRlfbAVRlSqUS8fHxqFmzJmQymbbDISIiomIQBAHPnj2Do6Mj5HJpjoUxASyD+Ph4ODs7azsMIiIiKoW7d++iVq1a2g5DK5gAlkHNmjUB5J5Apqam5dp2dnY29u/fj+7du0NPT69c26bKj58/8RwgngMVJzU1Fc7Ozqrf41LEBLAM8qZ9TU1NKyQBNDY2hqmpKb/xJYifP/EcIJ4DFU/Ky7ekOfFNREREJGFMAImIiIgkhglgKYSEhMDV1RWtWrXSdihEREREJcYEsBQCAgIQExODyMhIbYdCREREVGJMAImIiIgkhgkgERERkcQwASQiIiKSGCaARERERBLDBJCIiIhIYpgAEhEREUkME0AiIiIiiWECSERERCQxTACJiIiIJEZX2wEQUfnqu+pEodt3fdJRpEiIiKiy4gggERERkcQwASQiIiKSGCaARERERBLDBJCIiIhIYpgAEhEREUkME0AiIiIiiWECSERERCQxTACJiIiIJIYJIBEREZHEMAEkIiIikhgmgEREREQSwwSQiIiISGKYABIRERFJjK62AyCikuu76oS2Q6CirO1S+PaPjooTBxFRPpgAElVCfmtPw985999sgQP1RERUvvibhYiIiEhimAASERERSQyngIkkprD1g7s+6ShiJEREpC1MAImICsILOYiommICSEREJCK/3X6Fbg/tEypSJCRlTACJiLShsNFFjiwSUQXjRSBEREREEsMEkIiIiEhiOAVMRERUzopa50ekbRwBJCIiIpIYJoBEREREEsMEkIiIiEhimAASERERSYykE8C7d+/Cy8sLrq6uaNasGbZu3artkIiIiIgqnKSvAtbV1UVwcDA8PDyQkJAAT09P9OrVCyYmJtoOjSSgsGfy6slEDISIiCRH0gmgg4MDHBwcAAD29vawtrbG48ePmQASERFRtValp4CPHTuGvn37wtHRETKZDDt37tSoExISgjp16sDQ0BBt2rRBREREvm2dP38eCoUCzs7OFRw1ERERkXZV6RHA9PR0uLu7Y/To0Rg4cKDG9tDQUAQGBmLNmjVo06YNgoOD0aNHD1y/fh22traqeo8fP8bIkSOxfv16McMnIqJKrLCbOYf2CRUxEqLyV6UTQF9fX/j6+ha4ffny5Rg7dixGjRoFAFizZg327NmDDRs2YObMmQCAzMxM9O/fHzNnzkT79u0L7S8zMxOZmZmq16mpqQCA7OxsZGdnl/Vw1OS1V97tUuWhJ1MWsk145d+C65U3nm+vkekXvr2w96uofYtolz8DtE9XKPhXZFGfS2H7FuX1z57nQPnjewrIBEEQtB1EeZDJZNixYwf69+8PAMjKyoKxsTG2bdumKgMAf39/PH36FH/88QcEQcCwYcPQqFEjzJs3r8g+5s2bh/nz52uU//LLLzA2Ni6nIyEiIqKK9Pz5cwwbNgwpKSkwNTXVdjhaUaVHAAvz8OFDKBQK2NnZqZXb2dnh77//BgCcPHkSoaGhaNasmWr94E8//YSmTZvm2+asWbMQGBioep2amgpnZ2d079693E+g7OxsHDhwAN26dYOenl65tk2Vg9/a0wVu05MJGFbrKX65Z45sQbxLgkM/aidaX1XCj70K3z5qb+n3LaJd/gzQvvfD3tdq/7qCLgYKA/G77HfkyHIAABt7btRqTNVF3gyelFXbBLA4OnbsCKWy+NNrBgYGMDAw0CjX09OrsB/QFdk2aVe2UNg1WMr/6siKqFe+eK69RsgqfPuGrhXT7yufA38GaE9e0qVVQm4cebHwXCgffB+r+FXAhbG2toaOjg4SExPVyhMTE2Fvb6+lqIiIiIi0r9omgPr6+vD09ER4eLiqTKlUIjw8HO3acZqLiIiIpKtKTwGnpaUhNjZW9TouLg7R0dGwtLSEi4sLAgMD4e/vj5YtW6J169YIDg5Genq66qpgIqJKaW2X3KuI7SbkriV8fSr6o6PaiYuIqo0qnQCeO3cO3t7eqtd5F2j4+/tj48aN8PPzQ3JyMubMmYOEhAR4eHggLCxM48IQIiIiIimp0gmgl5cXirqLzYQJEzBhwoRy7TckJAQhISFQKBTl2i4RERGRGKp0AqgtAQEBCAgIQGpqKszMzLQdDlG56bvqRKHbd33SUaRIiIioIlXbi0CIiIiIKH8cASQi6VrbRdsREBFpBRNAIiKSJL/dftoOgUhrOAVMREREJDFMAImIiIgkhlPApcDbwBARkTYUNW0d2idUpEioquMIYCkEBAQgJiYGkZGR2g6FiIiIqMSYABIRERFJDBNAIiIiIolhAkhEREQkMbwIhKiCFPVYNSIiIm3hCCARERGRxDABJCIiIpIYJoBEREREEsMEsBRCQkLg6uqKVq1aaTsUIiIiohJjAlgKvBE0ERERVWVMAImIiIgkhgkgERERkcTwPoBEVL2t7aLtCEiL/Hb7aTsEokqJI4BEREREEsMEkIiIiEhimAASERERSQwTQCIiIiKJ4UUgRERVTWEXtnx0VLw4iKjK4ghgKfBJIERERFSVMQEsBT4JhIiIiKoyJoBEREREEsMEkIiIiEhimAASERERSYyoCWBYWBhOnDiheh0SEgIPDw8MGzYMT548ETMUIiIiIskSNQH89NNPkZqaCgC4fPkypk6dil69eiEuLg6BgYFihkJEREQkWaLeBzAuLg6urq4AgO3bt6NPnz4ICgpCVFQUevXqJWYoRERERJIl6gigvr4+nj9/DgA4ePAgunfvDgCwtLRUjQwSERERUcUSdQSwY8eOCAwMRIcOHRAREYHQ0FAAwI0bN1CrVi0xQyEiIiKSLFFHAFevXg1dXV1s27YN3333HZycnAAAf/31F3r27ClmKERERESSJeoIoIuLC3bv3q1R/n//939ihkFEREQkaaLfB/DmzZv44osvMHToUCQlJQHIHQG8evWq2KGUGp8FTERERFWZqAng0aNH0bRpU5w9exa///470tLSAAAXL17E3LlzxQylTPgsYCIiIqrKRE0AZ86ciYULF+LAgQPQ19dXlb/11ls4c+aMmKEQERERSZaoawAvX76MX375RaPc1tYWDx8+FDMUIiKqBvx2+2k7BKIqSdQRQHNzczx48ECj/MKFC6orgomIiIioYomaAA4ZMgQzZsxAQkICZDIZlEolTp48iWnTpmHkyJFihkJEREQkWaImgEFBQXjzzTfh7OyMtLQ0uLq6onPnzmjfvj2++OILMUMhIiIikixR1wDq6+tj/fr1mD17Nq5cuYK0tDQ0b94cDRs2FDMMonLTd9UJbYdARERUYqImgHlcXFzg4uKija6JiIiIJK/CE8DAwMBi112+fHkFRkJERFS9FXZVdGifUBEjocquwhPACxcuFKueTCar4EiIiIiICBAhATx8+HBFd0FEREREJSDqVcApKSl4/PixRvnjx4+RmpoqZihEREREkiX6fQC3bNmiUf7bb79hyJAhYoZCREREJFmiJoBnz56Ft7e3RrmXlxfOnj0rZihEREREkiVqApiZmYmcnByN8uzsbLx48ULMUMokJCQErq6uaNWqlbZDISIiIioxURPA1q1bY926dRrla9asgaenp5ihlElAQABiYmIQGRmp7VCIiIiISkzUG0EvXLgQXbt2xcWLF+Hj4wMACA8PR2RkJPbv3y9mKERERESSJeoIYIcOHXD69Gk4Ozvjt99+w65du9CgQQNcunQJnTp1EjMUIiIiIskS/VFwHh4e+Pnnn8XuloiIiIj+U+EJYGpqKkxNTVX/L0xePSIiIiKqOBWeAFpYWODBgwewtbWFubl5vo98EwQBMpkMCoWiosMhIiIikrwKTwAPHToES0tLAHwsHBEREVFlUOEJYJcuXVT/r1u3LpydnTVGAQVBwN27dys6FCIiIiKCyBeB1K1bVzUd/KrHjx+jbt26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yZMwNTWFv79/gfv5+/vj008/haWlJWxtbTF37lzI5XKN6d1hw4Zh2rRpWL9+PTZv3lxoPIaGhpgxYwamT58OfX19dOjQAcnJybh69SrGjBlT5PFYWFjAysoK69atg4ODA+7cuYOZM2cWuV9Jj62071t+zp8/DwCws7PT+BxtbW3x8OFDnDt3Tu1imqL2kcs5LkAkBUwAiSQsLCwMDg4OamWNGjXC33//Xaz9v/zyS9jY2GDRokW4desWzM3N0aJFC3z22WeF7rd8+XKMGzcOffr0gampKaZPn467d++qTVMCuevnBg0ahD179qB///5FxjN79mzo6upizpw5iI+Ph4ODA8aNG1esY5HL5diyZQsmTpwINzc3NGrUCCtXroSXl1ex9i/JsZX2fXtd3tXFDRs2VCs3MDBAamoqdu3ahdatW6sl9EXto6+vD0dHR7URv/v376utaySiqk8mCIKg7SCISNrS09Ph5OSEZcuWaYzW+fj4oEmTJli5cqWWoiubwo6tJLy8vODh4YHg4OBi79OvXz907NgR06dPL1FfOTk5aNy4MY4cOaK6COTUqVNqF4HIZDLs2LGjWIk5EVU+HOsnItFduHABv/76K27evImoqCjV0yheXav25MkT7NixA0eOHEFAQIC2Qi2x4hxbaX377beoUaMGLl++XKz6HTt2LNWFG7q6uli2bBm8vb3h4eGBqVOnqpK/cePG8WbRRNUARwCJSHQXLlzABx98gOvXr0NfXx+enp5Yvnw5mjZtqqpTp04dPHnyBLNnz8a0adO0GG3JFOfYSuP+/ft48eIFAMDFxUVrj9NLSkpCamoqgNzb35TmCm8i0j4mgEREREQSwylgIiIiIolhAkhEREQkMf8P6pn6cBcgaNAAAAAASUVORK5CYII=", + "text/html": [ + "\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Visualisation\n", + "\n", + "plt.figure()\n", + "bins = np.logspace(-1, 2.5 , 61)\n", + "\n", + "for t in [times_1[0], times_1[99], times_1[9999]]:\n", + " energies = groups_1.get_group(t).E\n", + " energies.hist(bins=bins, label=r\"$t={:.1}s, \\langle E\\rangle/E_0={:.1}$\".format(t, energies.mean()), alpha=0.8)\n", + "plt.loglog()\n", + "plt.xlabel('Energy change [$E/E_0$]')\n", + "plt.ylabel('Number of pseudo-particles')\n", + "plt.legend(loc='lower left')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Figure 1:** Time evolution of the energy spectrum for a burst-like injection $S(p, t) = \\delta(p-p_0)\\delta(t)$. It is visible that the particle ensemble gains energy on average but the distribution in momentum space gets wider, too." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "47be7aa8a3e74e90828da22c3b9e84f6", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "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", + "text/html": [ + "\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "No such comm: 9c35f3cce6a946699c7cb0f365cf00a3\n" + ] + } + ], + "source": [ + "plt.close()\n", + "plt.figure()\n", + "binEdges = np.logspace(-1., 2.3, 31)\n", + "\n", + "fit_range = slice(9, -14)\n", + "plot_range = slice(9,-1)\n", + "\n", + "#for t in [times[0], times[9], times[99], times[999], times[9999]]:\n", + "for t in [times_1[0], times_1[99], times_1[9999]]:\n", + "\n", + " J, dJ, bin_center, meanE = TimeIntegrateSpectrum(df_1, t, binEdges, weighted = False) #restrict to get spectrum close to the shock\n", + " plt.errorbar(bin_center, J/bin_center, yerr=dJ/bin_center, marker='x', linestyle='', label=r\"$t\\leq{:.1E}s, \\langle E\\rangle/E_0=${:.1E} \".format(t, meanE))\n", + "\n", + " if t == times_1[9999]:\n", + " popt, cov = curve_fit(linFit, np.log10(bin_center)[fit_range], np.log10(J)[fit_range])\n", + "\n", + " x_plot = bin_center[plot_range]\n", + " f_plot = logFit(x_plot, popt[0], 10**popt[1])\n", + " plt.plot(x_plot, f_plot/x_plot, color='k', linestyle='-')\n", + "\n", + " x_fit = bin_center[fit_range]\n", + " f_fit = logFit(x_fit, popt[0], 10**popt[1])\n", + " plt.plot(x_fit, f_fit/x_fit, color='r', linestyle='--', label=r'power law fit with $\\gamma={:.3}\\pm{:.1}$'.format(popt[0], np.sqrt(cov[0, 0])))\n", + "\n", + "\n", + " \n", + "\n", + "\n", + "plt.plot((1, 1), (1e-4, 2e4), 'k')\n", + "plt.ylim(2e-0, 2e4)\n", + "plt.loglog()\n", + "plt.xlabel('relative energy [$E/E_0$]')\n", + "plt.ylabel('n / E')\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Figure 2:** Different approximations of the stationary solution ($\\partial_t n=0$). The more snap shots of the time evolution are taken into accound (here by increasing the time) the better the analytically expected result $n\\propto E$ is matched. The solid line shows a power law fit to the data. As we do expect a cut-off in the energy spectrum due to the finite simulation time not all data are taken into account. The fitted energy range is denoted by the red dashed line. With sufficient resolution of the time snaps, the solution corresponds to the spectra at time $t$ with continuous injection of particles. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Fast time evolution setup \n", + "\n", + "Here, a momentum diffusion coefficient of $D_{pp}=10$ is used." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "# settings\n", + "\n", + "dpp_10 = 10\n", + "dxx_10 = 1\n", + "alpha_10 = 0.\n", + "p_0_10 = 1\n", + "mono_10 = True #switch for monoenergetic or power law injection.\n", + "\n", + "N_obs_10 = 10000\n", + "N_cand_10 = 1000\n", + "\n", + "step_10 = 1e-3 * c_light\n", + "deltaD_10 = 100 * step_10" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "crpropa::ModuleList: Number of Threads: 8\n", + "Run ModuleList\n", + " Started Mon Oct 16 15:31:33 2023 : [\u001b[1;32m Finished \u001b[0m] 100% Needed: 00:02:57 - Finished at Mon Oct 16 15:34:30 2023\n", + "\r" + ] + } + ], + "source": [ + "# Run the simulation\n", + "Run_MomentumDiffusion(dpp =dpp_10, dxx=dxx_10, alpha=alpha_10, p_0=p_0_10, mono=mono_10, N_obs=N_obs_10, N_cand=N_cand_10)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "# Load data\n", + "df_10 = loadData('MomentumDiffusion_p0-{}_dpp-{}_dxx-{}_delT-{}_Nobs-{}_delTobs-{}_mono-{}.txt'.format(p_0_10, dpp_10, dxx_10, step_10/c_light, N_obs_10, deltaD_10/c_light, mono_10))\n", + "df_10[\"T\"] = df_10[\"D\"]/c_light\n", + "del (df_10[\"D\"])\n", + "del (df_10[\"Y\"])\n", + "del (df_10[\"Z\"])\n", + "\n", + "times_10 = df_10[\"T\"].unique()\n", + "\n", + "groups_10 = df_10.groupby(df_10[\"T\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/tmp/ipykernel_3178606/2660489551.py:16: RuntimeWarning: divide by zero encountered in log10\n", + " popt, cov = curve_fit(linFit, np.log10(bin_center)[fit_range], np.log10(J)[fit_range])\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e97ffc89002b4ae88a90aa7d3a360c06", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAABtoklEQVR4nO3de1xUdf4/8NcMMCgoIKAC4q0UE00oFdbSwFumG2K25c+1JDONHLuxprZd2NrU1i3vo2huWm2tbn1DWTTLJcHyrghLYSpGqysqWgkyKowzn98fOEeGGeAwMzAM5/V8POYh55zPOed9mOPMm8/tqIQQAkRERESkGGpXB0BEREREzYsJIBEREZHCMAEkIiIiUhgmgEREREQKwwSQiIiISGGYABIREREpDBNAIiIiIoVhAkhERESkMEwAiYiIiBSGCSARERGRwjABJCIiIlIYJoBERERECsMEkIiIiEhhmAASERERKQwTQCIiIiKFYQJIREREpDBMAImIiIgUhgkgERERkcIwASQiIiJSGCaARERERArDBJCIiIhIYZgAEhERESkME0AiIiIihWECSERERKQwTACJiIiIFIYJIBEREZHCMAEkIiIiUhgmgEREREQKwwSQiIiISGGYABIREREpDBNAIiIiIoVhAkhERESkMEwAiYiIiBSGCSARERGRwjABJCIiIlIYJoBERERECsMEkIiIiEhhmAASERERKQwTQCIiIiKFYQJIREREpDBMAImIiIgUhgkgERERkcIwASQiIiJSGCaARERERArDBJCIiIhIYZgAEhERESkME0AiIiIihWECSERERKQwTACJiIiIFIYJIBEREZHCMAEkIiIiUhgmgEREREQKwwSQiIiISGGYABIREREpDBNAIiIiIoVhAkhERESkMJ6uDsCdmUwmlJSUoH379lCpVK4Oh4iIiGQQQuDKlSsICwuDWq3MujAmgHbQ6XTQ6XSoqqrCqVOnXB0OERER2eHMmTMIDw93dRguoRJCCFcH4a7KysoQEBCAM2fOwM/Pz9XhkIvo9XqEhYUBAEpKSuDr6+viiIiIqD7l5eXo2rUrLl++DH9/f1eH4xKsAXSAudnXz8+PCaCCeXh4SD/7+fkxASQichNK7r6lzIZvIiIiIgVjAkhERESkMEwAiYiIiBSGfQCJqEkIIXDjxg0YjUZXh0JECuPh4QFP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", + "text/html": [ + "\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Visualisation\n", + "\n", + "plt.close()\n", + "plt.figure()\n", + "binEdges = np.logspace(-1., 3., 31)\n", + "\n", + "fit_range = slice(9, -12)\n", + "plot_range = slice(7,-1)\n", + "\n", + "for t in [times_10[0], times_10[99], times_10[9999]]:\n", + "\n", + " J, dJ, bin_center, meanE = TimeIntegrateSpectrum(df_10, t, binEdges, weighted = False) #restrict to get spectrum close to the shock\n", + " plt.errorbar(bin_center, J/bin_center, yerr=dJ/bin_center, marker='x', linestyle='', label=r\"$t\\leq{:.1E}s, \\langle E\\rangle/E_0=${:.1E} \".format(t, meanE))\n", + "\n", + " if t == times_1[9999]:\n", + " popt, cov = curve_fit(linFit, np.log10(bin_center)[fit_range], np.log10(J)[fit_range])\n", + "\n", + " x_plot = bin_center[plot_range]\n", + " f_plot = logFit(x_plot, popt[0], 10**popt[1])\n", + " plt.plot(x_plot, f_plot/x_plot, color='k', linestyle='-')\n", + "\n", + " x_fit = bin_center[fit_range]\n", + " f_fit = logFit(x_fit, popt[0], 10**popt[1])\n", + " plt.plot(x_fit, f_fit/x_fit, color='r', linestyle='--', label=r'power law fit with $\\gamma={:.3}\\pm{:.1}$'.format(popt[0], np.sqrt(cov[0, 0])))\n", + "\n", + "\n", + " \n", + "\n", + "\n", + "plt.plot((1, 1), (1e-4, 2e4), 'k')\n", + "plt.ylim(2e-0, 2e4)\n", + "plt.loglog()\n", + "plt.xlabel('relative energy [$E/E_0$]')\n", + "plt.ylabel('n / E')\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Figure 3:** Same as in figure 2 but for a larger momentum diffusion scalar. It is visible that the time evolution is faster and higher energies are reached in the same time. However, the approximation close to $E_0$ is worse than for the case with $D_{pp}=1$. This could be improved by taking more snapshot at ealier times into account/increasing the resolution in time. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "crp_diffusion", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/doc/pages/example_notebooks/acceleration/diffusive_shock_acceleration.ipynb b/doc/pages/example_notebooks/acceleration/diffusive_shock_acceleration.ipynb new file mode 100644 index 000000000..8edea9568 --- /dev/null +++ b/doc/pages/example_notebooks/acceleration/diffusive_shock_acceleration.ipynb @@ -0,0 +1,825 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Diffusive Shock Acceleration (DSA)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In DSA - or First Order Fermi Acceleration - charged particles experience energy gain when they (repeatedly) cross a moving shock front. At non-relativistic, stationary, ideal shocks, neglecting backreaction of particles to the background plasma, the energy spectrum is a power-law, only depending on the shocks compression ratio $q = u_{\\mathrm{up}}/ u_{\\mathrm{down}}$. For a strong shock with compression $q = 4$, the expected spectral slope is $-2$." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the diffusive picture, DSA comes from adiabatic heating due to the changing advection field, $\\nabla \\vec{u} \\neq 0$. An infinitly thin shock can not be modeled, instead the shock profile is smoothed, e.g. in 1D $u(x) \\propto \\mathrm{tanh}(x/L_{\\mathrm{sh}})$. The shock width $L_{\\mathrm{sh}}$ now implies constraints on the diffusion coefficient $\\kappa$ and time step $\\Delta t$ of the simulation: \n", + "\n", + "1. The (average) diffusive step $\\sqrt{\\kappa \\Delta t}$ must be higher than the shock width $L_{\\mathrm{sh}}$. \n", + " 1. If diffusion is too small, (pseudo-)particles do not make it back over the shock and there is (almost) no acceleration\n", + " 2. If the shock width is too large compared to the diffusive step, a smooth velocity gradient is modeled instead of a real shock. This leads to steeper energy-spectra compared to the ideal shock\n", + "2. The advective step $\\left(u + \\partial \\kappa(x)/\\partial x \\right)\\Delta t$ must be smaller than the shock width $L_{\\mathrm{sh}}$. \n", + " 1. If advection is too high, the probability that pseudo-particles encounter the changing advection field is too low. With that acceleration is underestimated, leading to steeper spectra. \n", + " 2. The drift term due to changing diffusion coefficients, pushes pseudo-particles away from the shock. Currently, CRPropa3.2 supports energy-dependent diffusion that is constant in space. Thus, the advective step is only determined by the advection speed and time step." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "from crpropa import *\n", + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "\n", + "marker= ['.', 's', '^', 'v', '<', '>', 'd', '8']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Simple set-up for DSA at a 1D shock:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "#Parameters\n", + "\n", + "#Shock profile:\n", + "compression = 4\n", + "v_up = 1 #upstream velocity in m/s\n", + "l_sh = 0.02 #shock width in m\n", + "adv = OneDimensionalCartesianShock(compression, v_up, l_sh) #shock profile\n", + "\n", + "#Adiabatic Cooling for particle acceleration:\n", + "ac = AdiabaticCooling(adv)\n", + "\n", + "#Diffusion: \n", + "kappa = 1 #diffusion coefficient in m^2/s\n", + "epsilon = 0 #parallel diffusion only\n", + "alpha = 0 #energy-independent diffusion\n", + "\n", + "Bfield = UniformMagneticField(Vector3d(1*nG,0*nG,0*nG)) #parallel to advective field\n", + "\n", + "delta_t = 0.005 #simulation time step in s. So that, advective step < shock width < diffusive step\n", + "\n", + "minStep = delta_t * c_light \n", + "maxStep = minStep #no adaptive step length\n", + "precision = 1e-3\n", + "diffSDE = DiffusionSDE(Bfield, adv, precision, minStep, maxStep, epsilon)\n", + "\n", + "diffSDE.setAlpha(alpha)\n", + "diffSDE.setScale(kappa/(6.1*10**24)) #scaling in DiffusionSDE: kappa = scale * (6.1*10**24) * (R/4GV)^alpha\n", + "\n", + "#Source: \n", + "E0 = TeV \n", + "Id = nucleusId(1,1)\n", + "src_pos = 0 #candidates injected at the shock\n", + "\n", + "source = Source()\n", + "source.add(SourcePosition(Vector3d(src_pos, 0, 0)))\n", + "source.add(SourceParticleType(Id))\n", + "source.add(SourceEnergy(E0))\n", + "source.add(SourceIsotropicEmission())\n", + "\n", + "#Time Observer to construct stationary solution:\n", + "T_min = delta_t\n", + "T_max = 200+delta_t\n", + "n_time = 200 # approximation of stationary solution depends on number of candidates, simulation time step AND \"observing\" time step\n", + "\n", + "#simulate until T_max is reached, no escape boundaries in space:\n", + "maxTra = MaximumTrajectoryLength( T_max * c_light)\n", + "\n", + "N_cand = 10**4 #number of simulated pseudo-particles" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "crpropa::ModuleList: Number of Threads: 8\n", + "Run ModuleList\n", + " Started Fri Nov 3 10:20:17 2023 : [\u001b[1;32m Finished \u001b[0m] 100% Needed: 00:00:37 - Finished at Fri Nov 3 10:20:54 2023\n", + "\r" + ] + } + ], + "source": [ + "#Simulation\n", + "\n", + "file = \"SimpleDSA.txt\"\n", + "outTime = TextOutput(file)\n", + "outTime.setEnergyScale(TeV)\n", + "outTime.setLengthScale(meter)\n", + "outTime.disableAll()\n", + "outTime.enable(Output.TrajectoryLengthColumn)\n", + "outTime.enable(Output.CurrentEnergyColumn)\n", + "outTime.enable(Output.CurrentPositionColumn)\n", + "\n", + "obsTime = Observer()\n", + "obsTime.add(ObserverTimeEvolution(T_min*c_light, T_max*c_light, n_time, False)) \n", + "obsTime.onDetection(outTime)\n", + "obsTime.setDeactivateOnDetection(False)\n", + "\n", + "\n", + "m = ModuleList()\n", + "m.add(diffSDE)\n", + "m.add(ac)\n", + "m.add(obsTime)\n", + "m.add(maxTra)\n", + "m.setShowProgress(True)\n", + "m.run(source, N_cand)\n", + "outTime.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "columns = ['D', 'E', 'X', 'Y', 'Z']\n", + "file = \"SimpleDSA.txt\"\n", + "df = pd.read_csv(file, comment='#', delimiter = '\\t', names = columns ) \n", + "df[\"T\"] = df[\"D\"]/(c_light)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "def energy_spectrum(df, bins, weighted = False):\n", + " # calculates the energy spectrum J, dJ of dataframe df\n", + " # returns touple (N, dN, bin_center)\n", + " # weights are taken into account if weighted == True\n", + "\n", + " if weighted:\n", + " HW = np.histogram(df['E'], bins = bins, weights = df[\"W\"])\n", + " H = np.histogram(df['E'], bins = bins)\n", + "\n", + " bin_edges = H[1]\n", + " bin_width = bin_edges[1:] - bin_edges[:-1]\n", + " bin_center = bin_edges[:-1] + 0.5 * bin_width\n", + "\n", + " if weighted:\n", + " J = HW[0]/bin_width\n", + " dJ = J/np.sqrt(H[0]) \n", + " else:\n", + " J = H[0]/bin_width\n", + " dJ = np.sqrt(H[0])/bin_width \n", + "\n", + " return J, dJ, bin_center\n", + "\n", + "def number_density(df, bins, weighted = False):\n", + " # calculates the number density integrated over energy N, dN of dataframe df\n", + " # returns touple (N, dN, bin_center)\n", + " # weights are taken into account if weighted == True\n", + "\n", + " if weighted:\n", + " HW = np.histogram(df['X'], bins = bins, weights = df[\"W\"])\n", + " H = np.histogram(df['X'], bins = bins)\n", + "\n", + " bin_edges = H[1]\n", + " bin_width = bin_edges[1:] - bin_edges[:-1]\n", + " bin_center = bin_edges[:-1] + 0.5 * bin_width\n", + "\n", + " if weighted:\n", + " N = HW[0]/bin_width\n", + " dN = N/np.sqrt(H[0]) \n", + " else:\n", + " N = H[0]/bin_width\n", + " dN = np.sqrt(H[0])/bin_width \n", + "\n", + " return N, dN, bin_center\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Burst-like Injection at the Shock\n", + "\n", + "Pseudo-particles are injected at the shock at $t = 0$ and propagated until the maximum simulation time $T = 200$. We plot the energy-spectrum at the shock and number density (integrated over energy) in the acceleration region over time" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABY0AAAL2CAYAAAANc7nMAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAABcSAAAXEgFnn9JSAAEAAElEQVR4nOzdeXhTddo+8PskdG8hbWmxGy2Uguy2WBWEH+CCOKhMyzb6olbcRnFmGJx51XlFluoL4wgyo4yOjiDqywxgWxR0FHWgOCDIXkDAUugKQqkNdF+S/P6ISbOcJOe0SU7S3p/r4pJzTk7yLVR68uQ59yMYDAYDiIiIiIiIiIiIiIgAqJReABERERERERERERH5DhaNiYiIiIiIiIiIiMiMRWMiIiIiIiIiIiIiMmPRmIiIiIiIiIiIiIjMWDQmIiIiIiIiIiIiIjMWjYmIiIiIiIiIiIjIjEVjIiIiIiIiIiIiIjLrpfQCiIiIiIiIiIiIyDmDwQCDwaD0MsjPCIIAQRBkn8eiMRERERERERERkQ/S6XSoqalBXV0dWltblV4O+anAwEBEREQgOjoaarVa0jmCgR9REBERERERERER+RSdTofy8nI0NzcrvRTqJoKDg9G/f39JhWN2GhMREREREREREfmYmpoaNDc3Q61Wo1+/fggLC4NKxfFkJI9er0dDQwMuXryI5uZm1NTUIDY21uV5LBoTERERERERERH5mLq6OgBAv3790KdPH4VXQ/5KpVKZv3/Onz+Puro6SUVjfjxBRERERERERETkQwwGgznDOCwsTOHVUHdg+j5qbW2VNFCRRWMiIiIiIiIiIiIfYlnUYyQFuYPl9xGLxkREREREREREREQkCzONiYiIiIiIiIiIerjmNh3e2Fli3n5iUiqCA9QKroiUxKIxERERERERERFRD9fSrsefvyo2b88bP4BF4x6M8RREREREREREREREZMaiMREREREREREREZFEBw8exIoVK5CdnY3ExEQIggBBECSd29TUhBdeeAGDBw9GcHAw4uPjMW/ePFRVVXl41fKwaExERERERERERER+4/PPP4cgCHj88ccVef3c3Fw899xzKCgokFXsbW5uxi233ILc3FzU19dj+vTpSEpKwrp165Ceno6zZ896cNXysGhMREREREREREREfmPfvn0AgBtuuEGR1x87diwWLVqEjz/+GBcuXEBQUJCk81588UXs3bsXY8eOxffff4+NGzdi3759WLlyJaqrqzFv3jwPr1w6DsIjIiIiIiIiIiIiv2EqGmdmZiry+s8884zsc1pbW/H6668DANasWYPw8HDzsYULF2L9+vUoLCzEwYMHMWbMGLettbPYaUxERERERERERNTDldU0ON32BS+//DIEQcCnn34KABg9erQ5T/jWW29VeHXO7d69G1euXEFqairS09Ptjs+cORMAsHXrVm8vTRQ7jYmIiIiIiIiIiHqwTQcq8FzeMat9WWv2YPmMkZh9fZJCq7IXGxuLWbNmYfPmzYiNjcWdd95pPjZ58mQFV+ba0aNHAQAZGRmix037i4qKvLYmZ1g0JiIiIiIiIiIi6qHOXW7Ac/nHoDMYrPbrDAY8l38MmSlRGNA3TKHVWcvJycHAgQOxefNm3HHHHXj33XddnjNp0iQUFhbKep1169YhJyenc4t0oLy8HACQmJgoety0v6yszK2v21ksGhMREREREREREfVQG/dXQKc3iB7T6Q3YdKACz0y91surcuzIkSMAgOuuu07S46dOnYqUlBRZrzFo0CB5i5Kgvr4eABAaGip6PCzMWJivq6tz+2t3BovGREREREREREREPVRlbaOL401eWok0covGzz77rOcW041xEB4REREREREREVEPlRgp3vnacTzESyuRxpQNPHr0aIVXIk94eDgAoLFRvEjf0GAcPBgREeG1NTnDTmMiIiIiIiIiIqIeak5mEt7++qxoRIVaJfjUILz29nacOHECiYmJiI6OlnTOihUrcOrUKVmv88gjj2D8+PGdWaJD/fv3BwBUVlaKHjftT05OduvrdhaLxkRERERERERERD3UgL5hWJ49Es/lWQ/DUwsCVmSP9JkheABw8uRJtLS0yOoy/uyzz2QPwps0aZLbi8amNR86dEj0uGn/qFGj3Pq6ncWiMRERERERERERUQ82+/okXHtNBO55fbd5X8H8cRiVqFFuUSJOnjwJABgxYoTkc3bu3Omh1chz8803o0+fPigpKcGRI0fsMpk//PBDAMDdd9+twOrsMdOYiIiIiIiIiIioh0uODnO67Qva2toAOM4F9mWBgYF46qmnAADz5883ZxgDwKpVq1BUVISJEydizJgxSi3RCjuNiYiIiIiIiIiIyOfdeOONCAgIwF//+lecOXMGsbGxCA4OxptvvunVdXzyySfIzc01b7e2tgIAbrrpJvO+RYsWYdq0aVbnPf/88/jyyy+xZ88epKWlYcKECSgrK8O+ffsQExODtWvXeucLkIBFYyIiIiIiIiIiIvJ5gwYNwsaNG/Hiiy9i165daGhoUKQzt7q6Gvv27bPbb7mvurra7nhwcDB27NiB5cuXY8OGDdiyZQuioqKQk5OD3NxcJCYmenTdcggGg8F+NCIREREREREREREpQq/X4/Tp0wCAIUOGQKXyfMLslaY2jF663bx9dPEU9AkJ8PjrknfI/Z5ipjERERERERERERERmTGegoiIiIiIiIiIqIcL6qXCb25Ns9qmnotFYyIiIiIiIiIioh4uOECN394+WOllkI/gRwZEREREREREREREZMaiMRERERERERERERGZsWhMRERERERERERERGYsGhMRERERERERERGRGYvGRERERERERERERGTGojERERERERERERERmbFoTERERERERERERERmLBoTERERERERERERkVkvpRdARERERERERERECmtrBv7zasf2+N8CAcHKrYcUxaIxERERERERERFRT9feDBSu6Ni+6QkWjXswxlMQERERERERERERSdDY2IgtW7bg4YcfxpAhQxAcHIywsDCMHj0ay5YtQ319vdPzm5qa8MILL2Dw4MEIDg5GfHw85s2bh6qqKi99BdKwaExERERERERERER+4/PPP4cgCHj88ce9/tobNmxAVlYW1q5dC7VajXvuuQcTJkzAuXPnsHjxYmRmZuLSpUui5zY3N+OWW25Bbm4u6uvrMX36dCQlJWHdunVIT0/H2bNnvfzVOMaiMREREREREREREfmNffv2AQBuuOEGr792QEAAHnvsMXz33Xf47rvvsGnTJnz22Wc4ffo00tPTcerUKSxYsED03BdffBF79+7F2LFj8f3332Pjxo3Yt28fVq5cierqasybN8+7X4wTgsFgMCi9CCIiIiIiIiIiIjLS6/U4ffo0AGDIkCFQqbzQ99mkBf6Y3LH9TBkQovH863bCtGnT8Omnn+Lo0aMYNWqU0ssx++abbzBu3DgEBQXh6tWrCAwMNB9rbW1FbGwsrly5gkOHDiE9Pd3q3NGjR6OoqAgHDhzAmDFj3L42ud9T7DQmIiIiIiIiIiLq6X4853zbB7z88ssQBAGffvopAGOhVRAECIKAW2+9VeHVGdcDAC0tLaipqbE6tnv3bly5cgWpqal2BWMAmDlzJgBg69atnl+oBL2UXgAREREREREREREp6PAHwMe/tt7391uBe/4CpM9VZk0iYmNjMWvWLGzevBmxsbG48847zccmT56s4MqMTJnEAQEBiIqKsjp29OhRAEBGRobouab9RUVFHlyhdCwaExERERERERER9VQ1JcaCsUFnvd+gM+7vPxaITlVmbTZycnIwcOBAbN68GXfccQfeffddl+dMmjQJhYWFsl5n3bp1yMnJkb2+P//5zwCAqVOnIigoyOpYeXk5ACAxMVH0XNP+srIy2a/rCSwaExERERERERER9VSH3rMvGJsYdMDh94Hblnh1Sc4cOXIEAHDddddJevzUqVORkpIi6zUGDRokb1EAPv30U7zzzjsICAhAbm6u3fH6+noAQGhoqOj5YWFhAIC6ujrZr+0JLBoTERERERERERH1VNryrh33MrlF42effdZzi/nJqVOnMHfuXBgMBvzpT38yZxv7Mw7CIyIiIiIiIiIi6qk0/bt23MtM2cC+UpitqqrC1KlTUVtbi4ULF+I3v/mN6OPCw8MBAI2NjaLHGxoaAAARERGeWahM7DQmIiIiIiIiIiLqqTIeAPa8Jh5RIaiB9Pu9vyYH2tvbceLECSQmJiI6OlrSOStWrMCpU6dkvc4jjzyC8ePHu3zcjz/+iClTpqCsrAwPPfQQXnnlFYeP7d/fWHyvrKwUPW7an5ycLGutnsKiMRERERERERERUU8VnQrc8xf7YXiCGrjnNZ8ZggcAJ0+eREtLi6wu488++0z2ILxJkya5LBrX19fjzjvvxHfffYfs7Gy8/fbbEATB4eNNaz506JDocdP+UaNGyVqrp7BoTERERERERERE1JOlzwVihwNvT+rY98hXQEK6YksSc/LkSQDAiBEjJJ+zc+dOt6+jpaUF06dPx7fffos77rgD//jHP6BWq52ec/PNN6NPnz4oKSnBkSNH7DKZP/zwQwDA3Xff7fb1dgYzjYmIiIiIiIiIiHq6qAHOt31AW1sbAMe5wN6g0+lw77334t///jcmTJiA/Px8BAYGujwvMDAQTz31FABg/vz55gxjAFi1ahWKioowceJEjBkzxmNrl4OdxkREREREREREROTzbrzxRgQEBOCvf/0rzpw5g9jYWAQHB+PNN9/02hpef/11FBQUAAD69u2LJ598UvRxr7zyCvr27Wu17/nnn8eXX36JPXv2IC0tDRMmTEBZWRn27duHmJgYrF271uPrl4pFYyIiIiIiIiIiIvJ5gwYNwsaNG/Hiiy9i165daGho8Hpnbm1trfn3puKxmCVLltgVjYODg7Fjxw4sX74cGzZswJYtWxAVFYWcnBzk5uYiMTHRY+uWSzAYDAalF0FERERERERERERGer0ep0+fBgAMGTIEKpUXEmabtMAfkzu2nykDQjSef13yCrnfU8w0JiIiIiIiIiIiIiIzxlMQERERERERERH1dL2CgYnPWm9Tj8WiMRERERERERERUU8XEAxMfk7pVZCPYDwFEREREREREREREZmxaExEREREREREREREZiwaExEREREREREREZEZi8ZEREREREREREREZMaiMRERERERERERERGZsWhMRERERERERERERGYsGhMRERERERERERGRGYvGRERERERERERERGTWS+kFEBERERERERERkbJadC1459g75u2HRz6MIHWQgisiJbFoTERERERERERE1MO16FrwxtE3zNtzh81l0bgHYzwFEREREREREREREZmxaExERERERERERETUSTU1NYiNjYUgCBg0aJDTxzY1NeGFF17A4MGDERwcjPj4eMybNw9VVVVeWq00LBoTERERERERERGR3/j8888hCAIef/xxpZcCAHj66adx+fJll49rbm7GLbfcgtzcXNTX12P69OlISkrCunXrkJ6ejrNnz3phtdKwaExERERERERERER+Y9++fQCAG264QeGVAF999RXWr1+PRx991OVjX3zxRezduxdjx47F999/j40bN2Lfvn1YuXIlqqurMW/ePC+sWBoWjYmIiIiIiIiIiHq4iroKp9u+xFQ0zszMVHQdTU1NePzxxzFs2DD87ne/c/rY1tZWvP766wCANWvWIDw83Hxs4cKFGDVqFAoLC3Hw4EGPrlkqFo2JiIiIiIiIiIh6sILiAtz3yX1W++775D4UFBcotCJxL7/8MgRBwKeffgoAGD16NARBgCAIuPXWW72+nqVLl+Ls2bN48803ERAQ4PSxu3fvxpUrV5Camor09HS74zNnzgQAbN261SNrlauX0gsgIiIiIiIiIiIiZZRdLcPSb5ZCb9Bb7dcb9Fj6zVJk9MtAcu9khVZn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799vday1tRWvv/46AGDNmjXmgjEALFy4EKNGjUJhYSEOHjzo4a9AGhaNiYiIiIi8QKPRICUlBSkpKQgICIBKxUtxIiIi8h2t5eVOt33Byy+/DEEQ8OmnnwIARo8ebY6JvfXWW72yhqCgIEmPs20Q2L17N65cuYLU1FSkp6fbPX7mzJkAgK1bt3Z9kW7Q7a9UDx48iBUrViA7OxuJiYnmbyRXOhNKnZCQgF69emHUqFH48MMP3fllEBEREREREREReYQ2Lx+ls+dY7SudPQfavHyFViQuNjYWs2bNMv/+wQcfNP964IEHvLKGgQMHIjU1FadPn8aGDRusjp08eRIffPABIiMjkZWVZXXs6NGjAICMjAzR5zXtLyoq8sCq5ev2mca5ubn46KOPZJ1jCqXeu3cv4uLiMH36dJSWlmLdunXYtm0b9u7di4EDB5ofHxcXh5deegk33ngjmpqa8M4772DWrFnYsmULpk+f7u4viYiIiIjIZ5273ICN+ytQWduIxMhQzMlMwoC+YUovi4iIiBxoLS3FhRdeAGyH9Or1uPDCCwgdk4HAlBRF1mYrJycHAwcOxObNm3HHHXfg3XffdXnOpEmTUFhYKOt11q1bh5ycHNFjarUa69evx1133YX/+q//wsqVK5GWloZLly7h66+/xrBhw/Duu+8iKirK6rzynzq3ExMTRZ/XtL+srEzWWj2l2xeNx44di1GjRiEzMxOZmZlISUlBS0uL03PkhlLfcccduOOOO8zbd911FyZMmID//d//9dmiMS/miYiIiKirbK8pewf3wsovvodObzA/5u2vz2J59kjMvj5JwZUSERGRI9q8PECnEz+o00Gbl4/Ypxd6d1FOHDlyBABw3XXXSXr81KlTkSKz6D1o0CCnx2+++WYUFhYiKysLhw4dwqFDhwAAgYGBuP32262aTU3q6+sBAKGhoaLPGRZmrMvV1dXJWqundPui8TPPPCPr8a5CqdevX28OpR4zZozD55k+fTr+53/+p3OL9rBNByrwXP4xXswTERERUaeJXVOK0ekNeC7/GDJTotikQERE5IPanESxSjnubXKLxs8++6zb1/CPf/wDDz30EG666Sb84x//wPDhw3H+/Hm88sorWLlyJXbs2IE9e/ZIzj/2Rd0+01gufwulluvc5QbRi3vTxfy5yw0KrYyIiIiI/IWja0pHdHoD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6ec//7nsdrt+97vfXXJ7XqfQ+/rrryVJLVu21O23365bbrlFzz//vF588UXNmDFDnTt31l//+lf39uWvUbNmzdSwYUOfx+S9MPBsNptef/112e12/fSnP9UVV1yhH//4x7r++uvVq1cvtWvXTh999JGaN28uic8roMbMrlqjdmJjY/2OYCouLjaaNm1qSDK2b9/u1d+rVy9DkrF161Z3LDEx0Xj22Wc9tisf0fTBBx8ELnlElGBcixdjpDGqI5jXY25urtGqVStj3LhxhsvlCmjeiDzBfm8s9/Of/5wFaxFy99xzjyGp0s/nnJwc96JDMMfatWsNi8ViREdHGzt37nTH33zzTUOScc0111S6b9u2bQ1JXiMrUXOZmZmGJGPJkiXumL+RxrxOoffMM88YkoyoqCgjNjbWWLx4sXH06FEjLy/PePjhh92j9nfs2GEYhmF89tlnhiSjbdu2lR7zmmuuMSQZn332WYieRf2xa9cuo2PHjh53d8XExBgzZ840HA6He7unn37akGT89Kc/9Xmc0tJS92sL4AJGGke4msw1d9lll2nv3r0e25W3L7/88iBmi0jGvIcIJzW9Hh0Oh4YPH66UlBS9/vrrVZqrFvAnUO+Nffr0YbFaAB727t2riRMnyjAMPffcc+65jWGOgwcPavbs2bruuuuUnp5udjqohMvlknR+3YB58+ZpypQpSkxMVHJysp577jmNGzdOpaWleu6550zOFH/961/Vv39/tW/fXps3b9bp06e1b98+paena/78+br++utVXFxsdppAnUbROMLt2rVLktSvXz+f/eXx3bt3u2M33XSTPvjgA507d84dW758udLS0tSxY8cgZotIVpNrEQiWmlyPJSUlGj16tM6ePav33ntP8fHxwU8UES9Q743Z2dlKSUkJaG7ApTRq1EiSdPbsWZ/9Z86ckSQ1btw4ZDnhvEOHDunmm2/W8ePH9dBDD+nBBx/06L/Uayfx+gXaAw88oJKSEr300ktV3ofXKfTK/88l+VwIrzy2YcMGj+15jUIrJydHP/vZz9SiRQutWbNG/fv3V8OGDZWWlqaXX35Zt956q7Zv367XXntNEp9XQE1FmZ0Agqsmc/fcd999+sMf/qDx48dr+vTp2rFjh15++WX3Gy5QEzW5FgsKCtxfyM6ePau9e/dq+fLlatiwoX70ox8FOWNEsppc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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "E_bins = np.logspace(0, 3, 50)\n", + "x_bins = np.linspace(-10, 90, 100)\n", + "times = [10, 20, 40, 80, 160, 200]\n", + "dt = 10\n", + "\n", + "fig, axs = plt.subplots(1,2, figsize = (10,5), dpi = 150)\n", + "\n", + "for i in range(len(times)):\n", + "\n", + " #energy-spectrum at the shock:\n", + " J, dJ, bin_center = energy_spectrum(df.loc[(df['X'] > 0) & (df['X'] < 2) & (df['T'] > times[i] - dt) & (df['T'] < times[i] + dt)], E_bins)\n", + " #number-density (integrated over energy):\n", + " N, dN, xbin_center = number_density(df.loc[(df['T'] > times[i] - dt) & (df['T'] < times[i] + dt)], x_bins)\n", + "\n", + " axs[0].errorbar(bin_center, J*bin_center**2, yerr = dJ*bin_center**2, marker = '.', linestyle = '',label = r'$t = %i$' %times[i])\n", + " axs[1].errorbar(xbin_center, N, yerr = dN, marker = '.', linestyle = '',)\n", + " \n", + "\n", + "axs[0].set_xscale('log')\n", + "axs[0].set_yscale('log')\n", + "axs[0].set_xlabel(r\"$E/E_0$.\")\n", + "axs[0].set_ylabel(r\"$JE^2/\\mathrm{a.u.}$\")\n", + "\n", + "axs[1].set_xlim(-10, 90 )\n", + "axs[1].set_yscale('log')\n", + "axs[1].set_xlabel(r\"$x/x_0$.\")\n", + "axs[1].set_ylabel(r\"$n/\\mathrm{a.u.}$\")\n", + "fig.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Figure 1: With time, particles reach higher energy as they repeatedly cross the shock front. However, only few particles are still close to the shock at later times. The downstream number density shows the typical solution for the diffusion-advection eq. over time. Only few particles make it upstream against the advective flow. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Approximating the Stationary Solution\n", + "\n", + "In order to obtain the well-known $-2$ power-law, continuous injection of particles at the shock must be considered. This can be approximated by summing over the \"time snaps\" we plotted before. " + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABY0AAAL2CAYAAAANc7nMAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAABcSAAAXEgFnn9JSAAEAAElEQVR4nOzde1xUdf4/8NeZYbiDw1VBEBSpTNTAsDD9pZWXti0D1L61ZmRZu1l9Wdv9Vt/NK7a2bZr7NbfaNs1qbb0ApnbTdsnaUEvNS6aFCKhgXsgRQa7D/P6YZmCY2znDzJy5vJ6PB4865/OZcz5DpB/e8z7vt6DT6XQgIiIiIiIiIiIiIgKgkHsBREREREREREREROQ5GDQmIiIiIiIiIiIiIiMGjYmIiIiIiIiIiIjIiEFjIiIiIiIiIiIiIjJi0JiIiIiIiIiIiIiIjBg0JiIiIiIiIiIiIiIjBo2JiIiIiIiIiIiIyChA7gUQERERERERERGRbTqdDjqdTu5lkJcRBAGCIEh+HYPGREREREREREREHkir1aK+vh6XL19GW1ub3MshLxUYGIiIiAjExMRAqVSKeo2g40cUREREREREREREHkWr1eLkyZNoaWmReynkI4KDgzFgwABRgWNmGhMREREREREREXmY+vp6tLS0QKlUom/fvggLC4NCwfZkJE1nZyeamppw9uxZtLS0oL6+HvHx8XZfx6AxERERERERERGRh7l8+TIAoG/fvujTp4/MqyFvpVAojD8/dXV1uHz5sqigMT+eICIiIiIiIiIi8iA6nc5YwzgsLEzm1ZAvMPwctbW1iWqoyKAxERERERERERGRB+ke1GNJCnKG7j9HDBoTERERERERERERkSSsaUxEREREREREROTnWtq1ePWzSuPxb8alIVillHFFJCcGjYmIiIiIiIiIiPxca0cn/vKvCuPxrDEDGTT2YyxPQURERERERERERERGDBoTERERERERERERibRv3z688MILyMvLQ1JSEgRBgCAIol7b3NyM+fPn46qrrkJwcDASExMxa9Ys1NbWunjV0jBoTERERERERERERF7jk08+gSAIePTRR2W5f1FREZ599lmUlpZKCva2tLTglltuQVFRERobGzFlyhQkJydjzZo1yMzMxIkTJ1y4amkYNCYiIiIiIiIiIiKvsWfPHgDAqFGjZLl/Tk4O5s2bhy1btuDMmTMICgoS9bolS5Zg9+7dyMnJwQ8//ID169djz549WLZsGc6fP49Zs2a5eOXisREeEREREREREREReQ1D0Dg7O1uW+z/99NOSX9PW1oZXXnkFALBq1SqEh4cbx+bOnYu1a9di586d2LdvH0aOHOm0tTqKmcZERERERERERER+rqa+yeaxJ3jxxRchCAI+/PBDAMCIESOM9YRvvfVWmVdn25dffolLly4hLS0NmZmZZuNTp04FAGzdutXdS7OImcZERERERERERER+bMPeU3i2+LDJudxV5ViaPwzTr0+WaVXm4uPjMW3aNGzcuBHx8fG4/fbbjWPjx4+XcWX2HTx4EACQlZVlcdxw/tChQ25bky0MGhMREREREREREfmpqgtNeLbkMLQ6ncl5rU6HZ0sOIzs1GgNjw2RanamCggIMGjQIGzduxKRJk/DWW2/Zfc24ceOwc+dOSfdZs2YNCgoKHFukFSdPngQAJCUlWRw3nK+pqXHqfR3FoDEREREREREREZGfWv/1KWg7dRbHtJ06bNh7Ck9PvsbNq7LuwIEDAIDrrrtO1PzJkycjNTVV0j0GDx4sbVEiNDY2AgBCQ0MtjoeF6QPzly9fdvq9HcGgMRERERERERERkZ86ffGKnfFmN61EHKlB42eeecZ1i/FhbIRHRERERERERETkp5KiLGe+do2HuGkl4hhqA48YMULmlUgTHh4OALhyxXKQvqlJ33gwIiLCbWuyhZnGREREREREREREfuqe7GS88cUJiyUqlArBoxrhdXR04MiRI0hKSkJMTIyo17zwwgs4duyYpPs8/PDDGDNmjCNLtGrAgAEAgNOnT1scN5xPSUlx6n0dxaAxERERERERERGRnxoYG4alecPwbLFpMzylIOCFvGEe0wQPAI4ePYrW1lZJWcYff/yx5EZ448aNc3rQ2LDm/fv3Wxw3nB8+fLhT7+soBo2JiIiIiIiIiIj82PTrk3FNvwjc9cqXxnOlc0ZjeJJavkVZcPToUQBARkaG6Nd89tlnLlqNNDfddBP69OmDyspKHDhwwKwm86ZNmwAAd955pwyrM8eaxkRERERERERERH4uJSbM5rEnaG9vB2C9LrAnCwwMxOOPPw4AmDNnjrGGMQAsX74chw4dws0334yRI0fKtUQTzDQmIiIiIiIiIiIij3fDDTdApVLhr3/9K44fP474+HgEBwfjtddec+s6PvjgAxQVFRmP29raAAA33nij8dy8efNwxx13mLzuueeew6effory8nKkp6dj7NixqKmpwZ49exAXF4fVq1e75w2IwKAxERERERERERERebzBgwdj/fr1WLJkCT7//HM0NTXJkpl7/vx57Nmzx+x893Pnz583Gw8ODkZZWRmWLl2KdevWYfPmzYiOjkZBQQGKioqQlJTk0nVLIeh0OvPWiERERERERERERCSLzs5OfP/99wCAq6++GgqF6yvMXmpux4hF243HBxdMRJ8QlcvvS+4h9WeKNY2JiIiIiIiIiIiIyIjlKYiIiIiIiIiIiPxcUIAC/31ruskx+S8GjYmIiIiIiIiIiPxcsEqJ3064Su5lkIfgRwZEREREREREREREZMSgMREREREREREREREZMWhMREREREREREREREYMGhMRERERERERERGREYPGRERERERERERERGTEoDERERERERERERERGTFoTERERERERERERERGDBoTERERERERERERkVGA3AsgIiIiIiIiIiIimbW3AP95uet4zG8BVbB86yFZMWhMRERERERERETk7zpagJ0vdB3f+BsGjf0Yy1MQERERERERERERiXDlyhVs3rwZDz30EK6++moEBwcjLCwMI0aMwOLFi9HY2Gjz9c3NzZg/fz6uuuoqBAcHIzExEbNmzUJtba2b3oE4DBoTERERERERERGR1/jkk08gCAIeffRRt9973bp1yM3NxerVq6FUKnHXXXdh7NixqKqqwoIFC5CdnY1z585ZfG1LSwtuueUWFBUVobGxEVOmTEFycjLWrFmDzMxMnDhxws3vxjoGjYmIiIiIiIiIiMhr7NmzBwAwatQot99bpVLhkUcewXfffYfvvvsOGzZswMcff4zvv/8emZmZOHbsGAoLCy2+dsmSJdi9ezdycnLwww8/YP369dizZw+WLVuG8+fPY9asWe59MzYIOp1OJ/ciiIiIiIiIiIiISK+zsxPff/89AODqq6+GQuGGvM9mDfCnlK7jp2uAELXr7+uAO+64Ax9++CEOHjyI4cOHy70co127dmH06NEICgpCQ0MDAgMDjWNtbW2Ij4/HpUuXsH//fmRmZpq8dsSIETh06BD27t2LkSNHOn1tUn+mmGlMRERERERERETk736qsn3sAV588UUIgoAPP/wQgD7QKggCBEHArbfeKvPq9OsBgNbWVtTX15uMffnll7h06RLS0tLMAsYAMHXqVADA1q1bXb9QEQLkXgARERERERERERHJ6Jt3gS1Pmp77+63AXf8HZM6QZ00WxMfHY9q0adi4cSPi4+Nx++23G8fGjx8v48r0DDWJVSoVoqOjTcYOHjwIAMjKyrL4WsP5Q4cOuXCF4jFoTERERERERERE5K/qK/UBY53W9LxOqz8/IAeISZNnbT0UFBRg0KBB2LhxIyZNmoS33nrL7mvGjRuHnTt3SrrPmjVrUFBQIHl9f/nLXwAAkydPRlBQkMnYyZMnAQBJSUkWX2s4X1NTI/m+rsCgMRERERERERERkb/a/7Z5wNhApwW+eQe4baFbl2TLgQMHAADXXXedqPmTJ09GamqqpHsMHjxY2qIAfPjhh3jzzTehUqlQVFRkNt7Y2AgACA0Ntfj6sLAwAMDly5cl39sVGDQmIiIiIiIiIiLyV5qTvRt3M6lB42eeecZ1i/nZsWPHMGPGDOh0Ovz5z3821jb2ZmyER0RERERERERE5K/UA3o37maG2sCeEpitra3F5MmTcfHiRcydOxf//d//bXFeeHg4AODKlSsWx5uamgAAERERrlmoRMw0JiIiIiIiIiIi8ldZM4HylZZLVAhKIPN+96/Jio6ODhw5cgRJSUmIiYkR9ZoXXngBx44dk3Sfhx9+GGPGjLE776effsLEiRNRU1ODBx98EC+99JLVuQMG6IPvp0+ftjhuOJ+SkiJpra7CoDEREREREREREZG/ikkD7vo/82Z4ghK4a6XHNMEDgKNHj6K1tVVSlvHHH38suRHeuHHj7AaNGxsbcfvtt+O7775DXl4e3njjDQiCYHW+Yc379++3OG44P3z4cElrdRUGjYmIiIiIiIiIiPxZ5gwgfijwxriucw//C+ifKduSLDl69CgAICMjQ/RrPvvsM6evo7W1FVOmTMFXX32FSZMm4b333oNSqbT5mptuugl9+vRBZWUlDhw4YFaTedOmTQCAO++80+nrdQRrGhMREREREREREfm76IG2jz1Ae3s7AOt1gd1Bq9Xi3nvvxb///W+MHTsWJSUlCAwMtPu6wMBAPP744wCAOXPmGGsYA8Dy5ctx6NAh3HzzzRg5cqTL1i4FM42JiIiIiIiIiIjI491www1QqVT461//iuPHjyM+Ph7BwcF47bXX3LaGV155BaWlpQCA2NhYPPbYYxbnvfTSS4iNjTU599xzz+HTTz9FeXk50tPTMXbsWNTU1GDPnj2Ii4vD6tWrXb5+sRg0JiIiIiIiIiIiIo83ePBgrF+/HkuWLMHnn3+OpqYmt2fmXrx40fjvhuCxJQsXLjQLGgcHB6OsrAxLly7FunXrsHnzZkRHR6OgoABFRUVISkpy2bqlEnQ6nU7uRRAREREREREREZFeZ2cnvv/+ewDA1VdfDYXCDRVmmzXAn1K6jp+uAULUrr8vuYXUnynWNCYiIiIiIiIiIiIiI5anICIiIiIiIiIi8ncBwcDNz5gek99i0JiIiIiIiIiIiMjfqYKB8c/KvQryECxPQURERERERERERERGDBoTERERERERERERkRGDxkRERERERERERERkxKAxERERERERERERERkxaExERERERERERERERgwaExEREREREREREZERg8ZEREREREREREREZMSgMREREREREREREREZBci9ACIiIiIiIiIiIpJXq7YVbx5+03j80LCHEKQMknFFJCcGjYmIiIiIiIiIiPxcq7YVrx581Xg849oZDBr7MZanICIiIiIiIiIiIiIjBo2JiIiIiIiIiIiIHFRfX4/4+HgIgoDBgwfbnNvc3Iz58+fjqquuQnBwMBITEzFr1izU1ta6abXiMGhMREREREREREREXuOTTz6BIAh49NFH5V4KAOCpp57ChQsX7M5raWnBLbfcgqKiIjQ2NmLKlClITk7GmjVrkJmZiRMnTrhhteIwaExEREREREREREReY8+ePQCAUaNGybwS4F//+hfWrl2L2bNn2527ZMkS7N69Gzk5Ofjhhx+wfv167NmzB8uWLcP58+cxa9YsN6xYHAaNiYiIiIiIiIiI/Nypy6dsHnsSQ9A4Oztb1nU0Nzfj0UcfxbXXXovf/e53Nue2tbXhlVdeAQCsWrUK4eHhxrG5c+di+PDh2LlzJ/bt2+fSNYvFoDEREREREREREZEfK60oxX0f3Gdy7r4P7kNpRalMK7LsxRdfhCAI+PDDDwEAI0aMgCAIEAQBt956q9vXs2jRIpw4cQKvvfYaVCqVzblffvklLl26hLS0NGRmZpqNT506FQCwdetWl6xVqgC5F0BERERERERERETyqGmowaJdi9Cp6zQ536nrxKJdi5DVNwspkSkyrc5UfHw8pk2bho0bNyI+Ph633367cWz8+PFuXcuhQ4ewbNkyPPjggxg7diyqq6ttzj948CAAICsry+K44fyhQ4ecuk5HMWhMRERERERERETkp0oqSqDVaS2OaXValFaUonBkoXsXZUVBQQEGDRqEjRs3YtKkSXjrrbfsvmbcuHHYuXOnpPusWbMGBQUFVsc7Ozvx8MMPQ61W48UXXxR1zZMnTwIAkpKSLI4bztfU1Ehaq6swaExEREREREREROSn6hrrejXubgcOHAAAXHfddaLmT548GampqZLuMXjwYJvjK1euxNdff401a9YgJiZG1DUbGxsBAKGhoRbHw8LCAACXL1+WsFLXYdCYiIiIiIiIiIjITyWGJ/Zq3N2kBo2feeYZp97/5MmTeO6553DzzTfbzEb2dmyER0RERERERERE5Kfy0vOgFJQWx5SCErnpuW5ekW2G2sAjRoyQ5f5z5sxBW1sbXnvtNUmvCw8PBwBcuXLF4nhTUxMAICIioncLdBJmGhMREREREREREfmplMgULMhZgIW7Fpo0w1MICiwcvdBjmuABQEdHB44cOYKkpCTRZSFeeOEFHDt2TNJ9Hn74YYwZM8bi2LZt26BWq/HrX//a5HxLSwsAoLa2FuPGjQMA/POf/0S/fv0AAAMGDAAAnD592uJ1DedTUjzj+82gMRERERERERERkR/LTc/FVdFX4b+2/Zfx3Lo71mFozFAZV2Xu6NGjaG1tlZRl/PHHH0tuhDdu3DirQWMA0Gg0Vq/Z0tJiHDMEkoGuzOj9+/dbfJ3h/PDhwyWt1VUYNCYiIiIiIiIiIvJzyRHJNo89wdGjRwEAGRkZol/z2WefOXUNOp3O4vnq6moMHDgQaWlpOH78uNn4TTfdhD59+qCyshIHDhwwq8m8adMmAMCdd97p1PU6ikFjD9avXz80NTUZ09eJiIiIxDh58iTCwsLw448/yr0U6kaj0UCj0QAAsrOz0dLSwn0eERERWaRSqfDcc89h0KBBOHLkCARBAAC0tbVBqVTKVs9Xbu3t7QCs1wX2ZIGBgXj88cfx/PPPY86cOdi+fTvCwsIAAMuXL8ehQ4dw8803Y+TIkTKvVI9BYw/W1NRk/J+BiIiISKz29nZjIw3yHCtWrMCiRYuMx0ql5YYzRERERNbodDpotVq5lyGbG264ASqVCn/9619x/PhxxMfHIzg4WHJTOrk899xz+PTTT1FeXo709HSMHTsWNTU12LNnD+Li4rB69Wq5l2jEoLEHM2SeHDlyROaVEBERkTcZOtSzas+RXmFhIQoKCgAAEydOhFKp5D6PiIiILOrs7MT3338PALj66quhUCgAAN9++62cy5Ld4MGDsX79eixZsgSff/45mpqaPCYzV4zg4GCUlZVh6dKlWLduHTZv3ozo6GgUFBSgqKgISUlJci/RiEFjIiIiIiI3UKvVUKvVAPSPnBIRERGRdLm5ucjNzZV7GWZSU1Ot1jvuLiQkBIsXL8bixYvdsCrHKeReABERERERERERERF5DmYaExERERERERER+bkgZRB+M+I3Jsfkvxg0JiIiIiIiIiIi8nNByiA8dt1jci+DPATLUxARERERERERERGRETONiYiIiIjcQKPRQKPRAADa29uhVCrlXRARERERkRXMNCYiIiIicoMVK1Zg4MCBGDhwICoqKlBfXy/3koiIiIiILGLQmIiIiIjIDQoLC1FVVYWqqiqkp6cjJiZG7iUREREREVnE8hRERERERG6gVquhVqsBACqVSt7FEBERERHZwExjIiIiIiIiIiIiIjJi0JiIiIiIiIiIiIiIjFiegoiIiIiIiIiIyM91trai/m9vGI9jHpkNRVCQjCsiOTFoTERERERERERE5Od0ra24sGqV8Tj6gZkAg8Z+i0FjIiIiIiI30Gg00Gg0AID29nYolUp5F0REREREZAVrGhMRERERucGKFSswcOBADBw4EBUVFaivr5d7SURERETkoK+//hrTp09HYmIiVCoV1Go1xo4dizVr1kCn01l9XXNzM+bPn4+rrroKwcHBSExMxKxZs1BbW+vG1dvHoDERERERkRsUFhaiqqoKVVVVSE9PR0xMjNxLIiIiIvJKn3zyCQRBwKOPPirL/YuLi5GTk4ONGzciISEBeXl5yMrKwu7duzFr1izMmDHD4utaWlpwyy23oKioCI2NjZgyZQqSk5OxZs0aZGZm4sSJE25+J9YxaExERERE5AZqtRqpqalITU2FSqWCQsGtOBEREZEj9uzZAwAYNWqU2+/d0dGBxx57DFqtFv/4xz+wb98+rF+/Hv/+979x6NAhREdHY926dSgrKzN77ZIlS7B7927k5OTghx9+wPr167Fnzx4sW7YM58+fx6xZs9z+fqzhTpWI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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "E_bins = np.logspace(0, 3, 50)\n", + "x_bins = np.linspace(-10, 50, 60)\n", + "times = [10, 20, 40, 80, 160, 200]\n", + "\n", + "fig, axs = plt.subplots(1,2, figsize = (10,5), dpi = 150)\n", + "\n", + "for i in range(len(times)):\n", + " \n", + " #energy-spectrum at the shock - take all times <= t into account:\n", + " J, dJ, bin_center = energy_spectrum(df.loc[(df['X'] > 0) & (df['X'] < 2) & (df['T'] <= times[i])], E_bins)\n", + " #number-density (integrated over energy) - take all times <= t into account:\n", + " N, dN, xbin_center = number_density(df.loc[(df['T'] <= times[i])], x_bins)\n", + "\n", + " axs[0].errorbar(bin_center, J*bin_center**2, yerr = dJ*bin_center**2, marker = '.', linestyle = '',label = r'$t = %i$' %times[i])\n", + " axs[1].errorbar(xbin_center, N, yerr = dN, marker = '.', linestyle = '',)\n", + " \n", + "\n", + "axs[0].set_xscale('log')\n", + "axs[0].set_yscale('log')\n", + "axs[0].set_xlabel(r\"$E/E_0$.\")\n", + "axs[0].set_ylabel(r\"$JE^2/\\mathrm{a.u.}$\")\n", + "axs[0].set_xlim(1, 10**3)\n", + "\n", + "axs[1].set_xlim(-10, 50 )\n", + "axs[1].set_yscale('log')\n", + "axs[1].set_xlabel(r\"$x/x_0$.\")\n", + "axs[1].set_ylabel(r\"$n/\\mathrm{a.u.}$\")\n", + "\n", + "fig.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Figure 2: The energy spectrum shows the expected spectral slope $s = -2$, when sufficiently many 'time snaps' are taken into account at late times. For $E < 10 E_0$ the stationary solution is reached at time $t = 160$ at the shock. The same is visible for the number density. \n", + "\n", + "Assuming that the shock got active at time $t = 0$, the plot shows the time-evolution of the energy-spectrum and number density. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Increasing the Statistics at High Energies: Candidate Splitting" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Only a fraction of simulated pseudo-particles reaches high energy. This leads to bad statistics above $\\approx E = 10^2 E_0$ in Figure 2. For instance, the exponential cut-off is not visible. \n", + "\n", + "Increasing the number $N$ of simulated particles, lead to better statistics, however a lot of simulation time is wasted on the lower energies. Instead an importance sampling method can be used, by splitting pseudo-particles in copies, once they cross energy bins. This is done by the *CandidateSplitting* module" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "#Candidate Splitting:\n", + "spectral_index = -2 #expected spectral index \n", + "E_min = 10*E0 #minimal energy for splitting\n", + "factor = 5 #number of energy bins/maximal splitting\n", + "splitting = CandidateSplitting(spectral_index, E_min, factor)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "crpropa::ModuleList: Number of Threads: 8\n", + "Run ModuleList\n", + " Started Fri Nov 3 10:20:56 2023 : [\u001b[1;32m Finished \u001b[0m] 100% Needed: 00:00:41 - Finished at Fri Nov 3 10:21:37 2023\n", + "\r" + ] + } + ], + "source": [ + "#Simulation\n", + "\n", + "file = \"SimpleDSA_splitting.txt\"\n", + "outTime = TextOutput(file)\n", + "outTime.setEnergyScale(TeV)\n", + "outTime.setLengthScale(meter)\n", + "outTime.disableAll()\n", + "outTime.enable(Output.TrajectoryLengthColumn)\n", + "outTime.enable(Output.CurrentEnergyColumn)\n", + "outTime.enable(Output.CurrentPositionColumn)\n", + "outTime.enable(Output.WeightColumn)\n", + "\n", + "obsTime = Observer()\n", + "obsTime.add(ObserverTimeEvolution(T_min*c_light, T_max*c_light, n_time, False)) \n", + "obsTime.onDetection(outTime)\n", + "obsTime.setDeactivateOnDetection(False)\n", + "\n", + "\n", + "m = ModuleList()\n", + "m.add(diffSDE)\n", + "m.add(ac)\n", + "m.add(obsTime)\n", + "m.add(maxTra)\n", + "m.add(splitting)\n", + "m.setShowProgress(True)\n", + "m.run(source, N_cand)\n", + "outTime.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "file = \"SimpleDSA_splitting.txt\"\n", + "columns = ['D', 'E', 'X', 'Y', 'Z', 'W']\n", + "df = pd.read_csv(file, comment='#', delimiter = '\\t', names = columns ) \n", + "df[\"T\"] = df[\"D\"]/(c_light)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/hm/8552yhb509l530c14llpb1ym0000gn/T/ipykernel_90949/3921811185.py:16: RuntimeWarning: invalid value encountered in divide\n", + " dJ = J/np.sqrt(H[0])\n", + "/var/folders/hm/8552yhb509l530c14llpb1ym0000gn/T/ipykernel_90949/3921811185.py:38: RuntimeWarning: invalid value encountered in divide\n", + " dN = N/np.sqrt(H[0])\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABY0AAAL2CAYAAAANc7nMAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAABcSAAAXEgFnn9JSAAEAAElEQVR4nOzde1yUdd4//tfMMMjZAQTjoICIaZ5ikArTX1KptG0ZoHbXbUbeHXa3tpvVvb/W3qUCduu2q3mntrXtSpZrmQKmVqbtonWHmudTWIiCCqRIjAhyHOb3xzQjw5yuOZ9ez8fDR13X57rmeiMq17znfb3fIpVKpQIREREREREREREREQCxqwMgIiIiIiIiIiIiIvfBpDERERERERERERERaTFpTERERERERERERERaTBoTERERERERERERkRaTxkRERERERERERESkxaQxEREREREREREREWkxaUxEREREREREREREWn6uDoCIiIiIiIiIiIhMU6lUUKlUrg6DPIxIJIJIJLL4PCaNiYiIiIiIiIiI3JBSqURTUxOuX7+Orq4uV4dDHsrf3x+hoaGIjIyERCIRdI5IxY8oiIiIiIiIiIiI3IpSqcSFCxfQ0dHh6lDISwQEBGDo0KGCEsesNCYiIiIiIiIiInIzTU1N6OjogEQiweDBgxEcHAyxmOPJyDK9vb1oa2vD5cuX0dHRgaamJkRHR5s9j0ljIiIiIiIiIiIiN3P9+nUAwODBgzFw4EAXR0OeSiwWa//81NfX4/r164KSxvx4goiIiIiIiIiIyI2oVCptD+Pg4GAXR0PeQPPnqKurS9BARSaNiYiIiIiIiIiI3EjfpB5bUpA99P1zxKQxEREREREREREREVmEPY2JiIiIiIiIiIh8XEe3En/ZU63d/vWUZARIJS6MiFyJSWMiIiIiIiIiIiIf19nTi//9Z5V2e96kJCaNfRjbUxARERERERERERGRFpPGRERERERERERERAIdPnwYy5cvR05ODuLj4yESiSASiQSd297ejkWLFmHEiBEICAhAbGws5s2bh7q6OgdHbRkmjYmIiIiIiIiIiMhjfPHFFxCJRHjuuedccv2ioiK8/PLLKCsrsyjZ29HRgXvvvRdFRUVobW3FjBkzMGTIEBQXFyM1NRXnzp1zYNSWYdKYiIiIiIiIiIiIPMaBAwcAAHfccYdLrp+RkYFXX30V27ZtQ0NDAwYMGCDovKVLl2L//v3IyMjADz/8gE2bNuHAgQNYsWIFGhsbMW/ePAdHLhwH4REREREREREREZHH0CSN09PTXXL9hQsXWnxOV1cX1qxZAwBYu3YtQkJCtGvz58/H+vXrsXfvXhw+fBhpaWl2i9VarDQmIiIiIiIiIiLycbVNbSa33cHrr78OkUiEzz77DAAwfvx4bT/h++67z8XRmfbNN9/g2rVrSE5ORmpqqt76zJkzAQDbt293dmgGsdKYiIiIiIiIiIjIh3186CJeLjmpsy97bQWW5Y7F7AlDXBSVvujoaMyaNQubN29GdHQ0HnjgAe1aZmamCyMz7/jx4wAAuVxucF2z/8SJE06LyRQmjYmIiIiIiIiIiHzU+atteLn0JJQqlc5+pUqFl0tPIj0xAkmDgl0Una68vDwMGzYMmzdvxvTp0/Hee++ZPWfKlCnYu3evRdcpLi5GXl6edUEaceHCBQBAfHy8wXXN/traWrte11pMGhMREREREREREfmoTQcvQtmrMrim7FXh40MXsTBrpJOjMu7YsWMAgNtvv13Q8VlZWUhMTLToGsOHD7csKAFaW1sBAEFBQQbXg4PVifnr16/b/drWYNKYiIiIiIiIiIjIR11qvmFmvd1JkQhjadL4pZdeclwwXoyD8IiIiIiIiIiIiHxUfLjhyteb64FOikQYTW/g8ePHuzgSy4SEhAAAbtwwnKRva1MPHgwNDXVaTKaw0piIiIiIiIiIiMhHPZo+BO9+fc5giwqJWORWg/B6enpw+vRpxMfHIzIyUtA5y5cvx5kzZyy6ztNPP41JkyZZE6JRQ4cOBQBcunTJ4Lpmf0JCgl2vay0mjYmIiIiIiIiIiHxU0qBgLMsZi5dLdIfhSUQiLM8Z6zZD8ACgsrISnZ2dFlUZ79y50+JBeFOmTLF70lgT85EjRwyua/aPGzfOrte1FpPGREREREREREREPmz2hCEYeUsoHl7zjXZf2fMTMS5e5rqgDKisrAQAjBkzRvA5e/bscVA0lrn77rsxcOBAVFdX49ixY3o9mbds2QIAeOihh1wQnT72NCYiIiIiIiIiIvJxCZHBJrfdQXd3NwDjfYHdmb+/P1544QUAwPPPP6/tYQwAK1euxIkTJ3DPPfcgLS3NVSHqYKUxERERERERERERub0777wTUqkUb731Fs6ePYvo6GgEBATg7bffdmocn376KYqKirTbXV1dAIC77rpLu+/VV1/Fgw8+qHPeK6+8gi+//BIVFRVISUnB5MmTUVtbiwMHDiAqKgrr1q1zzhcgAJPGRERERERERERE5PaGDx+OTZs2YenSpfjqq6/Q1tbmksrcxsZGHDhwQG9/332NjY166wEBASgvL8eyZcuwceNGbN26FREREcjLy0NRURHi4+MdGrclRCqVSn80IhEREREREREREblEb28vvv/+ewDArbfeCrHY8R1mr7V3Y3zBLu328cXTMDBQ6vDrknNY+meKPY2JiIiIiIiIiIiISIvtKYiIiIiIiIiIiHzcAD8x/vO+FJ1t8l1MGhMREREREREREfm4AKkEv5s6wtVhkJvgRwZEREREREREREREpMWkMRERERERERERERFpMWlMRERERERERERERFpMGhMRERERERERERGRFpPGRERERERERERERKTFpDERERERERERERERaTFpTERERERERERERERaTBoTERERERERERERkZafqwMgIiIiIiIiIiIiF+vuAP7vjZvbk34HSANcFw+5FJPGREREREREREREvq6nA9i7/Ob2Xb9m0tiHsT0FERERERERERERkQA3btzA1q1b8R//8R+49dZbERAQgODgYIwfPx6FhYVobW01eX57ezsWLVqEESNGICAgALGxsZg3bx7q6uqc9BUIw6QxEREREREREREReYwvvvgCIpEIzz33nNOvvXHjRmRnZ2PdunWQSCR4+OGHMXnyZJw/fx6LFy9Geno6rly5YvDcjo4O3HvvvSgqKkJraytmzJiBIUOGoLi4GKmpqTh37pyTvxrjmDQmIiIiIiIiIiIij3HgwAEAwB133OH0a0ulUjz77LP47rvv8N133+Hjjz/Gzp078f333yM1NRVnzpxBfn6+wXOXLl2K/fv3IyMjAz/88AM2bdqEAwcOYMWKFWhsbMS8efOc+8WYIFKpVCpXB0FERERERERERERqvb29+P777wEAt956K8RiJ9R9tiuAPybc3F5YCwTKHH9dKzz44IP47LPPcPz4cYwbN87V4Wjt27cPEydOxIABA9DS0gJ/f3/tWldXF6Kjo3Ht2jUcOXIEqampOueOHz8eJ06cwKFDh5CWlmb32Cz9M8VKYyIiIiIiIiIiIl/303nT227g9ddfh0gkwmef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QIDFQ+lc5ZVXXsGXX36JiooKpKSkYPLkyaitrcWBAwcQFRWFdevWuTpELSaN3Zim8uT06dMujoSIiIg8yejR7tV7jtTy8/ORl5cHAJg2bRokEgnv84iIiMig3t5efP/99wCAW2+9FWKxGABw6tQpV4blcsOHD8emTZuwdOlSfPXVV2hra3ObylwhAgICUF5ejmXLlmHjxo3YunUrIiIikJeXh6KiIsTHx7s6RC0mjYmIiIiInEAmk0EmkwFQP3JKRERERJbLzs5Gdna2q8PQk5iYaLTfcV+BgYEoLCxEYWGhE6KyntjVARARERERERERERGR+2ClMRERERERERERkY8bIBmAX4//tc42+S4mjYmIiIiIiIiIiHzcAMkA/Ob237g6DHITTBoTERERETmBQqGAQqEAAHR3d0Mikbg2ICIiIiIiI9jTmIiIiIjICVatWoWkpCQkJSWhqqoKTU1Nrg6JiIiIiMggJo2JiIiIiJwgPz8f58+fx/nz55GSkoLIyEhXh0REREREZBDbUxAREREROYFMJoNMJgMASKVS1wZDRERERGQCK42JiIiIiIiIiIiISItJYyIiIiIiIiIiIiLSYtKYiIiIiIiIiIiIiLSYNLaD9957DyKRSO/Xnj17XB0aERERERERERGRWb2dnWhcvUb7q7ez09UhkQtxEJ4d/d///R8kEol2+7bbbnNhNERERERERERERMKoOjtxde1a7XbEk3OBAQNcGBG5EpPGdnTnnXfCz4+/pURERESkT6FQQKFQAAC6u7t1ig2IiIiIiNwJ21MQERERETnBqlWrkJSUhKSkJFRVVaGpqcnVIRERERGRlQ4ePIjZs2cjNjYWUqkUMpkMkydPRnFxMVQqldHz2tvbsWjRIowYMQIBAQGIjY3FvHnzUFdX58TozfP6pPHhw4exfPly5OTkID4+Xttv2BxrvoFxcXHw8/PDuHHjsGXLFnt+GURERETk4fLz83H+/HmcP38eKSkpiIyMdHVIRERERB7piy++gEgkwnPPPeeS65eUlCAjIwObN29GTEwMcnJyIJfLsX//fsybNw9z5swxeF5HRwfuvfdeFBUVobW1FTNmzMCQIUNQXFyM1NRUnDt3zslfiXFe30uhqKgIn3zyiUXnaL6B+/fvR0xMDGbMmIGamhoUFxdjx44d2L9/P4YNG6Y9PiYmBq+99hru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fY8OLH3UKhaLRd26dfO164vHx44d8zuub9+++tvf/hbSbAAQ9qrKpHWPSV63f7/XXddfxeah4ab0RKlm/GaGstZmacZvZqj0RKnRkQCg3YRs2ozVatVXvvIVvfjiiyovL9fu3buVl5enq6++Wq+//rruv/9+9ezZU8uWLQtVJAAAALSjvn376tChQ772NddcI0natm2b33F79+5VYmJiSLMBQNjbubJxwbie1y3t+mVo86BZJaUlum/9fdp1bJc+dX2qXcd26b7196mktMToaADQLgy713Lo0KGaN2+etm/frsOHD+vnP/+5Jk6cqJMnTxoVCQAAAG0wZswY/eUvf1FNTY0k6Wtf+5okKTc3V7/73e+0b98+fec739HHH3+sG2+80cioABB+XAfbNo6QqThVofyt+fJ4/Td19Xg9yt+ar4pTFQYlA4D2ExYL9F111VV6+OGHtW7dOn3ve98zOg4AAACuwJQpUxQfH6/f//73kupmGufm5urgwYOaNGmShg8frqVLl6pz58767//+b4PTAkCYsfVv2zhCpri0WO4mZoW7vW5mGwOICmFRNAYAAEDkmzRpko4ePaq7777b1/fss89q1apVuv/++3XHHXdozpw52rlzpwYMGGBg0tZbs2aNJk2apD59+qhbt2760pe+pM2bNxsdC0A0GjFDMjWxhr7JImU+FNo8aNKRM0faNA4AkaBDWy+wb98+LV26VE6nU9dcc43mzJmjQYMG+R2ze/duZWdn67PPPmvr0wEAACDCPPjgg3rwwQeNjnFFCgsL5XA4tHTpUiUmJmr58uWaMGGC/vznP2vYsGFGxwMQTZIypMkvNN4Mz2SRJi+pG0dYSElMadM4AESCNs00/uCDDzR69Ght3rxZ3bt31+9+9zsNHz5cBQUFfsfV1NSoooI1fVrD5XKpvLxc5eXlqq2tlcfjafkkAAAAA1x99dXKzc3VO++8o4sXLxodJyjWr1+vFStWKDs7WxMnTtSvfvUrXXPNNVq6dKnR0YKrtlratOjSo7ba6ERAbMicLv3fzVLqGCn5urp//t/NUua/GZ0MX5DtyJaliVnhFpNFWY6sECcCgPbXppnG/+///T9lZ2frV7/6lUwmkzwej5YsWaK5c+fqr3/9q1577TXFxcW1V9aYUFhYqPz8fF87OTnZwDQAAABN69Chg1544QUtWbJEXbp00Z133qnJkyfrq1/9qrp37250vHaRlJTk1zabzbr++uvldDoNShQi//xYem/xpfaAO6W+mcblAWJJ70HSrP81OgWakdY1TQvGLlDe1jy/zfDMJrPyxuUprWuagekAoH20aabxnj17NHPmTJlMprqLmc367ne/q02bNumPf/yjbr/9dh0/frxdgsaK3NxcOZ1OOZ1OORyORr+oAAAAhIsDBw7o448/1qJFizRkyBAVFRXpoYceUu/evXXrrbfqueeeU2lpadCe/6OPPtLixYuVnZ2tfv36yWQy+T6XNuf8+fOaP3++BgwYoPj4eKWkpGjmzJk6fPhwi+e63W59+OGHuuaaa9rjSwhPu16XXp7g3/fyhLp+AIAkKcuRpTfvflOZvTJ1je0aZfbK1Jt3v6l7r7nX6GgA0C7aNNO4c+fOOnPmTKP+G2+8UVu3btWkSZM0ZswYPfPMM215mphis9lks9kkSVar1dgwAAAALbj22mv17//+7/r3f/93VVVVaePGjVq3bp3efvttvf/++/r+978vh8Ohe+65R3fddZduvvnmVhV2W6OgoEBr1669rHOqq6t1++23a9u2berTp4/uuecelZeXa/ny5dqwYYO2bdumq6++usnzX3zxRR08eFCPPPJIW+OHp6qyxuupSnXtdY9J/ceyrioAfM7R3aGVX11pdAwACIo2zTQeMWJEkx/U7Xa7tmzZov79++tb3/pWW54GAAAAESApKUkzZszQm2++qePHj+u3v/2tZs+ererqav3oRz/Srbfeql69eukb3/iGioqKAk4+uBxjx47VvHnztG7dOh09erRVy6L94Ac/0LZt2zR27FgdOHBAq1ev1vbt2/Xss8/q2LFjmjlzZpPnbt++XU8//bSeeeYZDRkypE3Zw9bOlY0LxvW8bmnXL0ObBwAAAIZoU9F4xowZOnDggE6cOBFwvFu3bvrf//1f5eTkqH///m15KgAA2tWFgwebbQNoG6vVqq985St68cUXVV5ert27dysvL09XX321Xn/9dd1///3q2bOnli1bdsXP8dRTT2nhwoW6++67ddVVV7V4/IULF/Tiiy9KkpYuXarExETf2BNPPKGhQ4fqvffe00cffdTo3PLyct1zzz26++67tWDBgivOHPZcLbwWtjQOtJPqWreef/uA71Fd28QfMwAAQFC0aXmKqVOnaurUqc0eY7Va9fLLL7flaQAAaFeuomIdnTfPr6986gPqU1Ag25Rsg1IB0W3o0KEaOnSo5s2bp7///e9av3691q9fr5MnT4YswwcffKCTJ08qIyNDmZmNN3W77777tHfvXq1fv14jR4709btcLk2aNEl2u10rVqy4rOU1Bg8eHLC/rKxMGRlhuMyDrYWJHi2NA+3kwD9O6yfvXloTfcJ1vTS0n824QAAAxJg2zTQGACDSXCgv19H58yWPx3/A49HR+fN1obzckFxALLnqqqv08MMPa926dfre974Xsufds2ePpLol1gKp79+7d6+v78KFC8rOzta5c+e0du1aderUKfhBjTRihmSyBB4zWaTMh0KbBzFpzY5KZS3d4teXtXSL1uyoNCgRAACxp00zjRs6c+aM321+AACEG1dRkeRu4hZXt1uuomL1evKJ0IYCoshrr72m4uJi/fOf/1RKSoquv/56DR8+XMOHD292g7lQOPj5MjT9+vULOF7fX1FR4et75JFH9N5772nZsmVyOp1yOp2SpLi4uICzlRvav39/wP6mZiAbLilDmvxC483wTBZp8hI2wUPQOY+f1dzifXJ7vX79bq9Xc4v3abS9h9J7JhiUDgCA2NGuRePu3bvriSee0H/913+152UBQDXuGr2y7xVfe9aQWYqztLzhEdBQ7eHDbRoH0LQf/ehHevrpp+X9QrHnrbfe8i3n0KVLFw0dOlTDhw9XZmamvvnNb4Y0X/3Ge507dw44npBQV4g6ffq0r++dd96Rx+PRrFmz/I5NS0tTebTemZA5XUoZIW14XKo+KcV3k+56Xuo9yOhkiAGrP6yU2+MNOOb2eLVmR6WeunNgiFMBABB72rVo7Ha7dezYsYBjzzzzjO6++27deOON7fmUAGJEjbtGL+15ydeePmg6RWNcEWvfvm0aB9C0n//85zKbzXr55Zd155136vjx49q7d6927drle2zevFmbN2+WyWQKedH4SkRtYbglvQdJs/7X6BSIQYdOnGth/HyIkgAAENvatWjcnP/8z//UkSNHAhaNf/GLX6iqqkpz584NVRwAQIyyTZmiqleXB16iwmJhIzygDY4ePaoJEyboG9/4hiSpd+/eGjx4sL7+9a/7jqmsrPQVkEOtfhm1c+cCF6XOnj0rqW5GdDC4XC65XC5JUm1trSyWJtYOBmJYv+6B7wS4NB7l64oD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Oh09elRxcS3vlP6DH/xA27Zt09ixY3XgwAGtXr1a27dv17PPPqtjx45p5syZIUgOAAAAhDdmGjcwbNgwSdLOnTsDjtf3Dx06NGSZAAAA0NhTTz11WcdfuHBBL774oiRp6dKlvjvMJOmJJ57QihUr9N577+mjjz7SyJEjJdXNKj558qTfdVwul28MANpbRdXZRu2h/WzGhIlE/3I2bvdteYP6oF0HACIUM40buOmmm9StWzeVlZVp9+7djcbffPNNSdLdd98dlOd3uVwqLy9XeXm5amtr5fF4gvI8AAAAseaDDz7QyZMnlZGRoczMxr/433fffZKk9evX+/oGDBigTz75xO+4+va1114bxLQAYtGaHZXKWrrFry9r6Rat2VFpUKIIs+t16eUJ/n0vT6jrN+I6ABDBKBo30LFjRz366KOSpDlz5vjWMJak5557Tnv37tX48eN9s0/aW2FhodLT05Wenq7S0lJVVVUF5XkAAABizZ49eyRJI0aMCDhe3793715f31e+8hX95je/0fnz5319b775phwOh9/ax00ZPHhwwEdZWVlbvhQAUch5/KzmFu+T2+v163d7vZpbvE/O42ebOBOSpKoyad1jktft3+911/VXtfJ1t72uAwARLuqLxhs3btSYMWN8jwsXLkiSX9/GjRv9znnmmWd04403asuWLXI4HHrggQc0ZswYPfnkk0pOTtarr74atLy5ublyOp1yOp1yOBxKSkoK2nMBAADEkoMHD0qS+vXrF3C8vr+iosLX93//7/+Vx+PR1KlT9e677+rHP/6xfv7zn2vevHnBDwwgpqz+sFJujzfgmNvjZbZxS3aubFzored1S7t+GdrrAECEi/o1jY8dO6bt27c36v9i37Fjx/zG4uPjtWnTJi1atEirVq3SW2+9pR49eignJ0cFBQVN/qLRHmw2m2+HbqvVGrTnAQAAiDVnzpyRJHXu3DngeEJCgiTp9OnTvr7k5GS9/fbbevTRRzVp0iT17t1bzz33nB566KFWPef+/fsD9g8ePPhyogOIAYdOnGth/Hyz4zHPdbBt4+19HQCIcFFfNM7JyVFOTs5ln9epUyctXLhQCxcubP9QAAAAiBjDhw/X5s2bjY4BIMr16x74D1qXxjuFKEmEsvVv23h7XwcAIlzUL08BAAAASFJiYqIk6dy5wLP56vey6NKlS8gyAUC9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NGiQgWmiW2lpqWbMmHHZ53366acaO3asjh8/ruuvv1633HKLduzYoYULF+rdd9/Vu+++q7i4uCAkjhzV1dW6/fbbtW3bNvXp00f33HOPysvLtXz5cm3YsEHbtm3T1VdfbXTMsFdQUKC1a9de1jm5ubn6yU9+ok6dOmnixImqrq7W22+/rd///vd68803eW/+3KpVq/Twww9Lkq677jpNnjxZp06d0pYtW7RgwQL9z//8j9577z316tXL7zy+v633n//5nzp79qyGDh2qIUOGSJL279+vX/7yl/r1r3+t4uJi3XXXXX7n8P29Mk8++WSrfqfl+3v5pkyZosTExEb9ffv2bdTH9xdB5UVUWLhwoTc5Odl79uxZX9/s2bO9DofDwFRoyO12+/49LS3N+x//8R8GpkEgx48f92u73W7voEGDvA8//LBBidBaN910k/e+++4zOgYaKCkp8drtdu/TTz/t7du3r9Fx0MDy5cu9kry1tbVGR4kZn376qXfWrFnen/3sZ96PPvrIu3DhQq8k74IFC5o976abbvJK8j722GO+vtraWm9WVlarzo8F//Ef/+GV5B07dqz39OnTvv5nn33WK8k7fvx448JFkMWLF3vnzZvnXbdunffo0aPeuLg4b3O/Nr799tteSd6kpCTvgQMHfP1btmzxduzY0Wuz2bwnTpwIQfLw99prr3m//e1ve//617/69R85csSbmZnpleT9+te/7jfG9/fybN682Xv+/PlG/UuXLvVK8vbu3dvvPY/v75V55513vJK83/72t72SvBkZGQGP4/t7ecaPH++V5HU6na06nu8vgo2icZS46aabvN/4xjf8+v7whz94JXnLysqMCYVmUTSOHFOnTvXecccdRsdACyZPnuy95557jI6BL6ipqfFmZGR4f/3rX3sXLFhA0TgMUTQ23qJFi1os+m7fvt0rydurVy9vdXW139jf//53r9Vq9Xbv3j2mf441NTXebt26eSV5d+7c2Wh86NChXkneHTt2GJAusrVUNP7qV7/qleR9/vnnG4099thjXkneH//4x0FMGB22bNnileSNi4vz1tTU+Pr5/rafjIwMryTvnj17fH18fy/fuXPnvBkZGd5BgwZ5Dxw40GzRmO/v5bncojHfXwQbaxqHwJWuC3Y5a7IdOHBAAwcO9Ourb//tb39rny8kyoXi54S2MeJn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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "E_bins = np.logspace(0, 5, 40)\n", + "x_bins = np.linspace(-10, 50, 60)\n", + "times = [10, 20, 40, 80, 160, 200]\n", + "\n", + "fig, axs = plt.subplots(1,2, figsize = (10,5), dpi = 150)\n", + "\n", + "for i in range(len(times)):\n", + " \n", + " #energy-spectrum at the shock - take all times <= t into account:\n", + " #histogram is now weighted accordingly\n", + " J, dJ, bin_center = energy_spectrum(df.loc[(df['X'] > 0) & (df['X'] < 2) & (df['T'] <= times[i])], E_bins, weighted = True)\n", + " #number-density (integrated over energy) - take all times <= t into account:\n", + " #histogram is now weighted accordingly\n", + " N, dN, xbin_center = number_density(df.loc[(df['T'] <= times[i])], x_bins, weighted = True)\n", + "\n", + " axs[0].errorbar(bin_center, J*bin_center**2, yerr = dJ*bin_center**2, marker = '.', linestyle = '',label = r'$t = %i$' %times[i])\n", + " axs[1].errorbar(xbin_center, N, yerr = dN, marker = '.', linestyle = '',)\n", + " \n", + "\n", + "axs[0].set_xscale('log')\n", + "axs[0].set_yscale('log')\n", + "axs[0].set_xlabel(r\"$E/E_0$.\")\n", + "axs[0].set_ylabel(r\"$JE^2/\\mathrm{a.u.}$\")\n", + "axs[0].set_xlim(1, 10**5)\n", + "\n", + "axs[1].set_xlim(-10, 50 )\n", + "axs[1].set_yscale('log')\n", + "axs[1].set_xlabel(r\"$x/x_0$.\")\n", + "axs[1].set_ylabel(r\"$n/\\mathrm{a.u.}$\")\n", + "\n", + "fig.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Figure 3: Time evolution of energy-spectrum and number density with CandidateSplitting. The energy-sepctrum reaches higher energies, exponential cut-off at higher energies is now visible. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Energy-dependent Diffusion Coefficients" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Energy-dependent Diffusion with $\\kappa \\propto (E/E_0)^{\\alpha}, \\alpha > 0$ leads to higher diffusion with over time with particles reaching higher energies. This slows down the acceleration over time and leads to a maximal energy that can be reached at the shock. " + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "alpha = 1\n", + "diffSDE.setAlpha(alpha)\n", + "scale = TeV/(4*GeV)**alpha\n", + "diffSDE.setScale(kappa/(6.1*10**24)/scale) #scaling in DiffusionSDE: kappa = scale * (6.1*10**24) * (R/4GV)^alpha" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "crpropa::ModuleList: Number of Threads: 8\n", + "Run ModuleList\n", + " Started Fri Nov 3 10:21:39 2023 : [\u001b[1;32m Finished \u001b[0m] 100% Needed: 00:00:36 - Finished at Fri Nov 3 10:22:15 2023\n", + "\r" + ] + } + ], + "source": [ + "#Simulation\n", + "\n", + "file = \"SimpleDSA_energydependent.txt\"\n", + "outTime = TextOutput(file)\n", + "outTime.setEnergyScale(TeV)\n", + "outTime.setLengthScale(meter)\n", + "outTime.disableAll()\n", + "outTime.enable(Output.TrajectoryLengthColumn)\n", + "outTime.enable(Output.CurrentEnergyColumn)\n", + "outTime.enable(Output.CurrentPositionColumn)\n", + "outTime.enable(Output.WeightColumn)\n", + "\n", + "obsTime = Observer()\n", + "obsTime.add(ObserverTimeEvolution(T_min*c_light, T_max*c_light, n_time, False)) \n", + "obsTime.onDetection(outTime)\n", + "obsTime.setDeactivateOnDetection(False)\n", + "\n", + "\n", + "m = ModuleList()\n", + "m.add(diffSDE)\n", + "m.add(ac)\n", + "m.add(obsTime)\n", + "m.add(maxTra)\n", + "m.add(splitting)\n", + "m.setShowProgress(True)\n", + "m.run(source, N_cand)\n", + "outTime.close()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "columns = ['D', 'E', 'X', 'Y', 'Z', 'W']\n", + "file = \"SimpleDSA_energydependent.txt\"\n", + "df = pd.read_csv(file, comment='#', delimiter = '\\t', names = columns ) \n", + "df[\"T\"] = df[\"D\"]/(c_light)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/hm/8552yhb509l530c14llpb1ym0000gn/T/ipykernel_90949/3921811185.py:16: RuntimeWarning: invalid value encountered in divide\n", + " dJ = J/np.sqrt(H[0])\n", + "/var/folders/hm/8552yhb509l530c14llpb1ym0000gn/T/ipykernel_90949/3921811185.py:38: RuntimeWarning: invalid value encountered in divide\n", + " dN = N/np.sqrt(H[0])\n" + ] + }, + { + "data": { + "image/png": "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UojJkydDpVJ1e8yfP1/cpms/Jmf2ISIi6guVSoW1a9fizTffxNq1a/Haa69h//79iI6OFrfZtWsXsrOznd5nz549GD16NEaNGoW33nrL4z8TESmXShAEQeoQRNQzQRCg0+lQWFiIJ5980ua5gQMHYuDAgTCbzdDr9di7dy9SUlKc2oeIiKi/7r//fpw+fRoHDhzA5MmTxfVnz57FhAkTUFdXh6CgoDvu097ejoSEBBw6dAg6nQ7Jycn46quvMGTIEI/+PESkTBw8ikgBvvnmGzQ1NeHHP/4x9Hq93W269mNyZh8iIqL+2L9/P86dOwez2YyIiAib53bv3o2HH364W1HraJ9jx45h7Nix4tXbrKwsHDhwAE888YT7fxAiUjzeikykAKWlpfD398f48eMdbtO1H5Mz+xAREfVVWVkZ/uM//gP/8z//g6lTp2LFihU2z+/atQszZsxwep+amhqb25ijo6NRXV3t3h+CiLwGC1siBSgrK4PZbMaQIUPE24gHDhyIn//85+I2XfsxObMP+zIREVFfVFRUYNq0aVi+fDmeeOIJvPjii/j4449RVlYGALh27RpOnDiBRx991Ol97uT111/H1KlT3fLzEJHy8VZkIgUoKyvDE088gdWrV9usDwsLA2Dtx1RTU2PzC/9O+7S3t6OgoMCmL9PMmTPZl4mIiHpUX1+Pn/zkJ5gxYwaWLl0KAEhNTUVWVhaWL1+O/fv349NPP0VKSgrCw8Od3icqKsrmCm11dTVSUlLEdl1dHS5evOjBn5SIlISDRxEpQGhoKNauXYtf/OIXdp//7W9/i6+//ho7d+50ep+vvvoKGzduFPdZvHgxUlNT2ZeJiIj6LTs7G5MmTcKSJUuc3qe9vR1jxozBF198wcGjiKjXeMWWSOYuXbqE69evIzEx0eE2u3btws9+9rNe7cO+TERE5C6TJk3q9R9K/f398fLLLyM9PR0WiwVLlixhUUtETmNhSyRzpaWlAICIiAgYjUab54YOHYq6ujqcOHECu3fvdnoftbrn7vWvv/46du7cieLiYlf8CERE5GN6c6W2s+zsbJvxIoiInMXClkjmbg+qMWrUKJv1gYGBaGxs7NaPyZl9NBpNj32Z2I+JiIiIiJSEfWyJFK4v/ZgA9mUiIiIiIu/BK7ZECteXfkwA+zIRERERkffgFVsiIiIiIiJStJ5HkCEiIiIiIiKSORa2REREREREpGgsbImIiIiIiEjRWNgSERERERGRorGwJSIiIiIiIkVjYUtERERERESKxsKWiIiIiIiIFI2FLRERERERESkaC1siIiIiIiJSNBa2REREREREpGgsbImIiIiIiEjRWNgSERERERGRov1/qTut7CNE3LoAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "E_bins = np.logspace(0, 2, 40)\n", + "x_bins = np.linspace(-30, 50, 80)\n", + "times = [10, 20, 40, 80, 160, 200]\n", + "\n", + "fig, axs = plt.subplots(1,2, figsize = (10,5))\n", + "\n", + "for i in range(len(times)):\n", + " \n", + " #energy-spectrum at the shock - take all times <= t into account:\n", + " #histogram is now weighted accordingly\n", + " J, dJ, bin_center = energy_spectrum(df.loc[(df['X'] > 0) & (df['X'] < 2) & (df['T'] <= times[i])], E_bins, weighted = True)\n", + " #number-density (integrated over energy) - take all times <= t into account:\n", + " #histogram is now weighted accordingly\n", + " N, dN, xbin_center = number_density(df.loc[(df['T'] <= times[i])], x_bins, weighted = True)\n", + "\n", + " axs[0].errorbar(bin_center, J*bin_center**2, yerr = dJ*bin_center**2, marker = '.', linestyle = '',label = r'$t = %i$' %times[i])\n", + " axs[1].errorbar(xbin_center, N, yerr = dN, marker = '.', linestyle = '',)\n", + " \n", + "\n", + "axs[0].set_xscale('log')\n", + "axs[0].set_yscale('log')\n", + "axs[0].set_xlabel(r\"$E/E_0$.\")\n", + "axs[0].set_ylabel(r\"$JE^2/\\mathrm{a.u.}$\")\n", + "axs[0].set_xlim(1, 10**2)\n", + "\n", + "axs[1].set_xlim(-30, 50 )\n", + "axs[1].set_yscale('log')\n", + "axs[1].set_xlabel(r\"$x/x_0$.\")\n", + "axs[1].set_ylabel(r\"$n/\\mathrm{a.u.}$\")\n", + "\n", + "fig.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Figure 4: With energy-dependent diffusion, acceleration slows down over time and comparede to Figure 3 only a fraction of energy is reached at $t = 200$. With higher diffusion at high energy, more particles make it in the upstream region with increasing time" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Acceleration Time Scale\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From the previous simulations, the mean acceleration time scale can be calculated and compared with analytical predicitons:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "kappa_up = kappa\n", + "kappa_down = kappa\n", + "v_down = v_up/compression\n", + "\n", + "t_acc = 3./(v_up - v_down) * (kappa_up/v_up + kappa_down/v_down)\n", + "\n", + "def mean_acceleration_time(p, tacc, alpha, p0 = 1):\n", + " #returns the mean acceleration time to reach momentum p\n", + " #depends on diffusion coefficient, advection field, given by tacc\n", + " #and on energy-dependence of the diffusion coefficient fiven by alpha\n", + " #see, e.g. Drury, 1983 \n", + "\n", + " if alpha == 0:\n", + " return tacc * np.log(p/p0)\n", + " elif alpha == 1:\n", + " return (p/p0 - 1)*tacc\n", + " else:\n", + " print(\"Unknown alpha: alpha = 0,1,2\")\n", + "\n", + "def approximate_acceleration_time(df):\n", + " #calculate mean time to accelerate up to energy E\n", + " #given by dataframe df\n", + " #returns weighted mean time, error of the mean\n", + " if df['W'].sum() > 0:\n", + " average = np.average(df['T'], weights = df['W'])\n", + " error = (np.sqrt(np.average((df['T']-average)*(df['T']-average), weights = df['W'])/df['W'].sum())) \n", + " return average, error\n", + " else:\n", + " return 0, 0\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "columns = ['D', 'E', 'X', 'Y', 'Z', 'W']\n", + "#energy-independent:\n", + "file = \"SimpleDSA_splitting.txt\"\n", + "df0 = pd.read_csv(file, comment='#', delimiter = '\\t', names = columns ) \n", + "df0[\"T\"] = df0[\"D\"]/(c_light)\n", + "#energy-dependent:\n", + "file = \"SimpleDSA_energydependent.txt\"\n", + "df1 = pd.read_csv(file, comment='#', delimiter = '\\t', names = columns ) \n", + "df1[\"T\"] = df1[\"D\"]/(c_light)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "Energy = np.logspace(0, 1, 40)\n", + "dEnergy = np.logspace(-3, 0, 40)\n", + "\n", + "avTime0 = []\n", + "errTime0 = []\n", + "avTime1 = []\n", + "errTime1 = []\n", + "plot0 = []\n", + "plot1 = []\n", + "\n", + "for i in range(len(Energy)):\n", + " E = Energy[i]\n", + " dE = dEnergy[i]\n", + "\n", + " average, error = approximate_acceleration_time(df0.loc[(df0['X']> 0) & (df0['X'] < 1) & (df0['E'] <= E+dE) & (df0['E'] > E-dE)])\n", + " if average > 0:\n", + " plot0.append(E)\n", + " avTime0.append(average) \n", + " errTime0.append(error)\n", + "\n", + " average, error = approximate_acceleration_time(df1.loc[(df1['X']> 0) & (df1['X'] < 1) & (df1['E'] <= E+dE) & (df1['E'] > E-dE)])\n", + " if average > 0:\n", + " plot1.append(E)\n", + " avTime1.append(average) \n", + " errTime1.append(error)\n", + "\n", + "\n", + "plt.plot(Energy, mean_acceleration_time(Energy, t_acc, 0), label = r'$$, $\\alpha = 0$')\n", + "plt.errorbar(plot0, avTime0, errTime0, linestyle = '', marker = '.',label = r'SDE, $\\alpha = 0$')\n", + "\n", + "plt.plot(Energy, mean_acceleration_time(Energy, t_acc, 1), label = r'$$, $\\alpha = 1$')\n", + "plt.errorbar(plot1, avTime1, errTime1, linestyle = '', marker = '.',label = r'SDE, $\\alpha = 1$')\n", + "\n", + "plt.xscale('log')\n", + "plt.ylabel(r'$\\bar{t}/t_0$')\n", + "plt.xlabel(r'$E/E_0$')\n", + "plt.ylim([0, 100])\n", + "plt.xlim([1, 10])\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Figure 5: Mean acceleration time to reach energy $E/E_0$. At high energies, mean acceleration time of the CRPropa simulation deviates from the prediciton. This is due to finite simulation time $T = 200$. " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Documentation", + "language": "python", + "name": "documentation" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + }, + "vscode": { + "interpreter": { + "hash": "b0fa6594d8f4cbf19f97940f81e996739fb7646882a419484c72d19e05852a7e" + } + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/doc/pages/galactic_cosmic_rays.rst b/doc/pages/galactic_cosmic_rays.rst index a9a3612a4..89e632a1a 100644 --- a/doc/pages/galactic_cosmic_rays.rst +++ b/doc/pages/galactic_cosmic_rays.rst @@ -36,6 +36,25 @@ changes, which can be modeled following the next examples. .. toctree:: example_notebooks/Diffusion/AdiabaticCooling.ipynb +Diffusive Shock Acceleration +^^^^^^^^^^^^^^^^^^ + +Diffusive shock acceleration or first order Fermi acceleration can be modeled +in the diffusive picture as an interplay between diffusion, advection and +adiabatic cooling. Simple shock configurations are shown in the following +example notebook. + +.. toctree:: + example_notebooks/acceleration/diffusive_shock_acceleration.ipynb + +Momentum Diffusion +^^^^^^^^^^^^^^^^^^ + +Momentum diffusion or second order Fermi acceleration is explained in the +following example notebook. + +.. toctree:: + example_notebooks/Diffusion/MomentumDiffusion.ipynb Example of diffusion in the Milky way ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/include/CRPropa.h b/include/CRPropa.h index 822954bf8..b5ccfc27f 100644 --- a/include/CRPropa.h +++ b/include/CRPropa.h @@ -16,7 +16,6 @@ #include "crpropa/ParticleMass.h" #include "crpropa/ParticleState.h" #include "crpropa/PhotonBackground.h" -#include "crpropa/PhotonPropagation.h" #include "crpropa/Random.h" #include "crpropa/Referenced.h" #include "crpropa/Source.h" @@ -29,8 +28,8 @@ #include "crpropa/module/Acceleration.h" #include "crpropa/module/Boundary.h" #include "crpropa/module/BreakCondition.h" +#include "crpropa/module/CandidateSplitting.h" #include "crpropa/module/DiffusionSDE.h" -#include "crpropa/module/EMCascade.h" #include "crpropa/module/EMDoublePairProduction.h" #include "crpropa/module/EMInverseComptonScattering.h" #include "crpropa/module/EMPairProduction.h" @@ -38,13 +37,13 @@ #include "crpropa/module/ElasticScattering.h" #include "crpropa/module/ElectronPairProduction.h" #include "crpropa/module/HDF5Output.h" +#include "crpropa/module/MomentumDiffusion.h" #include "crpropa/module/NuclearDecay.h" #include "crpropa/module/Observer.h" #include "crpropa/module/OutputShell.h" #include "crpropa/module/ParticleCollector.h" #include "crpropa/module/PhotoDisintegration.h" #include "crpropa/module/PhotoPionProduction.h" -#include "crpropa/module/PhotonEleCa.h" #include "crpropa/module/PhotonOutput1D.h" #include "crpropa/module/PropagationBP.h" #include "crpropa/module/PropagationCK.h" diff --git a/include/crpropa/Grid.h b/include/crpropa/Grid.h index a13d6e4b3..3fe078da5 100644 --- a/include/crpropa/Grid.h +++ b/include/crpropa/Grid.h @@ -77,6 +77,7 @@ class GridProperties: public Referenced { Vector3d spacing; // Spacing vector between gridpoints bool reflective; // using reflective repetition of the grid instead of periodic interpolationType ipol; // Interpolation type used between grid points + bool clipVolume; // Set grid values to 0 outside the volume if true /** Constructor for cubic grid @param origin Position of the lower left front corner of the volume @@ -84,7 +85,7 @@ class GridProperties: public Referenced { @param spacing Spacing between grid points */ GridProperties(Vector3d origin, size_t N, double spacing) : - origin(origin), Nx(N), Ny(N), Nz(N), spacing(Vector3d(spacing)), reflective(false), ipol(TRILINEAR) { + origin(origin), Nx(N), Ny(N), Nz(N), spacing(Vector3d(spacing)), reflective(false), ipol(TRILINEAR), clipVolume(false) { } /** Constructor for non-cubic grid @@ -95,7 +96,7 @@ class GridProperties: public Referenced { @param spacing Spacing between grid points */ GridProperties(Vector3d origin, size_t Nx, size_t Ny, size_t Nz, double spacing) : - origin(origin), Nx(Nx), Ny(Ny), Nz(Nz), spacing(Vector3d(spacing)), reflective(false), ipol(TRILINEAR) { + origin(origin), Nx(Nx), Ny(Ny), Nz(Nz), spacing(Vector3d(spacing)), reflective(false), ipol(TRILINEAR), clipVolume(false) { } /** Constructor for non-cubic grid with spacing vector @@ -106,7 +107,7 @@ class GridProperties: public Referenced { @param spacing Spacing vector between grid points */ GridProperties(Vector3d origin, size_t Nx, size_t Ny, size_t Nz, Vector3d spacing) : - origin(origin), Nx(Nx), Ny(Ny), Nz(Nz), spacing(spacing), reflective(false), ipol(TRILINEAR) { + origin(origin), Nx(Nx), Ny(Ny), Nz(Nz), spacing(spacing), reflective(false), ipol(TRILINEAR), clipVolume(false) { } virtual ~GridProperties() { @@ -122,6 +123,11 @@ class GridProperties: public Referenced { void setInterpolationType(interpolationType i) { ipol = i; } + + /** If True, the grid is set to zero outside of the volume. */ + void setClipVolume(bool b) { + clipVolume = b; + } }; /** @@ -156,6 +162,7 @@ class Grid: public Referenced { setSpacing(Vector3d(spacing)); setReflective(false); setClipVolume(false); + setInterpolationType(TRILINEAR); } /** Constructor for non-cubic grid @@ -171,6 +178,7 @@ class Grid: public Referenced { setSpacing(Vector3d(spacing)); setReflective(false); setClipVolume(false); + setInterpolationType(TRILINEAR); } /** Constructor for non-cubic grid with spacing vector @@ -186,6 +194,7 @@ class Grid: public Referenced { setSpacing(spacing); setReflective(false); setClipVolume(false); + setInterpolationType(TRILINEAR); } /** Constructor for GridProperties @@ -194,6 +203,7 @@ class Grid: public Referenced { Grid(const GridProperties &p) : origin(p.origin), spacing(p.spacing), reflective(p.reflective), ipolType(p.ipol) { setGridSize(p.Nx, p.Ny, p.Nz); + setClipVolume(p.clipVolume); } void setOrigin(Vector3d origin) { @@ -242,6 +252,10 @@ class Grid: public Referenced { return origin; } + bool getClipVolume() const { + return clipVolume; + } + size_t getNx() const { return Nx; } diff --git a/include/crpropa/PhotonBackground.h b/include/crpropa/PhotonBackground.h index 5dc5bf7ab..7f7d60f8f 100644 --- a/include/crpropa/PhotonBackground.h +++ b/include/crpropa/PhotonBackground.h @@ -71,7 +71,7 @@ class PhotonField: public Referenced { class TabularPhotonField: public PhotonField { public: TabularPhotonField(const std::string fieldName, const bool isRedshiftDependent = true); - + double getPhotonDensity(double ePhoton, double z = 0.) const; double getRedshiftScaling(double z) const; double getMinimumPhotonEnergy(double z) const; @@ -194,6 +194,45 @@ class IRB_Stecker16_lower: public TabularPhotonField { IRB_Stecker16_lower() : TabularPhotonField("IRB_Stecker16_lower", true) {} }; +/** + @class IRB_Saldana21 + @brief Extragalactic background light model from Saldana-Lopez et al. 2021 + + Source info: + DOI:10.1093/mnras/stab2393 + https://ui.adsabs.harvard.edu/abs/2021MNRAS.507.5144S/abstract + */ +class IRB_Saldana21: public TabularPhotonField { +public: + IRB_Saldana21() : TabularPhotonField("IRB_Saldana21", true) {} +}; + +/** + @class IRB_Saldana21_upper + @brief Extragalactic background light model from Saldana-Lopez et al. 2021 (upper-bound model) + + Source info: + DOI:10.1093/mnras/stab2393 + https://ui.adsabs.harvard.edu/abs/2021MNRAS.507.5144S/abstract + */ +class IRB_Saldana21_upper: public TabularPhotonField { +public: + IRB_Saldana21_upper() : TabularPhotonField("IRB_Saldana21_upper", true) {} +}; + +/** + @class IRB_Saldana21_lower + @brief Extragalactic background light model from Saldana-Lopez et al. 2021 (lower-bound model) + + Source info: + DOI:10.1093/mnras/stab2393 + https://ui.adsabs.harvard.edu/abs/2021MNRAS.507.5144S/abstract + */ +class IRB_Saldana21_lower: public TabularPhotonField { +public: + IRB_Saldana21_lower() : TabularPhotonField("IRB_Saldana21_lower", true) {} +}; + /** @class URB @brief Extragalactic background light model from Protheroe & Biermann 1996 @@ -210,11 +249,11 @@ class URB_Protheroe96: public TabularPhotonField { /** @class URB @brief Extragalactic background light model based on ARCADE2 observations, by Fixsen et al. - Note that this model does not cover the same energy range as other URB models. Here, only ~10 MHz - 10 GHz is considered. + Note that this model does not cover the same energy range as other URB models. Here, only ~10 MHz - 10 GHz is considered. Therefore, it only makes sense to use this model in very specific studies. - + Source info: - DOI:10.1088/0004-637X/734/1/5 + DOI:10.1088/0004-637X/734/1/5 https://iopscience.iop.org/article/10.1088/0004-637X/734/1/5 */ class URB_Fixsen11: public TabularPhotonField { @@ -224,8 +263,8 @@ class URB_Fixsen11: public TabularPhotonField { /** @class URB - @brief Extragalactic background light model by Nitu et al. - + @brief Extragalactic background light model by Nitu et al. + Source info: DOI:10.1016/j.astropartphys.2020.102532 https://www.sciencedirect.com/science/article/pii/S0927650520301043? diff --git a/include/crpropa/PhotonPropagation.h b/include/crpropa/PhotonPropagation.h deleted file mode 100644 index a5097e1e4..000000000 --- a/include/crpropa/PhotonPropagation.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef CRPROPA_PHOTON_PROPAGATION_H -#define CRPROPA_PHOTON_PROPAGATION_H - -#include -#include - -/** - @file - @brief Calculation of the electromagnetic cascade outside of CRPropa's module list - */ - -namespace crpropa { - -/** - Propagate photons, electrons and positrons using the EleCa code. - The propagation is stopped when the particles reach the observer or their energy drops below the threshold energy. - */ -void ElecaPropagation( - const std::string &inputfile, //!< input in PhotonOutput1D format - const std::string &outputfile, //!< output in PhotonOutput1D format - bool showProgress = true, //!< show a progress bar - double lowerEnergyThreshold = 0.8010882435, //!< threshold energy [J], default = 5 EeV - double magneticFieldStrength = 1E-13, //!< magnetic field strength [T], default = 1 nG - const std::string &background = "ALL" //!< photon background string - ); - -/** - Calculate the electromagnetic cascade with DINT - */ -void DintPropagation( - const std::string &inputfile, //!< input in PhotonOutput1D format - const std::string &outputfile, //!< output spectrum (photons, electrons, positrons) - int IRFlag = 4, //!< EBL background 0: high, 1: low, 2: Primack, 4: Stecker'06 - int RadioFlag = 4, //!< radio background 0: high, 1: medium, 2: obs, 3: none, 4: Protheroe'96 - double magneticFieldStrength = 1E-13, //!< magnetic field strength [T], default = 1 nG - double aCutcascade_Magfield = 0 //!< a-parameter, see CRPropa 2 paper - ); - -/** - Propagate photons using EleCa for energies above the crossover energy and DINT below - */ -void DintElecaPropagation( - const std::string &inputfile, //!< input in PhotonOutput1D format - const std::string &outputfile, //!< output spectrum (photons, electrons, positrons) - bool showProgress = true, //!< show a progress bar - double crossOverEnergy = 0.08010882435, //!< crossover energy [J] between EleCa and DINT, default = 0.5 EeV - double magneticFieldStrength = 1E-13, //!< magnetic field strength [T], default = 1 nG - double aCutcascade_Magfield = 0 //!< a-parameter, see CRPropa 2 paper - ); - -} // namespace crpropa - -#endif // CRPROPA_PHOTON_PROPAGATION_H diff --git a/include/crpropa/Source.h b/include/crpropa/Source.h index f2e52518a..68f6a75e9 100644 --- a/include/crpropa/Source.h +++ b/include/crpropa/Source.h @@ -610,10 +610,6 @@ class SourceIsotropicEmission: public SourceFeature { class SourceDirectedEmission: public SourceFeature { Vector3d mu; // Mean emission direction in the vMF distribution double kappa; // Concentration parameter of the vMF distribution - double ca; // helpers for the efficient calculation of frame rotation - double sa; - double cd; - double sd; public: /** Constructor @param mu mean direction of the emission, mu should be normelized @@ -621,30 +617,6 @@ class SourceDirectedEmission: public SourceFeature { */ SourceDirectedEmission(Vector3d mu, double kappa); void prepareCandidate(Candidate &candidate) const; - /** - set sampling parameter Ca - @param alpha angle between x and y component of direction. alpha = arctan(mu.y / mu.x) - */ - void setCa(double alpha); - /** - set sampling parameter Sa - @param alpha angle between x and y component of direction. alpha = arctan(mu.y / mu.x) - */ - void setSa(double alpha); - /** - set sampling parameter Cd - @param delta angle between mu vector and z-axis. delta = arcsin(mu.z) - */ - void setCd(double delta); - /** - set sampling parameter Sd - @param delta angle between mu vector and z-axis. delta = arcsin(mu.z) - */ - void setSd(double delta); - double getCa() const; - double getSa() const; - double getCd() const; - double getSd() const; void setDescription(); }; diff --git a/include/crpropa/Variant.h b/include/crpropa/Variant.h index ac3bde873..90d4277a8 100644 --- a/include/crpropa/Variant.h +++ b/include/crpropa/Variant.h @@ -1,66 +1,142 @@ //------------------------------------------------------------- -// Based on Variant.hh in the Physics eXtension Library (PXL) - +// Based on Variant.hh of the Physics eXtension Library (PXL) - // http://vispa.physik.rwth-aachen.de/ - // Licensed under a LGPL-2 or later license - //------------------------------------------------------------- -#ifndef VARIANT_HH -#define VARIANT_HH +#ifndef CRPROPA_VARIANT_H +#define CRPROPA_VARIANT_H +#include +#include +#include +#include #include +#include #include -#include -#include #include -#include #include -#include -#include - -// Helper to set POD type methods to variant -#define VARIANT_ADD_TYPE_DECL_POD(NAME, TYPE, VALUE) \ - bool is ## NAME() const { return (type == TYPE); } \ - operator VALUE () const { return to ## NAME(); } \ - VALUE &as ## NAME() { check(TYPE); return data._##NAME; } \ - const VALUE &as ## NAME() const { check(TYPE); return data._##NAME; } \ - static Variant from ## NAME(const VALUE &a) { return Variant(a); } \ - VALUE to ## NAME() const; \ - Variant &operator = (const VALUE &a) { clear(); type = TYPE; data._##NAME = a; return *this; } \ - bool operator != (const VALUE &a) const { check(TYPE); return data._##NAME != a; } \ - bool operator == (const VALUE &a) const { check(TYPE); return data._##NAME == a; } \ - Variant(const VALUE &a) { data._ ## NAME = a; type = TYPE; } - -// Helper to set pointer type methods to variant -#define VARIANT_ADD_TYPE_DECL_PTR_BASE(NAME, TYPE, VALUE) \ - bool is ## NAME() const { return (type == TYPE); } \ - VALUE &as ## NAME() { check(TYPE); return *data._##NAME; } \ - const VALUE &as ## NAME() const { check(TYPE); return *data._##NAME; } \ - static Variant from ## NAME(const VALUE &a) { return Variant(a); } \ - -// Helper to set pointer type methods to variant -#define VARIANT_ADD_TYPE_DECL_PTR(NAME, TYPE, VALUE) \ - bool operator != (const VALUE &a) const { check(TYPE); return *data._##NAME != a; } \ - bool operator == (const VALUE &a) const { check(TYPE); return *data._##NAME == a; } \ - VARIANT_ADD_TYPE_DECL_PTR_BASE(NAME, TYPE, VALUE) \ - Variant &operator =(const VALUE &a) { if (type != TYPE) { clear(); data._##NAME = new VALUE; } type = TYPE; (*data._##NAME) = a; return *this; } \ - Variant(const VALUE &a) { data._ ## NAME = new VALUE(a); type = TYPE; } - -namespace crpropa -{ +#include + +#include "crpropa/Vector3.h" + + + +// defines copy constructor X(const X&), isX(), asX(), fromX(), toX(), op(), op=, op==, op!= +#define VARIANT_ADD_TYPE_DECL_POD(NAME, TYPE, VALUE, FIELD) \ + Variant(const VALUE& v) { \ + data._t_##FIELD = v; \ + type = TYPE; \ + } \ + bool is##NAME() const { \ + return type == TYPE; \ + } \ + VALUE& as##NAME() { \ + check(TYPE); \ + return data._t_##FIELD; \ + } \ + const VALUE& as##NAME() const { \ + check(TYPE); \ + return data._t_##FIELD; \ + } \ + static Variant from##NAME(const VALUE& v) { \ + return Variant(v); \ + } \ + VALUE to##NAME() const; \ + operator VALUE() const { \ + return to##NAME(); \ + } \ + Variant& operator=(const VALUE& v) { \ + clear(); \ + type = TYPE; \ + data._t_##FIELD = v; \ + return *this; \ + } \ + bool operator==(const VALUE& v) const { \ + check(TYPE); \ + return data._t_##FIELD == v; \ + } \ + bool operator!=(const VALUE& v) const { \ + check(TYPE); \ + return data._t_##FIELD != v; \ + } \ + +// defines isX(), asX(), fromX() +#define VARIANT_ADD_TYPE_DECL_PTR_BASE(NAME, TYPE, VALUE, FIELD) \ + bool is##NAME() const { \ + return type == TYPE; \ + } \ + VALUE& as##NAME() { \ + check(TYPE); \ + return *data._t_##FIELD; \ + } \ + const VALUE& as##NAME() const { \ + check(TYPE); \ + return *data._t_##FIELD; \ + } \ + static Variant from##NAME(const VALUE& v) { \ + return Variant(v); \ + } \ + +// defines isX(), asX(), fromX(), and copy constructor X(const X&), op=, op==, op!= +#define VARIANT_ADD_TYPE_DECL_PTR(NAME, TYPE, VALUE, FIELD) \ + VARIANT_ADD_TYPE_DECL_PTR_BASE(NAME, TYPE, VALUE, FIELD) \ + Variant(const VALUE& v) { \ + data._t_##FIELD = new VALUE(v); \ + type = TYPE; \ + } \ + Variant& operator=(const VALUE& v) { \ + if (type != TYPE) { \ + clear(); \ + data._t_##FIELD = new VALUE();\ + } \ + type = TYPE; \ + (*data._t_##FIELD) = v; \ + return *this; \ + } \ + bool operator==(const VALUE& v) const { \ + check(TYPE); \ + return *data._t_##FIELD == v; \ + } \ + bool operator!=(const VALUE& v) const { \ + return !(*this == v); \ + } \ + +#define VARIANT_ADD_ITER_DECL_PTR(NAME, TYPE, FIELD) \ + typedef FIELD##_t::iterator FIELD##_iterator; \ + typedef FIELD##_t::const_iterator FIELD##_const_iterator; \ + inline FIELD##_iterator begin##NAME() { \ + check(TYPE); \ + return data._t_##FIELD->begin(); \ + } \ + inline FIELD##_iterator end##NAME() { \ + check(TYPE); \ + return data._t_##FIELD->end(); \ + } \ + inline FIELD##_const_iterator begin##NAME() const { \ + check(TYPE); \ + return data._t_##FIELD->begin(); \ + } \ + inline FIELD##_const_iterator end##NAME() const { \ + check(TYPE); \ + return data._t_##FIELD->end(); \ + } + + + +namespace crpropa { /** @class Variant @brief storage container for data types as e.g. int, float, string, etc. - Allows storage of multiple data types in one base class. Used to construct a - map of `arbitrary' data types. - + Allows storage of multiple data types in one base class. Used to construct a map of `arbitrary' data types. + Note that most default C++ types allow default conversions from `Variant` to the corresponding type. + Types that require an explicit call via `toTargetType()` are: complex (float and double), Vector3, and vector. */ -class Variant -{ +class Variant { public: - enum Type - { + enum Type { TYPE_NONE = 0, TYPE_BOOL, TYPE_CHAR, @@ -73,144 +149,154 @@ class Variant TYPE_UINT64, TYPE_FLOAT, TYPE_DOUBLE, - TYPE_STRING + TYPE_LONGDOUBLE, + TYPE_COMPLEXF, + TYPE_COMPLEXD, + TYPE_STRING, + TYPE_VECTOR3F, + TYPE_VECTOR3D, + TYPE_VECTOR3C, + TYPE_VECTOR }; - class bad_conversion: public std::exception - { - std::string msg; - public: - const char* what() const throw () - { - return msg.c_str(); - } - bad_conversion(Type f, Type t) - { - msg = "Variant: bad conversion from '"; - msg += Variant::getTypeName(f); - msg += "' to '"; - msg += Variant::getTypeName(t); - msg += "'"; - } - ~bad_conversion() throw () - { - } + class bad_conversion: public std::exception { + protected: + std::string msg; + public: + const char* what() const throw () { + return msg.c_str(); + } + + bad_conversion(Type f, Type t) { + msg = "Variant: bad conversion from '"; + msg += Variant::getTypeName(f); + msg += "' to '"; + msg += Variant::getTypeName(t); + msg += "'"; + } + + ~bad_conversion() throw () { + } }; - Variant(); - ~Variant(); - - Variant(const Variant& a); - - const std::type_info& getTypeInfo() const; - - const char * getTypeName() const - { - return getTypeName(type); - } - - static Type toType(const std::string &name); + typedef std::complex complex_f; + typedef std::complex complex_d; + typedef Vector3> Vector3c; + typedef std::vector vector_t; - static const char *getTypeName(Type type); +protected: + Type type; - // copy the data to buffer via memcpy. Returns the size of the data - size_t copyToBuffer(void* buffer); - /// returns size of used data type in bytes - size_t getSize() const; + union { + bool _t_bool; + char _t_char; + unsigned char _t_uchar; + int16_t _t_int16; + uint16_t _t_uint16; + int32_t _t_int32; + uint32_t _t_uint32; + int64_t _t_int64; + uint64_t _t_uint64; + float _t_float; + double _t_double; + long double _t_ldouble; + complex_f* _t_complex_f; + complex_d* _t_complex_d; + std::string* _t_string; + Vector3f* _t_vector3f; + Vector3d* _t_vector3d; + Vector3c* _t_vector3c; + vector_t* _t_vector; + } data; - template - T to() const - { - throw bad_conversion(type, TYPE_NONE); - } - Type getType() const - { +public: + Variant(); + Variant(Type t); + Variant(const Variant& v); + Variant(const char* s); + ~Variant(); + inline Type getType() const { return type; } - - bool operator ==(const Variant &a) const; - - bool operator !=(const Variant &a) const; - - Variant &operator =(const Variant &a) - { - copy(a); - return *this; - } - - bool isValid() - { - return (type != TYPE_NONE); - } - - VARIANT_ADD_TYPE_DECL_POD(Bool, TYPE_BOOL, bool) - - VARIANT_ADD_TYPE_DECL_POD(Char, TYPE_CHAR, char) - - VARIANT_ADD_TYPE_DECL_POD(UChar, TYPE_UCHAR, unsigned char) - - VARIANT_ADD_TYPE_DECL_POD(Int16, TYPE_INT16, int16_t) - - VARIANT_ADD_TYPE_DECL_POD(UInt16, TYPE_UINT16, uint16_t) - - VARIANT_ADD_TYPE_DECL_POD(Int32, TYPE_INT32, int32_t) - - VARIANT_ADD_TYPE_DECL_POD(UInt32, TYPE_UINT32, uint32_t) - - VARIANT_ADD_TYPE_DECL_POD(Int64, TYPE_INT64, int64_t) - - VARIANT_ADD_TYPE_DECL_POD(UInt64, TYPE_UINT64, uint64_t) - - VARIANT_ADD_TYPE_DECL_POD(Float, TYPE_FLOAT, float) - - VARIANT_ADD_TYPE_DECL_POD(Double, TYPE_DOUBLE, double) - - VARIANT_ADD_TYPE_DECL_PTR(String, TYPE_STRING, std::string) - Variant(const char *s); - std::string toString() const; - static Variant fromString(const std::string &str, Type type); - operator std::string() const - { + const char* getTypeName() const; + static const char* getTypeName(Type t); + const std::type_info& getTypeInfo() const; + static Type toType(const std::string& name); + std::string toString(const std::string& delimiter = "\t") const; + std::complex toComplexFloat() const; + std::complex toComplexDouble() const; + Vector3f toVector3f() const; + Vector3d toVector3d() const; + Vector3c toVector3c() const; + vector_t toVector() const; + static Variant fromString(const std::string& str, Type type); + void clear(Type t = TYPE_NONE); + bool isValid() const; + size_t size() const; + size_t getSizeOf() const; + size_t getSize() const; + void resize(size_t i); + size_t copyToBuffer(void* buffer); + operator std::string() const { return toString(); } - bool operator !=(const char *a) const - { - check(TYPE_STRING); - return data._String->compare(a) != 0; + Variant& operator=(const Variant& v); + bool operator==(const Variant& v) const; + bool operator!=(const Variant& v) const; + bool operator!=(const char* a) const; + Variant& operator[](size_t i); + inline Variant& operator[](int i) { + return operator[]((size_t) i); } + const Variant& operator[](size_t i) const; + const Variant& operator[](int i) const { + return operator[]((size_t) i); + } + operator vector_t&(); + operator const vector_t&() const; - // clear pointer based data types - void clear(); - -protected: - Type type; - union - { - bool _Bool; - char _Char; - unsigned char _UChar; - int16_t _Int16; - uint16_t _UInt16; - int32_t _Int32; - uint32_t _UInt32; - int64_t _Int64; - uint64_t _UInt64; - double _Double; - float _Float; - std::string *_String; - } data; + template + T to() const { + throw bad_conversion(type, TYPE_NONE); + } + // automatically-generated functions + VARIANT_ADD_TYPE_DECL_POD(Bool, TYPE_BOOL, bool, bool) + VARIANT_ADD_TYPE_DECL_POD(Char, TYPE_CHAR, char, char) + VARIANT_ADD_TYPE_DECL_POD(UChar, TYPE_UCHAR, unsigned char, uchar) + VARIANT_ADD_TYPE_DECL_POD(Int16, TYPE_INT16, int16_t, int16) + VARIANT_ADD_TYPE_DECL_POD(UInt16, TYPE_UINT16, uint16_t, uint16) + VARIANT_ADD_TYPE_DECL_POD(Int32, TYPE_INT32, int32_t, int32) + VARIANT_ADD_TYPE_DECL_POD(UInt32, TYPE_UINT32, uint32_t, uint32) + VARIANT_ADD_TYPE_DECL_POD(Int64, TYPE_INT64, int64_t, int64) + VARIANT_ADD_TYPE_DECL_POD(UInt64, TYPE_UINT64, uint64_t, uint64) + VARIANT_ADD_TYPE_DECL_POD(Float, TYPE_FLOAT, float, float) + VARIANT_ADD_TYPE_DECL_POD(Double, TYPE_DOUBLE, double, double) + VARIANT_ADD_TYPE_DECL_POD(LongDouble, TYPE_LONGDOUBLE, long double, ldouble) + VARIANT_ADD_TYPE_DECL_PTR(ComplexFloat, TYPE_COMPLEXF, std::complex, complex_f) + VARIANT_ADD_TYPE_DECL_PTR(ComplexDouble, TYPE_COMPLEXD, std::complex, complex_d) + VARIANT_ADD_TYPE_DECL_PTR(String, TYPE_STRING, std::string, string) + VARIANT_ADD_TYPE_DECL_PTR(Vector3f, TYPE_VECTOR3F, Vector3f, vector3f) + VARIANT_ADD_TYPE_DECL_PTR(Vector3d, TYPE_VECTOR3D, Vector3d, vector3d) + VARIANT_ADD_TYPE_DECL_PTR(Vector3c, TYPE_VECTOR3C, Vector3c, vector3c) + VARIANT_ADD_TYPE_DECL_PTR(Vector, TYPE_VECTOR, vector_t, vector) + VARIANT_ADD_ITER_DECL_PTR(Vector, TYPE_VECTOR, vector) + private: - void copy(const Variant &a); + void copy(const Variant& v); void check(const Type t) const; void check(const Type t); }; #define VARIANT_TO_DECL(NAME, VALUE) \ - template<> inline VALUE Variant::to() const { return to ## NAME(); } \ + template<> inline VALUE Variant::to() const { \ + return to##NAME(); \ + } \ +// declare type conversion functions +// not implemented for Vector3 and complex_* VARIANT_TO_DECL(Bool, bool) VARIANT_TO_DECL(Char, char) VARIANT_TO_DECL(UChar, unsigned char) @@ -221,11 +307,28 @@ VARIANT_TO_DECL(UInt32, uint32_t) VARIANT_TO_DECL(Int64, int64_t) VARIANT_TO_DECL(UInt64, uint64_t) VARIANT_TO_DECL(Float, float) -VARIANT_TO_DECL(String, std::string) VARIANT_TO_DECL(Double, double) +VARIANT_TO_DECL(LongDouble, long double) +VARIANT_TO_DECL(String, std::string) +VARIANT_TO_DECL(Vector, Variant::vector_t) std::ostream& operator <<(std::ostream& os, const Variant &v); + +/** + Taken from PXL + https://git.rwth-aachen.de/3pia/pxl/pxl/-/blob/master/core/include/pxl/core/Functions.hh + */ +template +inline void safeDelete(T*& p) { + if (p) { + delete p; + p = 0; + } +} + + + } // namespace crpropa -#endif // VARIANT_HH +#endif // CRPROPA_VARIANT diff --git a/include/crpropa/advectionField/AdvectionField.h b/include/crpropa/advectionField/AdvectionField.h index 9d6a71bc5..2c9a2494a 100644 --- a/include/crpropa/advectionField/AdvectionField.h +++ b/include/crpropa/advectionField/AdvectionField.h @@ -128,6 +128,110 @@ class SphericalAdvectionField: public AdvectionField { std::string getDescription() const; }; +/** + @class OneDimensionalCartesianShock + @brief Advection field in x-direction with shock at x = 0 and width lShock approximated by tanh() + with variable compression ratio vUp/vDown + */ +class OneDimensionalCartesianShock: public AdvectionField { + double compressionRatio; //compression ratio of shock + double vUp; //upstream velocity + double lShock; //shock width +public: +/** Constructor + @param compressionRatio //compression ratio of shock + @param vUp //upstream velocity + @param lShock //shock width +*/ + OneDimensionalCartesianShock(double compressionRatio, double vUp, double lShock); + Vector3d getField(const Vector3d &position) const; + double getDivergence(const Vector3d &position) const; + + void setComp(double compressionRatio); + void setVup(double vUp); + void setShockwidth(double lShock); + + double getComp() const; + double getVup() const; + double getShockwidth() const; + + std::string getDescription() const; +}; + +/** + @class OneDimensionalSphericalShock + @brief Advection field in x-direction with shock at rShock and width lShock approximated by tanh() + with variable compression ratio ratio vUp/vDown + */ +class OneDimensionalSphericalShock: public AdvectionField { + double compressionRatio; //compression ratio of shock + double vUp; //upstream velocity + double lShock; //shock width + double rShock; //shock radius + bool coolUpstream; //flag for upstream cooling +public: +/** Constructor + @param compressionRatio //compression ratio of shock + @param vUp //upstream velocity + @param lShock //shock width + @param rShock //shock radius + @param coolUpstream //flag for upstream cooling +*/ + OneDimensionalSphericalShock(double rShock, double vUp, double compressionRatio, double lShock, bool coolUpstream); + Vector3d getField(const Vector3d &position) const; + double getDivergence(const Vector3d &position) const; + + void setComp(double compressionRatio); + void setVup(double vUp); + void setShockwidth(double lShock); + void setShockRadius(double rShock); + void setCooling(bool coolUpstream); + + double getComp() const; + double getVup() const; + double getShockwidth() const; + double getShockRadius() const; + bool getCooling() const; + + std::string getDescription() const; +}; + +/** + @class ObliqueAdvectionShock + @brief Advection field in x-y-direction with shock at x = 0 and width x_sh approximated by tanh() + with variable compression ratio r_comp = vx_up/vx_down. The y component vy is not shocked + and remains constant. + */ +class ObliqueAdvectionShock: public AdvectionField { + double compressionRatio; //compression ratio of shock + double vXUp; //upstream velocity x-component + double vY; //constant velocity y-component + double lShock; //shock width + +public: +/** Constructor + @param compressionRatio //compression ratio of shock + @param vXUp //upstream velocity x-component + @param vY //constant velocity y-component + @param lShock //shock width + +*/ + ObliqueAdvectionShock(double compressionRatio, double vXUp, double vY, double lShock); + Vector3d getField(const Vector3d &position) const; + double getDivergence(const Vector3d &position) const; + + void setComp(double compressionRatio); + void setVup(double vXUp); + void setVy(double vY); + void setShockwidth(double lShock); + + double getComp() const; + double getVup() const; + double getVy() const; + double getShockwidth() const; + + std::string getDescription() const; +}; /** @class SphericalAdvectionShock @@ -163,20 +267,20 @@ class SphericalAdvectionShock: public AdvectionField { void setR0(double r); void setV0(double v); void setLambda(double l); - /** - * @param r Normalization radius for rotation speed - */ void setRRot(double r); - /** - * @param vPhi Rotation speed at r_rot - */ void setAzimuthalSpeed(double vPhi); Vector3d getOrigin() const; double getR0() const; double getV0() const; double getLambda() const; + /** + * @param r Normalization radius for rotation speed + */ double getRRot() const; + /** + * @param vPhi Rotation speed at r_rot + */ double getAzimuthalSpeed() const; std::string getDescription() const; diff --git a/include/crpropa/module/CandidateSplitting.h b/include/crpropa/module/CandidateSplitting.h new file mode 100644 index 000000000..514775624 --- /dev/null +++ b/include/crpropa/module/CandidateSplitting.h @@ -0,0 +1,74 @@ +#ifndef CRPROPA_CANDIDATEPLITTING_H +#define CRPROPA_CANDIDATEPLITTING_H + +#include +#include +#include +#include +#include + +#include "crpropa/Vector3.h" +#include "crpropa/Module.h" +#include "crpropa/Units.h" +#include "kiss/logger.h" + + +namespace crpropa { +/** @addtogroup Acceleration +* @{ + */ + +/** +@class CandidateSplitting +@brief Candidates are split into n copies when they gain energy and cross specified energy bins. Weights are set accordingly. + In case of Diffusice Shock Acceleration, splitting number can be adapted to expected spectral index to + compensate for the loss of particles per magnitude in energy +*/ +class CandidateSplitting: public Module { +private: + double nSplit; + double minWeight; + std::vector Ebins; + +public: + + CandidateSplitting(); + + /** Constructor + @param nSplit Number of copies candidates are split + @param Emin Minimal energy for splitting + @param Emax Maximal energy for splitting + @param nBins Number of energy bins + @param minWeight Mimimal Weight + @param log Energy bins in log + */ + CandidateSplitting(int nSplit, double Emin, double Emax, double nBins, double minWeight, bool log = false); + + /** Constructor + @param spectralIndex Expected spectral index determines splitting numbe + @param Emin Minimal energy for splitting + @param nBins Number of bins in energy, with dE(spectralIndex) it determines Emax + */ + CandidateSplitting(double spectralIndex, double Emin, int nBins); + + void process(Candidate *c) const; + + void setEnergyBins(double Emin, double Emax, double nBins, bool log); + + void setEnergyBinsDSA(double Emin, double dE, int n); + + void setNsplit(int n); + + void setMinimalWeight(double w); + + int getNsplit() const; + + double getMinimalWeight() const; + + const std::vector& getEnergyBins() const; + +}; +/** @}*/ + +} // namespace crpropa +#endif // CRPROPA_CANDIDATESPLITTING_H diff --git a/include/crpropa/module/EMCascade.h b/include/crpropa/module/EMCascade.h deleted file mode 100644 index d12c4c9b5..000000000 --- a/include/crpropa/module/EMCascade.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef CRPROPA_EMCASCADE_H -#define CRPROPA_EMCASCADE_H - -#include "crpropa/Module.h" - -namespace crpropa { - -/** - @class EMCascade - @brief Collects and deactivates photons, electrons and positrons. Uses DINT to calculate the EM cascade. - */ -class EMCascade: public Module { -private: - // energy and distance binning - int nE, nD; - double logEmin, logEmax, dlogE, Dmax, dD; - - // histograms (distance,energy) of photons, electrons and positrons - mutable std::vector photonHist; - mutable std::vector electronHist; - mutable std::vector positronHist; - void init(); - -public: - EMCascade(); - - /** Change the distance binning */ - void setDistanceBinning( - double Dmax, //!< maximum distance [m] - int nD //!< number of distance bins - ); - - /** Collect and deactivate photons, electrons and positrons */ - void process(Candidate *candidate) const; - - /** Save the unpropagated histogram of EM particles */ - void save(const std::string &filename); - - /** Load the unpropagated histogram of EM particles */ - void load(const std::string &filename); - - /** Calculates the EM cascade with DINT */ - void runCascade( - const std::string &filename, //!< output filename - int IRBFlag = 4, //!< EBL background 0: high, 1: low, 2: Primack, 4: Stecker'06 - int RadioFlag = 4, //!< radio background 0: high, 1: medium, 2: obs, 3: none, 4: Protheroe'96 - double Bfield = 1E-13, //!< magnetic field strength [T], default = 1 nG - double cutCascade = 0 //!< a-parameter, see CRPropa 2 paper - ); - - std::string getDescription() const; -}; - -} // namespace crpropa - -#endif // CRPROPA_EMCASCADE_H diff --git a/include/crpropa/module/MomentumDiffusion.h b/include/crpropa/module/MomentumDiffusion.h new file mode 100644 index 000000000..026d762f9 --- /dev/null +++ b/include/crpropa/module/MomentumDiffusion.h @@ -0,0 +1,65 @@ +#ifndef CRPROPA_MOMENTUMDIFFUSION_H +#define CRPROPA_MOMENTUMDIFFUSION_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "kiss/logger.h" + +namespace crpropa { + +/** + * \addtogroup EnergyLosses + * @{ + */ + +/** + @class ConstantMomentumDiffusion + * Simplest model for diffusion in momentum space + */ + +class ConstantMomentumDiffusion: public Module { + +private: + double Dpp; // Diffusion coefficient + double limit; // maximal fractional energy loss + +public: + /** Constructor + @param Dpp momentum diffusion coefficient + */ + ConstantMomentumDiffusion(double Dpp); + + /** Constructor + @param Dpp momentum diffusion coefficient + @param limit maximal fractional energy loss + */ + ConstantMomentumDiffusion(double Dpp, double limit); + + void process(Candidate *candidate) const; + double calculateAScalar(double p) const; + double calculateBScalar() const; + + void setLimit(double l); + void setDpp(double Dpp); + + double getLimit() const; + double getDpp() const; + + std::string getDescription() const; + +}; + +/** @}*/ + +}; //end namespace crpropa + +#endif // CRPROPA_MOMENTUMDIFFUSION_H diff --git a/include/crpropa/module/PhotonEleCa.h b/include/crpropa/module/PhotonEleCa.h deleted file mode 100644 index c3238e6fe..000000000 --- a/include/crpropa/module/PhotonEleCa.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef CRPROPA_PHOTONELECA_H -#define CRPROPA_PHOTONELECA_H - -#include "crpropa/Module.h" -#include "crpropa/magneticField/MagneticField.h" -#include "crpropa/Referenced.h" - -#include -#include - -// forward declaration -namespace eleca { -class Propagation; -} - -namespace crpropa { - -class PhotonEleCa: public Module { -private: - std::auto_ptr propagation; - mutable std::ofstream output; - Vector3d observer; - bool saveOnlyPhotonEnergies; -public: - PhotonEleCa(const std::string background, const std::string &outputFilename); - ~PhotonEleCa(); - void process(Candidate *candidate) const; - std::string getDescription() const; - void setObserver(const Vector3d &position); - void setSaveOnlyPhotonEnergies(bool photonsOnly); -}; - -} // namespace crpropa - -#endif // CRPROPA_PHOTONELECA_H diff --git a/libs/EleCa/CMakeLists.txt b/libs/EleCa/CMakeLists.txt deleted file mode 100644 index db3e4ae68..000000000 --- a/libs/EleCa/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -cmake_minimum_required(VERSION 2.6) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) - -add_library(eleca STATIC - src/Common - src/EnergyLoss - src/Particle - src/Process - src/Propagation -) - -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - SET_TARGET_PROPERTIES(eleca PROPERTIES COMPILE_FLAGS "-fPIC -ffast-math -D__extern_always_inline=inline") -else() - SET_TARGET_PROPERTIES(eleca PROPERTIES COMPILE_FLAGS "-fPIC -ffast-math") -endif() diff --git a/libs/EleCa/include/EleCa/Common.h b/libs/EleCa/include/EleCa/Common.h deleted file mode 100644 index 627f1af2c..000000000 --- a/libs/EleCa/include/EleCa/Common.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef ELECA_COMMON_H_ -#define ELECA_COMMON_H_ - -namespace eleca { - -double z2Mpc(double z); -double Mpc2z(double D); -double Uniform(double min, double max); - -// set the seed for the random generator. If 0, current ime is used -void setSeed(long int seedval=0); - -void setUniformCallback(double (*Uniform)(double min, double max)); - - -// integer pow implementation as template that is evaluated at compile time -template -inline double pow_integer(double base) -{ - return pow_integer<(exponent >> 1)>(base*base) * (((exponent & 1) > 0) ? base : 1); -} - -template <> -inline double pow_integer<0>(double base) -{ - return 1; -} - - -} // namespace eleca - -#endif // ELECA_COMMON_H_ diff --git a/libs/EleCa/include/EleCa/Constants.h b/libs/EleCa/include/EleCa/Constants.h deleted file mode 100644 index 7263e116d..000000000 --- a/libs/EleCa/include/EleCa/Constants.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef ELECA_CONSTANTS_H_ -#define ELECA_CONSTANTS_H_ - -#include - -namespace eleca { - -static const double cPI = M_PI; - -static const int POINTS_VERY_FEW = 100; - -static const double M2MPC = 3.240779e-17 / 1.0e6; -static const double KM2MPC = 3.240779e-20; -static const double S2YR = 3.168808781403e-08; -static const double H0 = 70.4; -static const double H0y = H0 * (double) KM2MPC / S2YR; // H0 per years -static const double OC = 0.227; // Dark matter density -static const double OB = 0.0456; // Baryon density -static const double OM = OB + OC; // Matter density -static const double OL = 0.728; // Dark energy density - -static const double K_CBR = 1.318684673251832e+13; // =1/pi**2/hbarc**3 [eV^-3 cm^-3] -static const double eV2J = 1.602176487e-19; // from eV to J -static const double ElectronMass = 0.510998918e6; // [eV/c^2] -static const double K_boltz = 8.617342294984e-5; // [eV/K ] Boltzman constant -static const double C_speed = 299792458; // [m/s] speed of light -static const double SigmaThompson = 6.6524e-25; // cm**2 - -static const double T_CMB = 2.725; // [K] // evolution 2.725*(1-z) 1012.3164 -static const double T_COB = 5270; // [K] // Visible [380 - 760] nm. Scelgo 550 -static const double T_CIB = 1.45e+02; // [k] Middle IR 5 to (25-40) µm according to Nasa. scelgo 20e-6 m -static const double T_CRB = 3e-03; // [k] ~ cm - 10m. scelgo ~1 m - -static const double CMB_en = K_boltz * T_CMB; //2.348e-4; // [eV] -static const double CRB_en = K_boltz * T_CRB; -static const double COB_en = K_boltz * T_COB; -static const double CIB_en = K_boltz * T_CIB; -static const double CIOB_en = CIB_en + COB_en; // [eV] - -static const double h_Planck = 4.135667e-15; // [eV s]// -static const double hcut_Planck = h_Planck / 2 / cPI; // [eV s] hcut = h/2Pi [Js] -static const double LambdaCompton = hcut_Planck / (ElectronMass / C_speed); - -static const double eps_ph_inf_urb = 4.1e-12; // [eV] -static const double eps_ph_inf_cmb = 0.825e-6; // [eV] -static const double eps_ph_inf_cib = 2e-3; // [eV] -static const double eps_ph_inf_cob = 5e-2; // [eV] -static const double eps_ph_inf_ciob = 2e-3; // [eV] - -static const double eps_ph_sup_urb = eps_ph_inf_cmb; //4e-5; // [eV] -static const double eps_ph_sup_cmb = eps_ph_inf_cob; // [eV] -static const double eps_ph_sup_cob = 9.9; // [eV] -static const double eps_ph_sup_cib = 0.8; // [eV] -static const double eps_ph_sup_ciob = 9.9; // [eV] - -static const double eps_ph_sup_global = eps_ph_sup_cob; // [eV] *global -static const double eps_ph_inf_global = eps_ph_inf_urb; // [eV] *global - - - -} // namespace eleca - -#endif // ELECA_CONSTANTS_H_ diff --git a/libs/EleCa/include/EleCa/EnergyLoss.h b/libs/EleCa/include/EleCa/EnergyLoss.h deleted file mode 100644 index 6cd954bc6..000000000 --- a/libs/EleCa/include/EleCa/EnergyLoss.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef ELECA_ENERGY_LOSS_H_ -#define ELECA_ENERGY_LOSS_H_ - -namespace eleca { - -class Particle; -class Process; - -double dTdZ(double z); -double betaRsh(double z); -double fLossAdiabatic(double E, double z); -double AdiabaticELoss(double z0, double z, double E0); -double MeanRateSynchrotronLoss(double E, double B); -double ESynchrotronAdiabaticLoss(double z, double E, double B); - -void InitRK(); -double EnergyLoss1D(double Energy, double z0, double zfin, double B); -double dSigmadE_ICS(double Ee, double Eer, double s, double theta); -double dSigmadE_PP(double Ee, double E0, double eps, double theta, double s); -double ExtractPPSecondariesEnergy(Particle &pi, Particle &pt); -double ExtractPPSecondariesEnergy(Process &proc); -double ExtractICSSecondariesEnergy(Particle &pi, Particle &pt); -double ExtractICSSecondariesEnergy(Process &proc); -double ExtractTPPSecondariesEnergy(Particle &pi, Particle &pt); -double ExtractTPPSecondariesEnergy(Process &proc); -double ExtractDPPSecondariesEnergy(double E0); - -double __extractICSSecondaries(double Ee, double s, double theta); -} // namespace eleca - -#endif // ELECA_ENERGY_LOSS_H_ diff --git a/libs/EleCa/include/EleCa/Particle.h b/libs/EleCa/include/EleCa/Particle.h deleted file mode 100644 index b7b3ec176..000000000 --- a/libs/EleCa/include/EleCa/Particle.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef ELECA_PARTICLE_H_ -#define ELECA_PARTICLE_H_ - -#include "Constants.h" - -namespace eleca { - -class Particle { -private: - int ftype; - double fE0ph; - double fz0ph; - double fbeta; - double fmass; - bool fIsGood; - int fwi; - int fgeneration; - -public: - Particle(); - Particle(int _ft, double _fE, double _fz, int _fgeneration = 0); - ~ Particle(); - bool IsGood(); - int GetType() const; - - void SetType(int _ft); - - int GetWeigth() const; - - void SetWeigth(int _wi); - - double GetEnergy() const; - - void SetEnergy(double _fE); - - double Getz() const; - - void Setz(double _fz); - - double GetMass() const; - - double GetBeta() const; -// -// bool GetStatus() { -// fIsGood = IsGood(); -// return fIsGood; -// } - - void SetBetaAndMass(); - - int Generation(); - - - -}; - -} // namespace eleca - -#endif // ELECA_PARTICLE_H_ diff --git a/libs/EleCa/include/EleCa/Process.h b/libs/EleCa/include/EleCa/Process.h deleted file mode 100644 index 07f8e047a..000000000 --- a/libs/EleCa/include/EleCa/Process.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef ELECA_PROCESS_H_ -#define ELECA_PROCESS_H_ - -#include "Particle.h" - -#include -#include - -namespace eleca { - -class Process { - -public: - - enum Name - { - NONE, - PP, - DPP, - TPP, - ICS - }; - - double flambda; - double fsmin; - double fsmax; - double fCMEnergy; - double fInteractionAngle; - double feps_inf; - double feps_sup; - Particle fPi; - Particle fPt; - - std::string fback; - double fbackdensity; - - Process(); - Process(const Process&); - Process(Particle&, Particle&); - Process(Particle&, Particle&, Process::Name); - - ~Process(); - - void SetName(Process::Name nm); - const Process::Name &GetName() const; - - void SetInteractionAngle(double a); - double GetInteractionAngle() const; - - void SetLambda(double le); - double GetLambda() const; - - void SetLimits(double smin, double smax); - void SetLimits(Particle& p1, Process::Name nameproc); - void SetLimits(); - - void SetMax(double smax); - void SetMin(double smin); - double GetMin() const; - double GetMax() const; - - void SetCMEnergy(double s); - - void SetCMEnergy(Particle p1, Particle pb); - - void SetCMEnergy(); - double GetCMEnergy() const; - - void SetIncidentParticle(const Particle& p1); - void SetTargetParticle(Particle& p1); - const Particle &GetIncidentParticle() const; - const Particle &GetTargetParticle() const; - - const std::string &GetBackground() const; - void SetBackground(std::string BackRad); - -private: - - Process::Name _name; -}; - -} // namespace - -#endif diff --git a/libs/EleCa/include/EleCa/Propagation.h b/libs/EleCa/include/EleCa/Propagation.h deleted file mode 100644 index b3db0faec..000000000 --- a/libs/EleCa/include/EleCa/Propagation.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef ELECA_PROPAGATION_H -#define ELECA_PROPAGATION_H - -#include "EleCa/Particle.h" -#include "EleCa/Process.h" - -#include -#include - -namespace eleca { - -class Process; -class Propagation { - -private: - - double vPPle[1101]; - double vDPPle[1101]; - double vTPPle[1101]; - double vICSle[1101]; - double vEtab[1101]; - - std::vector BkgE, BkgA; - std::string Bkg; - double fEthr; - double _dEtab; - - double magneticFieldStrength; -public: - - Propagation(); - - void SetEthr(double eth) {fEthr = eth;}; - double GetEthr(); - ~Propagation(); - - void WriteOutput(std::ostream &out, Particle &p1, - std::vector &part) const; - - void ReadTables(const std::string &file); - void InitBkgArray(const std::string &BackRad); - - double GetMeanThetaBFDeflection(double Bin, double Ein, int ptype, - double Lin) const; - double GetLambdaTab(const Process &proc, Process::Name procName) const; - double ExtractMinDist(Process &proc, int type, double R, double R2, - std::vector &Etarget) const; - std::vector GetEtarget(Process &proc, - const Particle &particle) const; - void Propagate(Particle &curr_particle, - std::vector &ParticleAtMatrix, - std::vector &ParticleAtGround, - bool dropParticlesBelowEnergyThreshold = true) const; - double ExtractPhotonEnergyMC(double z, Process &proc) const; - double ShootPhotonEnergyMC(double z) const; - double ShootPhotonEnergyMC(double Emin, double z) const; - void SetInitVar(std::vector > bk, - std::vector > *le) const; - - void SetB(double B) - { - magneticFieldStrength = B; - } -}; - -} // namespace eleca - -#endif // ELECA_PROPAGATION_H diff --git a/libs/EleCa/src/Common.cpp b/libs/EleCa/src/Common.cpp deleted file mode 100644 index 32a1af8c5..000000000 --- a/libs/EleCa/src/Common.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "EleCa/Common.h" -#include "EleCa/Constants.h" - -#include -#include -#include -#include - -#include - -namespace eleca { - -double z2Mpc(double z) { - if (z < 0.4) { - return ((double) C_speed / 1000. / H0) * z; - } else { - // AV Uryson, Physics Particles and Nuclei, 2006, Vol. 37, No. 3, pp. 347 67 - // Assuming flat-matter-dominated cosmology. Error is negligible - return ((double) C_speed / 1000. / H0) * (2. / 3.) - * (1 - pow(1. + z, -1.5)); - } -} - -double Mpc2z(double D) { - if (D < 1700.) { - return (double) D / ((double) C_speed / 1000. / H0); - } else { - // AV Uryson, Physics Particles and Nuclei, 2006, Vol. 37, No. 3, pp. 347 67 - // Assuming flat-matter-dominated cosmology. Error is negligible - return pow(1 - (double) D / ((2. / 3.) * (double) C_speed / 1000. / H0), - -2. / 3.) - 1; - } -} - - -void setSeed(long int seedval) -{ - if (seedval == 0) - { // use system time - time(&seedval); - } - ::srand48(seedval); -} - - -double Uniform(double min, double max) { - return min + (max - min) * ::drand48(); -} - -} // namespace eleca - diff --git a/libs/EleCa/src/EnergyLoss.cpp b/libs/EleCa/src/EnergyLoss.cpp deleted file mode 100644 index c226d06f8..000000000 --- a/libs/EleCa/src/EnergyLoss.cpp +++ /dev/null @@ -1,612 +0,0 @@ -#ifndef ELECA_ENERGY_LOSS_H_ -#define ELECA_ENERGY_LOSS_H_ - -#include "EleCa/EnergyLoss.h" -#include "EleCa/Process.h" -#include "EleCa/Common.h" - -#include -#include -#include -#include - -namespace eleca { - -static const int MC_SAMPLING = 1000; - -double dTdZ(double z) { - // See High Energy Cosmic Rays, Todor Stanev, Pag. 232 (2009) - return -1. - / ((1 + z) * H0y - * sqrt( - pow_integer<3>(1. + z) * OM + OL - + (1 - OM - OL) * pow_integer<2>(1. + z))); -} - -double betaRsh(double z) { - // Energy loss term due to cosmological redshift - return H0y - * sqrt(pow_integer<3>(1. + z) * OM + OL + (1 - OM - OL) * pow_integer<2>(1. + z)); -} - -double fLossAdiabatic(double E, double z) { - return -dTdZ(z) * betaRsh(z) * E; -} - -double AdiabaticELoss(double z0, double z, double E0) { - return E0 * (double) (1. + z) / (1. + z0); -} - -// ################################################## -// # Synchrotron rate of Energy loss averaged over angles -// ################################################## -// for an ensemble of electrons that are scattered randomly in all directions: -double MeanRateSynchrotronLoss(double E, double B) { - double dEdt = 0; - if (B > 0) - dEdt = 3.79e-6 * pow_integer<2>(E / 1e9 * B) * 1e9 / E; - - return dEdt; -} - -// #################################### -// # Synchrotron Energy loss -// #################################### - -double ESynchrotronAdiabaticLoss(double z, double E, double B) { - double dEdt = MeanRateSynchrotronLoss(E, B); - - return E * (-dTdZ(z) * (dEdt + betaRsh(z))); -} - -static const int RK_ORDER = 6; -static double gRKa[RK_ORDER + 1]; -static double gRKc[RK_ORDER + 1]; -static double gRKcs[RK_ORDER + 1]; -static double gRKb[RK_ORDER + 1][RK_ORDER]; -static bool gRKInitialized = false; - -void InitRK() { - if (gRKInitialized) - return; - - // Current Runge-Kutta method for solving ODE - gRKa[0] = 0; - gRKa[1] = 0; - gRKa[2] = 1. / 5.; - gRKa[3] = 3. / 10.; - gRKa[4] = 3. / 5.; - gRKa[5] = 1.; - gRKa[6] = 7. / 8.; - - for (int i = 0; i < RK_ORDER + 1; i++) { - for (int j = 0; j < RK_ORDER; j++) - { - gRKb[i][j] = 0.; - } - } - - gRKb[2][1] = 1. / 5.; - gRKb[3][1] = 3. / 40.; - gRKb[3][2] = 9. / 40.; - gRKb[4][1] = 3. / 10.; - gRKb[4][2] = -9. / 10.; - gRKb[4][3] = 6. / 5.; - gRKb[5][1] = -11. / 54.; - gRKb[5][2] = 5. / 2.; - gRKb[5][3] = -70. / 27.; - gRKb[5][4] = 35. / 27.; - gRKb[6][1] = 1631. / 55296.; - gRKb[6][2] = 175. / 512.; - gRKb[6][3] = 575. / 13824.; - gRKb[6][4] = 44275. / 110592.; - gRKb[6][5] = 253. / 4096.; - - gRKc[0] = 0.; - gRKc[1] = 37. / 378.; - gRKc[2] = 0.; - gRKc[3] = 250. / 621.; - gRKc[4] = 125. / 594.; - gRKc[5] = 0.; - gRKc[6] = 512. / 1771.; - - gRKcs[0] = 0.; - gRKcs[1] = 2825. / 27648.; - gRKcs[2] = 0.; - gRKcs[3] = 18575. / 48384.; - gRKcs[4] = 13525. / 55296.; - gRKcs[5] = 277. / 14336.; - gRKcs[6] = 1. / 4.; - - gRKInitialized = true; -} - -//=================================== - -double EnergyLoss1D(double Energy, double z0, double zfin, double B) { - - double zStep = 2.5e-5; - -#pragma omp critical - { - InitRK(); - } - double k1, k2, k3, k4, k5, k6; - - bool FLAG_PROPAG = 1; - - while (z0 > zfin && FLAG_PROPAG) { - - k1 = -zStep * ESynchrotronAdiabaticLoss(z0 - zStep, Energy, B); - k2 = -zStep - * ESynchrotronAdiabaticLoss(z0 - zStep * gRKa[2], - Energy + k1 * gRKb[2][1], B); - - k3 = -zStep - * ESynchrotronAdiabaticLoss(z0 - zStep * gRKa[3], - Energy + k1 * gRKb[3][1] + k2 * gRKb[3][2], B); - k4 = -zStep - * ESynchrotronAdiabaticLoss(z0 - zStep * gRKa[4], - Energy + k1 * gRKb[4][1] + k2 * gRKb[4][2] - + k3 * gRKb[4][3], B); - k5 = -zStep - * ESynchrotronAdiabaticLoss(z0 - zStep * gRKa[5], - Energy + k1 * gRKb[5][1] + k2 * gRKb[5][2] - + k3 * gRKb[5][3] + k4 * gRKb[5][4], B); - k6 = -zStep - * ESynchrotronAdiabaticLoss(z0 - zStep * gRKa[6], - Energy + k1 * gRKb[6][2] + k2 * gRKb[6][2] - + k3 * gRKb[6][3] + k4 * gRKb[6][4] - + k5 * gRKb[6][5], B); - - Energy = Energy - + (k1 * gRKc[1] + k2 * gRKc[2] + k3 * gRKc[3] + k4 * gRKc[4] - + k5 * gRKc[5] + k6 * gRKc[6]); - - z0 -= zStep; - - if (fabs(z0) < 1e-8 || z0 < 0) { - z0 = 0.; - FLAG_PROPAG = 0; - } - if (fabs(z0 - zfin) < 1e-8 || z0 < zfin) - z0 = zfin; - - if (Energy < 1e9) { - FLAG_PROPAG = 0; - } - - if (std::isnan(Energy)) - return 0; - } - - return Energy; -} - -double dSigmadE_ICS(double Ee, double Eer, double s, double theta) { - /*! - Differential cross-section for inverse Compton scattering. from lee, eq. 23 - */ - - double beta = (s - ElectronMass * ElectronMass) - / (s + ElectronMass * ElectronMass); - // boundaries rewritten to avoid error due to numerical uncertainties - if ((1 - Eer / Ee) / (Eer / Ee +1) - beta > DBL_EPSILON || Eer / Ee > 1) - { - std::cerr << "ERROR, Energy outside limits for ICS [Lee96]! " << std::endl; - std::cerr << " Eer = " << Eer << " Ee = " << Ee << " Eer/Ee = " << - Eer / Ee << " (1 - beta) / (1 + beta) = " << (1 - beta) / (1 + beta) << - " beta = " << beta << std::endl; - return 0.; - } - else - { - double q = ((1 - beta) / beta) * (1 - Ee / Eer); - double A = Eer / Ee + Ee / Eer; - double k = (3.0 / 8.0) * (SigmaThompson * ElectronMass * ElectronMass) - / (s * Ee); - double dsigmadE = k * ((1 + beta) / beta) * (A + 2 * q + q * q); - - return dsigmadE; - } -} - - double dSigmadE_PP(double Ee, double E0, double eps, double theta, double s) { - /*! - Differential cross-section for pair production. - */ - // double s = ElectronMass * ElectronMass + 2 * eps * E0 * (1 - cos(theta)); - double beta = sqrt(1 - 4 * ElectronMass * ElectronMass / s); - - if (Ee / E0 <= 0.5 * (1 - beta) || Ee / E0 >= 0.5 * (1 + beta)) { - std::cerr << "ERROR, Energy outside limits for PP [Lee96]! " - << std::endl; - return 0.; - } else { - double q = E0 - Ee; - double k = (3.0 / 4.0) * (SigmaThompson * ElectronMass * ElectronMass) - / (s * E0); - double A = Ee / q + q / Ee; - double B = E0 * (1 - beta * beta) * (1. / Ee + 1. / q); - double C = -((1 - beta * beta) * (1 - beta * beta) * E0 * E0 / 4.0) - * pow_integer<2>(1. / Ee + 1. / q); - - double dsigmadE = k * (A + B + C); - - return dsigmadE; - } -} - -/// Differential cross-section for pair production for x = E/E0 -double dSigmadE_PPx(double x, double beta) { - - if ((x - 0.5 * (1 - beta)) < -1 * DBL_EPSILON || x - 0.5 * (1 + beta) > DBL_EPSILON ) { - std::cerr << "ERROR, Energy outside limits for PP [Lee96]! " << std::endl; - std::cerr << " x = " << x << " 0.5* (1-beta) = " << 0.5 * (1 - beta) << " 0.5* (1+beta) = " << 0.5 * (1 + beta) << " beta = " << beta << std::endl; - return 0.; - } else { - - const double A = (x / (1. - x) + (1. - x) / x ); - const double B = (1. / x + 1. / (1. - x) ); - - return A + (1. - beta*beta) * B - (1. - beta*beta) * (1. - beta*beta) / 4. * B*B; - } -} - - -/// Hold an data array to interpolate the energy distribution on -class PPSecondariesEnergyDistribution -{ - private: - double *_data; - size_t _Ns; - size_t _Nrer; - double _s_min; - double _s_max; - double _dls; - - public: - PPSecondariesEnergyDistribution(double s_min = 4. * ElectronMass * ElectronMass, double s_max =1e21, - size_t Ns = 1000, size_t Nrer = 1000 ) - { - if (s_min < 4.*ElectronMass*ElectronMass) - { - std::cerr << "Warning: Minimum COM Energy in PP Interpolation s = " << s_min << " < (2*m_e)**2 selected. Setting to s_min = (2*m_e)**2.\n" ; - s_min = 4.*ElectronMass*ElectronMass; - } - _Ns = Ns; - _Nrer = Nrer; - _s_min =s_min; - _s_max = s_max; - _data = new double[Ns*Nrer]; - - _dls = (log(s_max) - log(s_min)) / (Ns); - - for (size_t i = 0; i < Ns; i++) - { - const double s = s_min * exp(i*_dls); - double beta = sqrt(1. - 4. * ElectronMass*ElectronMass /s); - - double x0 = log((1.-beta) / 2.); - double dx = ( log((1. + beta)/2) - log((1.-beta) / 2.)) / (Nrer); - _data[i * Nrer] = exp(x0) ; - for (size_t j = 1; j < Nrer; j++) - { - double x = exp(x0 + j*dx); - _data[i * Nrer + j] = dSigmadE_PPx(x, beta) + _data[i * Nrer + j - 1]; - } - } - } - - // returns pointer to the the integrated distribution for a given s - double* getDistribution(double s) - { - size_t idx = (log(s / _s_min)) / _dls; - double *s0 = &_data[idx * _Nrer]; - return s0; - } - - //samples the integrated distribution and returns Eer(Ee, s) - double sample(double E0, double eps, double theta) - { - double s = 2. * E0 * eps * (1-cos(theta)); - - double *s0 = getDistribution(s); - double rnd = Uniform(0, 1.0) *s0[_Nrer-1]; - - for (size_t i=0; i < _Nrer; i++) - { - if (rnd < s0[i]) - { - double beta = sqrt(1. - 4.* ElectronMass * ElectronMass / s); - - double x0 = log((1.-beta) / 2.); - double dx = ( log((1. + beta)/2) - log((1.-beta) / 2.)) / (_Nrer); - if (Uniform(0, 1.0) < 0.5) - return exp(x0 + (i)*dx) * E0; - else - return E0 * (1-exp(x0 + (i)*dx) ); - } - } - std::cerr << "PPSecondariesEnergyDistribution out of bounds!" << std::endl; - std::cerr << " s0[0] = " << s0[0] << " s0[_Nrer-1] = " << s0[_Nrer-1] << " rnd = " << rnd << std::endl; - throw std::runtime_error("Grave logic error in PPSecondariesEnergyDistribution!"); - } -}; - - - -// Helper function for actual Monte Carlo sampling to avoid code-duplication -double __extractPPSecondariesEnergy(double E0, double eps, double beta) -{ - double theta = M_PI; - - static PPSecondariesEnergyDistribution interpolation; - return interpolation.sample(E0, eps, theta); -} - - -double ExtractPPSecondariesEnergy(Particle &pi, Particle &pt) { - /*! - Input: incident gamma Energy E0, background photon energy eps, - incidence angle theta. - Returns the energy of the produced e+ (e-) - */ - double E0 = pi.GetEnergy(); - double eps = pt.GetEnergy(); - double beta = pi.GetBeta(); - - return __extractPPSecondariesEnergy(E0, eps, beta); -} - - - -double ExtractPPSecondariesEnergy(Process &proc) { - /*! - Input: incident gamma Energy E0, background photon energy eps, - incidence angle theta. - Returns the energy of the produced e+ (e-) - */ - - double E0 = proc.GetIncidentParticle().GetEnergy(); - double s = proc.GetCMEnergy(); - double eps = proc.GetTargetParticle().GetEnergy(); - double theta = M_PI; - s = ElectronMass * ElectronMass + 2 * eps * E0 * (1 - cos(theta)); - double beta = sqrt(1 - 4 * ElectronMass * ElectronMass / s); - // double s2 = ElectronMass * ElectronMass - - return __extractPPSecondariesEnergy(E0, eps, beta); -} - - -/// Hold an data array to interpolate the energy distribution on -class ICSSecondariesEnergyDistribution -{ - private: - double *_data; - size_t _Ns; - size_t _Nrer; - double _s_min; - double _s_max; - double _dls; - - public: - ICSSecondariesEnergyDistribution(double s_min = 1.01 * ElectronMass * ElectronMass /*2.6373E+11*/, double s_max =1e21, - size_t Ns = 1000, size_t Nrer = 1000 ) - { - // ToDo: this boundary is just an estimate - const double l = 1.01; - if (s_min < l * ElectronMass*ElectronMass) - { - std::cerr << "Warning: Minimum COM Energy in ICS Interpolation s = " << s_min << " < " << l << " m_e**2 selected. Setting to s_min = " << l << " m_e**2.\n" ; - s_min = l * ElectronMass*ElectronMass; - } - _Ns = Ns; - _Nrer = Nrer; - _s_min =s_min; - _s_max = s_max; - _data = new double[Ns*Nrer]; - - double theta = M_PI; - - _dls = (log(s_max) - log(s_min)) / (Ns); - double dls_min = log(s_min); - - for (size_t i = 0; i < Ns; i++) - { - const double s = exp(dls_min + i*_dls); - double beta = (s - ElectronMass * ElectronMass) / (s + - ElectronMass * ElectronMass); - - double eer_0 = log((1-beta) / (1+beta)); - double deer = - log((1-beta) / (1+beta)) / (Nrer); - - const double Ee = 1E21; - _data[i * Nrer] = dSigmadE_ICS(Ee, Ee * exp(eer_0), s, theta); - for (size_t j = 1; j < Nrer; j++) - { - - double Eer = Ee * exp(eer_0 + (j)*deer); - _data[i * Nrer + j] = dSigmadE_ICS(Ee, Eer , s, theta) + _data[i * Nrer + j - 1]; - } - } - } - - // returns pointer to the the integrated distribution for a given s - double* getDistribution(double s) - { - size_t idx = (log(s / _s_min)) / _dls; - double *s0 = &_data[idx * _Nrer]; - return s0; - } - - //samples the integrated distribution and returns Eer(Ee, s) - double sample(double Ee, double s) - { - double *s0 = getDistribution(s); - double rnd = Uniform(0, 1.0) *s0[_Nrer-1]; - for (size_t i=0; i < _Nrer; i++) - { - if (rnd < s0[i]) - { - double beta = (s - ElectronMass * ElectronMass) / (s + - ElectronMass * ElectronMass); - double eer_0 = log((1-beta) / (1+beta)); - double deer = - log((1-beta) / (1+beta)) / (_Nrer ); - return exp(eer_0 + (i)*deer) * Ee; - } - } - throw std::runtime_error("Grave logic error in sampling ICSSecondariesEnergyDistribution!"); - } -}; - - -// Helper function for actual Monte Carlo sampling to avoid code-duplication -double __extractICSSecondaries(double Ee, double s, double theta) -{ - - static ICSSecondariesEnergyDistribution interpolation; - return interpolation.sample(Ee, s); - - //double beta = (s - ElectronMass * ElectronMass) - // / (s + ElectronMass * ElectronMass); - //bool failed = 1; - - //// reInitialization to zero.. - //double MC_Sampling_Hist[MC_SAMPLING][3]; - //for (int i = 0; i < MC_SAMPLING; i++) { - // for (int j = 0; j < 3; j++) - // MC_Sampling_Hist[i][j] = 0.; - //} - - //double f = pow((double) (1 + beta) / (1 - beta), (double) 1. / MC_SAMPLING); - //int cnt = 0; - //double NormFactor = 0; - - //for (double Eer = f * ((1 - beta) / (1 + beta)) * Ee; Eer <= Ee; Eer *= f) { - // MC_Sampling_Hist[cnt][0] = Eer; - // MC_Sampling_Hist[cnt][1] = dSigmadE_ICS(Ee, Eer, s, theta); - - // NormFactor += MC_Sampling_Hist[cnt][1]; - // MC_Sampling_Hist[cnt][2] = NormFactor; - - // if (MC_Sampling_Hist[cnt][1] > 0.) { - // cnt++; - // } else { - // break; - // } - //} - - //NormFactor = (double) 1. / (double) NormFactor; - - //for (int i = 0; i < cnt; i++) - // MC_Sampling_Hist[i][2] *= NormFactor; - - //double rnd = 0; - //double Eer = 0; - - //while (failed) { - // rnd = Uniform(0, 1.0); - // Eer = 0; - // for (int i = 0; i < cnt - 1; i++) { - // if (MC_Sampling_Hist[i][2] <= rnd <= MC_Sampling_Hist[i + 1][2]) { - // Eer = MC_Sampling_Hist[i][0]; - // failed = 0; - // break; - // } - // } - //} - //return Eer; -} - - -double ExtractICSSecondariesEnergy(Particle &pi, Particle &pt) { - /*! - Input: incident electron energy Ee, background photon energy eps, - incidence angle theta. - Returns the energy of the recoiled e+ (e-) - */ - if (::abs(pi.GetType()) != 11) { - std::cerr << "something wrong in type ExtractICSEnergy " << std::endl; - return 0.; - } - - double Ee = pi.GetEnergy(); - double eps = pt.GetEnergy(); - double theta = M_PI; - double s = 2 * Ee * eps * (1 - pi.GetBeta() * cos(cPI)) - + pi.GetMass() * pi.GetMass(); - - return __extractICSSecondaries(Ee, s, theta); -} - - -double ExtractICSSecondariesEnergy(Process &proc) { - /*! - Input: incident electron energy Ee, background photon energy eps, - incidence angle theta. - Returns the energy of the recoiled e+ (e-) - */ - double Ee = proc.GetIncidentParticle().GetEnergy(); - double s = proc.GetCMEnergy(); - double theta = proc.GetInteractionAngle(); - return __extractICSSecondaries(Ee, s , theta); -} - - -double ExtractTPPSecondariesEnergy(Particle &pi, Particle &pt) { - /* approximation based on A. Mastichiadis et al., - Astroph. Journ. 300:178-189 (1986), eq. 30. - This approx is valid only for alpha >=100 - where alpha = p0*eps*costheta - E0*eps; - for our purposes, me << E0 --> p0~ E0 --> - alpha = E0*eps*(costheta - 1) >= 100; - */ - - double E0 = pi.GetEnergy(); - double eps = pt.GetEnergy(); - double s = 2 * E0 * eps * (1 - pi.GetBeta() * cos(M_PI)) - + pi.GetMass() * pi.GetMass(); - double Epp = 5.7e-1 * pow(eps / ElectronMass, -0.56) * pow(E0 / ElectronMass, 0.44) * ElectronMass; - double Epp2 = E0 - * (1 - 1.768 * pow(s / ElectronMass / ElectronMass, -3.0 / 4.0)) - / 2.0; - //return the energy of each e+/e- in the pair. - return Epp; -} - - -double ExtractTPPSecondariesEnergy(Process &proc) { - /* approximation based on A. Mastichiadis et al., - Astroph. Journ. 300:178-189 (1986), eq. 30. - This approx is valid only for alpha >=100 - where alpha = p0*eps*costheta - E0*eps; - for our purposes, me << E0 --> p0~ E0 --> - alpha = E0*eps*(costheta - 1) >= 100; - */ - - double E0 = proc.GetIncidentParticle().GetEnergy(); - double eps = proc.GetTargetParticle().GetEnergy(); - double Epp = 5.7e-1 * pow(eps/ElectronMass, -0.56) * pow(E0/ElectronMass, 0.44) * ElectronMass; - double s = proc.GetCMEnergy(); - double Epp2 = E0 - * (1 - 1.768 * pow(s / ElectronMass / ElectronMass, -3.0 / 4.0)) - / 2.0; - return Epp; -} - - -double ExtractDPPSecondariesEnergy(double E0) { - /* - we use the same assumption of lee (i.e., all the energy goes equaly shared between only 1 couple of e+e-. - In DPPpaper has been shown that this approximation is valid within -1.5% - */ - if (E0 == 0) - std::cout << "error in extracting DPP: can not be =0 " << std::endl; - return (double) E0 / 2.0; -} - -} // namespace eleca - -#endif // ELECA_ENERGY_LOSS_H_ diff --git a/libs/EleCa/src/Particle.cpp b/libs/EleCa/src/Particle.cpp deleted file mode 100644 index 4a077c0f2..000000000 --- a/libs/EleCa/src/Particle.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "EleCa/Particle.h" -#include - -namespace eleca { - -Particle::~Particle() { -} - -bool Particle::IsGood() { - double zmax_prop0 = 0.91425; - double zmax_prop1 = -0.101717; - double zmax_prop2 = 0.002855; - double Eloc = log10(fE0ph); - if (fE0ph <=3.0e12) - return 0; //for interaction lengths tab - if (Eloc > 12 && Eloc < 18) - Eloc = 18; - if (fz0ph > zmax_prop0 + zmax_prop1 * Eloc + zmax_prop2 * Eloc * Eloc) - return 0; - return 1; -} - -int Particle::GetType() const { - return ftype; -} - -void Particle::SetType(int _ft) { - ftype = _ft; -} - -int Particle::GetWeigth() const { - return fwi; -} - -void Particle::SetWeigth(int _wi) { - fwi = _wi; -} - -double Particle::GetEnergy() const { - return fE0ph; -} - -void Particle::SetEnergy(double _fE) { - fE0ph = _fE; - SetBetaAndMass(); -} - -double Particle::Getz() const { - return fz0ph; -} - -void Particle::Setz(double _fz) { - fz0ph = _fz; -} - -double Particle::GetMass() const { - return fmass; -} - -double Particle::GetBeta() const { - return fbeta; -} - -void Particle::SetBetaAndMass() { - if (ftype == 22) { - fbeta = 1.0; - fmass = 0; - } - if (abs(ftype) == 11) { - fmass = ElectronMass; - fbeta = (double) sqrt(1 - fmass * fmass / (fE0ph * fE0ph)); - - } -} - -int Particle::Generation() { - return fgeneration; -} - -Particle::Particle(int _ft, double _fE, double _fz, int _fgeneration) { - ftype = _ft; - fE0ph = _fE; - fz0ph = _fz; - SetBetaAndMass(); - fIsGood = IsGood(); - fwi = 1; - fgeneration = _fgeneration; -} - -Particle::Particle() { - ftype = 22; - fE0ph = 0; - fz0ph = 0; - fmass = 0; - fbeta = 0; - fIsGood = 0; - fwi = 1; -} - -} // namespace eleca diff --git a/libs/EleCa/src/Process.cpp b/libs/EleCa/src/Process.cpp deleted file mode 100644 index 8e5138782..000000000 --- a/libs/EleCa/src/Process.cpp +++ /dev/null @@ -1,227 +0,0 @@ -#include "EleCa/Process.h" - -#include -#include -#include - -namespace eleca { - -void Process::SetName(Process::Name nm) { - _name = nm; -} - -const Process::Name &Process::GetName() const { - return _name; -} - -void Process::SetInteractionAngle(double a) { - fInteractionAngle = a; -} -double Process::GetInteractionAngle() const { - return fInteractionAngle; -} - -void Process::SetLambda(double le) { - flambda = le; -} -double Process::GetLambda() const { - return flambda; -} - -void Process::SetLimits(double smin, double smax) { - fsmin = smin; - fsmax = smax; -} - -void Process::SetLimits() { - SetLimits(fPi, _name); -} - -void Process::SetMax(double smax) { - fsmax = smax; -} -void Process::SetMin(double smin) { - fsmin = smin; -} -double Process::GetMin() const { - return fsmin; -} -double Process::GetMax() const { - return fsmax; -} - -void Process::SetCMEnergy(double s) { - fCMEnergy = s; -} - -void Process::SetCMEnergy(Particle p1, Particle pb) { - fCMEnergy = 2 * p1.GetEnergy() * pb.GetEnergy() - * (1 - p1.GetBeta() * cos(fInteractionAngle)) - + p1.GetMass() * p1.GetMass() + pb.GetMass() * pb.GetMass(); -} - -void Process::SetCMEnergy() { - fCMEnergy = 2 * fPi.GetEnergy() * fPt.GetEnergy() - * (1 - fPi.GetBeta() * cos(fInteractionAngle)) - + fPi.GetMass() * fPi.GetMass() + fPt.GetMass() * fPt.GetMass(); - -} - -double Process::GetCMEnergy() const { - return fCMEnergy; -} - -void Process::SetIncidentParticle(const Particle& p1) { - fPi = p1; - SetLimits(); -} -void Process::SetTargetParticle(Particle& p1) { - fPt = p1; - SetLimits(); -} - -const Particle &Process::GetIncidentParticle() const { - return fPi; -} -const Particle &Process::GetTargetParticle() const { - return fPt; -} - -const std::string &Process::GetBackground() const { - return fback; -} - -Process::Process() { - _name = Process::NONE; - SetLimits(0.0, 1.0e23); - flambda = 0; - fCMEnergy = 0; - fInteractionAngle = cPI; - fback = "ALL"; - fbackdensity = 0; - feps_inf = eps_ph_inf_global; - feps_sup = eps_ph_sup_global; -} - -Process::Process(Particle& p1, Particle& p2) { - fPi = p1; - fPt = p2; - if (p1.GetType() == 22) - _name = Process::PP; - else if (abs(p1.GetType()) == 11) { - std::cerr << "NB: by default process set to ICS" << std::endl; - _name = ICS; - } else - _name = Process::NONE; - SetCMEnergy(p1, p2); - flambda = 0; - fInteractionAngle = cPI; - fback = "ALL"; - SetLimits(p1, _name); - fbackdensity = 0; - feps_inf = eps_ph_inf_global; - feps_sup = eps_ph_sup_global; -} - -Process::Process(Particle& p1, Particle& p2, Process::Name name) { - _name = name; - SetCMEnergy(p1, p2); - flambda = 0; - fInteractionAngle = cPI; - fPi = p1; - fPt = p2; - fback = "ALL"; - SetLimits(p1, _name); - fbackdensity = 0; - feps_inf = eps_ph_inf_global; - feps_sup = eps_ph_sup_global; -} - -Process::Process(const Process& proc2) { - _name = proc2.GetName(); - SetLimits(proc2.GetMin(), proc2.GetMax()); - fCMEnergy = proc2.GetCMEnergy(); - fInteractionAngle = proc2.GetInteractionAngle(); - fPi = proc2.GetIncidentParticle(); - fPt = proc2.GetTargetParticle(); - fback = proc2.GetBackground(); - fbackdensity = 0; - feps_inf = eps_ph_inf_global; - feps_sup = eps_ph_sup_global; -} - -Process::~Process() { -} - -//----------- - -void Process::SetBackground(std::string BackRad) { - - fback = BackRad; - - double eps_min = eps_ph_inf_global; - double eps_max = eps_ph_sup_global; - - if (BackRad == "CMB") { - eps_min = eps_ph_inf_cmb; - eps_max = eps_ph_sup_cmb; - } else if (BackRad == "COB") { - eps_min = eps_ph_inf_cob; - eps_max = eps_ph_sup_cob; - } else if (BackRad == "CIB") { - eps_min = eps_ph_inf_cib; - eps_max = eps_ph_sup_cib; - } else if (BackRad == "CIOB") { - eps_min = eps_ph_inf_ciob; - eps_max = eps_ph_sup_ciob; - } else if (BackRad == "URB") { - eps_min = eps_ph_inf_urb; - eps_max = eps_ph_sup_urb; - } - - feps_inf = eps_min; - feps_sup = eps_max; - -#ifdef DEBUG_ELECA - std::cout << "eps range set to " << eps_min << " , " << eps_max - << std::endl; -#endif - -} - -void Process::SetLimits(Particle& p1, Process::Name nameproc) { - if (p1.GetType() != 22 && p1.GetType() != 11 && p1.GetType() != -11) - std::cout << "error in type " << p1.GetType() << " != 11 and !=22 " - << std::endl; - - if (nameproc == Process::PP) { - if (abs(p1.GetType()) != 22) - std::cout << "\nERROR!! wrong particle or process!! " << " PP " - << p1.GetType() << "\n" << std::endl; - fsmin = 2 * ElectronMass * ElectronMass; - fsmax = 4 * p1.GetEnergy() * feps_sup; - } - if (nameproc == Process::DPP) { - if (abs(p1.GetType()) != 22) - std::cout << "\nERROR!! wrong particle or process!! " << " DPP " - << p1.GetType() << "\n" << std::endl; - fsmin = 4 * ElectronMass*ElectronMass; - fsmax = 4 * p1.GetEnergy() * feps_sup; - } - if (nameproc == Process::ICS) { - if (abs(p1.GetType()) != 11) - std::cout << "\nERROR!! wrong particle or process!! " << " ICS " - << p1.GetType() << "\n" << std::endl; - fsmin = 4 * 1e12 * feps_inf + ElectronMass*ElectronMass; //given the min E in lambda - fsmax = 4 * p1.GetEnergy() * feps_inf + p1.GetMass() * p1.GetMass(); - } - if (nameproc == Process::TPP) { - if (abs(p1.GetType()) != 11) - std::cout << "\nERROR!! wrong particle or process!! " << " TPP " - << p1.GetType() << "\n" << std::endl; - fsmin = std::max(4 * 1e12 * feps_inf + ElectronMass*ElectronMass,3 * ElectronMass * ElectronMass); - fsmax = 4 * p1.GetEnergy() * feps_sup + p1.GetMass() * p1.GetMass(); - } -} - -} // namespace diff --git a/libs/EleCa/src/Propagation.cpp b/libs/EleCa/src/Propagation.cpp deleted file mode 100644 index 2359bc068..000000000 --- a/libs/EleCa/src/Propagation.cpp +++ /dev/null @@ -1,646 +0,0 @@ -#include "EleCa/Propagation.h" -#include "EleCa/Particle.h" -#include "EleCa/Process.h" -#include "EleCa/Common.h" -#include "EleCa/EnergyLoss.h" -#include "EleCa/Constants.h" -#include "XLoss_CBR.h" - -#include -#include -#include -#include - -//#define DEBUG_ELECA -namespace eleca { - -Propagation::Propagation() { - fEthr = 1e16; -} - -Propagation::~Propagation() { -} - -void Propagation::ReadTables(const std::string &filename) { - -#ifdef DEBUG_ELECA - std::cout << filename << std::endl; -#endif - - std::ifstream fin(filename.c_str()); - - if (!fin.is_open()) { - std::cerr << "Unable to open lambda_table file: " << filename - << " ! exiting... "; - return; - } - - int k = 0; - double Etab, PPle, ICSle, DPPle, TPPle; - while (fin.good()) { - fin >> Etab >> PPle >> ICSle >> DPPle >> TPPle; - vEtab[k] = Etab; - vPPle[k] = PPle; - vICSle[k] = ICSle; - vDPPle[k] = DPPle; - vTPPle[k] = TPPle; - k++; - } - // store dEtab - _dEtab = log10(vEtab[0] / vEtab[1]); - if (k != 1101) - std::cerr << "Failed to read lambda_table file: " << filename - << "! only " << k << " entries, expected 1101!"; -} - -void Propagation::InitBkgArray(const std::string &BackRad) { - // Routine to build the array of cumulative distribution of - // background photons - - Bkg = BackRad; - BkgE.resize(POINTS_VERY_FEW); - BkgA.resize(POINTS_VERY_FEW); - - if (BackRad == "CMB") { - double de = pow((double) eps_ph_sup_cmb / eps_ph_inf_cmb, - 1. / POINTS_VERY_FEW); - double e = eps_ph_inf_cmb; - for (size_t i = 0; i < POINTS_VERY_FEW; i++) { - BkgE[i] = e; - BkgA[i] = CMBR(e); - e *= de; - } - } - - else if (BackRad == "CIOB") { - double de = pow((double) eps_ph_sup_ciob / eps_ph_inf_ciob, - 1. / POINTS_VERY_FEW); - double e = eps_ph_inf_ciob; - for (size_t i = 0; i < POINTS_VERY_FEW; i++) { - BkgE[i] = e; - BkgA[i] = CIOBR(e); - e *= de; - } - } - - else if (BackRad == "URB") { - double de = pow((double) eps_ph_sup_urb / eps_ph_inf_urb, - 1. / POINTS_VERY_FEW); - double e = eps_ph_inf_urb; - for (size_t i = 0; i < POINTS_VERY_FEW; i++) { - BkgE[i] = e; - BkgA[i] = URB(e); - e *= de; - } - } - - else { - double de = pow((double) eps_ph_sup_global / eps_ph_inf_global, - (double) 1. / POINTS_VERY_FEW); - double e = eps_ph_inf_global; - for (size_t i = 0; i < POINTS_VERY_FEW; i++) { - BkgE[i] = e; - BkgA[i] = CBR(e); - e *= de; - } - } - - // cumulate - for (size_t i = 1; i < POINTS_VERY_FEW; i++) { - BkgA[i] += BkgA[i - 1]; - } - - // normalize - double a = 1.0 / BkgA[POINTS_VERY_FEW - 1]; - for (size_t i = 0; i < POINTS_VERY_FEW; i++) { - BkgA[i] *= a; - } -} - -double Propagation::GetMeanThetaBFDeflection(double Bin, double Ein, int ptype, - double Lin) const { - //from D. Hooper, S. Sarkar, M. Taylor, arXiv: 0608085, 2006 - - if (Bin == 0 || Ein == 0) - return 0; - if (ptype == 22) - return 0; - - double lcoher = 1; - - return 0.8 * (1.0e20 / Ein) * sqrt(Lin / 10 * lcoher) * (Bin / 1.0e-9) - / 180.0 * 3.1415927; -} - -double Propagation::ExtractMinDist(Process &proc, int type, double R, double R2, - std::vector &Etarget) const { - - double min_dist1 = 0; - double min_dist2 = 0; - Process proc1(proc); - Process proc2(proc); - double tmp_lambda1 = 0; - double tmp_lambda2 = 0; - Particle pt; - pt.SetType(0); - pt.Setz(proc.GetIncidentParticle().Getz()); - - if (type == 22) { - if (Etarget[0]) { - proc1.SetName(Process::PP); - pt.SetEnergy(Etarget[0]); - proc1.SetTargetParticle(pt); - proc1.SetCMEnergy(); - - tmp_lambda1 = GetLambdaTab(proc1, Process::PP); - - min_dist1 = -tmp_lambda1 * log(R); - } - if (Etarget[1]) { - pt.SetEnergy(Etarget[1]); - proc2.SetTargetParticle(pt); - proc2.SetCMEnergy(); - tmp_lambda2 = GetLambdaTab(proc2, Process::DPP); - min_dist2 = -tmp_lambda2 * log(R2); - } -#ifdef DEBUG_ELECA - std::cerr << "comparing 2 mindists: " << min_dist1 << "(" - << tmp_lambda1 << ") vs " << min_dist2 << " ( " - << tmp_lambda2 << ") " << std::endl; -#endif - - if (min_dist2 < min_dist1) { - min_dist1 = min_dist2; - proc.SetName(Process::DPP); - pt.SetEnergy(Etarget[1]); - proc.SetTargetParticle(pt); - proc.SetCMEnergy(); - } else { - proc.SetName(Process::PP); - pt.SetEnergy(Etarget[0]); - proc.SetTargetParticle(pt); - proc.SetCMEnergy(); - } - } //end if type 0 - else if (abs(type) == 11) { - - proc1.SetName(Process::ICS); - pt.SetEnergy(Etarget[0]); - proc1.SetTargetParticle(pt); - tmp_lambda1 = GetLambdaTab(proc1, Process::ICS); - min_dist1 = -tmp_lambda1 * log(R); - - proc2.SetName(Process::TPP); - pt.SetEnergy(Etarget[1]); - proc2.SetTargetParticle(pt); - tmp_lambda2 = GetLambdaTab(proc2, Process::TPP); - min_dist2 = -tmp_lambda2 * log(R2); - -#ifdef DEBUG_ELECA - std::cerr << "comparing 2 mindists: " << min_dist1 << "(" - << tmp_lambda1 << ") vs " << min_dist2 << " ( " - << tmp_lambda2 << ") " << std::endl; -#endif - - if (min_dist2 < min_dist1) { - min_dist1 = min_dist2; - proc.SetName(Process::TPP); - pt.SetEnergy(Etarget[1]); - proc.SetTargetParticle(pt); - proc.SetCMEnergy(); - } else { - proc.SetName(Process::ICS); - pt.SetEnergy(Etarget[0]); - proc.SetTargetParticle(pt); - proc.SetCMEnergy(); - } - } //else e+/e- - else - std::cerr << "something wrong in particle type ( " << type - << ". Propagation of photons and e+/e- is the only allowed.)" - << std::endl; - - return min_dist1; -} - -double Propagation::GetLambdaTab(const Process &proc, - const Process::Name procName) const { - - double E1 = proc.GetIncidentParticle().GetEnergy(); - double z = proc.GetIncidentParticle().Getz(); - double res = 0; - - double E0taborg = vEtab[0]; - - //double dEtab = log10(vEtab[0] / vEtab[1]); - double evolution = GetEvolution(proc.GetTargetParticle().GetEnergy(), z); - int i = (int) (log10(E0taborg / (E1 * (1 + z))) / _dEtab); - - if (i < 0) { - std::cout << "WARNING!! GetLambdaTab in " << procName << " : i= " << i - << " <0! E1*(1+z) = " << E1 << "* (1 + " << z << ") < " - << E0taborg << ".. returning lambda[0];" << std::endl; - } - - else if (i >= 1001) { - std::cout << "WARNING!! GetLambdaTab in " << procName << " : i>= " - << 1001 << " ! E1*(1+z) = " << E1 << "* (1 + " << z - << ") .. returning lambda[nentries];" << std::endl; - - } else { - if (procName == Process::PP) - res = vPPle[i]; - else if (procName == Process::DPP) - res = vDPPle[i]; - else if (procName == Process::ICS) - res = vICSle[i]; - else if (procName == Process::TPP) - res = vTPPle[i]; - } - - if (evolution != 0) { - if (res / evolution < 0) - std::cerr - << "ERROR UNPHYSICAL SOLUTION!! CHECK HERE LAMBDA OR EVOLUTION!!" - << std::endl; - return res / evolution; - } - std::cerr << "warning!! evolution ==0 " << std::endl; - return 0; -} - -double Propagation::ShootPhotonEnergyMC(double z) const { - // Routine for the MC sampling of background photon energy - - double h = Uniform(0, 1); - for (int i = 0; i < POINTS_VERY_FEW; i++) { - if (h < BkgA[i]) { - return BkgE[i] * (1. + z); - break; - } - } -#ifdef DEBUG_ELECA - std::cout << "ShootPhotonEnergyMC. z = " << z << " h: " << h << " => 0" - << std::endl; -#endif - - return 0.; -} - -double Propagation::ShootPhotonEnergyMC(double Emin, double z) const { - // Routine for the MC sampling of background photon energy - std::vector::const_iterator it; - - // find lowest energy bin - if (Emin == 0) return 0; - it = std::lower_bound(BkgE.begin(), BkgE.end(), Emin); - - size_t iE; - if (it == BkgE.begin()) - iE = 0; - else if (it == BkgE.end()) - iE = BkgE.size() - 1; - else - iE = it - BkgE.begin(); - - // random number in selected range - double h = Uniform(BkgA[iE], 1); - it = std::upper_bound(BkgA.begin(), BkgA.end(), h); - - if (it == BkgA.begin()) - return BkgE.front(); - else if (it == BkgA.end()) - return BkgE.back(); - else - return BkgE[it - BkgA.begin()]; - -} - -std::vector Propagation::GetEtarget(Process &proc, - const Particle &particle) const { - - std::vector Etarget; - double Etarget_tmp = 0; - double smintmp = 0; - double z_curr = particle.Getz(); - double Energy = particle.GetEnergy(); - int pType = particle.GetType(); - double Eexp = smintmp/(4.0 * Energy); - - if (pType == 22) { - proc.SetName(Process::PP); - proc.SetLimits(); - smintmp = proc.GetMin(); - Eexp = std::max(proc.feps_inf,ElectronMass*ElectronMass/Energy); - if (Eexp > proc.feps_sup) { -// std::cout << proc.GetName() << " " << Eexp << " too big wrt " << proc.feps_sup << " , " << proc.feps_inf << " .. it should not interact!" << std::endl; - Eexp = 0; - Etarget.push_back(0);} - else - Etarget_tmp = ShootPhotonEnergyMC(Eexp, z_curr); - Etarget.push_back(Etarget_tmp); - - proc.SetName(Process::DPP); - proc.SetLimits(); - smintmp = proc.GetMin(); - Eexp = std::max(proc.feps_inf,2*ElectronMass*ElectronMass/Energy); - if (Eexp > proc.feps_sup) { -// std::cout << proc.GetName() << " " << Eexp << " too big wrt " << proc.feps_sup << " , " << proc.feps_inf << " .. it should not interact!" << std::endl; - Eexp = 0; - Etarget.push_back(0);} - else - Etarget_tmp = ShootPhotonEnergyMC(Eexp, z_curr); - Etarget.push_back(Etarget_tmp); - } - - else if (abs(pType) == 11) { - proc.SetName(Process::ICS); - proc.SetLimits(); - smintmp = proc.GetMin(); - Eexp = proc.feps_inf; - Etarget_tmp = ShootPhotonEnergyMC(Eexp, z_curr); - - Etarget.push_back(Etarget_tmp); - - proc.SetName(Process::TPP); - proc.SetLimits(); - smintmp = proc.GetMin(); - Eexp = std::max(proc.feps_inf,2*ElectronMass*ElectronMass/Energy); - if (Eexp > proc.feps_sup) { -// std::cout << proc.GetName() << " " << Eexp << " too big wrt " << proc.feps_sup << " , " << proc.feps_inf << " .. it should not interact!" << std::endl; - Eexp = 0; - Etarget.push_back(0);} - else - Etarget_tmp = ShootPhotonEnergyMC(Eexp, z_curr); - - Etarget.push_back(Etarget_tmp); - } //end e/e - else - std::cerr << "something wrong in particle type ( " << pType - << ". Propagation of photons and e+/e- is the only allowed.)" - << std::endl; - - if (Etarget.size() != 2) { - std::cout << "something wrong with the Etarget!! " << std::endl; - exit(0); - } - - return Etarget; -} - -double Propagation::ExtractPhotonEnergyMC(double z, Process &proc) const { - double esoft = 0; -//double snew = 0; - double emin = proc.GetMin(); - Particle pi = proc.GetIncidentParticle(); - Particle pb = proc.GetTargetParticle(); - - double Epi = pi.GetEnergy(); - double m = pi.GetMass(); - esoft = ShootPhotonEnergyMC(emin / (4.0 * Epi), z); - //snew = 4 * Epi * esoft + m * m; - pb.SetEnergy(esoft); - proc.SetTargetParticle(pb); - proc.SetCMEnergy(); - return esoft; -} - -void Propagation::WriteOutput(std::ostream &out, Particle &p1, - std::vector &ParticleAtGround) const { - double Bfield = 0; - size_t NsecG = ParticleAtGround.size(); - - out << fEthr << " " << Bfield / 1e-9 << " " << p1.GetEnergy() << " " - << p1.Getz() << " " << NsecG; - for (int i = 0; i < NsecG; ++i) { - Particle &p = ParticleAtGround[i]; - out << " " << p.GetWeigth() << " " << p.GetEnergy() << " " - << p.GetType(); - } - out << std::endl; -} -// -//void Propagation::Spectrum(std::vector &spectrum) const { -// double emin = 7.0; -// double dE = (24.0 - 7.0) / 170.0; -// size_t ipos = 0; -// size_t NsecG = ParticleAtGround.size(); -// -// for (int h = 0; h < NsecG; ++h) { -// ipos = (int) ((log10(EGround.at(h)) - emin) / dE); -// if (typeGround.at(h) == 22) -// fdN[ipos] += wGround.at(h); -// } -//} -// -//void Propagation::AddSpectrum(std::vector &spectrum) const { -// double emin = 7.0; -// double dE = (24.0 - 7.0) / 170.0; -// size_t ipos = 0; -// size_t NsecG = ParticleAtGround.size(); -// -// for (int h = 0; h < NsecG; ++h) { -// ipos = (int) ((log10(EGround.at(h)) - emin) / dE); -// if (typeGround.at(h) == 22) -// fdN[ipos] += wGround.at(h); -// } -//} - -void Propagation::Propagate(Particle &curr_particle, - std::vector &ParticleAtMatrix, - std::vector &ParticleAtGround, - bool dropParticlesBelowEnergyThreshold - ) const { - - double theta_deflBF = 0.0; - double BNorm = magneticFieldStrength; - - double zin = curr_particle.Getz(); - double Ein = curr_particle.GetEnergy(); - int type = curr_particle.GetType(); - - int wi_last = curr_particle.GetWeigth(); - - double z_curr = zin; - double Ecurr = Ein; - - bool interacted = 0; - double min_dist = 1e12; - double walkdone = 0; - - double E1 = 0; - double E2 = 0; - double E3 = 0; - - double stepsize = 0; - double Elast = 0; - - double R = Uniform(0.0, 1.0); - double R2 = Uniform(0.0, 1.0); - - Process proc; - proc.SetIncidentParticle(curr_particle); - proc.SetBackground(Bkg); - - double Ethr2 = std::max(fEthr, std::max(ElectronMass,ElectronMass*ElectronMass/proc.feps_sup)); - if (Ecurr < Ethr2) - { - if (!dropParticlesBelowEnergyThreshold) - ParticleAtGround.push_back(curr_particle); - - return; - } - - - std::vector EtargetAll = GetEtarget(proc, curr_particle); - - min_dist = ExtractMinDist(proc, curr_particle.GetType(), R, R2, EtargetAll); - - interacted = 0; - double dz = 0; - double zpos = zin; - - double corrB_factor = 0; - double realpath = 0; - - double min_dist_last = min_dist; - - while (!interacted) { - - proc.SetInteractionAngle(cPI); - theta_deflBF = 0; - realpath = 0.1 * min_dist; - - theta_deflBF = GetMeanThetaBFDeflection(BNorm, - curr_particle.GetEnergy(), curr_particle.GetType(), min_dist); - corrB_factor = cos(theta_deflBF); - - stepsize = realpath * corrB_factor; - dz = Mpc2z(stepsize); - - - if (zpos - dz <= 0) { - dz = zpos; - stepsize = z2Mpc(dz); - realpath = stepsize / corrB_factor; - } - - zpos -= dz; - walkdone += realpath; - Elast = Ecurr; - - if (type == 0 || type == 22) - Ecurr = EnergyLoss1D(Ecurr, zpos + Mpc2z(realpath), zpos, 0); - else - Ecurr = EnergyLoss1D(Ecurr, zpos + Mpc2z(realpath), zpos, BNorm); - - z_curr = zpos; - - curr_particle.Setz(z_curr); - curr_particle.SetEnergy(Ecurr); - - proc.SetIncidentParticle(curr_particle); - proc.SetCMEnergy(); - proc.SetLimits(); - // std::vector EtargetAll=GetEtarget(proc,curr_particle); - min_dist = ExtractMinDist(proc, curr_particle.GetType(), R, R2, - EtargetAll); - - if (Ecurr <= Ethr2) - { - if (!dropParticlesBelowEnergyThreshold) - { - ParticleAtGround.push_back(curr_particle); - } - return; - } - if (walkdone > min_dist) { - interacted = 1; - break; - } - - if (z_curr <= 0) - { - ParticleAtGround.push_back(curr_particle); - return; - } - - } //end while - - if (interacted == 1) { - if (proc.GetName() == Process::PP) { - - E1 = ExtractPPSecondariesEnergy(proc); - - if (E1 == 0 || E1 == Ecurr) - std::cerr << "ERROR in PP process: E : " << Ecurr << " " << E1 - << " " << std::endl; - - Particle pp(11, E1, z_curr,curr_particle.Generation()+1); - pp.SetWeigth(wi_last); - ParticleAtMatrix.push_back(pp); - - Particle pe(-11, Ecurr - E1, z_curr,curr_particle.Generation()+1); - pe.SetWeigth(wi_last); - ParticleAtMatrix.push_back(pe); - return; - } //if PP - else if (proc.GetName() == Process::DPP) { - E1 = (Ecurr - 2 * ElectronMass) / 2.0; - if (E1 == 0) - std::cerr << "ERROR in DPP process E : " << E1 << std::endl; - - Particle pp(11, E1, z_curr,curr_particle.Generation()+1); - pp.SetWeigth(wi_last); - ParticleAtMatrix.push_back(pp); - - Particle pe(-11, E1, z_curr,curr_particle.Generation()+1); - pe.SetWeigth(wi_last); - ParticleAtMatrix.push_back(pe); - - return; - } //end if DPP - else if (proc.GetName() == Process::ICS) { - - E1 = ExtractICSSecondariesEnergy(proc); - E2 = Ecurr - E1; - if (E1 == 0 || E2 == 0) - std::cerr << "ERROR in ICS process E : " << E1 << " " << E2 - << std::endl; - - Particle pp(curr_particle.GetType(), E1, z_curr,curr_particle.Generation()+1); - pp.SetWeigth(wi_last); - ParticleAtMatrix.push_back(pp); - Particle pg(22, E2, z_curr,curr_particle.Generation()+1); - pg.SetWeigth(wi_last); - ParticleAtMatrix.push_back(pg); - - return; - } //end if ics - else if (proc.GetName() == Process::TPP) { - E1 = E2 = ExtractTPPSecondariesEnergy(proc); - E3 = Ecurr - E1 - E2; - if (E1 == 0 || E2 == 0 || E3 == 0) - std::cerr << "ERROR in TPP process E : " << E1 << " " << E2 - << std::endl; - - Particle pp(11, E1, z_curr,curr_particle.Generation()+1); - pp.SetWeigth(wi_last); - ParticleAtMatrix.push_back(pp); - - Particle pe(-11, E1, z_curr,curr_particle.Generation()+1); - pe.SetWeigth(wi_last); - ParticleAtMatrix.push_back(pe); - - Particle psc(curr_particle.GetType(), E3, z_curr,curr_particle.Generation()+1); - psc.SetWeigth(wi_last); - ParticleAtMatrix.push_back(psc); - return; - } - } - - return; - -} - -} // namespace eleca diff --git a/libs/EleCa/src/XLoss_CBR.h b/libs/EleCa/src/XLoss_CBR.h deleted file mode 100644 index c89c94e6b..000000000 --- a/libs/EleCa/src/XLoss_CBR.h +++ /dev/null @@ -1,317 +0,0 @@ -#ifndef ELECA_XLOSS_CBR_H -#define ELECA_XLOSS_CBR_H - -#include - -namespace eleca { -/*===================================================================== - - License - ======= - - This file is part of xHERMES () and EleCa packages for - multi messenger data analysis. - - (C) Copyright 2009, 2010, 2011 Manlio De Domenico and Mariangela Settimo - - Author: Manlio De Domenico - Lab. for Complex Systems, Scuola Superiore di Catania - Universita' degli Studi di Catania, Italy - Mail: manlio.dedomenico@ct.infn.it - - (C) Copyright 2011, 2012 Mariangela Settimo - Author: Mariangela Settimo - Universaat Siegen, Germany, now at LPNHE Paris - Mail: mariangela.settimo@gmail.com - - =====================================================================*/ - -//########################################################################## -//# Cosmic Background Radiations -//########################################################################## -double CIB_Evolution_Baseline(double z) { - // Function for the CIB baseline evolution. - // Stecker, Malkan, Scully (2006) arXiv:astro-ph/0510449v4 - - double tmp = 0; - double m = 3.1; - double z_flat = 1.3; - - if (z <= z_flat) - tmp = pow(1. + z, m); - if (z_flat < z && z < 6) - tmp = pow(1. + z_flat, m); - if (z > 6) - tmp = 0; - - return tmp; -} - -double CIB_Evolution_Fast(double z) { - // Function for the CIB fast evolution. - // Stecker, Malkan, Scully (2006) arXiv:astro-ph/0510449v4 - - double tmp = 0; - double m = 4.; - double z_flat = 1.; - - if (z <= z_flat) - tmp = pow(1. + z, m); - if (z_flat < z && z < 6) - tmp = pow(1. + z_flat, m); - if (z > 6) - tmp = 0; - - return tmp; -} - -double CMB_Evolution(double z) { - return pow_integer<3>(1. + z); -} - -double CIB_Evolution(double z) { - return CIB_Evolution_Fast(z); -} - -double CIOB_Evolution(double z) { - return CIB_Evolution_Fast(z); -} - -double COB_Evolution(double z) { - return pow_integer<3>(1. + z); -} - -double URB_Evolution(double z) { - //from Protheroe - Bierman astro-ph:9605119 - if (z < 0.8) - return pow_integer<4>(1. + z); - return pow_integer<4>(1 + 0.8); // z>= z0 -} - -double CMBR(double eps) { - double tmp = 0; - - if (eps > eps_ph_inf_cmb && eps < eps_ph_sup_cmb) { - tmp = (K_CBR * eps * eps) / (exp((double) eps / (K_boltz * T_CMB)) - 1); - } else { - tmp = 0; - } - - if (std::isnan(tmp)) - tmp = 0; - - return tmp; -} - -double CIBR(double eps) { - double tmp = 0; - - if (eps > eps_ph_inf_cib && eps <= eps_ph_sup_cib) { - tmp = 5e-1 - * ((2.2e-6 * K_CBR * eps * eps) - / (exp((double) eps / (K_boltz * T_CMB) / 9.17) - 1) - + (2.e-11 * K_CBR * eps * eps) - / (exp( - (double) eps / (K_boltz * T_CMB) - / 128.44) - 1)); - } else { - tmp = 0; - } - - if (std::isnan(tmp)) - tmp = 0; - - return tmp; -} - -double CIOBR(double eps) { - // parametrization for infrared/optical by - // Hopkins, A. M. & Beacom, J. F. 2006, ApJ, 651, 142 - // See Model D Finke et al, arXiv:0905.1115v2 - - double tmp = 0; - - if (eps > eps_ph_inf_ciob && eps < eps_ph_sup_ciob) { - double x = log(eps); - tmp = -5.32524895349885 - 0.0741140642891119 * x - - 0.252586527659431 * pow_integer<2>(x) - + 0.234971297531891 * pow_integer<3>(x) - - 0.217014471117521 * pow_integer<4>(x) - - 0.364936722063572 * pow_integer<5>(x) - + 0.0880702191711222 * pow_integer<6>(x) - + 0.221947767409286 * pow_integer<7>(x) - + 0.0445499623085708 * pow_integer<8>(x) - - 0.0517435600939147 * pow_integer<9>(x) - - 0.0295646851279071 * pow_integer<10>(x) - - 0.00011943632049331 * pow_integer<11>(x) - + 0.00461621589174355 * pow_integer<12>(x) - + 0.00150906100702171 * pow_integer<13>(x) - + 1.91459088023263e-05 * pow_integer<14>(x) - - 0.000110272619218937 * pow_integer<15>(x) - - 3.45221358079085e-05 * pow_integer<16>(x) - - 5.42000122025042e-06 * pow_integer<17>(x) - - 4.90862622314226e-07 * pow_integer<18>(x) - - 2.45145316799091e-08 * pow_integer<19>(x) - - 5.25792204884819e-10 * pow_integer<20>(x); - tmp = 0.4 * (double) exp(tmp) / eps / eps; - } else { - tmp = 0; - } - - if (std::isnan(tmp)) - tmp = 0; - - return tmp; -} - -double COBR(double eps) { - double tmp = 0; - - if (eps > eps_ph_inf_cob && eps < eps_ph_sup_cob) { - tmp = 1.2e-15 * (K_CBR * eps * eps) - / (exp((double) eps / (K_boltz * T_COB)) - 1); - } else { - tmp = 0; - } - - if (std::isnan(tmp)) - tmp = 0; - - return tmp; -} - -// Universal Radio Background from Protheroe, Bierman 1996. - -double URB(double eps) { - //if (eps < eps_ph_inf_urb || eps > eps_ph_sup_urb) - if (eps < eps_ph_inf_urb) - return 0; - - double v = eps / h_Planck; - double x = log10(v / 1e9); - - double p0 = -2.23791e+01; - double p1 = -2.59696e-01; - double p2 = 3.51067e-01; - double p3 = -6.80104e-02; - double p4 = 5.82003e-01; - double p5 = -2.00075e+00; - double p6 = -1.35259e+00; - double p7 = -7.12112e-01; //xbreak - - double intensity = 0; - if (x > p7) - intensity = p0 + p1 * x + p3 * x * x * x / (exp(p4 * x) - 1) + p6 + p5 * x; - else - intensity = p0 + p1 * x + p2 * x * x - + p3 * x * x * x / (exp(p4 * x) - 1); - intensity = pow(10, intensity); - double n_eps = 0; - n_eps = 4 * M_PI / (h_Planck * C_speed) * (intensity / eps); - return n_eps / eV2J / 1.0e6; - -} - -double CMIBR(double eps) { - /*! - Cosmic background radiation photon number density (eV^-1 cm^-3) - as a function of ambient photon energy (eV), from CMB to Optical (COB) - - Ref: - - Funk et al, Astropart.Phys. 9 (1998) 97-103 - J.L. Puget, F.W. Stecker and J. Bredekamp, Astroph. J. 205 (1976) 638–654. - */ - return CMBR(eps) + CIBR(eps); -} - -double CMIOBR(double eps) { - /*! - Cosmic background radiation photon number density (eV^-1 cm^-3) - as a function of ambient photon energy (eV), from CMB to Optical (COB) - - Ref: - - Funk et al, Astropart.Phys. 9 (1998) 97-103 - J.L. Puget, F.W. Stecker and J. Bredekamp, Astroph. J. 205 (1976) 638–654. - */ - return CMBR(eps) + CIOBR(eps); -} - -double CBR(double eps, double z) { - /*! - Cosmic background radiation photon number density (eV^-1 cm^-3) - as a function of ambient photon energy (eV), from CMB to Optical (COB) - - Ref: - - Funk et al, Astropart.Phys. 9 (1998) 97-103 - J.L. Puget, F.W. Stecker and J. Bredekamp, Astroph. J. 205 (1976) 638–654. - */ - return CMBR(eps) * CMB_Evolution(z) + CIOBR(eps) * CIOB_Evolution(z) - + URB(eps) * URB_Evolution(z); -} - -double CBR(double eps) { - return CMBR(eps) + CIOBR(eps) + URB(eps); -} - -double GetEvolution(double eps, double z) { - - if (eps >= eps_ph_inf_urb && eps <= eps_ph_sup_urb) - return URB_Evolution(z); - if (eps >= eps_ph_inf_ciob && eps <= eps_ph_sup_ciob) - return CIOB_Evolution(z); - if (eps >= eps_ph_inf_cmb && eps <= eps_ph_sup_cmb) - return CMB_Evolution(z); - return 1; -} - -double GetEvolution(double z, std::string background) { - if (background == "CMB") - return CMB_Evolution(z); - if (background == "CIB") - return CIB_Evolution(z); - if (background == "CMIOB") - return CIOB_Evolution(z); - if (background == "CIOB") - return CIOB_Evolution(z); - if (background == "COB") - return COB_Evolution(z); - if (background == "URB") - return URB_Evolution(z); - - if (background == "ALL") { // come trattare questo caso???? - return CMB_Evolution(z); - } - return 1; -} - -//------ - -double CBR(double eps, double z, std::string background) { - double evolution = 1; - if (z == 0) - evolution = 1; - else - evolution = GetEvolution(eps, z); - - if (background == "CMB") - return CMBR(eps) * evolution; - else if (background == "URB") - return URB(eps) * evolution; - else if (background == "CIOB") - return CIOBR(eps) * evolution; - else if (background == "CMIB") - return CMIBR(eps) * evolution; - else if (background == "CMIOB") - return CMIOBR(eps) * evolution; - else - return (CMBR(eps) * CMB_Evolution(z) + CIOBR(eps) * CIOB_Evolution(z) - + URB(eps) * URB_Evolution(z)); -} - -} // namespace eleca - -#endif // ELECA_XLOSS_CBR_H - diff --git a/libs/dint/CMakeLists.txt b/libs/dint/CMakeLists.txt deleted file mode 100644 index fa1b9bb78..000000000 --- a/libs/dint/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -cmake_minimum_required(VERSION 2.6) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) - -add_library(dint STATIC - src/advance.cpp - src/background.cpp - src/binfread.cpp - src/check.cpp - src/cvector.cpp - src/decay.cpp - src/deriv.cpp - src/error.cpp - src/final.cpp - src/fold.cpp - src/frag.cpp - src/gauleg.cpp - src/inject.cpp - src/io_util.cpp - src/load.cpp - src/math_util.cpp - src/prepare.cpp - src/prop_second.cpp - src/rate.cpp - src/spectrum.cpp - src/sync.cpp - src/vector.cpp - src/DintEMCascade.cpp -) - -SET_TARGET_PROPERTIES(dint PROPERTIES COMPILE_FLAGS -fPIC) - diff --git a/libs/dint/include/dint/DintEMCascade.h b/libs/dint/include/dint/DintEMCascade.h deleted file mode 100644 index 3e9e9cd18..000000000 --- a/libs/dint/include/dint/DintEMCascade.h +++ /dev/null @@ -1,200 +0,0 @@ -#ifndef DINT_EMCASCADE_H -#define DINT_EMCASCADE_H - -#include "dint/rate.h" -#include "dint/const.h" -#include "dint/spectrum.h" -#include "dint/cvector.h" -#include "dint/load.h" -#include "dint/prepare.h" -#include "dint/sync.h" -#include "dint/inject.h" -#include "dint/background.h" -#include "dint/fold.h" -#include "dint/advance.h" -#include "dint/final.h" -#include "dint/utilities.h" - - -// DintEMCascade. -// Class based on the original DINT prop_second function, intended as starting -// point to create a simplified EM cascade calculation based on transport -// equations to replace DINT completely in a future release of CRPropa. -class DintEMCascade { - private: - //-------- Declaration of main variables -------- - //---- Interaction table coefficients ---- - RawTotalRate ICSTotalRate; - RawTotalRate PPTotalRate; - RawTotalRate TPPTotalRate; - RawTotalRate DPPRate; - - RawTotalRate PPPProtonLossRate; - RawTotalRate PPPNeutronLossRate; - RawTotalRate NPPTotalRate; - // total (interaction) rates before being folded into the background - - RawDiffRate ICSPhotonRate; - RawDiffRate ICSScatRate; - RawDiffRate PPDiffRate; - RawDiffRate TPPDiffRate; - - RawDiffRate PPPProtonScatRate; - RawDiffRate PPPProtonNeutronRate; - RawDiffRate PPPNeutronProtonRate; - RawDiffRate PPPProtonPhotonRate; - RawDiffRate PPPProtonElectronRate; - RawDiffRate PPPProtonPositronRate; - RawDiffRate PPPNeutronElectronRate; - RawDiffRate NPPDiffRate; - RawDiffRate PPPProtonElectronNeutrinoRate; - RawDiffRate PPPProtonAntiElectronNeutrinoRate; - RawDiffRate PPPProtonMuonNeutrinoRate; - RawDiffRate PPPProtonAntiMuonNeutrinoRate; - RawDiffRate PPPNeutronAntiElectronNeutrinoRate; - RawDiffRate PPPNeutronMuonNeutrinoRate; - RawDiffRate PPPNeutronAntiMuonNeutrinoRate; - // differential rates before being folded into the background - - TotalRate neutronDecayRate; - DiffRate neutronDecayElectronRate; - DiffRate neutronDecayProtonRate; - - TotalRate NNElNeutTotalRate; - TotalRate NNMuonNeutTotalRate; - TotalRate NNTauNeutTotalRate; - // These total rates are net rates; i.e. scattered flux into same bin is subtracted - DiffRate NNElNeutScatRate; - DiffRate NNElNeutMuonNeutRate; - DiffRate NNElNeutTauNeutRate; - DiffRate NNElNeutElectronRate; - DiffRate NNElNeutPhotonRate; - DiffRate NNElNeutProtonRate; - DiffRate NNMuonNeutScatRate; - DiffRate NNMuonNeutElNeutRate; - DiffRate NNMuonNeutTauNeutRate; - DiffRate NNMuonNeutElectronRate; - DiffRate NNMuonNeutPhotonRate; - DiffRate NNMuonNeutProtonRate; - DiffRate NNTauNeutScatRate; - DiffRate NNTauNeutElNeutRate; - DiffRate NNTauNeutMuonNeutRate; - DiffRate NNTauNeutElectronRate; - DiffRate NNTauNeutPhotonRate; - DiffRate NNTauNeutProtonRate; - // rates from neutrino-neutrino interaction - DiffRate syncRate; - - // Energy Bins - dCVector deltaG; // dg used in continuous energy loss calculation - - dCVector bgEnergy; - dCVector bgEnergyWidth; - dCVector bgPhotonDensity; - - Spectrum Q_0; // standard injection function - Spectrum spectrumNew; - Spectrum derivative; - - //---- interaction rates folded with photon background ---- - TotalRate leptonTotalRate; - TotalRate photonTotalRate; - TotalRate protonTotalRate; - TotalRate neutronTotalRate; - - DiffRate leptonScatRate; - DiffRate leptonExchRate; - DiffRate leptonPhotonRate; - DiffRate photonLeptonRate; - - DiffRate protonScatRate; - DiffRate protonNeutronRate; - DiffRate neutronProtonRate; - DiffRate protonPhotonRate; - DiffRate protonElectronRate; - DiffRate protonPositronRate; - DiffRate neutronElectronRate; - DiffRate neutronPositronRate; - DiffRate protonElectronNeutrinoRate; - DiffRate protonAntiElectronNeutrinoRate; - DiffRate protonMuonNeutrinoRate; - DiffRate protonAntiMuonNeutrinoRate; - DiffRate neutronAntiElectronNeutrinoRate; - DiffRate neutronMuonNeutrinoRate; - DiffRate neutronAntiMuonNeutrinoRate; - - TotalRate elNeutTotalRate; - TotalRate muonNeutTotalRate; - TotalRate tauNeutTotalRate; - - DiffRate elNeutElectronRate; - DiffRate elNeutPhotonRate; - DiffRate muonNeutElectronRate; - DiffRate muonNeutPhotonRate; - DiffRate tauNeutElectronRate; - DiffRate tauNeutPhotonRate; - // rates from neutrino-neutrino interaction - - dCVector synchrotronLoss; // sgdot - dCVector otherLoss; // tgdot - dCVector continuousLoss; // gdot - - dCVector pEnergy; - dCVector pEnergyWidth; - - dCVector RedshiftArray ; - dCVector DistanceArray ; - - // switches - const int synchrotronSwitch; - const int sourceTypeSwitch; - const int tauNeutrinoMassSwitch; - const int ICSSwitch; - const int PPSwitch; - const int TPPSwitch; - const int DPPSwitch; - const int PPPSwitch; - const int NPPSwitch; - const int neutronDecaySwitch; - const int nucleonToSecondarySwitch; - const int neutrinoNeutrinoSwitch; - - const int aIRFlag; - const int aRadioFlag; - - const double aZmax_IR; - - const double aH0; - const double aOmegaM; - const double aOmegaLambda; - - dCVector pB_field; - string aDirTables; - -public: - DintEMCascade( - int _aIRFlag, //!< EBL background 0: high, 1: low, 2: Primack, 4: Stecker'06 - int _aRadioFlag, //!< radio background 0: high, 1: medium, 2: obs, 3: none, 4: Protheroe'96 - string _aDirTables, //!< DINT data path - double B = 1E-9, //!< magnetic field strength [G], default = 1 nG - double _aH0 = H_0, //!< Hubble parameter in [km/s/Mpc] - double _aOmegaM = OMEGA_M, //!< omegaM parameter - double _aOmegaLambda = OMEGA_LAMBDA //!< omegaL parameter - ); - - ~DintEMCascade(); - - void propagate( - const double start_distance, // -#include "dint/spectrum.h" -#include "dint/rate.h" -#include "dint/cvector.h" -#include "dint/const.h" -#include "dint/deriv.h" -#include "dint/error.h" - -const double EPSILON = 1.e-18; - -void ComputeRedshifts(const int sourceTypeSwitch, const double leftRedshift, - double* pDeltaRedshift, double* pRightRedshift, - double* pCentralRedshift, int* pLastIndex); -void AdvanceNucleonStep(const int sourceTypeSwitch, - const int PPPSwitch, const int NPPSwitch, - const int neutronDecaySwitch, - const int neutrinoNeutrinoSwitch, - const double smallDistanceStep, - const double evolutionFactor, - const double convergeParameter, - const double bkgFactor, - const Spectrum* pQ_0, - const DiffRate* elNeutProtonRate, - const DiffRate* muonNeutProtonRate, - const DiffRate* tauNeutProtonRate, - const TotalRate* protonTotalRate, - const TotalRate* neutronTotalRate, - const TotalRate* neutronDecayRate, - const DiffRate* protonScatRate, - const DiffRate* protonNeutronRate, - const DiffRate* neutronProtonRate, - const DiffRate* neutronDecayProtonRate, - const dCVector* protonContinuousLoss, - const dCVector* deltaG, const Spectrum* pSpectrum, - Spectrum* pSpectrumNew); -void AdvanceNeutrinoStep(const int sourceTypeSwitch, - const int neutrinoNeutrinoSwitch, - const int PPPSwitch, const int neutronDecaySwitch, - const int nucleonToSecondarySwitch, - const double smallDistanceStep, - const double evolutionFactor, - const double convergeParameter, - const double bkgFactor, - const Spectrum* pQ_0, - const DiffRate* protonMuonNeutrinoRate, - const DiffRate* neutronAntiMuonNeutrinoRate, - const DiffRate* protonAntiMuonNeutrinoRate, - const DiffRate* neutronMuonNeutrinoRate, - const DiffRate* protonElectronNeutrinoRate, - const DiffRate* neutronAntiElectronNeutrinoRate, - const DiffRate* protonAntiElectronNeutrinoRate, - const DiffRate* neutronDecayElectronRate, - const TotalRate* elNeutTotalRate, - const TotalRate* muonNeutTotalRate, - const TotalRate* tauNeutTotalRate, - const DiffRate* elNeutScatRate, - const DiffRate* elNeutMuonNeutRate, - const DiffRate* elNeutTauNeutRate, - const DiffRate* muonNeutElNeutRate, - const DiffRate* muonNeutScatRate, - const DiffRate* muonNeutTauNeutRate, - const DiffRate* tauNeutElNeutRate, - const DiffRate* tauNeutMuonNeutRate, - const DiffRate* tauNeutScatRate, - const Spectrum* pSpectrum, Spectrum* pSpectrumNew); -void AdvanceNucNeutStep(const int sourceTypeSwitch, - const int PPPSwitch, const int NPPSwitch, - const int neutronDecaySwitch, - const int nucleonToSecondarySwitch, - const int neutrinoNeutrinoSwitch, - const double smallDistanceStep, - const double evolutionFactor, - const double convergeParameter, - const double bkgFactor, - const Spectrum* pQ_0, - const DiffRate* elNeutProtonRate, - const DiffRate* muonNeutProtonRate, - const DiffRate* tauNeutProtonRate, - const TotalRate* protonTotalRate, - const TotalRate* neutronTotalRate, - const TotalRate* neutronDecayRate, - const DiffRate* protonScatRate, - const DiffRate* protonNeutronRate, - const DiffRate* neutronProtonRate, - const DiffRate* neutronDecayProtonRate, - const DiffRate* protonMuonNeutrinoRate, - const DiffRate* neutronAntiMuonNeutrinoRate, - const DiffRate* protonAntiMuonNeutrinoRate, - const DiffRate* neutronMuonNeutrinoRate, - const DiffRate* protonElectronNeutrinoRate, - const DiffRate* neutronAntiElectronNeutrinoRate, - const DiffRate* protonAntiElectronNeutrinoRate, - const DiffRate* neutronDecayElectronRate, - const TotalRate* elNeutTotalRate, - const TotalRate* muonNeutTotalRate, - const TotalRate* tauNeutTotalRate, - const DiffRate* elNeutScatRate, - const DiffRate* elNeutMuonNeutRate, - const DiffRate* elNeutTauNeutRate, - const DiffRate* muonNeutElNeutRate, - const DiffRate* muonNeutScatRate, - const DiffRate* muonNeutTauNeutRate, - const DiffRate* tauNeutElNeutRate, - const DiffRate* tauNeutMuonNeutRate, - const DiffRate* tauNeutScatRate, - const dCVector* protonContinuousLoss, - const dCVector* deltaG, const Spectrum* pSpectrum, - Spectrum* pSpectrumNew); -void AdvanceEMStep(const int sourceTypeSwitch, const int PPSwitch, - const int ICSSwitch, const int TPPSwitch, - const int DPPSwitch, const int synchrotronSwitch, - const int PPPSwitch, const int NPPSwitch, - const int neutronDecaySwitch, - const int nucleonToSecondarySwitch, - const int neutrinoNeutrinoSwitch, - const double smallDistanceStep, - const double evolutionFactor, - const double convergeParameter, const double bkgFactor, - const Spectrum* pQ_0, - const DiffRate* photonLeptonRate, - const DiffRate* protonElectronRate, - const DiffRate* neutronPositronRate, - const DiffRate* protonPositronRate, - const DiffRate* neutronElectronRate, - const DiffRate* neutronDecayElectronRate, - const DiffRate* elNeutElectronRate, - const DiffRate* muonNeutElectronRate, - const DiffRate* tauNeutElectronRate, - const DiffRate* protonPhotonRate, - const DiffRate* elNeutPhotonRate, - const DiffRate* muonNeutPhotonRate, - const DiffRate* tauNeutPhotonRate, - const TotalRate* leptonTotalRate, - const DiffRate* leptonScatRate, - const DiffRate* leptonExchRate, - const dCVector* continuousLoss, const dCVector* deltaG, - const TotalRate* photonTotalRate, - const DiffRate* leptonPhotonRate, - const DiffRate* syncRate, const Spectrum* pSpectrum, - Spectrum* pSpectrumNew); -void RedshiftDown(const int lastIndex, const double redshiftRatio, - const dCVector* pEnergy, Spectrum* pSpectrum, - Spectrum* pSpectrumNew); -void RedshiftBinsDown(const int lastIndex, const double evolutionFactor, - const dCVector* pEnergy, double* pSpectrum, - double* pSpectrumNew); -void GetExternalFlux(const int sourceTypeSwitch, const double evolutionFactor, - const PARTICLE particle, const Spectrum* pQ_0, - Spectrum* pInfluxExt); -void ImplicitEquation(const double smallDistanceStep, - const PARTICLE particle, const Spectrum* pInflux, - const Spectrum* pInflux0, const Spectrum* pInfluxExt, - const Spectrum* pOutflux, const Spectrum* pSpectrum, - Spectrum* pSpectrumNew); -void ExplicitEquation(const double smallDistanceStep, - const PARTICLE particle, const Spectrum* pInflux, - const Spectrum* pInflux0, const Spectrum* pInfluxExt, - const Spectrum* pOutflux, const Spectrum* pSpectrum, - const Spectrum* pSpectrumNew); -void ComputeChange(const Spectrum* pSpectrumTemp, - const Spectrum* pSpectrumNew, - const PARTICLE particle, double* pChangeMax); - -#endif diff --git a/libs/dint/include/dint/background.h b/libs/dint/include/dint/background.h deleted file mode 100644 index 06ba5eae4..000000000 --- a/libs/dint/include/dint/background.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef DINT__BACKGROUND_H -#define DINT__BACKGROUND_H - -#include -#include -#include -#include -#include -#include -#include - -#include "dint/cvector.h" -#include "dint/error.h" -#include "dint/utilities.h" -#include "dint/const.h" -#include "dint/gauleg.h" - -#define GAULEG_POINTS 31 // number of gaussian quadrature points for integration - -using namespace std; - -void LoadPhotonBackground(const double redshift, - dCVector* pBgEnergy, dCVector* pBgEnergyWidth, - dCVector* pBgPhotonDensity, const int aIRFlag, - const double aZmax_IR, const int aRadioFlag, - const double aH0, const double aOmegaM, const double aOmegaLambda); -void LoadCMB(const double redshift, const dCVector* pBgEnergy, - const dCVector* pBgEnergyWidth, dCVector* pBgPhotonDensity); -void LoadIR(const double redshift, const dCVector* pBgEnergy, - const dCVector* pBgEnergyWidth, dCVector* pBgPhotonDensity, - const int aIRFlag, const double aZmax_IR); -double IR2(const double redshift, const double BgEnergy); -double HighIR(const double zTarget, const double zObserve, - const double energy0, const double deltaO, - const double deltaD); -double LowIR(const double zTarget, const double zObserve, - const double energy0, const double deltaO, - const double deltaD); -double OpticalIR(const double energy); -double DustIR(const double energy); -void LoadRadio(const double redshift, const dCVector* pBgEnergy, - const dCVector* pBgEnergyWidth, dCVector* pBgPhotonDensity, - const int aRadioFlag, const double aH0, const double aOmegaM, - const double aOmegaLambda); -double HighRadio(const double zTarget, const double zObserve, - const double energy0, const double aH0, - const double aOmegaM, const double aOmegaLambda); -double MedRadio(const double zTarget, const double zObserve, - const double energy0, const double aH0, const double aOmegaM, - const double aOmegaLambda); -double ObsRadio(const double zTarget, const double zObserve, - const double energy0, const double aH0, - const double aOmegaM, const double aOmegaLambda); -double ElecaRadio(const double zTarget, const double zObserve, - const double energy0, const double aH0, - const double aOmegaM, const double aOmegaLambda); - -/* -// Routine added by Gunter (July 2005) : -void DumpBgSpectrum(const dCVector* pBgEnergy, const dCVector* pBgEnergyWidth, - const dCVector* pBgPhotonDensity, const char* filename); -*/ - -#endif diff --git a/libs/dint/include/dint/binfread.h b/libs/dint/include/dint/binfread.h deleted file mode 100644 index da5f8b8ce..000000000 --- a/libs/dint/include/dint/binfread.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef DINT__BINFREAD_H -#define DINT__BINFREAD_H - -// T. Beau 2005 - -// Allow to deal with big / little endian machines. -// Data have been written on a Intel Machine... - -#include -#include -#include - -#if HAVE_ARPA_INET_H -#include -#endif - -#if HAVE_NETINET_IN_H -#include -#endif - -size_t binfread(void *, size_t, size_t, FILE *); - -#endif - diff --git a/libs/dint/include/dint/check.h b/libs/dint/include/dint/check.h deleted file mode 100644 index b7550b614..000000000 --- a/libs/dint/include/dint/check.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef DINT__CHECK_H -#define DINT__CHECK_H - -#include "dint/cvector.h" - -void CheckIndex(const int lowerLimit, const int upperLimit, const int i, - const char* functionName); -void DumpArray(const dCVector* pVector); - -#endif diff --git a/libs/dint/include/dint/const.h b/libs/dint/include/dint/const.h deleted file mode 100644 index d43c7630d..000000000 --- a/libs/dint/include/dint/const.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef DINT__CONST_H -#define DINT__CONST_H - - -#define ELECTRON_MASS 5.110e5 -#define DISTANCE_UNIT 3.0856e18 -#define VOLUME_UNIT 6.652448e-25*3.0856e18 -#define PI 3.141592 -#define C 3.e10 -#define H_0 71. -// Added July 2005 : cosmological parameters -#define OMEGA_M 0.3// NOW THEY ARE NOT defined like this, but taken as input parameters. -#define OMEGA_LAMBDA 0.7 // if not specified as parameters, take these values - -// CHANGE (Guenter; 7/20/1998) -#define DMAX 1.e6 -#define CLUSTER_DISTANCE 100. -#define CLUSTER_FACTOR 1. -#define SOURCE_CLUSTER_DISTANCE 0.1 -#define SOURCE_CLUSTER_FACTOR 1. - -#define NUM_IP_ELEMENTS 1309125 -#define NUM_IS_ELEMENTS 571200 -#define NUM_PP_ELEMENTS 558050 -#define NUM_TPP_ELEMENTS 548250 -// photopion production -#define NUM_PPP_PROTON_SCAT_ELEMENTS 111541 -#define NUM_PPP_PROTON_NEUTRON_ELEMENTS 111541 -#define NUM_PPP_PROTON_PHOTON_ELEMENTS 20000 -#define NUM_PPP_PROTON_ELECTRON_ELEMENTS 20000 -#define NUM_PPP_PROTON_POSITRON_ELEMENTS 20000 -// nucleon pair production -#define NUM_NPP_ELEMENTS 20000 -// neutrino production from PPP -#define NUM_PPP_PROTON_ANTI_ELECTRON_NEUTRINO_ELEMENTS 20000 -#define NUM_PPP_PROTON_MUON_NEUTRINO_ELEMENTS 20000 -#define NUM_PPP_PROTON_ANTI_MUON_NEUTRINO_ELEMENTS 20000 - -// Parameters used in the code -// Warning : those cannot be changed unless various parts of CRPropa are also changed! -#define BINS_PER_DECADE 10 // number of bins per decade -#define MIN_ENERGY_EXP 7 // minimum spectrum energy = 10 MeV -#define MAX_ENERGY_EXP (MIN_ENERGY_EXP + 17) // maximum spectrum energy - -#define BG_MIN_ENERGY_EXP (-8 - MIN_ENERGY_EXP + 7) -#define BG_MAX_ENERGY_EXP (2 - MIN_ENERGY_EXP + 7) -#define EM_MIN_ENERGY_EXP (MIN_ENERGY_EXP) -#define NUC_MIN_ENERGY_EXP (14 + MIN_ENERGY_EXP - 7) -#define NEUT_MIN_ENERGY_EXP (17 + MIN_ENERGY_EXP - 7) -#define NUM_MAIN_BINS ((MAX_ENERGY_EXP - MIN_ENERGY_EXP)*BINS_PER_DECADE) -#define NUM_BG_BINS ((BG_MAX_ENERGY_EXP - BG_MIN_ENERGY_EXP)*BINS_PER_DECADE) - -#define EM_NUM_MAIN_BINS ((MAX_ENERGY_EXP - EM_MIN_ENERGY_EXP)*BINS_PER_DECADE) -#define NUC_NUM_MAIN_BINS ((MAX_ENERGY_EXP - NUC_MIN_ENERGY_EXP)*BINS_PER_DECADE) -#define NEUT_NUM_MAIN_BINS ((MAX_ENERGY_EXP - NEUT_MIN_ENERGY_EXP)*BINS_PER_DECADE) - - -#endif diff --git a/libs/dint/include/dint/cvector.h b/libs/dint/include/dint/cvector.h deleted file mode 100644 index ce9c5e9a1..000000000 --- a/libs/dint/include/dint/cvector.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef DINT__CVECTOR_H -#define DINT__CVECTOR_H - -#include "dint/vector.h" -#include - -// these are variants of structs defined in vector.h; they have dimensional -// info built-in, and they are initialized when assigned memory -typedef struct -{ - int dimension; - dVector vector; -} dCVector; - -typedef struct -{ - int dimension1; - int dimension2; - iMatrix matrix; -} iCMatrix; - -void New_dCVector(dCVector* pVector, const int n); -void Delete_dCVector(dCVector* pVector); -void Initialize_dCVector(dCVector* pVector); - -void New_iCMatrix(iCMatrix* pMatrix, const int n1, const int n2); -void Delete_iCMatrix(iCMatrix* pMatrix); -void Initialize_iCMatrix(iCMatrix* pMatrix); - -#endif diff --git a/libs/dint/include/dint/decay.h b/libs/dint/include/dint/decay.h deleted file mode 100644 index 78351824b..000000000 --- a/libs/dint/include/dint/decay.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef DINT__DECAY_H -#define DINT__DECAY_H - -double PionToPhoton(const int iPhoton, const int iPion); -double PionToLepton(const double leptonEnergy, const double pionEnergy); -double PionToElectronNeutrino(const double neutrinoEnergy, - const double pionEnergy); -double PionToMuonNeutrino(const int iNeutrino, const int iPion); - -#endif diff --git a/libs/dint/include/dint/deriv.h b/libs/dint/include/dint/deriv.h deleted file mode 100644 index 2055d7f28..000000000 --- a/libs/dint/include/dint/deriv.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef DINT__DERIV_H -#define DINT__DERIV_H - -#include "dint/rate.h" -#include "dint/spectrum.h" -#include "dint/cvector.h" - - -void GetLeptonInfluxFromPhotons(const DiffRate* photonLeptonRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux); -void GetLeptonFluxFromLeptons(const TotalRate* leptonTotalRate, - const DiffRate* leptonScatRate, - const DiffRate* leptonExchRate, - const dCVector* continuousLoss, - const dCVector* deltaG, - const Spectrum* pSpectrumNew, Spectrum* pInflux, - Spectrum* pOutflux); -void GetPhotonInfluxFromLeptons(const DiffRate* leptonPhotonRate, - const int synchrotronSwitch, - const DiffRate* syncRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux); -void GetPhotonFluxFromPhotons(const TotalRate* photonTotalRate, - Spectrum* pOutflux); -void GetLeptonInfluxFromNucleons(const int neutronDecaySwitch, - const DiffRate* protonElectronRate, - const DiffRate* neutronPositronRate, - const DiffRate* protonPositronRate, - const DiffRate* neutronElectronRate, - const DiffRate* neutronDecayElectronRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux); -void GetPhotonInfluxFromNucleons(const DiffRate* protonPhotonRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux); -void GetLeptonInfluxFromNeutrinos(const double bkgFactor, - const DiffRate* elNeutElectronRate, - const DiffRate* muonNeutElectronRate, - const DiffRate* tauNeutElectronRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux0); -void GetPhotonInfluxFromNeutrinos(const double bkgFactor, - const DiffRate* elNeutPhotonRate, - const DiffRate* muonNeutPhotonRate, - const DiffRate* tauNeutPhotonRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux0); -void GetNucleonFluxFromNucleons(const int neutronDecaySwitch, - const TotalRate* protonTotalRate, - const TotalRate* neutronTotalRate, - const TotalRate* neutronDecayRate, - const DiffRate* protonScatRate, - const DiffRate* neutronProtonRate, - const DiffRate* protonNeutronRate, - const DiffRate* neutronDecayProtonRate, - const dCVector* protonContinuousLoss, - const dCVector* deltaG, - const Spectrum* pSpectrumNew, - Spectrum* pInflux, Spectrum* pOutflux); -void GetNeutrinoInfluxFromNucleons(const int neutronDecaySwitch, - const DiffRate* protonMuonNeutrinoRate, - const DiffRate* neutronAntiMuonNeutrinoRate, - const DiffRate* neutronMuonNeutrinoRate, - const DiffRate* protonAntiMuonNeutrinoRate, - const DiffRate* protonElectronNeutrinoRate, - const DiffRate* neutronAntiElectronNeutrinoRate, - const DiffRate* protonAntiElectronNeutrinoRate, - const DiffRate* neutronDecayElectronRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux0); -void GetNucleonInfluxFromNeutrinos(const double bkgFactor, - const DiffRate* elNeutProtonRate, - const DiffRate* muonNeutProtonRate, - const DiffRate* tauNeutProtonRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux0); -void GetNeutrinoFluxFromNeutrinos(const double bkgFactor, - const TotalRate* elNeutTotalRate, - const TotalRate* muonNeutTotalRate, - const TotalRate* tauNeutTotalRate, - const DiffRate* elNeutScatRate, - const DiffRate* elNeutMuonNeutRate, - const DiffRate* elNeutTauNeutRate, - const DiffRate* muonNeutElNeutRate, - const DiffRate* muonNeutScatRate, - const DiffRate* muonNeutTauNeutRate, - const DiffRate* tauNeutElNeutRate, - const DiffRate* tauNeutMuonNeutRate, - const DiffRate* tauNeutScatRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux, Spectrum* pOutflux); - -void ComputeOutflux(const double bkgFactor, const TotalRate* pRate, - const PARTICLE parent, Spectrum* pOutflux); -void ComputeInflux(const double bkgFactor, const DiffRate* pRate, - const PARTICLE parent, const PARTICLE daughter, - const Spectrum* pSpectrum, Spectrum* pInflux); - -#endif diff --git a/libs/dint/include/dint/error.h b/libs/dint/include/dint/error.h deleted file mode 100644 index f619c0bcf..000000000 --- a/libs/dint/include/dint/error.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef DINT__ERROR_H -#define DINT__ERROR_H - -typedef enum {NO_ERROR = 0, ARRAY_ERROR = 1, IO_ERROR = 2, PROGRAM_ERROR = 3} -ErrorCode; - -void Error(const char* errorMessage, const ErrorCode errorCode); - -#endif diff --git a/libs/dint/include/dint/final.h b/libs/dint/include/dint/final.h deleted file mode 100644 index 95245f5b9..000000000 --- a/libs/dint/include/dint/final.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DINT__FINAL_H -#define DINT__FINAL_H - -#include "dint/spectrum.h" -#include "dint/cvector.h" - -void CheckEnergy(const int sourceTypeSwitch, const double brightPhaseExp, - const double startingRedshift, - const double rightRedshift, const Spectrum* pSpectrum, - const dCVector* pEnergy, const double initialTotalEnergy); -void FinalPrintOutToTheScreen(const double distance, - const double startingRedshift, - const double propagatingDistance); - -#endif diff --git a/libs/dint/include/dint/fold.h b/libs/dint/include/dint/fold.h deleted file mode 100644 index 883134abc..000000000 --- a/libs/dint/include/dint/fold.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef DINT__FOLD_H -#define DINT__FOLD_H - -#include "dint/rate.h" -#include "dint/cvector.h" - -void InitializeLeptonCoefficients(TotalRate* leptonTotalRate, - DiffRate* leptonScatRate, - DiffRate* leptonExchRate, - DiffRate* leptonPhotonRate); -void InitializePhotonCoefficients(TotalRate* photonTotalRate, - DiffRate* photonLeptonRate); -void InitializeNucleonCoefficients(TotalRate* protonTotalRate, - TotalRate* neutronTotalRate, - DiffRate* protonScatRate, - DiffRate* protonNeutronRate, - DiffRate* neutronProtonRate, - DiffRate* protonPhotonRate, - DiffRate* protonElectronRate, - DiffRate* protonPositronRate, - DiffRate* neutronElectronRate, - DiffRate* neutronPositronRate, - DiffRate* protonElectronNeutrinoRate, - DiffRate* protonAntiElectronNeutrinoRate, - DiffRate* protonMuonNeutrinoRate, - DiffRate* protonAntiMuonNeutrinoRate, - DiffRate* neutronAntiElectronNeutrinoRate, - DiffRate* neutronMuonNeutrinoRate, - DiffRate* neutronAntiMuonNeutrinoRate); -void InitializeNeutrinoCoefficients(TotalRate* elNeutTotalRate, - TotalRate* muonNeutTotalRate, - TotalRate* tauNeutTotalRate, - DiffRate* elNeutScatRate, - DiffRate* elNeutMuonNeutRate, - DiffRate* elNeutTauNeutRate, - DiffRate* elNeutElectronRate, - DiffRate* elNeutPhotonRate, - DiffRate* elNeutProtonRate, - DiffRate* muonNeutElNeutRate, - DiffRate* muonNeutScatRate, - DiffRate* muonNeutTauNeutRate, - DiffRate* muonNeutElectronRate, - DiffRate* muonNeutPhotonRate, - DiffRate* muonNeutProtonRate, - DiffRate* tauNeutElNeutRate, - DiffRate* tauNeutMuonNeutRate, - DiffRate* tauNeutScatRate, - DiffRate* tauNeutElectronRate, - DiffRate* tauNeutPhotonRate, - DiffRate* tauNeutProtonRate); -void FoldTotalRate(const dCVector* pBgPhotonDensity, - const RawTotalRate* pRawTotalRate, TotalRate* pTotalRate); -void FoldDiffRate(const dCVector* pBgPhotonDensity, - const RawDiffRate* pRawDiffRate, - DiffRate* pDiffRate, const int scatSwitch, ...); -void FoldICS(const dCVector* pBgPhotonDensity, - const RawTotalRate* ICSTotalRate, - const RawDiffRate* ICSPhotonRate, const RawDiffRate* ICSScatRate, - TotalRate* leptonTotalRate, DiffRate* leptonPhotonRate, - DiffRate* leptonScatRate); -void FoldTPP(const dCVector* pBgPhotonDensity, const dCVector* pEnergy, - const RawTotalRate* TPPTotalRate, const RawDiffRate* TPPDiffRate, - TotalRate* leptonTotalRate, DiffRate* leptonScatRate, - DiffRate* leptonExchRate, dCVector* otherLoss); -void FoldPP(const dCVector* pBgPhotonDensity, const RawTotalRate* PPTotalRate, - const RawDiffRate* PPDiffRate, TotalRate* photonTotalRate, - DiffRate* photonLeptonRate); -void FoldDPP(const dCVector* pBgPhotonDensity, const RawTotalRate* DPPRate, - TotalRate* photonTotalRate, DiffRate* photonLeptonRate); -void FoldPPPNucleon(const dCVector* pBgPhotonDensity, - const RawTotalRate* PPPProtonLossRate, - const RawTotalRate* PPPNeutronLossRate, - const RawDiffRate* PPPProtonScatRate, - const RawDiffRate* PPPProtonNeutronRate, - const RawDiffRate* PPPNeutronProtonRate, - TotalRate* protonTotalRate, TotalRate* neutronTotalRate, - DiffRate* protonScatRate, DiffRate* protonNeutronRate, - DiffRate* neutronProtonRate); -void FoldPPPSecondary(const dCVector* pBgPhotonDensity, - const RawDiffRate* PPPProtonPhotonRate, - const RawDiffRate* PPPProtonElectronRate, - const RawDiffRate* PPPProtonPositronRate, - const RawDiffRate* PPPNeutronElectronRate, - const RawDiffRate* PPPProtonElectronNeutrinoRate, - const RawDiffRate* PPPProtonAntiElectronNeutrinoRate, - const RawDiffRate* PPPProtonMuonNeutrinoRate, - const RawDiffRate* PPPProtonAntiMuonNeutrinoRate, - const RawDiffRate* PPPNeutronAntiElectronNeutrinoRate, - const RawDiffRate* PPPNeutronMuonNeutrinoRate, - const RawDiffRate* PPPNeutronAntiMuonNeutrinoRate, - DiffRate* protonPhotonRate, - DiffRate* protonElectronRate, - DiffRate* protonPositronRate, - DiffRate* neutronElectronRate, - DiffRate* neutronPositronRate, - DiffRate* protonElectronNeutrinoRate, - DiffRate* protonAntiElectronNeutrinoRate, - DiffRate* protonMuonNeutrinoRate, - DiffRate* protonAntiMuonNeutrinoRate, - DiffRate* neutronAntiElectronNeutrinoRate, - DiffRate* neutronMuonNeutrinoRate, - DiffRate* neutronAntiMuonNeutrinoRate); -void FoldNPPNucleon(const dCVector* pBgPhotonDensity, const dCVector* pEnergy, - const RawTotalRate* NPPTotalRate, - dCVector* protonContinuousLoss); -void FoldNPPSecondary(const dCVector* pBgPhotonDensity, - const RawDiffRate* NPPDiffRate, - DiffRate* protonPositronRate, - DiffRate* protonElectronRate); - -void MapNeutTotalRate(const double redshift, const int lastIndex, - const int tauNeutrinoMassSwitch, - const TotalRate* NNTotalRate, - TotalRate* totalRate); -void MapNeutDiffRate(const double redshift, const int lastIndex, - const int tauNeutrinoMassSwitch, - const DiffRate* NNDiffRate, - DiffRate* diffRate); -void MapNeutRates(const double redshift, const int lastIndex, - const int tauNeutrinoMassSwitch, - const TotalRate* NNElNeutTotalRate, - const TotalRate* NNMuonNeutTotalRate, - const TotalRate* NNTauNeutTotalRate, - const DiffRate* NNElNeutScatRate, - const DiffRate* NNElNeutMuonNeutRate, - const DiffRate* NNElNeutTauNeutRate, - const DiffRate* NNElNeutElectronRate, - const DiffRate* NNElNeutPhotonRate, - const DiffRate* NNElNeutProtonRate, - const DiffRate* NNMuonNeutElNeutRate, - const DiffRate* NNMuonNeutScatRate, - const DiffRate* NNMuonNeutTauNeutRate, - const DiffRate* NNMuonNeutElectronRate, - const DiffRate* NNMuonNeutPhotonRate, - const DiffRate* NNMuonNeutProtonRate, - const DiffRate* NNTauNeutElNeutRate, - const DiffRate* NNTauNeutMuonNeutRate, - const DiffRate* NNTauNeutScatRate, - const DiffRate* NNTauNeutElectronRate, - const DiffRate* NNTauNeutPhotonRate, - const DiffRate* NNTauNeutProtonRate, - TotalRate* elNeutTotalRate, TotalRate* muonNeutTotalRate, - TotalRate* tauNeutTotalRate, DiffRate* elNeutScatRate, - DiffRate* elNeutMuonNeutRate, DiffRate* elNeutTauNeutRate, - DiffRate* elNeutElectronRate, DiffRate* elNeutPhotonRate, - DiffRate* elNeutProtonRate, DiffRate* muonNeutElNeutRate, - DiffRate* muonNeutScatRate, DiffRate* muonNeutTauNeutRate, - DiffRate* muonNeutElectronRate, DiffRate* muonNeutPhotonRate, - DiffRate* muonNeutProtonRate, DiffRate* tauNeutElNeutRate, - DiffRate* tauNeutMuonNeutRate, DiffRate* tauNeutScatRate, - DiffRate* tauNeutElectronRate, DiffRate* tauNeutPhotonRate, - DiffRate* tauNeutProtonRate); -#endif diff --git a/libs/dint/include/dint/frag.h b/libs/dint/include/dint/frag.h deleted file mode 100644 index 3dc172932..000000000 --- a/libs/dint/include/dint/frag.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef DINT__FRAG_H -#define DINT__FRAG_H - -double OldFrag(const double x); -double HillFrag(const double x); -double TestFrag(const double x); -double MLLA_25(const double x); -double MLLA_24(const double x); -double MLLA_23(const double x); -double MLLA_22(const double x); -double Susy_MLLA_25(const double x); -double Susy_MLLA_24(const double x); -double Susy_MLLA_23(const double x); -double Susy_MLLA_22(const double x); -double TDFolded(const double x); - -#endif diff --git a/libs/dint/include/dint/gauleg.h b/libs/dint/include/dint/gauleg.h deleted file mode 100644 index 9915e2492..000000000 --- a/libs/dint/include/dint/gauleg.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef DINT__GAULEG_H -#define DINT__GAULEG_H - -void Gauleg(const double x1, const double x2, double x[], double w[], - const int n); - -#endif diff --git a/libs/dint/include/dint/inject.h b/libs/dint/include/dint/inject.h deleted file mode 100644 index 9b521c166..000000000 --- a/libs/dint/include/dint/inject.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef DINT__INJECT_H -#define DINT__INJECT_H - -#include "dint/cvector.h" -#include "dint/spectrum.h" - -void SetInjectionSpectrum(const PARTICLE part, const double InjEnergy, - const double HInjEnergy, const double deltaE_hadron, - const dCVector* pEnergy, - const dCVector* pEnergyWidth, Spectrum* pQ_0); - -#endif diff --git a/libs/dint/include/dint/io_util.h b/libs/dint/include/dint/io_util.h deleted file mode 100644 index 31df6e4cb..000000000 --- a/libs/dint/include/dint/io_util.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef DINT__IO_UTIL_H -#define DINT__IO_UTIL_H - -#include - -FILE* SafeFOpen(const char* filename, const char* mode); - -#endif diff --git a/libs/dint/include/dint/load.h b/libs/dint/include/dint/load.h deleted file mode 100644 index 88bfa4e49..000000000 --- a/libs/dint/include/dint/load.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef DINT__LOAD_H -#define DINT__LOAD_H - -#include "dint/rate.h" -#include "dint/utilities.h" -#include "dint/const.h" - -#include -#include -#include -#include -#include - -#include "binfread.h" - -using namespace std; - -void LoadICSTables(RawTotalRate* ICSTotalRate, RawDiffRate* ICSPhotonRate, - RawDiffRate* ICSScatRate, const int num_main_bins, - string aDirTables); -void LoadPPTables(RawTotalRate* PPTotalRate, RawDiffRate* PPDiffRate, - const int num_main_bins, - string aDirTables); -void LoadTPPTables(RawTotalRate* TPPTotalRate, RawDiffRate* TPPDiffRate, - const int num_main_bins, string aDirTables); -void LoadDPPTables(RawTotalRate* DPPRate, const int num_main_bins, - string aDirTables); -void LoadPPPNucleonTables(RawTotalRate* PPPProtonLossRate, - RawTotalRate* PPPNeutronLossRate, - RawDiffRate* PPPProtonScatRate, - RawDiffRate* PPPProtonNeutronRate, - RawDiffRate* PPPNeutronProtonRate, - const int num_main_bins, string aDirTables); -void LoadPPPEMTables(RawDiffRate* PPPProtonPhotonRate, - RawDiffRate* PPPProtonElectronRate, - RawDiffRate* PPPProtonPositronRate, - RawDiffRate* PPPNeutronElectronRate, - const int num_main_bins, string aDirTables); -void LoadNPPNucleonTables(RawTotalRate* NPPTotalRate, const int num_main_bins, - string aDirTables); -void LoadNPPSecondaryTables(RawDiffRate* NPPDiffRate, const int num_main_bins, - string aDirTables); -void LoadPPPNeutrinoTables(RawDiffRate* PPPProtonElectronNeutrinoRate, - RawDiffRate* PPPProtonAntiElectronNeutrinoRate, - RawDiffRate* PPPProtonMuonNeutrinoRate, - RawDiffRate* PPPProtonAntiMuonNeutrinoRate, - RawDiffRate* PPPNeutronAntiElectronNeutrinoRate, - RawDiffRate* PPPNeutronMuonNeutrinoRate, - RawDiffRate* PPPNeutronAntiMuonNeutrinoRate, - const int num_main_bins, string aDirTables); -void LoadNeutronDecayNucleonTables(TotalRate* neutronDecayRate, - DiffRate* neutronDecayProtonRate, - const int num_main_bins, string aDirTables); -void LoadNeutronDecaySecondaryTables(DiffRate* neutronDecayElectronRate, - const int num_main_bins, - string aDirTables); -void LoadNeutrinoTables(const int tauNeutrinoMassSwitch, - TotalRate* NNElNeutTotalRate, - TotalRate* NNMuonNeutTotalRate, - TotalRate* NNTauNeutTotalRate, - DiffRate* NNElNeutScatRate, - DiffRate* NNElNeutMuonNeutRate, - DiffRate* NNElNeutTauNeutRate, - DiffRate* NNElNeutElectronRate, - DiffRate* NNElNeutPhotonRate, - DiffRate* NNElNeutProtonRate, - DiffRate* NNMuonNeutScatRate, - DiffRate* NNMuonNeutElNeutRate, - DiffRate* NNMuonNeutTauNeutRate, - DiffRate* NNMuonNeutElectronRate, - DiffRate* NNMuonNeutPhotonRate, - DiffRate* NNMuonNeutProtonRate, - DiffRate* NNTauNeutScatRate, - DiffRate* NNTauNeutElNeutRate, - DiffRate* NNTauNeutMuonNeutRate, - DiffRate* NNTauNeutElectronRate, - DiffRate* NNTauNeutPhotonRate, - DiffRate* NNTauNeutProtonRate, - const int num_main_bins, string aDirTables); - -#endif diff --git a/libs/dint/include/dint/math_util.h b/libs/dint/include/dint/math_util.h deleted file mode 100644 index 436b201a3..000000000 --- a/libs/dint/include/dint/math_util.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef DINT__MATH_UTIL_H -#define DINT__MATH_UTIL_H - -double DMax(const double double1, const double double2); -double DMin(const double double1, const double double2); -int IMax(const int integer1, const int integer2); -int IMin(const int integer1, const int integer2); - -#endif diff --git a/libs/dint/include/dint/prepare.h b/libs/dint/include/dint/prepare.h deleted file mode 100644 index 55b0e7a8b..000000000 --- a/libs/dint/include/dint/prepare.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef DINT__PREPARE_H -#define DINT__PREPARE_H - -#include -#include "dint/spectrum.h" -#include "dint/cvector.h" - -void SetEnergyBins(const int min_energy_exp, dCVector* pEnergy, - dCVector* pEnergyWidth); -void SetDeltaG(const dCVector* pEnergy, dCVector* pDeltaG); -void GetModeOfInput(FILE* input, int* pInputMethodSwitch); -void BasicParameterInput(FILE* input, const int argc, int* pMinEnergyExp, - int* pNumSmallSteps, - double* pConvergeParameter, - double* pStartingRedshift, - double* pStartingDistanceInMpc); -void InteractionParameterInput(FILE* input, const int argc, - int* pSynchrotronSwitch, double* pB_0, - int* pTauNeutrinoMassSwitch, int* pICSSwitch, - int* pPPSwitch, int* pTPPSwitch, - int* pDPPSwitch, int* pPPPSwitch, - int* pNPPSwitch, int* pNeutronDecaySwitch, - int* pNucleonToSecondarySwitch, - int* pNeutrinoNeutrinoSwitch); -void ModelParameterInput(FILE* input, const int argc, - int* pSourceTypeSwitch, double* pMinDistance, - double* pBrightPhaseExp, int* pModelTypeSwitch); -/* CHANGE (Guenter; 7/20/1998): BrightPhaseExp added */ -void PrepareSpectra(const int sourceTypeSwitch, const Spectrum* pQ_0, - Spectrum* pSpectrum, Spectrum* pSpectrumNew, - Spectrum* pDerivative); -void ComputeTotalInitialContent(const dCVector* pEnergy, const Spectrum* pQ_0, - double* initialPhotonEnergy, - double* initialLeptonEnergy, - double* initialNucleonEnergy, - double* initialNeutrinoEnergy, - double* initialTotalEnergy, - double* initialPhotonNumber, - double* initialLeptonNumber, - double* initialNucleonNumber, - double* initialNeutrinoNumber, - double* initialTotalNumber); -void ComputeContinuousEnergyLoss(const int synchrotronSwitch, - const dCVector* synchrotronLoss, - const dCVector* otherLoss, - dCVector* continuousLoss); - -#endif diff --git a/libs/dint/include/dint/prop_second.h b/libs/dint/include/dint/prop_second.h deleted file mode 100644 index bad37bebf..000000000 --- a/libs/dint/include/dint/prop_second.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef DINT__PROPSECOND_H -#define DINT__PROPSECOND_H - -#include -#include -#include "dint/rate.h" -#include "dint/const.h" -#include "dint/spectrum.h" -#include "dint/cvector.h" -#include "dint/load.h" -#include "dint/prepare.h" -#include "dint/sync.h" -#include "dint/inject.h" -#include "dint/background.h" -#include "dint/fold.h" -#include "dint/advance.h" -#include "dint/final.h" -#include "dint/utilities.h" -#include -#include -#include -#include -#include - -/*-------------------------------------------------------------------------- - prop_second - Main routine for the dint package - E. Armengaud - Jan 2006 ---------------------------------------------------------------------------*/ - -/* - Arguments : - - dist_observer : light travel distance in Mpc - pB_field : in Gauss - pEnergy, pEnergyWidth : in ELECTRON_MASS*eV - apInjectionSpectrum : INPUT mean number of particles per energy bin - pSpectrum : OUTPUT mean number of particles per energy bin - aDirTables : directory for cascade tables - Photon background flags : - aIRFlag = 0 (High IR), 1 (Low IR) or 2 (Primack IR) - aZmax_IR = max redshift of the infrared background - aRadioFlag = 0 (High Radio), 1 (Low Radio), 2 (Obs Radio) or 3 (Null Radio) - Cosmological parameters : H0, Omega_M/Lambda. The unit of H0 is km/s/Mpc - aCutcascade_Magfield : flag to "cut" of the e+/- cascade by the magnetic deflections. -*/ - -/*-------------------------------------------------------------------------- - The routine prop_second, used in CRPropa, propagates an electromagnetic cascade - in the extragalactic medium over a given light travel distance. - - Propagation takes place in redshift space. The energy unit used in dint is m_e (~511 keV). - The distance unit is in cm. - The magnetic field perpendicular to the trajectory must be specified. It can be - inhomogeneous, allowing to take into account probable B field concentrations inside the - clusters. 3 models of homogeneous cosmic IR background and 3 models of cosmic radio - background are implemented. - - The redshift evolution of radio background is consistent with its model (see background.cpp). - The redshift evolution of IR background is the same as for CMB until aZmax_IR. - - The input spectrum must have the same format as the output : - The output is a spectrum, computed for 170 values of energy ranging from 10^7 to 10^24 eV. - - If the aCutcascade_Magfield flag is set : at each step, we define a critical energy E_c - based on the comparison between Larmor, synchrotron and ICS time scales. - Only the electrons with r_Larmor > aCutcascade_Magfield) * min(t_synchrotron,t_ICS) are kept: - this mimics the loss of the cascade due to the deflections (useful for the study of a "point" - source; allows to test roughly the effect of B fields on the 1D approximation for the cascade). ---------------------------------------------------------------------------*/ - -void prop_second(const double dist_observer, - //const double InjEnergy, - //const PARTICLE part, - //const double HInjEnergy, const double deltaE_hadron, - const dCVector* pB_field, - const dCVector* pEnergy, - const dCVector* pEnergyWidth, - Spectrum* apInjectionSpectrum, - Spectrum* pSpectrum, string aDirTables, - const int aIRFlag, const double aZmax_IR, const int aRadioFlag, - const double aH0, const double aOmegaM, const double aOmegaLambda, - const double aCutcascade_Magfield); - -void BuildRedshiftTable(double aH0, double aOmegaM, double aOmegaLambda, - dCVector* pRedshiftArray, dCVector* pDistanceArray); - -double getRedshift(dCVector RedshiftArray, dCVector DistanceArray, double distance) ; -double getDistance(dCVector RedshiftArray, dCVector DistanceArray, double redshift) ; - -#endif diff --git a/libs/dint/include/dint/rate.h b/libs/dint/include/dint/rate.h deleted file mode 100644 index fb3c47f10..000000000 --- a/libs/dint/include/dint/rate.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef DINT__RATE_H -#define DINT__RATE_H - -#include "dint/vector.h" -#include "dint/binfread.h" - -typedef struct -{ - int mainDimension; - int bgDimension; - // int mainDimension2; /* number of daughter bins */ - int numberOfElements; - i3Tensor bound; - dVector diffRate; -} RawDiffRate; -/* although RawDiffRate is really a 3-dimensional matrix, I "serialize" - the matrix to tighten up the memory: instead of using the full - 3-dimensional matrix with lots of zeros, I replace it by a serialized - 1-dimensional array with non-zero elements and with appropriate lower - and upper bounds (bound) */ - -typedef struct -{ - int mainDimension; - int bgDimension; - dMatrix totalRate; -} RawTotalRate; - -typedef struct -{ - int mainDimension; - iMatrix bound; - dMatrix diffRate; -} DiffRate; - -typedef struct -{ - int mainDimension; - dVector totalRate; -} TotalRate; -/* NOTE: all rates are initialized when assigned memory. All bounds are - properly invalidated. */ - - -void NewRawTotalRate(RawTotalRate* pRate, const int num_main_bins, - const int num_bg_bins); -void DeleteRawTotalRate(RawTotalRate* pRate); -void InitializeRawTotalRate(RawTotalRate* pRate); -void CopyRawTotalRate(RawTotalRate* pLRate, const RawTotalRate* pRRate); -void ClipRawTotalRate(RawTotalRate* pRate, const int newSize); -void EnlargeRawTotalRate(RawTotalRate* pRate, const int newSize); -void ModifyRawTotalRate(RawTotalRate* pRate, const int newSize); -void ReadRawTotalRate(RawTotalRate* pRate, const char* filename); - - -void NewRawDiffRate(RawDiffRate* pRate, const int num_main_bins, - const int num_bg_bins, const int num_elements); -void DeleteRawDiffRate(RawDiffRate* pRate); -void InitializeRawDiffRate(RawDiffRate* pRate); -void CheckRawDiffRate(RawDiffRate* pRate); -#ifdef DEBUG -double RawDiffRateElement(const RawDiffRate* pRate, const int i, const int j, - const int k); -/* although this is a very good and safe way of getting the element - it is a very expensive call: it is recommended only for checking */ -#endif -void CopyRawDiffRate(RawDiffRate* pLRate, const RawDiffRate* pRRate); -void CopyRawDiffRateBound(RawDiffRate* pLRate, const RawDiffRate* pRRate); -void ClipRawDiffRate(RawDiffRate* pRate, const int newSize); -void EnlargeRawDiffRate(RawDiffRate* pRate, const int newSize); -void ModifyRawDiffRate(RawDiffRate* pRate, const int newSize); -void ReadRawDiffRate(RawDiffRate* pRate, const char* filename); - - -void NewTotalRate(TotalRate* pRate, const int num_main_bins); -void DeleteTotalRate(TotalRate* pRate); -void InitializeTotalRate(TotalRate* pRate); -void CopyTotalRate(TotalRate* pLRate, const TotalRate* pRRate); -void ClipTotalRate(TotalRate* pRate, const int newSize); -void EnlargeTotalRate(TotalRate* pRate, const int newSize); -void ModifyTotalRate(TotalRate* pRate, const int newSize); -void ReadTotalRate(TotalRate* pRate, const char* filename); - - -void NewDiffRate(DiffRate* pRate, const int num_main_bins); -void DeleteDiffRate(DiffRate* pRate); -void InitializeDiffRate(DiffRate* pRate); -void CopyDiffRate(DiffRate* pLRate, const DiffRate* pRRate); -void ClipDiffRate(DiffRate* pRate, const int newSize); -void EnlargeDiffRate(DiffRate* pRate, const int newSize); -void ModifyDiffRate(DiffRate* pRate, const int newSize); -void ReadDiffRate(DiffRate* pRate, const char* filename); -void CopyDiffRateBound(DiffRate* pLRate, const DiffRate* pRRate); -void SetStandardDiffRateBound(DiffRate* pRate); -/* sets DiffRate bound to 0 <= k <= i */ -void InvalidateDiffRateBound(DiffRate* pRate); - -#endif -/* Copy*Rate: perform real deep copies; i.e. they reformat the dimensions - according to the size of the rate being copied. - Copy*DiffRateBound: copy bounds without altering size. -*/ diff --git a/libs/dint/include/dint/spectrum.h b/libs/dint/include/dint/spectrum.h deleted file mode 100644 index e99ca7c46..000000000 --- a/libs/dint/include/dint/spectrum.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef DINT__SPECTRUM_H -#define DINT__SPECTRUM_H - -#include "dint/vector.h" -#include "dint/cvector.h" - -#define NUM_SPECIES 11 - -typedef enum PARTICLE { - PHOTON = 0, - ELECTRON = 1, - POSITRON = 2, - PROTON = 3, - NEUTRON = 4, - ELECTRON_NEUTRINO = 5, - ANTI_ELECTRON_NEUTRINO = 6, - MUON_NEUTRINO = 7, - ANTI_MUON_NEUTRINO = 8, - TAU_NEUTRINO = 9, - ANTI_TAU_NEUTRINO = 10, - NOTHING = 11 -} PARTICLE; -// NOTHING type added by Gunter (2005) for secondary from pair production - -/* Spectrum is a struct that corresponds to the total spectrum. It - has all particle spectra in it. Since particle data is more or less - fixed and independent, we do not specify the number of particle species. */ -typedef struct Spectrum { - int numberOfMainBins; - dMatrix spectrum; -} Spectrum; - -void NewSpectrum(Spectrum* pSpectrum, const int num_bins); -void DeleteSpectrum(Spectrum* pSpectrum); -void InitializeSpectrum(Spectrum* pSpectrum); -void InitializeEMSpectrum(Spectrum* pSpectrum); -void InitializeNucleonSpectrum(Spectrum* pSpectrum); -void InitializeNeutrinoSpectrum(Spectrum* pSpectrum); -void AddSpectrum(Spectrum* a, const Spectrum* b); -void SetSpectrum(Spectrum* pSpectrum1, const Spectrum* pSpectrum2); -void SetEMSpectrum(Spectrum* pSpectrum1, const Spectrum* pSpectrum2); -void SetNucleonSpectrum(Spectrum* pSpectrum1, const Spectrum* pSpectrum2); -void SetNeutrinoSpectrum(Spectrum* pSpectrum1, const Spectrum* pSpectrum2); -double GetNumber(const Spectrum* pSpectrum); -double GetEMNumber(const Spectrum* pSpectrum); -double GetNucleonNumber(const Spectrum* pSpectrum); -double GetNeutrinoNumber(const Spectrum* pSpectrum); -double GetEnergy(const Spectrum* pSpectrum, const dCVector* pEnergy); -double GetEMEnergy(const Spectrum* pSpectrum, const dCVector* pEnergy); -double GetNucleonEnergy(const Spectrum* pSpectrum, const dCVector* pEnergy); -double GetNeutrinoEnergy(const Spectrum* pSpectrum, const dCVector* pEnergy); -void DumpSpectrum(const dCVector* pEnergy, const dCVector* pEnergyWidth, - const Spectrum* pSpectrum, const char* filename); - -#endif diff --git a/libs/dint/include/dint/sync.h b/libs/dint/include/dint/sync.h deleted file mode 100644 index 043f68f36..000000000 --- a/libs/dint/include/dint/sync.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef DINT__SYNC_H -#define DINT__SYNC_H - -#include "dint/rate.h" -#include "dint/cvector.h" -#include -#include -#include "dint/utilities.h" -#include "dint/const.h" -#include -#include -#include -#include -using namespace std; - -void LoadSyncTable(dCVector* syncTable, string aDirTables); -void InitializeSynchrotron(const double B_0, const dCVector* pEnergy, - const dCVector* pEnergyWidth, - dCVector* synchrotronLoss, DiffRate* syncRate, - string aDirTables); - -#endif diff --git a/libs/dint/include/dint/utilities.h b/libs/dint/include/dint/utilities.h deleted file mode 100644 index fc30d0c4c..000000000 --- a/libs/dint/include/dint/utilities.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef DINT__UTILITIES_H -#define DINT__UTILITIES_H - -#include "dint/error.h" -#include "dint/io_util.h" -#include "dint/math_util.h" - -#include "dint/check.h" - -#endif diff --git a/libs/dint/include/dint/vector.h b/libs/dint/include/dint/vector.h deleted file mode 100644 index efa6098f5..000000000 --- a/libs/dint/include/dint/vector.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef DINT__VECTOR_H -#define DINT__VECTOR_H - -/* Vectors, matrices, and tensors defined here are very simple, dynamic - objects. They do not provide any bound checking nor has extra data - structure, but have very little overhead because of that. For structs - that have dimensional data built-in, see "cvector.h". -*/ - -typedef double* dVector; -typedef int* iVector; -typedef double** dMatrix; -typedef int** iMatrix; -typedef double*** d3Tensor; -typedef int*** i3Tensor; - - -dVector New_dVector(const int n); -iVector New_iVector(const int n); -dMatrix New_dMatrix(const int n1, const int n2); -iMatrix New_iMatrix(const int n1, const int n2); -d3Tensor New_d3Tensor(const int n1, const int n2, const int n3); -i3Tensor New_i3Tensor(const int n1, const int n2, const int n3); -void Delete_dVector(dVector vector); -void Delete_iVector(iVector vector); -void Delete_dMatrix(dMatrix matrix); -void Delete_iMatrix(iMatrix matrix); -void Delete_d3Tensor(d3Tensor tensor); -void Delete_i3Tensor(i3Tensor tensor); - -#endif diff --git a/libs/dint/src/DintEMCascade.cpp b/libs/dint/src/DintEMCascade.cpp deleted file mode 100644 index bee94c9bc..000000000 --- a/libs/dint/src/DintEMCascade.cpp +++ /dev/null @@ -1,363 +0,0 @@ -#include "dint/prop_second.h" -#include "dint/DintEMCascade.h" - -#include -#include -#include - - -DintEMCascade::DintEMCascade(int _aIRFlag, int _aRadioFlag, string _aDirTables, - double B, double _aH0, double _aOmegaM, double - _aOmegaLambda) : synchrotronSwitch(1), sourceTypeSwitch(0), - tauNeutrinoMassSwitch(1), ICSSwitch(1), PPSwitch(1), TPPSwitch(1), - DPPSwitch(1), PPPSwitch(0), NPPSwitch(0), neutronDecaySwitch(0), - nucleonToSecondarySwitch(0), neutrinoNeutrinoSwitch(0), aIRFlag(_aIRFlag), - aRadioFlag(_aRadioFlag), aH0(_aH0), aOmegaM(_aOmegaM), - aOmegaLambda(_aOmegaLambda), aZmax_IR(5.), aDirTables(_aDirTables) -{ - BuildRedshiftTable(aH0, aOmegaM, aOmegaLambda, &RedshiftArray, &DistanceArray) ; - - // Initialize the bField - New_dCVector(&pB_field, 1); - for (size_t i = 0; i < 1; i++) - pB_field.vector[i] = B; // B in gauss - - //-------- Set up energy bins -------- - New_dCVector(&deltaG, NUM_MAIN_BINS); - New_dCVector(&bgEnergy, NUM_BG_BINS); - New_dCVector(&bgEnergyWidth, NUM_BG_BINS); - New_dCVector(&bgPhotonDensity, NUM_BG_BINS); - - New_dCVector(&pEnergy, NUM_MAIN_BINS); - New_dCVector(&pEnergyWidth, NUM_MAIN_BINS); - SetEnergyBins(MIN_ENERGY_EXP, &pEnergy, &pEnergyWidth); - - // set energy bins - SetDeltaG(&pEnergy, &deltaG); - - SetEnergyBins(BG_MIN_ENERGY_EXP, &bgEnergy, &bgEnergyWidth); - - NewSpectrum(&Q_0, NUM_MAIN_BINS); - NewSpectrum(&spectrumNew, NUM_MAIN_BINS); - NewSpectrum(&derivative, NUM_MAIN_BINS); - - New_dCVector(&synchrotronLoss, NUM_MAIN_BINS); - New_dCVector(&otherLoss, NUM_MAIN_BINS); - New_dCVector(&continuousLoss, NUM_MAIN_BINS); - - if (ICSSwitch == 1) { - NewRawTotalRate(&ICSTotalRate, EM_NUM_MAIN_BINS, NUM_BG_BINS); - NewRawDiffRate(&ICSPhotonRate, EM_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_IP_ELEMENTS); - NewRawDiffRate(&ICSScatRate, EM_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_IS_ELEMENTS); - } - - if (PPSwitch == 1) { - NewRawTotalRate(&PPTotalRate, EM_NUM_MAIN_BINS, NUM_BG_BINS); - NewRawDiffRate(&PPDiffRate, EM_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_PP_ELEMENTS); - } - - if (TPPSwitch == 1) { - NewRawTotalRate(&TPPTotalRate, EM_NUM_MAIN_BINS, NUM_BG_BINS); - NewRawDiffRate(&TPPDiffRate, EM_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_TPP_ELEMENTS); - } - - if (DPPSwitch == 1) - NewRawTotalRate(&DPPRate, EM_NUM_MAIN_BINS, NUM_BG_BINS); - - //---- read in coefficient tables; clipping is done here if necessary ---- - if (ICSSwitch == 1) - LoadICSTables(&ICSTotalRate, &ICSPhotonRate, &ICSScatRate, - NUM_MAIN_BINS, aDirTables); - if (PPSwitch == 1) - LoadPPTables(&PPTotalRate, &PPDiffRate, NUM_MAIN_BINS, aDirTables); - if (TPPSwitch == 1) - LoadTPPTables(&TPPTotalRate, &TPPDiffRate, NUM_MAIN_BINS, aDirTables); - if (DPPSwitch == 1) - LoadDPPTables(&DPPRate, NUM_MAIN_BINS, aDirTables); - - NewTotalRate(&leptonTotalRate, NUM_MAIN_BINS); - NewTotalRate(&photonTotalRate, NUM_MAIN_BINS); - - NewTotalRate(&protonTotalRate, NUM_MAIN_BINS); - NewTotalRate(&neutronTotalRate, NUM_MAIN_BINS); - - NewDiffRate(&leptonScatRate, NUM_MAIN_BINS); - NewDiffRate(&leptonExchRate, NUM_MAIN_BINS); - NewDiffRate(&leptonPhotonRate, NUM_MAIN_BINS); - NewDiffRate(&photonLeptonRate, NUM_MAIN_BINS); - - NewDiffRate(&protonScatRate, NUM_MAIN_BINS); - NewDiffRate(&protonNeutronRate, NUM_MAIN_BINS); - NewDiffRate(&neutronProtonRate, NUM_MAIN_BINS); - NewDiffRate(&protonPhotonRate, NUM_MAIN_BINS); - NewDiffRate(&protonElectronRate, NUM_MAIN_BINS); - NewDiffRate(&protonPositronRate, NUM_MAIN_BINS); - NewDiffRate(&neutronElectronRate, NUM_MAIN_BINS); - NewDiffRate(&neutronPositronRate, NUM_MAIN_BINS); - NewDiffRate(&protonElectronNeutrinoRate, NUM_MAIN_BINS); - NewDiffRate(&protonAntiElectronNeutrinoRate, NUM_MAIN_BINS); - NewDiffRate(&protonMuonNeutrinoRate, NUM_MAIN_BINS); - NewDiffRate(&protonAntiMuonNeutrinoRate, NUM_MAIN_BINS); - NewDiffRate(&neutronAntiElectronNeutrinoRate, NUM_MAIN_BINS); - NewDiffRate(&neutronMuonNeutrinoRate, NUM_MAIN_BINS); - NewDiffRate(&neutronAntiMuonNeutrinoRate, NUM_MAIN_BINS); - - NewTotalRate(&elNeutTotalRate, NUM_MAIN_BINS); - NewTotalRate(&muonNeutTotalRate, NUM_MAIN_BINS); - NewTotalRate(&tauNeutTotalRate, NUM_MAIN_BINS); - - NewDiffRate(&elNeutElectronRate, NUM_MAIN_BINS); - NewDiffRate(&elNeutPhotonRate, NUM_MAIN_BINS); - NewDiffRate(&muonNeutElectronRate, NUM_MAIN_BINS); - NewDiffRate(&muonNeutPhotonRate, NUM_MAIN_BINS); - NewDiffRate(&tauNeutElectronRate, NUM_MAIN_BINS); - NewDiffRate(&tauNeutPhotonRate, NUM_MAIN_BINS); -} - -DintEMCascade::~DintEMCascade() -{ - DeleteDiffRate(&leptonScatRate); - DeleteDiffRate(&leptonExchRate); - DeleteDiffRate(&leptonPhotonRate); - DeleteDiffRate(&photonLeptonRate); - DeleteDiffRate(&protonScatRate); - DeleteDiffRate(&protonNeutronRate); - DeleteDiffRate(&neutronProtonRate); - DeleteDiffRate(&protonPhotonRate); - DeleteDiffRate(&protonElectronRate); - DeleteDiffRate(&protonPositronRate); - DeleteDiffRate(&neutronElectronRate); - DeleteDiffRate(&neutronPositronRate); - DeleteDiffRate(&protonElectronNeutrinoRate); - DeleteDiffRate(&protonAntiElectronNeutrinoRate); - DeleteDiffRate(&protonMuonNeutrinoRate); - DeleteDiffRate(&protonAntiMuonNeutrinoRate); - DeleteDiffRate(&neutronAntiElectronNeutrinoRate); - DeleteDiffRate(&neutronMuonNeutrinoRate); - DeleteDiffRate(&neutronAntiMuonNeutrinoRate); - - DeleteDiffRate(&elNeutElectronRate); - DeleteDiffRate(&elNeutPhotonRate); - DeleteDiffRate(&muonNeutElectronRate); - DeleteDiffRate(&muonNeutPhotonRate); - DeleteDiffRate(&tauNeutElectronRate); - DeleteDiffRate(&tauNeutPhotonRate); - - DeleteTotalRate(&leptonTotalRate); - DeleteTotalRate(&photonTotalRate); - DeleteTotalRate(&protonTotalRate); - DeleteTotalRate(&neutronTotalRate); - DeleteTotalRate(&elNeutTotalRate); - DeleteTotalRate(&muonNeutTotalRate); - DeleteTotalRate(&tauNeutTotalRate); - - if (ICSSwitch == 1) { - DeleteRawDiffRate(&ICSPhotonRate); - DeleteRawDiffRate(&ICSScatRate); - DeleteRawTotalRate(&ICSTotalRate); - } - if (PPSwitch == 1) { - DeleteRawDiffRate(&PPDiffRate); - DeleteRawTotalRate(&PPTotalRate); - } - if (TPPSwitch == 1) { - DeleteRawDiffRate(&TPPDiffRate); - DeleteRawTotalRate(&TPPTotalRate); - } - if (DPPSwitch == 1) - DeleteRawTotalRate(&DPPRate); - - DeleteSpectrum(&Q_0); - DeleteSpectrum(&spectrumNew); - DeleteSpectrum(&derivative); - - Delete_dCVector(&synchrotronLoss); - Delete_dCVector(&continuousLoss); - Delete_dCVector(&otherLoss); - - Delete_dCVector(&deltaG); - Delete_dCVector(&bgEnergy); - Delete_dCVector(&bgEnergyWidth); - Delete_dCVector(&bgPhotonDensity); - - Delete_dCVector(&RedshiftArray) ; - Delete_dCVector(&DistanceArray) ; - - Delete_dCVector(&pEnergy); - Delete_dCVector(&pEnergyWidth); -} - - -void DintEMCascade::propagate(const double start_distance, - const double stop_distance, Spectrum* apInjectionSpectrum, - Spectrum* pSpectrum, const double aCutcascade_Magfield) { - - double convergeParameter = 1.e-8; - - // -------- Redshift Estimation --------------- - double startingRedshift = getRedshift(RedshiftArray, DistanceArray, start_distance) ; - double stopRedshift = getRedshift(RedshiftArray, DistanceArray, stop_distance) ; - - double minDistance = 0.; - double brightPhaseExp = 0.; - - //---- Initialize distance ---- - - SetSpectrum(&Q_0, apInjectionSpectrum) ; - PrepareSpectra(sourceTypeSwitch, &Q_0, pSpectrum, &spectrumNew, &derivative); - - //--------- START of actual computation -------- - //---- initialize indices and parameters ---- - double leftRedshift = startingRedshift; - double deltaRedshift = 1. - (pEnergy.vector)[2]/(pEnergy.vector)[3]; - int lastIndex = 0; - double propagatingDistance = 0.; - double distance = 0.; // distance variable: dist in FORTRAN - - //-------- This is where propagation takes place -------- - do { - double rightRedshift, centralRedshift; - // this firstIndex & lastIndex pair is used to bin redshift finer - // near the end of propagation (z close to 0) - ComputeRedshifts(sourceTypeSwitch, leftRedshift, &deltaRedshift, - &rightRedshift, ¢ralRedshift, &lastIndex); - // limit the distance step to the stop redshift - if (rightRedshift < stopRedshift) - rightRedshift = stopRedshift; - - //---- compute various distance parameters ---- - double redshiftRatio = (1. + rightRedshift)/(1. + leftRedshift); - - // (cosmological parameters added July 2005) - double leftDistance = getDistance(RedshiftArray,DistanceArray,leftRedshift) ; - double rightDistance = getDistance(RedshiftArray,DistanceArray,rightRedshift) ; - double distanceStep = leftDistance - rightDistance ; - distance += distanceStep; - - int numSmallSteps = (int)(ceil(distanceStep/DISTANCE_UNIT/DMAX)); - double smallDistanceStep = distanceStep/DISTANCE_UNIT/numSmallSteps; - double x = 0.; - - //---- compute the photon background at given redshift ---- - LoadPhotonBackground(centralRedshift, &bgEnergy, &bgEnergyWidth, - &bgPhotonDensity, aIRFlag, aZmax_IR, aRadioFlag, - aH0, aOmegaM, aOmegaLambda); - - //---- initialize rates ---- - InitializeLeptonCoefficients(&leptonTotalRate, &leptonScatRate, - &leptonExchRate, &leptonPhotonRate); - InitializePhotonCoefficients(&photonTotalRate, &photonLeptonRate); - - Initialize_dCVector(&continuousLoss); - - Initialize_dCVector(&otherLoss); - - //---- fold interaction rates w/ photon background ---- - if (ICSSwitch == 1) - FoldICS(&bgPhotonDensity, &ICSTotalRate, &ICSPhotonRate, - &ICSScatRate, &leptonTotalRate, &leptonPhotonRate, - &leptonScatRate); - if (TPPSwitch == 1) - FoldTPP(&bgPhotonDensity, &pEnergy, &TPPTotalRate, &TPPDiffRate, - &leptonTotalRate, &leptonScatRate, &leptonExchRate, - &otherLoss); - if (PPSwitch == 1) - FoldPP(&bgPhotonDensity, &PPTotalRate, &PPDiffRate, - &photonTotalRate, &photonLeptonRate); - if (DPPSwitch == 1) - FoldDPP(&bgPhotonDensity, &DPPRate, &photonTotalRate, - &photonLeptonRate); - - //---- main iteration (convergence) block ---- - - for (int loopCounter = 0; loopCounter < numSmallSteps; loopCounter++) - { - double B_loc = 0; - if (synchrotronSwitch == 1) - { - NewDiffRate(&syncRate, NUM_MAIN_BINS); - int B_bins = pB_field.dimension; - int B_bin = (int)((double)(B_bins)*(propagatingDistance+x)/1.e6/ - start_distance); - B_loc=(pB_field.vector)[B_bin]; - InitializeSynchrotron(B_loc, &pEnergy, &pEnergyWidth, - &synchrotronLoss, &syncRate, - aDirTables); - } - //---- compute continuous energy loss for electrons ---- - ComputeContinuousEnergyLoss(synchrotronSwitch, &synchrotronLoss, - &otherLoss, &continuousLoss); - - // used for source evolution, disabled here - double bkgFactor = 1.; - double evolutionFactor = 0; - - AdvanceEMStep(sourceTypeSwitch, PPSwitch, ICSSwitch, - TPPSwitch, DPPSwitch, synchrotronSwitch, PPPSwitch, - NPPSwitch, neutronDecaySwitch, nucleonToSecondarySwitch, - neutrinoNeutrinoSwitch, smallDistanceStep, evolutionFactor, - convergeParameter, bkgFactor, &Q_0, &photonLeptonRate, - &protonElectronRate, &neutronPositronRate, - &protonPositronRate, &neutronElectronRate, - &neutronDecayElectronRate, &elNeutElectronRate, - &muonNeutElectronRate, &tauNeutElectronRate, - &protonPhotonRate, &elNeutPhotonRate, &muonNeutPhotonRate, - &tauNeutPhotonRate, &leptonTotalRate, &leptonScatRate, - &leptonExchRate, &continuousLoss, &deltaG, &photonTotalRate, - &leptonPhotonRate, &syncRate, pSpectrum, &spectrumNew); - - SetEMSpectrum(pSpectrum, &spectrumNew); - // update spectrum - - if (aCutcascade_Magfield != 0 && B_loc != 0 ) - { - // Estimate the effect of B field on the 1D approximation (added E.A. June 2006) - bool lEcFlag = 0 ; - int lIndex = 0; - - double a_ics = (3.-log10(4.))/4. ; - double b_ics = pow(10.,8.-7.*a_ics) ; - while (!lEcFlag) - { - double lEnergy = (pEnergy.vector)[lIndex] ; - // Time scales are computed in parsec - double t_sync = 3.84e6/(lEnergy*B_loc*B_loc*ELECTRON_MASS) ; - double t_larmor = (1.1e-21)*ELECTRON_MASS*lEnergy/(B_loc*aCutcascade_Magfield) ; - double t_ics; - if (lEnergy <= 1.e15/ELECTRON_MASS) { - t_ics = 4.e2*1.e15/(ELECTRON_MASS*lEnergy) ; - } else if (lEnergy <= 1.e18/ELECTRON_MASS) { - t_ics = 4.e2*lEnergy*ELECTRON_MASS/1.e15 ; - } else if (lEnergy <= 1.e22/ELECTRON_MASS) { - t_ics = b_ics*pow(lEnergy*ELECTRON_MASS/1.e15,a_ics) ; - } else t_ics = 1.e8*lEnergy*ELECTRON_MASS/1.e22 ; - if (t_larmor >= t_sync || t_larmor >= t_ics) lEcFlag = 1 ; - // defines the "critical" energy : the e+/- spectrum is set to 0 for Espectrum)[ELECTRON][lIndex]=0 ; - (pSpectrum->spectrum)[POSITRON][lIndex]=0 ; - lIndex++ ; - } - } - - if (synchrotronSwitch == 1) // synchrotron == true (on) - DeleteDiffRate(&syncRate); - - x += smallDistanceStep; - } // for loopCounter < numSmallSteps - - propagatingDistance += x; // increment distance - - //---- redshift bins down ---- - // Force redshiftdown to use more accurate method, see issue #174 - RedshiftDown(-1, redshiftRatio, &pEnergy, pSpectrum, &spectrumNew); - - //---- prepare for new step ---- - leftRedshift = rightRedshift; - } while ((lastIndex != 1) && (leftRedshift > stopRedshift)); - -} - diff --git a/libs/dint/src/advance.cpp b/libs/dint/src/advance.cpp deleted file mode 100644 index fdecf1248..000000000 --- a/libs/dint/src/advance.cpp +++ /dev/null @@ -1,845 +0,0 @@ - -#include "dint/advance.h" - -#ifdef DEBUG -void PrintEnergy(const dCVector* pArray, const dCVector* pEnergy) -{ - double temp = 0.; - int i; - - if (pArray->dimension != pEnergy->dimension) - { - Error("PrintEnergy: inconsistent dimensions", PROGRAM_ERROR); - } - - for (i = 0; i < pEnergy->dimension; i++) - { - temp += (pArray->vector)[i]*(pEnergy->vector)[i]; - } - - printf("%15.6E\n", temp); -} -#endif - -void ComputeRedshifts(const int sourceTypeSwitch, const double leftRedshift, - double* pDeltaRedshift, double* pRightRedshift, - double* pCentralRedshift, int* pLastIndex) { - double clusterRedshift,localRedshift,minRedshift,maxRedshift; - - clusterRedshift = pow(1.-1.5e5*H_0/C*CLUSTER_DISTANCE,-2./3.)-1.; - localRedshift = pow(1.-1.5e5*H_0/C*SOURCE_CLUSTER_DISTANCE,-2./3.)-1.; - maxRedshift = localRedshift; - minRedshift = maxRedshift; - if (clusterRedshift > maxRedshift) - maxRedshift = clusterRedshift; - else - minRedshift = clusterRedshift; - if (sourceTypeSwitch == 0) - minRedshift = maxRedshift; - - if ((*pLastIndex == 0) && (leftRedshift < 0.6)) { - *pDeltaRedshift /= 2.; - *pLastIndex = 3; - } - *pRightRedshift = leftRedshift - (1. + leftRedshift)*(*pDeltaRedshift); - if (*pRightRedshift < 0.) { - *pRightRedshift = 0.; - *pLastIndex = 1; - } - *pCentralRedshift = (leftRedshift + *pRightRedshift)/2.; - if ((*pLastIndex == 1) && (*pCentralRedshift > maxRedshift)) { - *pRightRedshift = maxRedshift; - *pCentralRedshift = (leftRedshift + *pRightRedshift)/2.; - *pLastIndex = 2; - } - - if ((*pLastIndex == 1) && (*pCentralRedshift > minRedshift)) { - *pRightRedshift = minRedshift; - *pCentralRedshift = (leftRedshift + *pRightRedshift)/2.; - *pLastIndex = 2; - } - -} - -void AdvanceNucleonStep(const int sourceTypeSwitch, - const int PPPSwitch, const int NPPSwitch, - const int neutronDecaySwitch, - const int neutrinoNeutrinoSwitch, - const double smallDistanceStep, - const double evolutionFactor, - const double convergeParameter, - const double bkgFactor, - const Spectrum* pQ_0, - const DiffRate* elNeutProtonRate, - const DiffRate* muonNeutProtonRate, - const DiffRate* tauNeutProtonRate, - const TotalRate* protonTotalRate, - const TotalRate* neutronTotalRate, - const TotalRate* neutronDecayRate, - const DiffRate* protonScatRate, - const DiffRate* protonNeutronRate, - const DiffRate* neutronProtonRate, - const DiffRate* neutronDecayProtonRate, - const dCVector* protonContinuousLoss, - const dCVector* deltaG, const Spectrum* pSpectrum, - Spectrum* pSpectrumNew) { - Spectrum spectrumTemp; - Spectrum influx; - Spectrum influx0; - Spectrum influxExt; - Spectrum outflux; - int num_main_bins; - double changeMax; - - num_main_bins = pSpectrum->numberOfMainBins; - - NewSpectrum(&spectrumTemp, num_main_bins); - NewSpectrum(&influx, num_main_bins); - NewSpectrum(&influx0, num_main_bins); - NewSpectrum(&influxExt, num_main_bins); - NewSpectrum(&outflux, num_main_bins); - - GetExternalFlux(sourceTypeSwitch, evolutionFactor, PROTON, pQ_0, - &influxExt); - GetExternalFlux(sourceTypeSwitch, evolutionFactor, NEUTRON, pQ_0, - &influxExt); - - if (neutrinoNeutrinoSwitch == 1) - GetNucleonInfluxFromNeutrinos(bkgFactor, elNeutProtonRate, - muonNeutProtonRate, tauNeutProtonRate, - pSpectrumNew, &influx0); - - do { - SetNucleonSpectrum(&spectrumTemp, pSpectrumNew); - - InitializeSpectrum(&influx); - InitializeSpectrum(&outflux); - - if ((PPPSwitch == 1) || (NPPSwitch == 1) || - (neutronDecaySwitch == 1)) { - // call all the processes that produce nucleons from nucleons - GetNucleonFluxFromNucleons(neutronDecaySwitch, protonTotalRate, - neutronTotalRate, neutronDecayRate, protonScatRate, - neutronProtonRate, protonNeutronRate, - neutronDecayProtonRate, protonContinuousLoss, - deltaG, pSpectrumNew, &influx, &outflux); - } - - ImplicitEquation(smallDistanceStep, PROTON, &influx, &influx0, - &influxExt, &outflux, pSpectrum, pSpectrumNew); - ImplicitEquation(smallDistanceStep, NEUTRON, &influx, &influx0, - &influxExt, &outflux, pSpectrum, pSpectrumNew); - - changeMax = 0.; - ComputeChange(&spectrumTemp, pSpectrumNew, PROTON, &changeMax); - ComputeChange(&spectrumTemp, pSpectrumNew, NEUTRON, &changeMax); - } while (changeMax > convergeParameter); - - DeleteSpectrum(&spectrumTemp); - DeleteSpectrum(&influx); - DeleteSpectrum(&influx0); - DeleteSpectrum(&influxExt); - DeleteSpectrum(&outflux); -} - - -void AdvanceNeutrinoStep(const int sourceTypeSwitch, - const int neutrinoNeutrinoSwitch, - const int PPPSwitch, - const int neutronDecaySwitch, - const int nucleonToSecondarySwitch, - const double smallDistanceStep, - const double evolutionFactor, - const double convergeParameter, - const double bkgFactor, - const Spectrum* pQ_0, - const DiffRate* protonMuonNeutrinoRate, - const DiffRate* neutronAntiMuonNeutrinoRate, - const DiffRate* protonAntiMuonNeutrinoRate, - const DiffRate* neutronMuonNeutrinoRate, - const DiffRate* protonElectronNeutrinoRate, - const DiffRate* neutronAntiElectronNeutrinoRate, - const DiffRate* protonAntiElectronNeutrinoRate, - const DiffRate* neutronDecayElectronRate, - const TotalRate* elNeutTotalRate, - const TotalRate* muonNeutTotalRate, - const TotalRate* tauNeutTotalRate, - const DiffRate* elNeutScatRate, - const DiffRate* elNeutMuonNeutRate, - const DiffRate* elNeutTauNeutRate, - const DiffRate* muonNeutElNeutRate, - const DiffRate* muonNeutScatRate, - const DiffRate* muonNeutTauNeutRate, - const DiffRate* tauNeutElNeutRate, - const DiffRate* tauNeutMuonNeutRate, - const DiffRate* tauNeutScatRate, - const Spectrum* pSpectrum, Spectrum* pSpectrumNew) { - double changeMax; - int num_main_bins; - Spectrum spectrumTemp; - Spectrum influx; - Spectrum influx0; - Spectrum influxExt; - Spectrum outflux; - - num_main_bins = pSpectrum->numberOfMainBins; - - NewSpectrum(&spectrumTemp, num_main_bins); - NewSpectrum(&influx, num_main_bins); - NewSpectrum(&influx0, num_main_bins); - NewSpectrum(&influxExt, num_main_bins); - NewSpectrum(&outflux, num_main_bins); - - // SetNeutrinoSpectrum(spectrumNew, spectrum); - - GetExternalFlux(sourceTypeSwitch, evolutionFactor, MUON_NEUTRINO, pQ_0, - &influxExt); - GetExternalFlux(sourceTypeSwitch, evolutionFactor, ANTI_MUON_NEUTRINO, - pQ_0, &influxExt); - GetExternalFlux(sourceTypeSwitch, evolutionFactor, ELECTRON_NEUTRINO, pQ_0, - &influxExt); - GetExternalFlux(sourceTypeSwitch, evolutionFactor, ANTI_ELECTRON_NEUTRINO, - pQ_0, &influxExt); - GetExternalFlux(sourceTypeSwitch, evolutionFactor, TAU_NEUTRINO, pQ_0, - &influxExt); - GetExternalFlux(sourceTypeSwitch, evolutionFactor, ANTI_TAU_NEUTRINO, pQ_0, - &influxExt); - - InitializeSpectrum(&influx0); - /* this is not really necessary but will keep it for redundancy */ - - /* neutrino influx from nucleons */ - if (nucleonToSecondarySwitch == 1) - { - if ((PPPSwitch == 1) || (neutronDecaySwitch == 1)) - { - GetNeutrinoInfluxFromNucleons(neutronDecaySwitch, - protonMuonNeutrinoRate, neutronAntiMuonNeutrinoRate, - neutronMuonNeutrinoRate, protonAntiMuonNeutrinoRate, - protonElectronNeutrinoRate, neutronAntiElectronNeutrinoRate, - protonAntiElectronNeutrinoRate, neutronDecayElectronRate, - pSpectrumNew, &influx0); - } - } - - do { - SetNeutrinoSpectrum(&spectrumTemp, pSpectrumNew); - - InitializeSpectrum(&influx); - InitializeSpectrum(&outflux); - - /* call processes that produce neutrinos from neutrinos */ - if (neutrinoNeutrinoSwitch == 1) - { - GetNeutrinoFluxFromNeutrinos(bkgFactor, elNeutTotalRate, - muonNeutTotalRate, - tauNeutTotalRate, elNeutScatRate, elNeutMuonNeutRate, - elNeutTauNeutRate, muonNeutElNeutRate, muonNeutScatRate, - muonNeutTauNeutRate, tauNeutElNeutRate, tauNeutMuonNeutRate, - tauNeutScatRate, pSpectrumNew, &influx, &outflux); - } - - ImplicitEquation(smallDistanceStep, MUON_NEUTRINO, &influx, - &influx0, &influxExt, &outflux, pSpectrum, pSpectrumNew); - ImplicitEquation(smallDistanceStep, ANTI_MUON_NEUTRINO, &influx, - &influx0, &influxExt, &outflux, pSpectrum, pSpectrumNew); - ImplicitEquation(smallDistanceStep, ELECTRON_NEUTRINO, &influx, - &influx0, &influxExt, &outflux, pSpectrum, pSpectrumNew); - ImplicitEquation(smallDistanceStep, ANTI_ELECTRON_NEUTRINO, &influx, - &influx0, &influxExt, &outflux, pSpectrum, pSpectrumNew); - ImplicitEquation(smallDistanceStep, TAU_NEUTRINO, &influx, - &influx0, &influxExt, &outflux, pSpectrum, pSpectrumNew); - ImplicitEquation(smallDistanceStep, ANTI_TAU_NEUTRINO, &influx, - &influx0, &influxExt, &outflux, pSpectrum, pSpectrumNew); - - changeMax = 0.; - ComputeChange(&spectrumTemp, pSpectrumNew, ELECTRON_NEUTRINO, - &changeMax); - ComputeChange(&spectrumTemp, pSpectrumNew, ANTI_ELECTRON_NEUTRINO, - &changeMax); - ComputeChange(&spectrumTemp, pSpectrumNew, MUON_NEUTRINO, - &changeMax); - ComputeChange(&spectrumTemp, pSpectrumNew, ANTI_MUON_NEUTRINO, - &changeMax); - ComputeChange(&spectrumTemp, pSpectrumNew, TAU_NEUTRINO, - &changeMax); - ComputeChange(&spectrumTemp, pSpectrumNew, ANTI_TAU_NEUTRINO, - &changeMax); - } while (changeMax > convergeParameter); - - DeleteSpectrum(&spectrumTemp); - DeleteSpectrum(&influx); - DeleteSpectrum(&influx0); - DeleteSpectrum(&influxExt); - DeleteSpectrum(&outflux); -} - -void AdvanceNucNeutStep(const int sourceTypeSwitch, - const int PPPSwitch, const int NPPSwitch, - const int neutronDecaySwitch, - const int nucleonToSecondarySwitch, - const int neutrinoNeutrinoSwitch, - const double smallDistanceStep, - const double evolutionFactor, - const double convergeParameter, - const double bkgFactor, - const Spectrum* pQ_0, - const DiffRate* elNeutProtonRate, - const DiffRate* muonNeutProtonRate, - const DiffRate* tauNeutProtonRate, - const TotalRate* protonTotalRate, - const TotalRate* neutronTotalRate, - const TotalRate* neutronDecayRate, - const DiffRate* protonScatRate, - const DiffRate* protonNeutronRate, - const DiffRate* neutronProtonRate, - const DiffRate* neutronDecayProtonRate, - const DiffRate* protonMuonNeutrinoRate, - const DiffRate* neutronAntiMuonNeutrinoRate, - const DiffRate* protonAntiMuonNeutrinoRate, - const DiffRate* neutronMuonNeutrinoRate, - const DiffRate* protonElectronNeutrinoRate, - const DiffRate* neutronAntiElectronNeutrinoRate, - const DiffRate* protonAntiElectronNeutrinoRate, - const DiffRate* neutronDecayElectronRate, - const TotalRate* elNeutTotalRate, - const TotalRate* muonNeutTotalRate, - const TotalRate* tauNeutTotalRate, - const DiffRate* elNeutScatRate, - const DiffRate* elNeutMuonNeutRate, - const DiffRate* elNeutTauNeutRate, - const DiffRate* muonNeutElNeutRate, - const DiffRate* muonNeutScatRate, - const DiffRate* muonNeutTauNeutRate, - const DiffRate* tauNeutElNeutRate, - const DiffRate* tauNeutMuonNeutRate, - const DiffRate* tauNeutScatRate, - const dCVector* protonContinuousLoss, - const dCVector* deltaG, const Spectrum* pSpectrum, - Spectrum* pSpectrumNew) -{ - Spectrum spectrumGlobalTemp; - /* temporary spectrum used in swapping spectra */ - double changeGlobal; - int num_main_bins; - - num_main_bins = pSpectrum->numberOfMainBins; - - NewSpectrum(&spectrumGlobalTemp, num_main_bins); - - do { - SetNucleonSpectrum(&spectrumGlobalTemp, pSpectrumNew); - SetNeutrinoSpectrum(&spectrumGlobalTemp, pSpectrumNew); - - - AdvanceNucleonStep(sourceTypeSwitch, PPPSwitch, NPPSwitch, - neutronDecaySwitch, neutrinoNeutrinoSwitch, smallDistanceStep, - evolutionFactor, convergeParameter, bkgFactor, pQ_0, - elNeutProtonRate, muonNeutProtonRate, tauNeutProtonRate, - protonTotalRate, neutronTotalRate, neutronDecayRate, - protonScatRate, protonNeutronRate, neutronProtonRate, - neutronDecayProtonRate, protonContinuousLoss, deltaG, pSpectrum, - pSpectrumNew); - - AdvanceNeutrinoStep(sourceTypeSwitch, neutrinoNeutrinoSwitch, - PPPSwitch, neutronDecaySwitch, nucleonToSecondarySwitch, - smallDistanceStep, evolutionFactor, convergeParameter, bkgFactor, - pQ_0, protonMuonNeutrinoRate, neutronAntiMuonNeutrinoRate, - protonAntiMuonNeutrinoRate, neutronMuonNeutrinoRate, - protonElectronNeutrinoRate, neutronAntiElectronNeutrinoRate, - protonAntiElectronNeutrinoRate, neutronDecayElectronRate, - elNeutTotalRate, muonNeutTotalRate, tauNeutTotalRate, - elNeutScatRate, elNeutMuonNeutRate, elNeutTauNeutRate, - muonNeutElNeutRate, muonNeutScatRate, muonNeutTauNeutRate, - tauNeutElNeutRate, tauNeutMuonNeutRate, tauNeutScatRate, - pSpectrum, pSpectrumNew); - - /*global convergence */ - changeGlobal = 0.; - ComputeChange(&spectrumGlobalTemp, pSpectrumNew, PROTON, - &changeGlobal); - ComputeChange(&spectrumGlobalTemp, pSpectrumNew, NEUTRON, - &changeGlobal); - ComputeChange(&spectrumGlobalTemp, pSpectrumNew, ELECTRON_NEUTRINO, - &changeGlobal); - ComputeChange(&spectrumGlobalTemp, pSpectrumNew, - ANTI_ELECTRON_NEUTRINO, &changeGlobal); - ComputeChange(&spectrumGlobalTemp, pSpectrumNew, MUON_NEUTRINO, - &changeGlobal); - ComputeChange(&spectrumGlobalTemp, pSpectrumNew, ANTI_MUON_NEUTRINO, - &changeGlobal); - ComputeChange(&spectrumGlobalTemp, pSpectrumNew, TAU_NEUTRINO, - &changeGlobal); - ComputeChange(&spectrumGlobalTemp, pSpectrumNew, ANTI_TAU_NEUTRINO, - &changeGlobal); - } while (changeGlobal > convergeParameter); - - - DeleteSpectrum(&spectrumGlobalTemp); -} - - -void AdvanceEMStep(const int sourceTypeSwitch, const int PPSwitch, - const int ICSSwitch, const int TPPSwitch, - const int DPPSwitch, const int synchrotronSwitch, - const int PPPSwitch, const int NPPSwitch, - const int neutronDecaySwitch, - const int nucleonToSecondarySwitch, - const int neutrinoNeutrinoSwitch, - const double smallDistanceStep, - const double evolutionFactor, - const double convergeParameter, const double bkgFactor, - const Spectrum* pQ_0, - const DiffRate* photonLeptonRate, - const DiffRate* protonElectronRate, - const DiffRate* neutronPositronRate, - const DiffRate* protonPositronRate, - const DiffRate* neutronElectronRate, - const DiffRate* neutronDecayElectronRate, - const DiffRate* elNeutElectronRate, - const DiffRate* muonNeutElectronRate, - const DiffRate* tauNeutElectronRate, - const DiffRate* protonPhotonRate, - const DiffRate* elNeutPhotonRate, - const DiffRate* muonNeutPhotonRate, - const DiffRate* tauNeutPhotonRate, - const TotalRate* leptonTotalRate, - const DiffRate* leptonScatRate, - const DiffRate* leptonExchRate, - const dCVector* continuousLoss, const dCVector* deltaG, - const TotalRate* photonTotalRate, - const DiffRate* leptonPhotonRate, - const DiffRate* syncRate, const Spectrum* pSpectrum, - Spectrum* pSpectrumNew) -{ - int i; - Spectrum spectrumTemp; - Spectrum spectrumGlobalTemp; - /* temporary spectra used in swapping spectra */ - Spectrum influx; - Spectrum influx0; - Spectrum influxExt; - Spectrum outflux; - double changeMax; - /* maximum difference by advance: diff in FORTRAN */ - double changeGlobal; - int num_main_bins; - - num_main_bins = pSpectrum->numberOfMainBins; - - NewSpectrum(&spectrumTemp, num_main_bins); - NewSpectrum(&spectrumGlobalTemp, num_main_bins); - NewSpectrum(&influx, num_main_bins); - NewSpectrum(&influx0, num_main_bins); - NewSpectrum(&influxExt, num_main_bins); - NewSpectrum(&outflux, num_main_bins); - - do { - SetEMSpectrum(&spectrumGlobalTemp, pSpectrumNew); - - // for (i = 0; i < NUM_MAIN_BINS; i++) - // spectrumOld[PHOTON][i] = spectrumNew[PHOTON][i]; - /* I don't think I need it here... */ - - /*---- Converge e+/- first ----*/ - InitializeSpectrum(&influxExt); - - /* external injection */ - GetExternalFlux(sourceTypeSwitch, evolutionFactor, ELECTRON, pQ_0, - &influxExt); - GetExternalFlux(sourceTypeSwitch, evolutionFactor, POSITRON, pQ_0, - &influxExt); - - - InitializeSpectrum(&influx0); - - /* influx from pair production/double pair production */ - if ((PPSwitch == 1) || (DPPSwitch == 1)) - { - GetLeptonInfluxFromPhotons(photonLeptonRate, pSpectrumNew, - &influx0); - } - - /* influx from nucleons */ - if (nucleonToSecondarySwitch == 1) /* secondary tables included */ - { - if ((PPPSwitch == 1) || (NPPSwitch == 1) || - (neutronDecaySwitch == 1)) - { - GetLeptonInfluxFromNucleons(neutronDecaySwitch, - protonElectronRate, neutronPositronRate, - protonPositronRate, neutronElectronRate, - neutronDecayElectronRate, pSpectrumNew, &influx0); - } - } - - /* influx from neutrinos */ - if (neutrinoNeutrinoSwitch == 1) - { - GetLeptonInfluxFromNeutrinos(bkgFactor, elNeutElectronRate, - muonNeutElectronRate, tauNeutElectronRate, pSpectrumNew, - &influx0); - } - - do { - for (i = 0; i < num_main_bins; i++) - { - spectrumTemp.spectrum[ELECTRON][i] = - (pSpectrumNew->spectrum)[ELECTRON][i]; - spectrumTemp.spectrum[POSITRON][i] = - (pSpectrumNew->spectrum)[POSITRON][i]; - } - - InitializeSpectrum(&influx); - InitializeSpectrum(&outflux); - - /* influx & outflux from inverse Compton scattering/synchrotron - radiation */ - if ((ICSSwitch == 1) || (TPPSwitch == 1) || - (synchrotronSwitch == 1)) - { - GetLeptonFluxFromLeptons(leptonTotalRate, leptonScatRate, - leptonExchRate, continuousLoss, deltaG, pSpectrumNew, - &influx, &outflux); - } - - ImplicitEquation(smallDistanceStep, ELECTRON, &influx, &influx0, - &influxExt, &outflux, pSpectrum, pSpectrumNew); - ImplicitEquation(smallDistanceStep, POSITRON, &influx, &influx0, - &influxExt, &outflux, pSpectrum, pSpectrumNew); - /* main difference equation part */ - - changeMax = 0.; - ComputeChange(&spectrumTemp, pSpectrumNew, ELECTRON, &changeMax); - ComputeChange(&spectrumTemp, pSpectrumNew, POSITRON, &changeMax); - } while (changeMax > convergeParameter); - - - /*---- Converge photons ----*/ - /* external influx */ - InitializeSpectrum(&influxExt); - - GetExternalFlux(sourceTypeSwitch, evolutionFactor, PHOTON, pQ_0, - &influxExt); - - InitializeSpectrum(&influx0); - - /* influx from electrons (ICS/synchrotron) */ - if ((ICSSwitch == 1) || (synchrotronSwitch == 1)) - { - GetPhotonInfluxFromLeptons(leptonPhotonRate, synchrotronSwitch, - syncRate, pSpectrumNew, &influx0); - } - - /* influx from nucleons */ - if ((nucleonToSecondarySwitch == 1) && (PPPSwitch == 1)) - { - GetPhotonInfluxFromNucleons(protonPhotonRate, pSpectrumNew, - &influx0); - } - if (neutrinoNeutrinoSwitch == 1) - { - GetPhotonInfluxFromNeutrinos(bkgFactor, elNeutPhotonRate, - muonNeutPhotonRate, tauNeutPhotonRate, pSpectrumNew, &influx0); - } - - do { - for (i = 0; i < num_main_bins; i++) - { - spectrumTemp.spectrum[PHOTON][i] = - (pSpectrumNew->spectrum)[PHOTON][i]; - } - - /* loss (and zero gain) by PP/DPP */ - InitializeSpectrum(&outflux); - if ((PPSwitch == 1) || (DPPSwitch == 1)) - { - GetPhotonFluxFromPhotons(photonTotalRate, &outflux); - } - - ImplicitEquation(smallDistanceStep, PHOTON, &influx, &influx0, - &influxExt, &outflux, pSpectrum, pSpectrumNew); - /* main difference equation */ - - changeMax = 0.; /* reset it for photons */ - ComputeChange(&spectrumTemp, pSpectrumNew, PHOTON, &changeMax); - } while (changeMax > convergeParameter); - - /*global convergence */ - changeGlobal = 0.; - ComputeChange(&spectrumGlobalTemp, pSpectrumNew, ELECTRON, - &changeGlobal); - ComputeChange(&spectrumGlobalTemp, pSpectrumNew, POSITRON, - &changeGlobal); - ComputeChange(&spectrumGlobalTemp, pSpectrumNew, PHOTON, - &changeGlobal); - } while (changeGlobal > convergeParameter); - - DeleteSpectrum(&spectrumTemp); - DeleteSpectrum(&spectrumGlobalTemp); - DeleteSpectrum(&influx); - DeleteSpectrum(&influx0); - DeleteSpectrum(&influxExt); - DeleteSpectrum(&outflux); -} - - -void RedshiftDown(const int lastIndex, const double redshiftRatio, - const dCVector* pEnergy, Spectrum* pSpectrum, - Spectrum* pSpectrumNew) -{ - int i; - - if (pEnergy->dimension != pSpectrum->numberOfMainBins) - { - Error("RedshiftDown: inconsistent dimensions", PROGRAM_ERROR); - } - for (i = 0; i < NUM_SPECIES; i++) - { - RedshiftBinsDown(lastIndex, redshiftRatio, pEnergy, - pSpectrum->spectrum[i], pSpectrumNew->spectrum[i]); - } -} - - -void RedshiftBinsDown(const int lastIndex, const double redshiftRatio, - const dCVector* pEnergy, double* pSpectrum, - double* pSpectrumNew) -/* redshift particle distributions at the end of a big dx */ -{ - int i; - int num_main_bins; - double averaging_factor; - - averaging_factor = (pow(10., 1./2./BINS_PER_DECADE) + - pow(10., -1./2./BINS_PER_DECADE))/2.; - - num_main_bins = pEnergy->dimension; - - if (lastIndex == 0) /* normal steps far from end */ - { - for (i = 0; i < num_main_bins-1; i++) - { - pSpectrum[i] = pSpectrum[i+1]*redshiftRatio* - redshiftRatio*redshiftRatio; - } - pSpectrum[num_main_bins-1] = 0.; - } - else - /* if it's close to z = 0, need some fine tuning because redshift - steps are taken more finely */ - { - // double spectrumTemp[NUM_MAIN_BINS]; - dCVector spectrumTemp; - double energyTemp; - double inflow; - int iMod; - int iMod2; - double tempFraction; - double tempExponent; - - New_dCVector(&spectrumTemp, num_main_bins); - - for (i = 0; i < num_main_bins; i++) - { - energyTemp = (pEnergy->vector)[i]/redshiftRatio; - if (energyTemp > (pEnergy->vector)[num_main_bins-1]/ - averaging_factor*pow(10., 1./2./BINS_PER_DECADE)) - { - inflow = 0.; - } - else - { - iMod = (int)(BINS_PER_DECADE*(log10(energyTemp*ELECTRON_MASS) - - MAX_ENERGY_EXP) + (num_main_bins + 0.5)); -#ifdef DEBUG - CheckIndex(0, num_main_bins, iMod, "RedshiftBinsDown"); -#endif - if ((pEnergy->vector)[iMod] > energyTemp) - { - iMod--; - } - if (iMod < 0) - { - Error("RedshiftBinsDown: iMod became negative.", - PROGRAM_ERROR); /* get the hell out of here! */ - } - iMod2 = iMod + 1; - if (iMod2 >= num_main_bins) - { - inflow = pSpectrum[num_main_bins-1]; - } - else if ((pSpectrum[iMod] < 1.e-40) || - (pSpectrum[iMod2] < 1.e-40)) - { -#ifdef DEBUG - CheckIndex(0, num_main_bins, iMod2, "RedshiftBinsDown"); -#endif - tempFraction = (energyTemp - (pEnergy->vector)[iMod])/ - ((pEnergy->vector)[iMod2] - (pEnergy->vector)[iMod]); - if (tempFraction < 0.) - { - tempFraction = 0.; - } - inflow = pSpectrum[iMod]*(1. - tempFraction) + - pSpectrum[iMod2]*tempFraction; - } - else - { - tempExponent = log(energyTemp/(pEnergy->vector)[iMod])/ - log((pEnergy->vector)[iMod2]/(pEnergy->vector)[iMod]); - inflow = pSpectrum[iMod]*pow(pSpectrum[iMod2]/ - pSpectrum[iMod], tempExponent); - } - } - spectrumTemp.vector[i] = inflow*redshiftRatio*redshiftRatio* - redshiftRatio; - } - -#ifdef DEBUG - if (spectrumTemp.vector[num_main_bins-1] > pSpectrum[num_main_bins-1]) - printf("Auch!!!\n"); -#endif - - for (i = 0; i < num_main_bins; i++) - { - if (spectrumTemp.vector[i] < 0.) - { - Error("RedshiftBinsDown: spectrumTemp negative.", - PROGRAM_ERROR); - } - pSpectrum[i] = spectrumTemp.vector[i]; - pSpectrumNew[i] = pSpectrum[i]; - } - Delete_dCVector(&spectrumTemp); - } -} - - -void GetExternalFlux(const int sourceTypeSwitch, const double evolutionFactor, - const PARTICLE particle, const Spectrum* pQ_0, - Spectrum* pInfluxExt) -{ - int i; - - if (pQ_0->numberOfMainBins != pInfluxExt->numberOfMainBins) - { - Error("GetExternalFlux: inconsistent dimensions", PROGRAM_ERROR); - } - - for (i = 0; i < pQ_0->numberOfMainBins; i++) - { - if (sourceTypeSwitch == 0) /* single source */ - { - (pInfluxExt->spectrum)[particle][i] = 0.; - } - else - { - (pInfluxExt->spectrum)[particle][i] = - (pQ_0->spectrum)[particle][i]*evolutionFactor; - } - } -} - -void ImplicitEquation(const double smallDistanceStep, - const PARTICLE particle, const Spectrum* pInflux, - const Spectrum* pInflux0, const Spectrum* pInfluxExt, - const Spectrum* pOutflux, const Spectrum* pSpectrum, - Spectrum* pSpectrumNew) -{ - /* influx: influx from the same KIND of species (e-: e+/-, p: p/n, etc.) - influx0: influx from other species - influxExt: external influx - NOTE: there is no fundamental distinction between influx and influx0 */ - int i; - int num_main_bins; - - num_main_bins = pSpectrum->numberOfMainBins; - - if ((pInflux->numberOfMainBins != num_main_bins) || - (pInflux0->numberOfMainBins != num_main_bins) || - (pInfluxExt->numberOfMainBins != num_main_bins) || - (pOutflux->numberOfMainBins != num_main_bins) || - (pSpectrumNew->numberOfMainBins != num_main_bins)) - { - Error("ImplicitEquation: inconsistent dimensions", PROGRAM_ERROR); - } - - for (i = 0; i < num_main_bins; i++) - { - (pSpectrumNew->spectrum)[particle][i] = - ((pInflux->spectrum)[particle][i] + - (pInflux0->spectrum)[particle][i] + - (pInfluxExt->spectrum)[particle][i] + - (pSpectrum->spectrum)[particle][i]/smallDistanceStep)/ - ((pOutflux->spectrum)[particle][i] + 1./smallDistanceStep); - /* main difference equation */ - - if ((pSpectrumNew->spectrum)[particle][i] < 0.) - { - (pSpectrumNew->spectrum)[particle][i] = 0.; - } - /* reset if it passes below zero */ - } -} - -void ExplicitEquation(const double smallDistanceStep, - const PARTICLE particle, const Spectrum* pInflux, - const Spectrum* pInflux0, const Spectrum* pInfluxExt, - const Spectrum* pOutflux, const Spectrum* pSpectrum, - const Spectrum* pSpectrumNew) -{ - int i; - int num_main_bins; - - num_main_bins = pSpectrum->numberOfMainBins; - - if ((pInflux->numberOfMainBins != num_main_bins) || - (pInflux0->numberOfMainBins != num_main_bins) || - (pInfluxExt->numberOfMainBins != num_main_bins) || - (pOutflux->numberOfMainBins != num_main_bins) || - (pSpectrumNew->numberOfMainBins != num_main_bins)) - { - Error("ImplicitEquation: inconsistent dimensions", PROGRAM_ERROR); - } - - for (i = 0; i < num_main_bins; i++) - { - (pSpectrumNew->spectrum)[particle][i] = - (pSpectrum->spectrum)[particle][i] + smallDistanceStep* - ((pInflux->spectrum)[particle][i] + - (pInflux0->spectrum)[particle][i] + - (pInfluxExt->spectrum)[particle][i] - - (pSpectrum->spectrum)[particle][i]* - (pOutflux->spectrum)[particle][i]); - - if ((pSpectrumNew->spectrum)[particle][i] < 0.) - { - (pSpectrumNew->spectrum)[particle][i] = 0.; - } - } -} - -void ComputeChange(const Spectrum* pSpectrumTemp, - const Spectrum* pSpectrumNew, - const PARTICLE particle, double* pChangeMax) -{ - double change; - int i; - - if (pSpectrumTemp->numberOfMainBins != pSpectrumNew->numberOfMainBins) - { - Error("ComputeChange: inconsistent dimensions", PROGRAM_ERROR); - } - - for (i = 0; i < pSpectrumNew->numberOfMainBins; i++) - { - change = fabs((pSpectrumNew->spectrum)[particle][i] - - (pSpectrumTemp->spectrum)[particle][i])/ - (fabs((pSpectrumTemp->spectrum)[particle][i]) + EPSILON); - if (change > *pChangeMax) - { - *pChangeMax = change; - } - } -} diff --git a/libs/dint/src/background.cpp b/libs/dint/src/background.cpp deleted file mode 100644 index 86e68a032..000000000 --- a/libs/dint/src/background.cpp +++ /dev/null @@ -1,529 +0,0 @@ - -#include "dint/background.h" -#include - -// integer pow implementation as template that is evaluated at compile time -template -inline double pow_integer(double base) -{ - return pow_integer<(exponent >> 1)>(base*base) * (((exponent & 1) > 0) ? base : 1); -} - -template <> -inline double pow_integer<0>(double base) -{ - return 1; -} - - - -void LoadPhotonBackground(const double redshift, - dCVector* pBgEnergy, dCVector* pBgEnergyWidth, - dCVector* pBgPhotonDensity, - const int aIRFlag, const double aZmax_IR, const int aRadioFlag, - const double aH0, const double aOmegaM, const double aOmegaLambda) { - if ((pBgEnergy->dimension != pBgEnergyWidth->dimension) || - (pBgEnergyWidth->dimension != pBgPhotonDensity->dimension)) - Error("LoadPhotonBackground: inconsistent dimensions", PROGRAM_ERROR); - - LoadCMB(redshift, pBgEnergy, pBgEnergyWidth, pBgPhotonDensity); - LoadIR(redshift, pBgEnergy, pBgEnergyWidth, pBgPhotonDensity, aIRFlag, aZmax_IR); - LoadRadio(redshift, pBgEnergy, pBgEnergyWidth, pBgPhotonDensity, aRadioFlag, - aH0, aOmegaM, aOmegaLambda); - - for (int i=0; idimension; i++) - (pBgPhotonDensity->vector)[i] *= VOLUME_UNIT; // normalization - -#ifdef PRINT_PHOTON_BACKGROUND // Output the density and exit (July 2005) - cout << "z=" << redshift << endl; - for (int i=0; idimension; i++) - cout << (pBgEnergy->vector)[i] << " " << (pBgPhotonDensity->vector)[i] << endl; - exit(-1) ; -#endif - -} - - -void LoadCMB(const double redshift, const dCVector* pBgEnergy, - const dCVector* pBgEnergyWidth, dCVector* pBgPhotonDensity) { - double numberDensity = 0.; // to test CMB was computed correctly - const double PRESENT_TEMPERATURE = 2.73; // present CMB temperature (K) - double exponent; - double tempNumber; - double temperature; - - temperature = 1.6863e-10*PRESENT_TEMPERATURE*(1. + redshift); - //temperature at redshift (K) - - for (int i=0; idimension; i++) { - exponent = (pBgEnergy->vector)[i]/temperature; - if (exponent < 550.) { - tempNumber = (pBgEnergy->vector)[i]*(pBgEnergy->vector)[i]/ - (exp(exponent) - 1.); // thermal distribution - } else tempNumber = 0.; - (pBgPhotonDensity->vector)[i] = tempNumber* - (pBgEnergyWidth->vector)[i]*1.75586e30; - numberDensity += (pBgPhotonDensity->vector)[i]; - } - -#ifdef TEST_CMB - printf("Computed CMB number density: %g\n", numberDensity); - numberDensity = 20.2417*PRESENT_TEMPERATURE*PRESENT_TEMPERATURE* - PRESENT_TEMPERATURE*(1. + redshift)*(1. + redshift)* - (1. + redshift); - printf("Predicted CMB number density: %g\n", numberDensity); -#endif - -} - - -double CIOBR(double eps) { - // parametrization for infrared/optical by - // Hopkins, A. M. & Beacom, J. F. 2006, ApJ, 651, 142 - // See Model D Finke et al, arXiv:0905.1115v2 - const double eps_ph_sup_ciob = 9.9; // [eV] - const double eps_ph_inf_ciob = 2e-3; // [eV] - - double tmp = 0; - - if (eps > eps_ph_inf_ciob && eps < eps_ph_sup_ciob) { - double x = log(eps); - tmp = -5.32524895349885 - 0.0741140642891119 * x - - 0.252586527659431 * pow_integer<2>(x) - + 0.234971297531891 * pow_integer<3>(x) - - 0.217014471117521 * pow_integer<4>(x) - - 0.364936722063572 * pow_integer<5>(x) - + 0.0880702191711222 * pow_integer<6>(x) - + 0.221947767409286 * pow_integer<7>(x) - + 0.0445499623085708 * pow_integer<8>(x) - - 0.0517435600939147 * pow_integer<9>(x) - - 0.0295646851279071 * pow_integer<10>(x) - - 0.00011943632049331 * pow_integer<11>(x) - + 0.00461621589174355 * pow_integer<12>(x) - + 0.00150906100702171 * pow_integer<13>(x) - + 1.91459088023263e-05 * pow_integer<14>(x) - - 0.000110272619218937 * pow_integer<15>(x) - - 3.45221358079085e-05 * pow_integer<16>(x) - - 5.42000122025042e-06 * pow_integer<17>(x) - - 4.90862622314226e-07 * pow_integer<18>(x) - - 2.45145316799091e-08 * pow_integer<19>(x) - - 5.25792204884819e-10 * pow_integer<20>(x); - tmp = 0.4 * (double) exp(tmp) / eps / eps; - } else { - tmp = 0; - } - - if (std::isnan(tmp)) - tmp = 0; - - return tmp; -} - -double CIB_Evolution_Fast(double z) { - // Function for the CIB fast evolution. - // Stecker, Malkan, Scully (2006) arXiv:astro-ph/0510449v4 - - double tmp = 0; - double m = 4.; - double z_flat = 1.; - - if (z <= z_flat) - tmp = pow(1. + z, m); - if (z_flat < z && z < 6) - tmp = pow(1. + z_flat, m); - if (z > 6) - tmp = 0; - - return tmp; -} - -double CIOB_Evolution(double z) { - return CIB_Evolution_Fast(z); -} - -double ElecaIOBR(double E, double z) -{ - double eps = E * ELECTRON_MASS; - return CIOBR(eps) * CIOB_Evolution(z) * ELECTRON_MASS; -} - - -void LoadIR(const double redshift, const dCVector* pBgEnergy, - const dCVector* pBgEnergyWidth, dCVector* pBgPhotonDensity, - const int aIRFlag, const double aZmax_IR) { - - double IRStartRedshift = aZmax_IR ; // Primack CDM - // const double IRStartRedshift = 4.3; // Primack CHDM - // parameters from Franceschini, Yoshi, and Takahara burst of both components - const double deltaO = 7.; - const double deltaD = 7.; - double (*IRFunction)(const double zTarget, const double zObserve, - const double energy0, const double deltaO, - const double deltaD); - if (aIRFlag == 0) IRFunction = HighIR ; - else if (aIRFlag == 1) IRFunction = LowIR ; - else if (aIRFlag == 2) IRFunction = NULL ; - else if (aIRFlag == 4) IRFunction = NULL; - else Error("LoadIR : Uncorrect IR flag",IO_ERROR) ; - - // eleca IR model - if (aIRFlag == 4) - { - for (int i=0; idimension; i++) - { - - (pBgPhotonDensity->vector)[i] += ElecaIOBR((pBgEnergy->vector)[i], redshift)*(pBgEnergyWidth->vector)[i]; - } - - } - else if (redshift <= IRStartRedshift) - { - double z[GAULEG_POINTS]; - double w[GAULEG_POINTS]; - double observeRedshift; - for (int i=0; idimension; i++) - { - if (aIRFlag == 2) { - (pBgPhotonDensity->vector)[i] += - IR2(redshift,(pBgEnergy->vector)[i])*(pBgEnergyWidth->vector)[i]*ELECTRON_MASS; - } else { - double temp = 0; - Gauleg(redshift, IRStartRedshift, z, w, GAULEG_POINTS); //find integration points - observeRedshift = redshift; - for (int j=0; jvector)[i], deltaO, deltaD)*w[j]; - } - (pBgPhotonDensity->vector)[i] += temp*(pBgEnergyWidth->vector)[i]; - } - } - } - -} - - -double IR2(const double redshift, const double BgEnergy) { - - // Primack et al. (1999) CIB parameters - - const double flux_conversion = 2.9979e10/4./PI*1.602e-19*1.e9*1.e4; - // xData is log10(wavelength/micrometers) - // yData is log10(\nu I_\nu/[nW m^-2 sr^-1]) - - // Redshift effect : we assume the following evolution of photon number density : - // n(e,z) = (1+z)**2 * n_0(e/(1+z)) - // It's the same as for CMB (pysically no injection of photons) and therefore the total - // number density evolves as (1+z)**3 - - // Changed to Kneiske Background for consistency with CRPropa interactions, JK - // Kneiske et al. Astron.\ Astrophys.\ {\bf 413} (2004) 807 - const double xData[15] = {-1.00000, -0.750000, -0.500000, -0.250000, 0.00000, 0.250000, 0.500000, 0.750000, - 1.00000, 1.25000, 1.50000, 1.75000, 2.00000, 2.25000, 2.50000}; - const double yData[15] = { -0.214401, 0.349313, 0.720354, 0.890389, 1.16042, 1.24692, 1.06525, 0.668659, 0.536312, 0.595859, 0.457456, - 0.623521, 1.20208, 1.33657, 1.04461}; - -// const double xData[15] = {-1., -0.75, -0.5, -0.25, 0., 0.25, 0.5, -// 0.75, 1., 1.25, 1.5, 1.75, 2., 2.25, 2.5}; -// const double yData[15] = {0.8, 1.1, 1.15, 1.2, 1.3, 1.2, 1.05, 0.7, -// 0.4, 0.3, 0.5, 0.8, 1.1, 1.3, 1.}; - - double result; - double lLocalEnergy = BgEnergy / (1.+redshift) ; // Redshift effect - double x = C/(lLocalEnergy*ELECTRON_MASS*2.42e14)*1.e4; // convert energy into microns - if (x > 500. || log10(x) <= xData[0]) { - result = 0.; - } else if (log10(x) >= xData[14]) { - result = (yData[14] - yData[13])/(xData[14] - xData[13])* - (log10(x) - xData[13]) + yData[13]; - result = pow(10., result); - } else { - int index = 1; - while (xData[index] < log10(x)) index++; - result = (yData[index] - yData[index-1])/ - (xData[index] - xData[index-1])*(log10(x) - xData[index-1]) + - yData[index-1]; - result = pow(10., result); - } - result *= pow(1.+redshift,2.)/pow(lLocalEnergy*ELECTRON_MASS, 2.)/ - flux_conversion; // Redshift effect - - return result; -} - - -double HighIR(const double zTarget, const double zObserve, - const double energy0, const double deltaO, - const double deltaD) { - const double normalization = 2./125.*1.e-5; - // high norm: this is the only difference from LowIR - - double coefficient = 1./pow(1. + zTarget, 4.5)/H_0*4.*PI* - (1. + zObserve)*(1. + zObserve); - double energyTarget = energy0*(1. + zTarget)/(1. + zObserve); - - double function = OpticalIR(energyTarget)*pow(1. + zTarget, deltaO)/30. + - DustIR(energyTarget)/300.*pow(1. + zTarget, deltaD)/2.; - // for no evolution for both (i.e. initial burst) - - return (normalization*coefficient*function) ; -} - - -double LowIR(const double zTarget, const double zObserve, - const double energy0, const double deltaO, - const double deltaD) { - const double normalization = 0.4/125.*1.e-5; - // low norm: this is the only difference from HighIR - - double coefficient = 1./pow(1. + zTarget, 4.5)/H_0*4.*PI* - (1. + zObserve)*(1. + zObserve); - double energyTarget = energy0*(1. + zTarget)/(1. + zObserve); - - double function = OpticalIR(energyTarget)*pow(1. + zTarget, deltaO)/30. + - DustIR(energyTarget)/300.*pow(1. + zTarget, deltaD)/2.; - // for no evolution for both (i.e. initial burst) - - return (normalization*coefficient*function) ; -} - - -double OpticalIR(const double energy) { - const double xData[9] = {-1.0402, -0.9, -0.7, -0.63, -0.4, -0.1, 0.1, 0.6, - 1.}; - const double yData[9] = {-30., -1.45, -1.65, -1.74, -0.33, 0.1, 0.2, -0.6, - -2.6}; - double result; - double x = C/(energy*ELECTRON_MASS*2.42e14)*1.e4; // convert energy into microns - // cut off far IR excess completely - - if (x > 100. || log10(x) <= xData[0]) { - result = 0.; - } else if (log10(x) >= xData[8]) { - result = (yData[8] - yData[7])/(xData[8] - xData[7])* - (log10(x) - xData[7]) + yData[7]; - result = pow(10., result)/energy/energy; - } else { - int index = 1 ; - while (xData[index] < log10(x)) index++; - result = (yData[index] - yData[index-1])/ - (xData[index] - xData[index-1])*(log10(x) - xData[index-1]) + - yData[index-1]; - result = pow(10., result)/energy/energy; - } - - return result; -} - - -double DustIR(const double energy) { - const double xData[6] = {-0.18, 0.54, 1.06, 1.4, 1.8, 2.9}; - const double yData[6] = {-3.0, 0.77, 0.6, 1.37, 1.5, -3.0}; - double result; - double x = C/(energy*ELECTRON_MASS*2.42e14)*1.e4; - - if (log10(x) <= xData[0]) result = 0.; - else if (log10(x) >= xData[5]) { - result = (yData[5] - yData[4])/(xData[5] - xData[4])* - (log10(x) - xData[4]) + yData[4]; - result = pow(10., result)/energy/energy; - } else { - int index = 1 ; - while (xData[index] < log10(x)) index++; - result = (yData[index] - yData[index-1])/ - (xData[index] - xData[index-1])*(log10(x) - xData[index-1]) + - yData[index-1]; - result = pow(10., result)/energy/energy; - } - - return result; -} - - -// Universal Radio Background from Protheroe, Bierman 1996. -double URB(double eps) { - const double eps_ph_inf_urb = 4.1e-12; // [eV] - const double eps_ph_inf_cmb = 0.825e-6; // [eV] - const double eps_ph_sup_urb = 4E-5; //4e-5; // [eV] - if (eps < eps_ph_inf_urb || eps > eps_ph_sup_urb) - return 0; - - const double h_Planck = 4.135667e-15; // [eV s]// - const double C_speed = 299792458; // [m/s] speed of light - const double eV2J = 1.602176487e-19; // from eV to J - - double v = eps / h_Planck; - double x = log10(v / 1e9); - - double p0 = -2.23791e+01; - double p1 = -2.59696e-01; - double p2 = 3.51067e-01; - double p3 = -6.80104e-02; - double p4 = 5.82003e-01; - double p5 = -2.00075e+00; - double p6 = -1.35259e+00; - double p7 = -7.12112e-01; //xbreak - - double intensity = 0; - if (x > p7) - intensity = p0 + p1 * x + p3 * x * x * x / (exp(p4 * x) - 1) + p6 + p5 * x; - else - intensity = p0 + p1 * x + p2 * x * x - + p3 * x * x * x / (exp(p4 * x) - 1); - intensity = pow(10, intensity); - double n_eps = 0; - n_eps = 4 * M_PI / (h_Planck * C_speed) * (intensity / eps); - return n_eps / eV2J / 1.0e6; -} -double URB_Evolution(double z) { - //from Protheroe - Bierman astro-ph:9605119 - if (z < 0.8) - return pow_integer<4>(1. + z); - return pow_integer<4>(1 + 0.8); // z>= z0 -} - -/// Provide Radio Background from Eleca for Dint -double ElecaRadio(const double zTarget, const double zObserve, - const double energy0, const double aH0, - const double aOmegaM, const double aOmegaLambda) { - - // Convert DINT unit to eps - const double eps = energy0 * ELECTRON_MASS; - return URB(eps) * URB_Evolution(zTarget) * ELECTRON_MASS; -} - - -void LoadRadio(const double redshift, const dCVector* pBgEnergy, - const dCVector* pBgEnergyWidth, dCVector* pBgPhotonDensity, - const int aRadioFlag, const double aH0, const double aOmegaM, - const double aOmegaLambda) { - const double radioStartRedshift = 5.; - // although the source distribution does not vanish at high redshift, - // one might as well cut it off effectively - // (5 is 6 sigma away from peak) - double (*RadioFunction)(const double zObserve, const double zTarget, - const double energy0, const double H, - const double OM, const double OL); - const double B = 2.58734e-28; - if (aRadioFlag == 4) - { - for (int i=0; idimension; i++) { - (pBgPhotonDensity->vector)[i] += - ElecaRadio(redshift, redshift, - (pBgEnergy->vector)[i], aH0, aOmegaM, aOmegaLambda) * (pBgEnergyWidth->vector)[i]; - } - } - else if (aRadioFlag != 3) { - // aRadioFlag == 3 : Null radio, so do nothing - if (aRadioFlag == 0) { - RadioFunction = HighRadio ; - } else if (aRadioFlag == 1) { - RadioFunction = MedRadio ; - } else if (aRadioFlag == 2) { - RadioFunction = ObsRadio ; - } else Error("LoadRadio : Uncorrect Radio flag",IO_ERROR) ; - - if (redshift <= radioStartRedshift ) { - double z[GAULEG_POINTS]; - double w[GAULEG_POINTS]; - double cutoffFactor; // cutoffFactor removed from function - - for (int i=0; idimension; i++) { - double temp = 0 ; - Gauleg(redshift, radioStartRedshift, z, w, GAULEG_POINTS); - double observeRedshift = redshift; - for (int j=0; jvector)[i], aH0, aOmegaM, aOmegaLambda)*w[j]; - } - if (RadioFunction == ObsRadio) - cutoffFactor = exp(-B/(pBgEnergy->vector)[i]/ (pBgEnergy->vector)[i]); - // this is a cutoff of the spectrum due to ISM absorption - else cutoffFactor = 1.; - (pBgPhotonDensity->vector)[i] += cutoffFactor*temp * (pBgEnergyWidth->vector)[i]; - } - } - } -} - - -double HighRadio(const double zTarget, const double zObserve, - const double energy0, const double aH0, - const double aOmegaM, const double aOmegaLambda) { - double B0 = 25.26*log(10.); - double B1 = 1.18*log(10.); - double B2 = 0.28*log(10.); - double H_z,coefficient,function,energyTarget; - - H_z = aH0*sqrt(aOmegaM*pow(1.+zTarget,3.)+aOmegaLambda); - energyTarget = energy0*(1. + zTarget)/(1. + zObserve); - coefficient = 4.*PI/H_z*DISTANCE_UNIT*1.e6/1.e5*4.2458e-56* - pow(1. + zObserve, 2.)/(1.40576e-28 + 1.81075e-45/energyTarget + - 6.38227e-8*pow(energyTarget, 1.3) + pow(energyTarget, 1.8)); - function = exp(B0 + B1*zTarget - B2*zTarget*zTarget); - - return (1.e0*coefficient*function); -} - - -double MedRadio(const double zTarget, const double zObserve, - const double energy0, const double aH0, - const double aOmegaM, const double aOmegaLambda) { - - return (HighRadio(zTarget,zObserve,energy0,aH0,aOmegaM,aOmegaLambda)/pow(10.,0.7)); -} - - -double ObsRadio(const double zTarget, const double zObserve, - const double energy0, const double aH0, - const double aOmegaM, const double aOmegaLambda) { - double B0 = 25.26*log(10.); - double B1 = 1.18*log(10.); - double B2 = 0.28*log(10.); - double H_z,coefficient,function,energyTarget; - - H_z = aH0*sqrt(aOmegaM*pow(1.+zTarget,3.)+aOmegaLambda); - energyTarget = energy0*(1. + zTarget)/(1. + zObserve); - coefficient = 4.*PI/H_z*DISTANCE_UNIT*1.e6/1.e5*4.2458e-56* - pow(1. + zObserve, 2.)*pow(energyTarget, -1.8); - function = exp(B0 + B1*zTarget - B2*zTarget*zTarget); - - return (coefficient*function); -} - - - - -/* -// Routine to "dump" the spectrum. -// Not needed -void DumpBgSpectrum(const dCVector* pBgEnergy, const dCVector* pBgEnergyWidth, - const dCVector* pBgPhotonDensity, const char* filename) -{ - int i; - int j; - FILE* dumpFile; - char f1[80] = "datafiles/"; - - if ((pBgEnergy->dimension != pBgEnergyWidth->dimension) || - (pBgEnergyWidth->dimension != pBgPhotonDensity->dimension)) - { - Error("DumpBgSpectrum: inconsistent dimensions", PROGRAM_ERROR); - } - - strncat(f1, filename, 79 - strlen(filename)); - dumpFile = SafeFOpen(f1, "w"); -// this is to send the dump file to a different directory (datafiles) -// by Guenter (7/20/1998) - - for (i = 0; i < pBgEnergy->dimension; i++) - { - fprintf(dumpFile, "%15.4E %15.4E\n", - ELECTRON_MASS*(pBgEnergy->vector)[i], - (pBgPhotonDensity->vector)[i]/ELECTRON_MASS/ - (pBgEnergyWidth->vector)[i]/VOLUME_UNIT); -// proper unit conversion for energy - } - fclose(dumpFile); -} -*/ diff --git a/libs/dint/src/binfread.cpp b/libs/dint/src/binfread.cpp deleted file mode 100644 index 1cd926f7f..000000000 --- a/libs/dint/src/binfread.cpp +++ /dev/null @@ -1,64 +0,0 @@ - -#include "dint/binfread.h" - -#include - -static int ToSwap() { - static int ToSwap = -1 ; - if ( ToSwap != -1 ) goto endToSwap ; - else { - if ( ntohs(1234) != ntohs(1234) ) ToSwap = 1; - else ToSwap = 0; - } - -endToSwap: - //cerr << "ToSwap = " << ToSwap << endl; - return ToSwap ; -} - -static int16_t Swap2(int16_t a) { - return ( ((a >> 8)&0xff) | ((a << 8)&0xff00) ) ; -} - -static int32_t Swap4(int32_t a) { - return ( ((a >> 24)&0xff) | ((a >> 8 )&0xff00 ) | - ((a << 8 )&0xff0000 ) | ((a << 24)&0xff000000) ) ; -} - -static int64_t Swap8(int64_t a) { - return ( ((a >> 56)&0xff) | ((a >> 40 )&0xff00 ) | - ((a >> 24)&0xff0000) | ((a >> 8 )&0xff000000) | - ((a << 8 )&(((int64_t)(0xff))<<32)) | - ((a << 24)&(((int64_t)(0xff))<<40)) | - ((a << 40)&(((int64_t)(0xff))<<48)) | - ((a << 56)&(((int64_t)(0xff))<<56)) ) ; -} - -size_t binfread(void *ptr, size_t size, size_t nmemb, FILE *stream) { - size_t i; - size_t s = fread(ptr, size, nmemb, stream); - - if ( ToSwap() && size>1 ) { - if ( size == 2 ) { - int16_t *temp = (int16_t*)ptr; - for ( i=0; i -#include -#include "dint/error.h" -#include "dint/cvector.h" -#include "dint/const.h" - - -void DumpArray(const dCVector* pVector) -{ - int i; - for (i = 0; i < pVector->dimension; i++) - { - printf("%15.6E\n", pVector->vector[i]*ELECTRON_MASS); - } -} - -void CheckIndex(const int lowerLimit, const int upperLimit, const int i, - const char* functionName) -{ - if (i < lowerLimit || i >= upperLimit) - { - printf("%s: index out of bounds!!!\n", functionName); - printf("Should have satisfied %i <= %i < %i.\n", lowerLimit, i, - upperLimit); - exit (ARRAY_ERROR); - } -} diff --git a/libs/dint/src/cvector.cpp b/libs/dint/src/cvector.cpp deleted file mode 100644 index 9bf664ef2..000000000 --- a/libs/dint/src/cvector.cpp +++ /dev/null @@ -1,36 +0,0 @@ - -#include "dint/cvector.h" - -void New_dCVector(dCVector* pVector, const int n) { - pVector->dimension = n; - pVector->vector = New_dVector(n); - - Initialize_dCVector(pVector); -} - -void Delete_dCVector(dCVector* pVector) { - Delete_dVector(pVector->vector); -} - -void Initialize_dCVector(dCVector* pVector) { - for (int i = 0; idimension; i++) pVector->vector[i] = 0.; -} - - -void New_iCMatrix(iCMatrix* pMatrix, const int n1, const int n2) { - pMatrix->dimension1 = n1; - pMatrix->dimension2 = n2; - pMatrix->matrix = New_iMatrix(n1, n2); - - Initialize_iCMatrix(pMatrix); -} - -void Delete_iCMatrix(iCMatrix* pMatrix) { - Delete_iMatrix(pMatrix->matrix); -} - -void Initialize_iCMatrix(iCMatrix* pMatrix) { - for (int i=0; idimension1; i++) { - for (int j=0; jdimension2; j++) pMatrix->matrix[i][j] = 0; - } -} diff --git a/libs/dint/src/decay.cpp b/libs/dint/src/decay.cpp deleted file mode 100644 index 3eb5c275b..000000000 --- a/libs/dint/src/decay.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include -#include "dint/const.h" -#include "dint/utilities.h" - - -/* NOTE: note that these functions use MIN_ENERGY_EXP, etc. instead of - NUC_MIN_ENERGY_EXP, etc. Thus these functions are tied with the main - routine only. */ -double PionToPhoton(const int iPhoton, const int iPion) -{ - double piEnergyRight; - double piEnergyLeft; - double deltaPiE; - double result; - - piEnergyRight = pow(10., MIN_ENERGY_EXP + (iPion+0.5)/BINS_PER_DECADE)/ - ELECTRON_MASS; - piEnergyLeft = pow(10., MIN_ENERGY_EXP + (iPion-0.5)/BINS_PER_DECADE)/ - ELECTRON_MASS; - deltaPiE = piEnergyRight - piEnergyLeft; - - if (iPhoton < iPion) - result = 2./deltaPiE/BINS_PER_DECADE*log(10.); - else if (iPhoton == iPion) - { - result = 2.*(1./deltaPiE - piEnergyLeft/deltaPiE/deltaPiE/ - BINS_PER_DECADE*log(10.)); - } - else - result = 0.; - - if (result < 0.) - Error("PionToPhoton: decay spectrum negative.", PROGRAM_ERROR); - - return result; -} - - -double PionToLepton(const double leptonEnergy, const double pionEnergy) -{ - const double r = (1.056595e8/1.39567e8)*(1.056595e8/1.39567e8); - const double A0 = 0.94486e0; - const double A2 = -2.7892e0; - const double A3 = 1.2397e0; - const double B0 = -2.4126e0; - const double B0p = -2.8951e0; - const double B2 = 4.3426e0; - const double B3 = -1.9300e0; - - double ratio; - double result; - - ratio = leptonEnergy/pionEnergy; - if (leptonEnergy < r*pionEnergy) - { - result = 1./(1.0 - r)/pionEnergy*(A0 + A2*ratio*ratio + A3*ratio* - ratio*ratio); - } - else - { - result = 1./(1.0 - r)/pionEnergy*(B0 + B0p*log(ratio) + - B2*ratio*ratio + B3*ratio*ratio*ratio); - } - if (result < 0.) - result = 0.; - - return result; -} - -double PionToElectronNeutrino(const double neutrinoEnergy, - const double pionEnergy) -{ - const double r = (1.056595e8/1.39567e8)*(1.056595e8/1.39567e8); - const double C0 = 1.1053e0; - const double C2 = -4.46883e0; - const double C3 = 3.71887e0; - const double D0 = 13.846e0; - const double D0p = 5.37053e0; - const double D1 = -28.1116e0; - const double D2 = 20.0558e0; - const double D3 = -5.7902e0; - - double ratio; - double result; - - ratio = neutrinoEnergy/pionEnergy; - if (neutrinoEnergy < r*pionEnergy) - { - result = 1./(1. - r)/pionEnergy*(C0 + C2*ratio*ratio + C3*ratio*ratio - *ratio); - } - else - { - result = 1./(1. - r)/pionEnergy*(D0 + D0p*log(ratio) + D1*ratio + - D2*ratio*ratio + D3*ratio*ratio*ratio); - } - if (result < 0.) - result = 0.; - - return result; -} - -double PionToMuonNeutrino(const int iNeutrino, const int iPion) -{ - const double r = (1.056595e8/1.39567e8)*(1.056595e8/1.39567e8); - - double neutEnergyLeft; - double neutEnergyRight; - double piEnergyLeft; - double piEnergyRight; - double deltaNeutE; - double deltaPiE; - double result; - - neutEnergyRight = pow(10., MIN_ENERGY_EXP + (iNeutrino+0.5)/ - BINS_PER_DECADE)/ELECTRON_MASS; - neutEnergyLeft = pow(10., MIN_ENERGY_EXP + (iNeutrino-0.5)/ - BINS_PER_DECADE)/ELECTRON_MASS; - deltaNeutE = neutEnergyRight - neutEnergyLeft; - - piEnergyRight = pow(10., MIN_ENERGY_EXP + (iPion+0.5)/BINS_PER_DECADE)/ - ELECTRON_MASS; - piEnergyLeft = pow(10., MIN_ENERGY_EXP + (iPion-0.5)/BINS_PER_DECADE)/ - ELECTRON_MASS; - deltaPiE = piEnergyRight - piEnergyLeft; - - if (neutEnergyRight < piEnergyLeft*(1.-r)) - result = log(piEnergyRight/piEnergyLeft)/(1. - r)/deltaPiE; - else if (neutEnergyLeft < piEnergyLeft*(1.-r)) - { - result = (deltaNeutE/(1. - r)*log(piEnergyRight*(1. - r)/ - neutEnergyRight) + neutEnergyRight/(1. - r) - piEnergyLeft - - neutEnergyLeft/(1. - r)*log(neutEnergyRight/(piEnergyLeft* - (1. - r))))/deltaPiE/deltaNeutE; - } - else if ((neutEnergyLeft < piEnergyRight*(1.-r)) && - (neutEnergyRight > piEnergyRight*(1.-r))) - { - result = (piEnergyRight - neutEnergyLeft/(1. - r) - neutEnergyLeft/ - (1. - r)*log(piEnergyRight*(1. - r)/neutEnergyLeft))/deltaPiE/ - deltaNeutE; - } - else - result = 0.; - - if (result < 0.) - result = 0.; - - return result; -} diff --git a/libs/dint/src/deriv.cpp b/libs/dint/src/deriv.cpp deleted file mode 100644 index 07976f216..000000000 --- a/libs/dint/src/deriv.cpp +++ /dev/null @@ -1,477 +0,0 @@ -#include "dint/deriv.h" -#include "dint/rate.h" -#include "dint/spectrum.h" -#include "dint/error.h" -#include "dint/check.h" -#include "dint/cvector.h" - - -void GetLeptonInfluxFromPhotons(const DiffRate* photonLeptonRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux0) -{ - ComputeInflux(1., photonLeptonRate, PHOTON, ELECTRON, pSpectrumNew, - pInflux0); - ComputeInflux(1., photonLeptonRate, PHOTON, POSITRON, pSpectrumNew, - pInflux0); -} - -void GetLeptonInfluxFromNucleons(const int neutronDecaySwitch, - const DiffRate* protonElectronRate, - const DiffRate* neutronPositronRate, - const DiffRate* protonPositronRate, - const DiffRate* neutronElectronRate, - const DiffRate* neutronDecayElectronRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux0) -{ - /* lepton influx from nucleons */ - ComputeInflux(1., protonElectronRate, PROTON, ELECTRON, pSpectrumNew, - pInflux0); - ComputeInflux(1., neutronPositronRate, NEUTRON, POSITRON, pSpectrumNew, - pInflux0); - ComputeInflux(1., protonPositronRate, PROTON, POSITRON, pSpectrumNew, - pInflux0); - ComputeInflux(1., neutronElectronRate, NEUTRON, ELECTRON, pSpectrumNew, - pInflux0); - if (neutronDecaySwitch == 1) - { - ComputeInflux(1., neutronDecayElectronRate, NEUTRON, ELECTRON, - pSpectrumNew, pInflux0); - } -} - -void GetLeptonInfluxFromNeutrinos(const double bkgFactor, - const DiffRate* elNeutElectronRate, - const DiffRate* muonNeutElectronRate, - const DiffRate* tauNeutElectronRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux0) -{ - ComputeInflux(bkgFactor, elNeutElectronRate, ELECTRON_NEUTRINO, ELECTRON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, elNeutElectronRate, ANTI_ELECTRON_NEUTRINO, - ELECTRON, pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, elNeutElectronRate, ELECTRON_NEUTRINO, POSITRON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, elNeutElectronRate, ANTI_ELECTRON_NEUTRINO, - POSITRON, pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, muonNeutElectronRate, MUON_NEUTRINO, ELECTRON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, muonNeutElectronRate, ANTI_MUON_NEUTRINO, - ELECTRON, pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, muonNeutElectronRate, MUON_NEUTRINO, POSITRON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, muonNeutElectronRate, ANTI_MUON_NEUTRINO, - POSITRON, pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, tauNeutElectronRate, TAU_NEUTRINO, ELECTRON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, tauNeutElectronRate, ANTI_TAU_NEUTRINO, ELECTRON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, tauNeutElectronRate, TAU_NEUTRINO, POSITRON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, tauNeutElectronRate, ANTI_TAU_NEUTRINO, POSITRON, - pSpectrumNew, pInflux0); -} - -void GetLeptonFluxFromLeptons(const TotalRate* leptonTotalRate, - const DiffRate* leptonScatRate, - const DiffRate* leptonExchRate, - const dCVector* continuousLoss, - const dCVector* deltaG, - const Spectrum* pSpectrumNew, Spectrum* pInflux, - Spectrum* pOutflux) -{ - int i; - int num_main_bins; - - num_main_bins = pOutflux->numberOfMainBins; - if ((continuousLoss->dimension != num_main_bins) || - (deltaG->dimension != num_main_bins)) - { - Error("GetLeptonFluxFromLeptons: inconsistent dimensions", - PROGRAM_ERROR); - } - - /* ICS & TPP (differential) */ - ComputeOutflux(1., leptonTotalRate, ELECTRON, pOutflux); - ComputeOutflux(1., leptonTotalRate, POSITRON, pOutflux); - /* outflux */ - - ComputeInflux(1., leptonScatRate, ELECTRON, ELECTRON, pSpectrumNew, - pInflux); - ComputeInflux(1., leptonScatRate, POSITRON, POSITRON, pSpectrumNew, - pInflux); - ComputeInflux(1., leptonExchRate, ELECTRON, POSITRON, pSpectrumNew, - pInflux); - ComputeInflux(1., leptonExchRate, POSITRON, ELECTRON, pSpectrumNew, - pInflux); - /* this is for TPP */ - - /* continuous energy loss (synchrotron & TPP) */ - for (i = 0; i < num_main_bins; i++) - { - double fraction; - - fraction = (continuousLoss->vector)[i]/(deltaG->vector)[i]; - (pOutflux->spectrum)[ELECTRON][i] += -fraction; - (pOutflux->spectrum)[POSITRON][i] += -fraction; - if (i != num_main_bins - 1) - { - (pInflux->spectrum)[ELECTRON][i] += - -(continuousLoss->vector)[i+1]/(deltaG->vector)[i+1]* - (pSpectrumNew->spectrum)[ELECTRON][i+1]; - (pInflux->spectrum)[POSITRON][i] += - -(continuousLoss->vector)[i+1]/(deltaG->vector)[i+1]* - (pSpectrumNew->spectrum)[POSITRON][i+1]; - } - } -} - - -void GetPhotonInfluxFromLeptons(const DiffRate* leptonPhotonRate, - const int synchrotronSwitch, - const DiffRate* syncRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux0) -{ - int i; - int num_main_bins; - - num_main_bins = pInflux0->numberOfMainBins; - if (synchrotronSwitch == 1) - { - if (syncRate->mainDimension != num_main_bins) - { - Error("GetPhotonInfluxFromLeptons: inconsistent dimensions", - PROGRAM_ERROR); - } - } - - ComputeInflux(1., leptonPhotonRate, ELECTRON, PHOTON, pSpectrumNew, - pInflux0); - ComputeInflux(1., leptonPhotonRate, POSITRON, PHOTON, pSpectrumNew, - pInflux0); - /* influx from ICS */ - - /* influx from synchrotron */ - if (synchrotronSwitch == 1) - { - for (i = 0; i < num_main_bins; i++) - { - if (((syncRate->bound)[i][0] != num_main_bins - 1) || - (syncRate->bound)[i][1] != 0) - { - int j; - - for (j = (syncRate->bound)[i][0]; j <= (syncRate->bound)[i][1]; - j++) - { - (pInflux0->spectrum)[PHOTON][j] += - (syncRate->diffRate)[i][j]* - ((pSpectrumNew->spectrum)[ELECTRON][i] + - (pSpectrumNew->spectrum)[POSITRON][i]); - } - } - } - } -} - -void GetPhotonInfluxFromNucleons(const DiffRate* protonPhotonRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux0) -{ - ComputeInflux(1., protonPhotonRate, PROTON, PHOTON, pSpectrumNew, - pInflux0); - ComputeInflux(1., protonPhotonRate, NEUTRON, PHOTON, pSpectrumNew, - pInflux0); -} - -void GetPhotonInfluxFromNeutrinos(const double bkgFactor, - const DiffRate* elNeutPhotonRate, - const DiffRate* muonNeutPhotonRate, - const DiffRate* tauNeutPhotonRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux0) -{ - ComputeInflux(bkgFactor, elNeutPhotonRate, ELECTRON_NEUTRINO, PHOTON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, elNeutPhotonRate, ANTI_ELECTRON_NEUTRINO, PHOTON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, muonNeutPhotonRate, MUON_NEUTRINO, PHOTON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, muonNeutPhotonRate, ANTI_MUON_NEUTRINO, PHOTON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, tauNeutPhotonRate, TAU_NEUTRINO, PHOTON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, tauNeutPhotonRate, ANTI_TAU_NEUTRINO, PHOTON, - pSpectrumNew, pInflux0); -} - - -void GetPhotonFluxFromPhotons(const TotalRate* photonTotalRate, - Spectrum* pOutflux) -{ - ComputeOutflux(1., photonTotalRate, PHOTON, pOutflux); -} - -void GetNucleonFluxFromNucleons(const int neutronDecaySwitch, - const TotalRate* protonTotalRate, - const TotalRate* neutronTotalRate, - const TotalRate* neutronDecayRate, - const DiffRate* protonScatRate, - const DiffRate* neutronProtonRate, - const DiffRate* protonNeutronRate, - const DiffRate* neutronDecayProtonRate, - const dCVector* protonContinuousLoss, - const dCVector* deltaG, - const Spectrum* pSpectrumNew, - Spectrum* pInflux, Spectrum* pOutflux) -{ - int i; - int num_main_bins; - - num_main_bins = pInflux->numberOfMainBins; - if ((protonContinuousLoss->dimension != num_main_bins) || - (deltaG->dimension != num_main_bins)) - { - Error("GetNucleonFluxFromNucleons: inconsistent dimensions", - PROGRAM_ERROR); - } - - ComputeOutflux(1., protonTotalRate, PROTON, pOutflux); - ComputeOutflux(1., neutronTotalRate, NEUTRON, pOutflux); - if (neutronDecaySwitch == 1) - { - ComputeOutflux(1., neutronDecayRate, NEUTRON, pOutflux); - } - /* compute outflux */ - - ComputeInflux(1., protonScatRate, PROTON, PROTON, pSpectrumNew, pInflux); - ComputeInflux(1., neutronProtonRate, NEUTRON, PROTON, pSpectrumNew, - pInflux); - ComputeInflux(1., protonScatRate, NEUTRON, NEUTRON, pSpectrumNew, pInflux); - ComputeInflux(1., protonNeutronRate, PROTON, NEUTRON, pSpectrumNew, - pInflux); - /* compute influx by PPP */ - - if (neutronDecaySwitch == 1) - { - /*ComputeInflux(1., neutronDecayProtonRate, NEUTRON, PROTON, pSpectrumNew, - pInflux);*/ - - for (i = 0; i < neutronDecayRate->mainDimension; i++) - { - pInflux->spectrum[PROTON][i] += (neutronDecayRate->totalRate[i])* - (pSpectrumNew->spectrum)[NEUTRON][i]; - } - - } - /* add proton influx by neutron decay */ - - for (i = 0; i < num_main_bins; i++) - { - double fraction; - - fraction = (protonContinuousLoss->vector)[i]/(deltaG->vector)[i]; - (pOutflux->spectrum)[PROTON][i] += -fraction; - if (i != num_main_bins - 1) - { - (pInflux->spectrum)[PROTON][i] += -fraction* - (pSpectrumNew->spectrum)[PROTON][i+1]; - } - } -} - -void GetNeutrinoInfluxFromNucleons(const int neutronDecaySwitch, - const DiffRate* protonMuonNeutrinoRate, - const DiffRate* neutronAntiMuonNeutrinoRate, - const DiffRate* neutronMuonNeutrinoRate, - const DiffRate* protonAntiMuonNeutrinoRate, - const DiffRate* protonElectronNeutrinoRate, - const DiffRate* neutronAntiElectronNeutrinoRate, - const DiffRate* protonAntiElectronNeutrinoRate, - const DiffRate* neutronDecayElectronRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux0) -{ - ComputeInflux(1., protonMuonNeutrinoRate, PROTON, MUON_NEUTRINO, - pSpectrumNew, pInflux0); - ComputeInflux(1., neutronAntiMuonNeutrinoRate, NEUTRON, - ANTI_MUON_NEUTRINO, pSpectrumNew, pInflux0); - ComputeInflux(1., protonAntiMuonNeutrinoRate, PROTON, ANTI_MUON_NEUTRINO, - pSpectrumNew, pInflux0); - ComputeInflux(1., neutronMuonNeutrinoRate, NEUTRON, MUON_NEUTRINO, - pSpectrumNew, pInflux0); - ComputeInflux(1., protonElectronNeutrinoRate, PROTON, ELECTRON_NEUTRINO, - pSpectrumNew, pInflux0); - ComputeInflux(1., neutronAntiElectronNeutrinoRate, NEUTRON, - ANTI_ELECTRON_NEUTRINO, pSpectrumNew, pInflux0); - ComputeInflux(1., protonAntiElectronNeutrinoRate, PROTON, - ANTI_ELECTRON_NEUTRINO, pSpectrumNew, pInflux0); - ComputeInflux(1., protonAntiElectronNeutrinoRate, NEUTRON, - ELECTRON_NEUTRINO, pSpectrumNew, pInflux0); - - if (neutronDecaySwitch == 1) - { - ComputeInflux(1., neutronDecayElectronRate, NEUTRON, - ANTI_ELECTRON_NEUTRINO, pSpectrumNew, pInflux0); - } -} - -void GetNucleonInfluxFromNeutrinos(const double bkgFactor, - const DiffRate* elNeutProtonRate, - const DiffRate* muonNeutProtonRate, - const DiffRate* tauNeutProtonRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux0) -{ - ComputeInflux(bkgFactor, elNeutProtonRate, ELECTRON_NEUTRINO, PROTON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, elNeutProtonRate, ANTI_ELECTRON_NEUTRINO, PROTON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, muonNeutProtonRate, MUON_NEUTRINO, PROTON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, muonNeutProtonRate, ANTI_MUON_NEUTRINO, PROTON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, tauNeutProtonRate, TAU_NEUTRINO, PROTON, - pSpectrumNew, pInflux0); - ComputeInflux(bkgFactor, tauNeutProtonRate, ANTI_TAU_NEUTRINO, PROTON, - pSpectrumNew, pInflux0); - - /* neutron is unchanged: this has to be replaced after proton-antiproton - symmetry is solved */ -} - -void GetNeutrinoFluxFromNeutrinos(const double bkgFactor, - const TotalRate* elNeutTotalRate, - const TotalRate* muonNeutTotalRate, - const TotalRate* tauNeutTotalRate, - const DiffRate* elNeutScatRate, - const DiffRate* elNeutMuonNeutRate, - const DiffRate* elNeutTauNeutRate, - const DiffRate* muonNeutElNeutRate, - const DiffRate* muonNeutScatRate, - const DiffRate* muonNeutTauNeutRate, - const DiffRate* tauNeutElNeutRate, - const DiffRate* tauNeutMuonNeutRate, - const DiffRate* tauNeutScatRate, - const Spectrum* pSpectrumNew, - Spectrum* pInflux, Spectrum* pOutflux) -{ - int i; - int k; - int num_main_bins; - - num_main_bins = pInflux->numberOfMainBins; - - ComputeOutflux(bkgFactor, elNeutTotalRate, ELECTRON_NEUTRINO, pOutflux); - ComputeOutflux(bkgFactor, elNeutTotalRate, ANTI_ELECTRON_NEUTRINO, - pOutflux); - ComputeOutflux(bkgFactor, muonNeutTotalRate, MUON_NEUTRINO, pOutflux); - ComputeOutflux(bkgFactor, muonNeutTotalRate, ANTI_MUON_NEUTRINO, pOutflux); - ComputeOutflux(bkgFactor, tauNeutTotalRate, TAU_NEUTRINO, pOutflux); - ComputeOutflux(bkgFactor, tauNeutTotalRate, ANTI_TAU_NEUTRINO, pOutflux); - - - ComputeInflux(bkgFactor, elNeutScatRate, ELECTRON_NEUTRINO, - ELECTRON_NEUTRINO, pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, elNeutScatRate, ANTI_ELECTRON_NEUTRINO, - ELECTRON_NEUTRINO, pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, muonNeutElNeutRate, MUON_NEUTRINO, - ELECTRON_NEUTRINO, pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, muonNeutElNeutRate, ANTI_MUON_NEUTRINO, - ELECTRON_NEUTRINO, pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, tauNeutElNeutRate, TAU_NEUTRINO, - ELECTRON_NEUTRINO, pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, tauNeutElNeutRate, ANTI_TAU_NEUTRINO, - ELECTRON_NEUTRINO, pSpectrumNew, pInflux); - - ComputeInflux(bkgFactor, elNeutMuonNeutRate, ELECTRON_NEUTRINO, - MUON_NEUTRINO, pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, elNeutMuonNeutRate, ANTI_ELECTRON_NEUTRINO, - MUON_NEUTRINO, pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, muonNeutScatRate, MUON_NEUTRINO, MUON_NEUTRINO, - pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, muonNeutScatRate, ANTI_MUON_NEUTRINO, - MUON_NEUTRINO, pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, tauNeutMuonNeutRate, TAU_NEUTRINO, MUON_NEUTRINO, - pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, tauNeutMuonNeutRate, ANTI_TAU_NEUTRINO, - MUON_NEUTRINO, pSpectrumNew, pInflux); - - ComputeInflux(bkgFactor, elNeutTauNeutRate, ELECTRON_NEUTRINO, - TAU_NEUTRINO, pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, elNeutTauNeutRate, ANTI_ELECTRON_NEUTRINO, - TAU_NEUTRINO, pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, muonNeutTauNeutRate, MUON_NEUTRINO, TAU_NEUTRINO, - pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, muonNeutTauNeutRate, ANTI_MUON_NEUTRINO, - TAU_NEUTRINO, pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, tauNeutScatRate, TAU_NEUTRINO, TAU_NEUTRINO, - pSpectrumNew, pInflux); - ComputeInflux(bkgFactor, tauNeutScatRate, ANTI_TAU_NEUTRINO, TAU_NEUTRINO, - pSpectrumNew, pInflux); - - /* ??? */ - for (i = 0; i < num_main_bins; i++) - { - for (k = 0; k <= i; k++) - { - (pInflux->spectrum)[ANTI_ELECTRON_NEUTRINO][k] = - (pInflux->spectrum)[ELECTRON_NEUTRINO][k]; - (pInflux->spectrum)[ANTI_MUON_NEUTRINO][k] = - (pInflux->spectrum)[MUON_NEUTRINO][k]; - (pInflux->spectrum)[ANTI_TAU_NEUTRINO][k] = - (pInflux->spectrum)[TAU_NEUTRINO][k]; - } - } -} - -void ComputeOutflux(const double bkgFactor, const TotalRate* pRate, - const PARTICLE parent, Spectrum* pOutflux) -{ - int i; - - if (pRate->mainDimension != pOutflux->numberOfMainBins) - { - Error("ComputeOutflux: inconsistent dimension", PROGRAM_ERROR); - } - - for (i = 0; i < pRate->mainDimension; i++) - { - pOutflux->spectrum[parent][i] += bkgFactor*(pRate->totalRate[i]); - } -} - -void ComputeInflux(const double bkgFactor, const DiffRate* pRate, - const PARTICLE parent, const PARTICLE daughter, - const Spectrum* pSpectrum, Spectrum* pInflux) -{ - int i; - int k; - - if ((pRate->mainDimension != pSpectrum->numberOfMainBins) || - (pSpectrum->numberOfMainBins != pInflux->numberOfMainBins)) - { - Error("ComputeInflux: inconsistent dimensions", PROGRAM_ERROR); - } - - for (i = 0; i < pRate->mainDimension; i++) - { - if ((pRate->bound[i][0] != pRate->mainDimension - 1) || - (pRate->bound[i][1] != 0)) - /* bound is valid */ - { - for (k = pRate->bound[i][0]; k <= pRate->bound[i][1]; k++) - { -#ifdef DEBUG - CheckIndex(0, i+1, k, "ComputeInflux"); -#endif - pInflux->spectrum[daughter][k] += bkgFactor* - (pRate->diffRate)[i][k]* - (pSpectrum->spectrum)[parent][i]; - } - } - } -} diff --git a/libs/dint/src/error.cpp b/libs/dint/src/error.cpp deleted file mode 100644 index 90dfb063f..000000000 --- a/libs/dint/src/error.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -#include "dint/error.h" - -void Error(const char* errorMessage, const ErrorCode errorCode) -{ - printf("%s\n", errorMessage); - exit (errorCode); -} diff --git a/libs/dint/src/final.cpp b/libs/dint/src/final.cpp deleted file mode 100644 index e50887e76..000000000 --- a/libs/dint/src/final.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include -#include "dint/spectrum.h" -#include "dint/const.h" - -void CheckEnergy(const int sourceTypeSwitch, const double brightPhaseExp, - const double startingRedshift, - const double rightRedshift, const Spectrum* pSpectrum, - const dCVector* pEnergy, const double initialTotalEnergy) -{ - int i; - double tempFraction; - double photonNumber = 0.; - double leptonNumber = 0.; - double nucleonNumber = 0.; - double neutrinoNumber = 0.; - double totalNumber = 0.; - double photonEnergy = 0.; - double leptonEnergy = 0.; - double nucleonEnergy = 0.; - double neutrinoEnergy = 0.; - double totalEnergy = 0.; - double energyRedshiftFactor; - - tempFraction = (1. + startingRedshift)/(1. + rightRedshift); - for (i = 0; i < pEnergy->dimension; i++) - { - photonNumber += (pSpectrum->spectrum)[PHOTON][i]; - photonEnergy += (pSpectrum->spectrum)[PHOTON][i]*(pEnergy->vector)[i]; - leptonNumber += (pSpectrum->spectrum)[ELECTRON][i] + - (pSpectrum->spectrum)[POSITRON][i]; - leptonEnergy += (pEnergy->vector)[i]* - ((pSpectrum->spectrum)[ELECTRON][i] + - (pSpectrum->spectrum)[POSITRON][i]); - } - - nucleonNumber = GetNucleonNumber(pSpectrum); - nucleonEnergy = GetNucleonEnergy(pSpectrum, pEnergy); - neutrinoNumber = GetNeutrinoNumber(pSpectrum); - neutrinoEnergy = GetNeutrinoEnergy(pSpectrum, pEnergy); - totalNumber = photonNumber + leptonNumber + nucleonNumber + neutrinoNumber; - totalEnergy = photonEnergy + leptonEnergy + nucleonEnergy + neutrinoEnergy; - - if (sourceTypeSwitch == 0) /* single source */ - energyRedshiftFactor = 1./pow(tempFraction, 4); - else - { - energyRedshiftFactor = C/H_0*1.e6/1.e5*pow(1. + startingRedshift, - -1.5)/pow(tempFraction,1.5+brightPhaseExp)/(brightPhaseExp-2.5)* - (pow(tempFraction,brightPhaseExp-2.5) - 1.); - } - - // printf(" Total energy = %15.6E (arbitrary units)\n", totalEnergy); - // printf(" (total energy)/(injected energy) = %g\n", - // totalEnergy/initialTotalEnergy/energyRedshiftFactor); -} - - -void FinalPrintOutToTheScreen(const double distance, - const double startingRedshift, - const double propagatingDistance) -{ - double analyticalDistance; - - printf("\n\nTotal distance was %g Mpc ", - distance/DISTANCE_UNIT/1.e6); - analyticalDistance = 2./3.*C*1.e-5/H_0*(1. - - pow(1. + startingRedshift, -3./2.)); - printf("vs. real distance %g Mpc.\n", analyticalDistance); - printf("And total x was %g pc\n", propagatingDistance); -} diff --git a/libs/dint/src/fold.cpp b/libs/dint/src/fold.cpp deleted file mode 100644 index 7fb4dfd9c..000000000 --- a/libs/dint/src/fold.cpp +++ /dev/null @@ -1,826 +0,0 @@ -#include -#include -#include "dint/rate.h" -#include "dint/const.h" -#include "dint/cvector.h" -#include "dint/check.h" -#include "dint/utilities.h" - - -void InitializeLeptonCoefficients(TotalRate* leptonTotalRate, - DiffRate* leptonScatRate, - DiffRate* leptonExchRate, - DiffRate* leptonPhotonRate) -{ - InitializeTotalRate(leptonTotalRate); - InitializeDiffRate(leptonScatRate); - InitializeDiffRate(leptonExchRate); - InitializeDiffRate(leptonPhotonRate); -} - - -void InitializePhotonCoefficients(TotalRate* photonTotalRate, - DiffRate* photonLeptonRate) -{ - InitializeTotalRate(photonTotalRate); - InitializeDiffRate(photonLeptonRate); -} - -void InitializeNucleonCoefficients(TotalRate* protonTotalRate, - TotalRate* neutronTotalRate, - DiffRate* protonScatRate, - DiffRate* protonNeutronRate, - DiffRate* neutronProtonRate, - DiffRate* protonPhotonRate, - DiffRate* protonElectronRate, - DiffRate* protonPositronRate, - DiffRate* neutronElectronRate, - DiffRate* neutronPositronRate, - DiffRate* protonElectronNeutrinoRate, - DiffRate* protonAntiElectronNeutrinoRate, - DiffRate* protonMuonNeutrinoRate, - DiffRate* protonAntiMuonNeutrinoRate, - DiffRate* neutronAntiElectronNeutrinoRate, - DiffRate* neutronMuonNeutrinoRate, - DiffRate* neutronAntiMuonNeutrinoRate) -{ - InitializeTotalRate(protonTotalRate); - InitializeTotalRate(neutronTotalRate); - - InitializeDiffRate(protonScatRate); - InitializeDiffRate(protonNeutronRate); - InitializeDiffRate(neutronProtonRate); - InitializeDiffRate(protonPhotonRate); - InitializeDiffRate(protonElectronRate); - InitializeDiffRate(protonPositronRate); - InitializeDiffRate(neutronElectronRate); - InitializeDiffRate(neutronPositronRate); - InitializeDiffRate(protonElectronNeutrinoRate); - InitializeDiffRate(protonAntiElectronNeutrinoRate); - InitializeDiffRate(protonMuonNeutrinoRate); - InitializeDiffRate(protonAntiMuonNeutrinoRate); - InitializeDiffRate(neutronAntiElectronNeutrinoRate); - InitializeDiffRate(neutronMuonNeutrinoRate); - InitializeDiffRate(neutronAntiMuonNeutrinoRate); -} - -void InitializeNeutrinoCoefficients(TotalRate* elNeutTotalRate, - TotalRate* muonNeutTotalRate, - TotalRate* tauNeutTotalRate, - DiffRate* elNeutScatRate, - DiffRate* elNeutMuonNeutRate, - DiffRate* elNeutTauNeutRate, - DiffRate* elNeutElectronRate, - DiffRate* elNeutPhotonRate, - DiffRate* elNeutProtonRate, - DiffRate* muonNeutElNeutRate, - DiffRate* muonNeutScatRate, - DiffRate* muonNeutTauNeutRate, - DiffRate* muonNeutElectronRate, - DiffRate* muonNeutPhotonRate, - DiffRate* muonNeutProtonRate, - DiffRate* tauNeutElNeutRate, - DiffRate* tauNeutMuonNeutRate, - DiffRate* tauNeutScatRate, - DiffRate* tauNeutElectronRate, - DiffRate* tauNeutPhotonRate, - DiffRate* tauNeutProtonRate) -{ - InitializeTotalRate(elNeutTotalRate); - InitializeTotalRate(muonNeutTotalRate); - InitializeTotalRate(tauNeutTotalRate); - - InitializeDiffRate(elNeutScatRate); - InitializeDiffRate(elNeutMuonNeutRate); - InitializeDiffRate(elNeutTauNeutRate); - InitializeDiffRate(elNeutElectronRate); - InitializeDiffRate(elNeutPhotonRate); - InitializeDiffRate(elNeutProtonRate); - InitializeDiffRate(muonNeutElNeutRate); - InitializeDiffRate(muonNeutScatRate); - InitializeDiffRate(muonNeutTauNeutRate); - InitializeDiffRate(muonNeutElectronRate); - InitializeDiffRate(muonNeutPhotonRate); - InitializeDiffRate(muonNeutProtonRate); - InitializeDiffRate(tauNeutElNeutRate); - InitializeDiffRate(tauNeutMuonNeutRate); - InitializeDiffRate(tauNeutScatRate); - InitializeDiffRate(tauNeutElectronRate); - InitializeDiffRate(tauNeutPhotonRate); - InitializeDiffRate(tauNeutProtonRate); -} - - -void FoldTotalRate(const dCVector* pBgPhotonDensity, - const RawTotalRate* pRawTotalRate, TotalRate* pTotalRate) -{ - int i; - int j; - - if ((pBgPhotonDensity->dimension != pRawTotalRate->bgDimension) || - (pRawTotalRate->mainDimension != pTotalRate->mainDimension)) - { - Error("FoldTotalRate: inconsistent dimensions", PROGRAM_ERROR); - } - - for (i = 0; i < pRawTotalRate->mainDimension; i++) - { - for (j = 0; j < pRawTotalRate->bgDimension; j++) - { - (pTotalRate->totalRate)[i] += (pBgPhotonDensity->vector)[j]* - (pRawTotalRate->totalRate)[i][j]; - } - } -} - -void FoldDiffRate(const dCVector* pBgPhotonDensity, - const RawDiffRate* pRawDiffRate, - DiffRate* pDiffRate, const int scatSwitch, ...) -{ - int i; - int j; - int k; - int offset = 0; - int jLower; - int jUpper; - int num_main_bins; - int num_bg_bins; - - num_main_bins = pRawDiffRate->mainDimension; - num_bg_bins = pRawDiffRate->bgDimension; - - if ((pBgPhotonDensity->dimension != num_bg_bins) || - (num_main_bins != pDiffRate->mainDimension)) - { - Error("FoldDiffRate: inconsistent dimensions", PROGRAM_ERROR); - } - - if (scatSwitch != 0) - /* scattering type: adjustment of total rate(s) needed */ - { - va_list pArg; -// TotalRate* totalRateArray[scatSwitch]; - TotalRate* totalRateArray[3]; - - va_start(pArg, scatSwitch); - for (i = 0; i < scatSwitch; i++) - totalRateArray[i] = va_arg(pArg, TotalRate*); - /* Let totalRateArray[i] point to the totalRate* we will modify; we do - not need to update the arguments later - (i.e. va_arg(...) = totalRateArray[i];) because the actual values - they point to have been properly updated */ - - for (i = 0; i < num_main_bins; i++) - { - jLower = num_main_bins - 1; - jUpper = 0; - for (j = 0; j < num_bg_bins; j++) - { - if (pRawDiffRate->bound[i][j][0] != -1) - /* above threshold */ - { - offset += -(pRawDiffRate->bound)[i][j][0]; - jLower = IMin(jLower, (pRawDiffRate->bound)[i][j][0]); - jUpper = IMax(jUpper, (pRawDiffRate->bound)[i][j][1]); - for (k = (pRawDiffRate->bound)[i][j][0]; - k <= (pRawDiffRate->bound)[i][j][1]; k++) - { -#ifdef DEBUG - CheckIndex(0, i+1, k, "FoldDiffRate"); - CheckIndex(0, pRawDiffRate->numberOfElements, k+offset, - "FoldDiffRate"); -#endif - (pDiffRate->diffRate)[i][k] += - (pBgPhotonDensity->vector)[j]* - (pRawDiffRate->diffRate)[k+offset]; - } - /* these lines take care of the appropriate subtractions - made in the main implicit formula */ - if ((pRawDiffRate->bound)[i][j][1] == i) - /* if (((pRawDiffRate->bound)[i][j][0] <= i) && - ((pRawDiffRate->bound)[i][j][1] >= i)) */ - { - int l; - - for (l = 0; l < scatSwitch; l++) - { - (totalRateArray[l]->totalRate)[i] += - -(pRawDiffRate->diffRate)[i+offset]* - (pBgPhotonDensity->vector)[j]; - } - (pDiffRate->diffRate)[i][i] += - -(pRawDiffRate->diffRate)[i+offset]* - (pBgPhotonDensity->vector)[j]; - } - offset += (pRawDiffRate->bound)[i][j][1] + 1; - /* reset the offset index */ - } - } - (pDiffRate->bound)[i][0] = IMin((pDiffRate->bound)[i][0], jLower); - (pDiffRate->bound)[i][1] = IMax((pDiffRate->bound)[i][1], jUpper); - } - va_end(pArg); - } - else - { - for (i = 0; i < num_main_bins; i++) - { - jLower = num_main_bins - 1; - jUpper = 0; - for (j = 0; j < num_bg_bins; j++) - { - if (pRawDiffRate->bound[i][j][0] != -1) - /* if no threshold or above threshold */ - { - offset += -(pRawDiffRate->bound)[i][j][0]; - jLower = IMin(jLower, (pRawDiffRate->bound)[i][j][0]); - jUpper = IMax(jUpper, (pRawDiffRate->bound)[i][j][1]); - for (k = (pRawDiffRate->bound)[i][j][0]; - k <= (pRawDiffRate->bound)[i][j][1]; k++) - { -#ifdef DEBUG - CheckIndex(0, i+1, k, "FoldDiffRate"); - CheckIndex(0, pRawDiffRate->numberOfElements, k+offset, - "FoldDiffRate"); -#endif - (pDiffRate->diffRate)[i][k] += - (pBgPhotonDensity->vector)[j]* - (pRawDiffRate->diffRate)[k+offset]; - } - offset += (pRawDiffRate->bound)[i][j][1] + 1; - /* reset the offset index */ - } - } - (pDiffRate->bound)[i][0] = IMin((pDiffRate->bound)[i][0], jLower); - (pDiffRate->bound)[i][1] = IMax((pDiffRate->bound)[i][1], jUpper); - } - } -} - - -void FoldICS(const dCVector* pBgPhotonDensity, - const RawTotalRate* ICSTotalRate, - const RawDiffRate* ICSPhotonRate, const RawDiffRate* ICSScatRate, - TotalRate* leptonTotalRate, DiffRate* leptonPhotonRate, - DiffRate* leptonScatRate) -{ - FoldTotalRate(pBgPhotonDensity, ICSTotalRate, leptonTotalRate); - FoldDiffRate(pBgPhotonDensity, ICSScatRate, leptonScatRate, 1, - leptonTotalRate); - FoldDiffRate(pBgPhotonDensity, ICSPhotonRate, leptonPhotonRate, 0); -} - - -void FoldTPP(const dCVector* pBgPhotonDensity, const dCVector* pEnergy, - const RawTotalRate* TPPTotalRate, const RawDiffRate* TPPDiffRate, - TotalRate* leptonTotalRate, DiffRate* leptonScatRate, - DiffRate* leptonExchRate, dCVector* otherLoss) -{ - int i; - int j; - - if ((pEnergy->dimension != TPPTotalRate->mainDimension) || - (TPPTotalRate->bgDimension != pBgPhotonDensity->dimension) || - (otherLoss->dimension != pEnergy->dimension)) - { - Error("FoldTPP: inconsistent dimensions", PROGRAM_ERROR); - } - - /* add TPP total rates in continuous energy loss */ - for (i = 0; i < TPPTotalRate->mainDimension; i++) - { - (otherLoss->vector)[i] = 0.; - for (j = 0; j < TPPTotalRate->bgDimension; j++) - { - (otherLoss->vector)[i] += -(pEnergy->vector)[i]* - (pBgPhotonDensity->vector)[j]* - (TPPTotalRate->totalRate)[i][j]; - } - } - - FoldDiffRate(pBgPhotonDensity, TPPDiffRate, leptonScatRate, 1, - leptonTotalRate); - FoldDiffRate(pBgPhotonDensity, TPPDiffRate, leptonExchRate, 0); -} - - -void FoldPP(const dCVector* pBgPhotonDensity, const RawTotalRate* PPTotalRate, - const RawDiffRate* PPDiffRate, TotalRate* photonTotalRate, - DiffRate* photonLeptonRate) -{ - FoldTotalRate(pBgPhotonDensity, PPTotalRate, photonTotalRate); - FoldDiffRate(pBgPhotonDensity, PPDiffRate, photonLeptonRate, 0); -} - - -void FoldDPP(const dCVector* pBgPhotonDensity, const RawTotalRate* DPPRate, - TotalRate* photonTotalRate, DiffRate* photonLeptonRate) -/* I adopt a simple model where one pair of e-/e+ gets all the energy - equally (1/2); see PRD paper */ -{ - int i; - int j; - int jLower; - int jUpper; - int num_main_bins; - int num_bg_bins; - - double averaging_factor; - int offset; - double ratio; - - - num_main_bins = DPPRate->mainDimension; - num_bg_bins = DPPRate->bgDimension; - - if ((pBgPhotonDensity->dimension != num_bg_bins) || - (photonTotalRate->mainDimension != num_main_bins) || - (photonLeptonRate->mainDimension != num_main_bins)) - { - Error("FoldDPP: inconsistent dimensions", PROGRAM_ERROR); - } - - averaging_factor = (pow(10., 1./2./BINS_PER_DECADE) + - pow(10., -1./2./BINS_PER_DECADE))/2.; - /* although this could be supplied through arguments, I provide a local - version to keep the modality */ - offset = -(int)(BINS_PER_DECADE*log10(averaging_factor/2.) + 0.5); - ratio = offset/BINS_PER_DECADE - log10(2.); - - for (i = 0; i < num_main_bins; i++) - { - jLower = photonLeptonRate->bound[i][0]; - jUpper = photonLeptonRate->bound[i][1]; - for (j = 0; j < num_bg_bins; j++) - { - (photonTotalRate->totalRate)[i] += (pBgPhotonDensity->vector)[j]* - (DPPRate->totalRate)[i][j]; - if ((DPPRate->totalRate)[i][j] > 0.) - { - /* this is supplanted by the new implementation... - (photonLeptonRate->diffRate)[i][i-6] += - (pBgPhotonDensity->vector)[j]* - (DPPRate->totalRate)[i][j]*(1. - alpha); - (photonLeptonRate->diffRate)[i][i-7] += - (pBgPhotonDensity->vector)[j]* - (DPPRate->totalRate)[i][j]*alpha; - jLower = IMin((photonLeptonRate->bound)[i][0], i-7); - jUpper = IMax((photonLeptonRate->bound)[i][1], i-6); - */ - if (ratio < 1.) - { - if (i-offset >= 0) - { -#ifdef DEBUG - CheckIndex(0, num_main_bins, i-offset, "FoldDPP"); -#endif - (photonLeptonRate->diffRate)[i][i-offset] += - (pBgPhotonDensity->vector)[j]* - (DPPRate->totalRate)[i][j]*ratio; - - jLower = IMin(jLower, i-offset); - jUpper = IMax(jUpper, i-offset); - } - if (i-offset-1 >= 0) - { -#ifdef DEBUG - CheckIndex(0, num_main_bins, i-offset-1, "FoldDPP"); -#endif - (photonLeptonRate->diffRate)[i][i-offset-1] += - (pBgPhotonDensity->vector)[j]* - (DPPRate->totalRate)[i][j]*(1. - ratio); - - jLower = IMin(jLower, i-offset-1); - } - } - else - { - if (i-offset >= 0) - { -#ifdef DEBUG - CheckIndex(0, num_main_bins, i-offset, "FoldDPP"); -#endif - (photonLeptonRate->diffRate)[i][i-offset] += - (pBgPhotonDensity->vector)[j]* - (DPPRate->totalRate)[i][j]*(2. - ratio); - - jLower = IMin(jLower, i-offset); - jUpper = IMax(jUpper, i-offset); - } - if (i-offset+1 >= 0) - { -#ifdef DEBUG - CheckIndex(0, num_main_bins, i-offset+1, "FoldDPP"); -#endif - (photonLeptonRate->diffRate)[i][i-offset+1] += - (pBgPhotonDensity->vector)[j]* - (DPPRate->totalRate)[i][j]*(ratio - 1.); - - jUpper = IMax(jUpper, i-offset+1); - } - } - } - } - (photonLeptonRate->bound)[i][0] = jLower; - (photonLeptonRate->bound)[i][1] = jUpper; - /* update bounds */ - } -} - - -void FoldPPPNucleon(const dCVector* pBgPhotonDensity, - const RawTotalRate* PPPProtonLossRate, - const RawTotalRate* PPPNeutronLossRate, - const RawDiffRate* PPPProtonScatRate, - const RawDiffRate* PPPProtonNeutronRate, - const RawDiffRate* PPPNeutronProtonRate, - TotalRate* protonTotalRate, TotalRate* neutronTotalRate, - DiffRate* protonScatRate, DiffRate* protonNeutronRate, - DiffRate* neutronProtonRate) -{ - FoldTotalRate(pBgPhotonDensity, PPPProtonLossRate, protonTotalRate); - FoldTotalRate(pBgPhotonDensity, PPPNeutronLossRate, neutronTotalRate); - - /*---- nucleon -> nucleon from PPP ----*/ - FoldDiffRate(pBgPhotonDensity, PPPProtonScatRate, protonScatRate, - 2, protonTotalRate, neutronTotalRate); - FoldDiffRate(pBgPhotonDensity, PPPProtonNeutronRate, protonNeutronRate, - 0); - FoldDiffRate(pBgPhotonDensity, PPPNeutronProtonRate, neutronProtonRate, - 0); -} - - -void FoldPPPSecondary(const dCVector* pBgPhotonDensity, - const RawDiffRate* PPPProtonPhotonRate, - const RawDiffRate* PPPProtonElectronRate, - const RawDiffRate* PPPProtonPositronRate, - const RawDiffRate* PPPNeutronElectronRate, - const RawDiffRate* PPPProtonElectronNeutrinoRate, - const RawDiffRate* PPPProtonAntiElectronNeutrinoRate, - const RawDiffRate* PPPProtonMuonNeutrinoRate, - const RawDiffRate* PPPProtonAntiMuonNeutrinoRate, - const RawDiffRate* PPPNeutronAntiElectronNeutrinoRate, - const RawDiffRate* PPPNeutronMuonNeutrinoRate, - const RawDiffRate* PPPNeutronAntiMuonNeutrinoRate, - DiffRate* protonPhotonRate, - DiffRate* protonElectronRate, - DiffRate* protonPositronRate, - DiffRate* neutronElectronRate, - DiffRate* neutronPositronRate, - DiffRate* protonElectronNeutrinoRate, - DiffRate* protonAntiElectronNeutrinoRate, - DiffRate* protonMuonNeutrinoRate, - DiffRate* protonAntiMuonNeutrinoRate, - DiffRate* neutronAntiElectronNeutrinoRate, - DiffRate* neutronMuonNeutrinoRate, - DiffRate* neutronAntiMuonNeutrinoRate) -{ - /*---- nucleon -> EM species (gamma, e+/-) from PPP ----*/ - FoldDiffRate(pBgPhotonDensity, PPPProtonPhotonRate, protonPhotonRate, - 0); - FoldDiffRate(pBgPhotonDensity, PPPProtonPositronRate, protonPositronRate, - 0); - FoldDiffRate(pBgPhotonDensity, PPPNeutronElectronRate, - neutronElectronRate, 0); - FoldDiffRate(pBgPhotonDensity, PPPProtonElectronRate, protonElectronRate, - 0); - FoldDiffRate(pBgPhotonDensity, PPPProtonElectronRate, neutronPositronRate, - 0); - - /*---- nucleons -> neutrinos from PPP ----*/ - FoldDiffRate(pBgPhotonDensity, PPPProtonMuonNeutrinoRate, - protonMuonNeutrinoRate, 0); - FoldDiffRate(pBgPhotonDensity, PPPNeutronAntiMuonNeutrinoRate, - neutronAntiMuonNeutrinoRate, 0); - FoldDiffRate(pBgPhotonDensity, PPPProtonAntiMuonNeutrinoRate, - protonAntiMuonNeutrinoRate, 0); - FoldDiffRate(pBgPhotonDensity, PPPNeutronMuonNeutrinoRate, - neutronMuonNeutrinoRate, 0); - FoldDiffRate(pBgPhotonDensity, PPPProtonElectronNeutrinoRate, - protonElectronNeutrinoRate, 0); - FoldDiffRate(pBgPhotonDensity, PPPNeutronAntiElectronNeutrinoRate, - neutronAntiElectronNeutrinoRate, 0); - FoldDiffRate(pBgPhotonDensity, PPPProtonAntiElectronNeutrinoRate, - protonAntiElectronNeutrinoRate, 0); -} - -void FoldNPPNucleon(const dCVector* pBgPhotonDensity, const dCVector* pEnergy, - const RawTotalRate* NPPTotalRate, - dCVector* protonContinuousLoss) -{ - int i; - int j; - int num_main_bins; - int num_bg_bins; - - num_main_bins = pEnergy->dimension; - num_bg_bins = pBgPhotonDensity->dimension; - - if ((NPPTotalRate->mainDimension != num_main_bins) || - (NPPTotalRate->bgDimension != num_bg_bins) || - (protonContinuousLoss->dimension != num_main_bins)) - { - Error("FoldNPP: inconsistent dimensions", PROGRAM_ERROR); - } - - /*---- continuous energy loss ----*/ - for (i = 0; i < num_main_bins; i++) - { - (protonContinuousLoss->vector)[i] = 0.; - /* this is very important! */ - for (j = 0; j < num_bg_bins; j++) - { - (protonContinuousLoss->vector)[i] += -(pEnergy->vector)[i]* - (pBgPhotonDensity->vector)[j]* - (NPPTotalRate->totalRate)[i][j]; - } - } -} - -void FoldNPPSecondary(const dCVector* pBgPhotonDensity, - const RawDiffRate* NPPDiffRate, - DiffRate* protonPositronRate, - DiffRate* protonElectronRate) -{ - FoldDiffRate(pBgPhotonDensity, NPPDiffRate, protonPositronRate, 0); - FoldDiffRate(pBgPhotonDensity, NPPDiffRate, protonElectronRate, 0); -} - - -void MapNeutTotalRate(const double redshift, const int lastIndex, - const int tauNeutrinoMassSwitch, - const TotalRate* NNTotalRate, TotalRate* pRate) -/* This is for m_nu = 0 */ -{ - double redshiftFactor; - int i; - int offset; - int iNew; - int num_main_bins; - - num_main_bins = pRate->mainDimension; - - if (NNTotalRate->mainDimension != pRate->mainDimension) - { - Error("ManNeutTotalRate: inconsistent dimensions", PROGRAM_ERROR); - } - redshiftFactor = (1. + redshift)*(1. + redshift)*(1. + redshift); - - if (tauNeutrinoMassSwitch == 2) /* massless case */ - { - if (lastIndex == 0) /* away from z = 0 (simple sliding applies) */ - { - offset = (int)(BINS_PER_DECADE*log10(1. + redshift)); - for (i = 0; i < num_main_bins; i++) - { - iNew = i + offset; - /* map to the right index */ - if (iNew >= num_main_bins) - iNew = num_main_bins - 1; - /* if the index is beyond range, simply set it to maximum - (unsatisfactory?) */ -#ifdef DEBUG - CheckIndex(0, num_main_bins, iNew, "MapNeutTotalRate"); -#endif - (pRate->totalRate)[i] = redshiftFactor* - (NNTotalRate->totalRate)[iNew]; - } - } - else - { - double fraction; - - fraction = BINS_PER_DECADE*log10(1. + redshift); - offset = (int)fraction; - for (i = 0; i < num_main_bins; i++) - { - iNew = i + offset; - if (iNew < num_main_bins - 1) - { -#ifdef DEBUG - CheckIndex(0, num_main_bins, iNew, "MapNeutTotalRate"); -#endif - (pRate->totalRate)[i] = redshiftFactor* - ((NNTotalRate->totalRate)[iNew]* - (1. - fraction) + (NNTotalRate->totalRate)[iNew+1]* - fraction); - } - else - { - (pRate->totalRate)[i] = redshiftFactor* - (NNTotalRate->totalRate)[num_main_bins-1]; - } - } - } - } - else /* massive neutrinos */ - { - for (i = 0; i < num_main_bins; i++) - { - (pRate->totalRate)[i] = redshiftFactor* - (NNTotalRate->totalRate)[i]; - } - } -} - -void MapNeutDiffRate(const double redshift, const int lastIndex, - const int tauNeutrinoMassSwitch, - const DiffRate* NNDiffRate, DiffRate* pRate) -{ - int i; - int j; - int offset; - int iNew; - int jNew; - double redshiftFactor; - int num_main_bins; - - num_main_bins = pRate->mainDimension; - - if (NNDiffRate->mainDimension != pRate->mainDimension) - { - Error("ManNeutDiffRate: inconsistent dimensions", PROGRAM_ERROR); - } - - redshiftFactor = (1. + redshift)*(1. + redshift)*(1. + redshift); - - if (tauNeutrinoMassSwitch == 2) /* massless case */ - { - if (lastIndex == 0) /* away from z = 0 (simple sliding applies) */ - { - offset = (int)(BINS_PER_DECADE*log10(1. + redshift)); - for (i = 0; i < num_main_bins; i++) - { - iNew = i + offset; - /* map to the right index */ - if (iNew >= num_main_bins) - iNew = num_main_bins - 1; - /* if the index is beyond range, simply set it to maximum - (unsatisfactory?) */ - for (j = 0; j < num_main_bins; j++) - { - jNew = j + offset; - if (jNew >= num_main_bins) - jNew = num_main_bins - 1; - -#ifdef DEBUG - CheckIndex(0, num_main_bins, iNew, "MapNeutDiffRate"); - CheckIndex(0, num_main_bins, jNew, "MapNeutDiffRate"); -#endif - (pRate->diffRate)[i][j] = redshiftFactor* - (NNDiffRate->diffRate)[iNew][jNew]; - } - } - } - else - { - double fraction; - - fraction = BINS_PER_DECADE*log10(1. + redshift); - offset = (int)fraction; - for (i = 0; i < num_main_bins; i++) - { - iNew = i + offset; - for (j = 0; j < num_main_bins; j++) - { - jNew = j + offset; - if (iNew < num_main_bins - 1) - { -#ifdef DEBUG - CheckIndex(0, num_main_bins, iNew, "MapNeutDiffRate"); - CheckIndex(0, num_main_bins, jNew, "MapNeutDiffRate"); - CheckIndex(0, num_main_bins, iNew+1, - "MapNeutDiffRate"); - CheckIndex(0, num_main_bins, jNew+1, - "MapNeutDiffRate"); -#endif - (pRate->diffRate)[i][j] = redshiftFactor* - ((NNDiffRate->diffRate)[iNew][jNew]* - (1. - fraction)*(1. - fraction) + - ((NNDiffRate->diffRate)[iNew+1][jNew] + - (NNDiffRate->diffRate)[iNew][jNew+1])*fraction* - (1. - fraction) + - (NNDiffRate->diffRate)[iNew+1][jNew+1]*fraction* - fraction); - } - else if (jNew < num_main_bins - 1) - { -#ifdef DEBUG - CheckIndex(0, num_main_bins, jNew, "MapNeutDiffRate"); - CheckIndex(0, num_main_bins, jNew+1, - "MapNeutDiffRate"); -#endif - (pRate->diffRate)[i][j] = redshiftFactor* - ((NNDiffRate->diffRate)[num_main_bins-1][jNew]* - (1. - fraction) + - (NNDiffRate->diffRate)[num_main_bins-1][jNew+1]* - fraction); - } - else - { - (pRate->diffRate)[i][j] = redshiftFactor* - (NNDiffRate->diffRate)[num_main_bins-1][num_main_bins-1]; - } - } - } - } - } - else /* massive neutrino: simply multiply by redshift factor */ - { - for (i = 0; i < num_main_bins; i++) - { - for (j = 0; j < num_main_bins; j++) - { - (pRate->diffRate)[i][j] = redshiftFactor* - (NNDiffRate->diffRate)[i][j]; - } - } - } - - /* take care of bounds: simply make it standard (0 <= k <= i) */ - for (i = 0; i < pRate->mainDimension; i++) - { - pRate->bound[i][0] = 0; - pRate->bound[i][1] = i; - } -} - -void MapNeutRates(const double redshift, const int lastIndex, - const int tauNeutrinoMassSwitch, - const TotalRate* NNElNeutTotalRate, - const TotalRate* NNMuonNeutTotalRate, - const TotalRate* NNTauNeutTotalRate, - const DiffRate* NNElNeutScatRate, - const DiffRate* NNElNeutMuonNeutRate, - const DiffRate* NNElNeutTauNeutRate, - const DiffRate* NNElNeutElectronRate, - const DiffRate* NNElNeutPhotonRate, - const DiffRate* NNElNeutProtonRate, - const DiffRate* NNMuonNeutElNeutRate, - const DiffRate* NNMuonNeutScatRate, - const DiffRate* NNMuonNeutTauNeutRate, - const DiffRate* NNMuonNeutElectronRate, - const DiffRate* NNMuonNeutPhotonRate, - const DiffRate* NNMuonNeutProtonRate, - const DiffRate* NNTauNeutElNeutRate, - const DiffRate* NNTauNeutMuonNeutRate, - const DiffRate* NNTauNeutScatRate, - const DiffRate* NNTauNeutElectronRate, - const DiffRate* NNTauNeutPhotonRate, - const DiffRate* NNTauNeutProtonRate, - TotalRate* elNeutTotalRate, TotalRate* muonNeutTotalRate, - TotalRate* tauNeutTotalRate, DiffRate* elNeutScatRate, - DiffRate* elNeutMuonNeutRate, DiffRate* elNeutTauNeutRate, - DiffRate* elNeutElectronRate, DiffRate* elNeutPhotonRate, - DiffRate* elNeutProtonRate, DiffRate* muonNeutElNeutRate, - DiffRate* muonNeutScatRate, DiffRate* muonNeutTauNeutRate, - DiffRate* muonNeutElectronRate, DiffRate* muonNeutPhotonRate, - DiffRate* muonNeutProtonRate, DiffRate* tauNeutElNeutRate, - DiffRate* tauNeutMuonNeutRate, DiffRate* tauNeutScatRate, - DiffRate* tauNeutElectronRate, DiffRate* tauNeutPhotonRate, - DiffRate* tauNeutProtonRate) -{ - MapNeutTotalRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNElNeutTotalRate, elNeutTotalRate); - MapNeutTotalRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNMuonNeutTotalRate, muonNeutTotalRate); - MapNeutTotalRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNTauNeutTotalRate, tauNeutTotalRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNElNeutScatRate, elNeutScatRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNElNeutMuonNeutRate, elNeutMuonNeutRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNElNeutTauNeutRate, elNeutTauNeutRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNElNeutElectronRate, elNeutElectronRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNElNeutPhotonRate, elNeutPhotonRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNElNeutProtonRate, elNeutProtonRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNMuonNeutElNeutRate, muonNeutElNeutRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNMuonNeutScatRate, muonNeutScatRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNMuonNeutTauNeutRate, muonNeutTauNeutRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNMuonNeutElectronRate, muonNeutElectronRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNMuonNeutPhotonRate, muonNeutPhotonRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNMuonNeutProtonRate, muonNeutProtonRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNTauNeutElNeutRate, tauNeutElNeutRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNTauNeutMuonNeutRate, tauNeutMuonNeutRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNTauNeutScatRate, tauNeutScatRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNTauNeutElectronRate, tauNeutElectronRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNTauNeutPhotonRate, tauNeutPhotonRate); - MapNeutDiffRate(redshift, lastIndex, tauNeutrinoMassSwitch, - NNTauNeutProtonRate, tauNeutProtonRate); -} diff --git a/libs/dint/src/frag.cpp b/libs/dint/src/frag.cpp deleted file mode 100644 index ba2394cf1..000000000 --- a/libs/dint/src/frag.cpp +++ /dev/null @@ -1,582 +0,0 @@ -#include -#include -#include "dint/utilities.h" - -double OldFrag(const double x) -{ - double result; - - if ((x > 1.) || (x < 0.)) - Error("OldFrag: invalid x in FragFunction.", PROGRAM_ERROR); - - result = 15./16.*pow(x, -1.5)*(1. - x)*(1. - x); - return result; -} - -double HillFrag(const double x) -{ - double result; - - if ((x > 1.) || (x < 0.)) - Error("HillFrag: invalid x in FragFunction.", PROGRAM_ERROR); - - result = 0.08*exp(2.6*pow(log(1./x),0.5))*pow(1.-x,2.)/ - (x*pow(log(1./x),0.5)); - return result; -} - -double TestFrag(const double x) -{ - double result,dum; - - if ((x > 1.) || (x < 0.)) - Error("TestFrag: invalid x in FragFunction.", PROGRAM_ERROR); - - dum=log(1.e16*x); - result=pow(10.,16.40245282549585 + (0.972599977555579 + - (-0.437688709005956 + (0.07127838644906224 + - (-0.0096795444540692 + - (0.001074648803851362 + - (-0.0001017698959101458 + - (8.29188862155849e-6 + - (-6.028775483570168e-7 + - (3.722893226065044e-8 - - 5.328241092075332e-9* - (-14.27185163534489 + - 0.4342944819032517*dum))* - (-12.58946076125045 + - 0.4342944819032517*dum))* - (-10.90706988715602 + - 0.4342944819032517*dum))* - (-9.22467901306159 + - 0.4342944819032517*dum))* - (-7.542288138967164 + 0.4342944819032517*dum)) - *(-5.859897264872732 + 0.4342944819032517*dum))* - (-4.1775063907783 + 0.4342944819032517*dum))* - (-2.495115516683869 + 0.4342944819032517*dum))* - (-0.812724642589438 + 0.4342944819032517*dum))* - (0.869666231504994 + 0.4342944819032517*dum)); - - return result; -} - -double MLLA_25(const double x) -{ - double result,dum; - - if ((x > 1.) || (x < 0.)) - Error("MLLA_25: invalid x in FragFunction.", PROGRAM_ERROR); - - dum=log(5.e15*x); - result=pow(2.,15.40458956729789 + (0.985611314574832 + - (-0.4486531617591206 + (0.07437713380769515 + - (-0.01028351361441756 + - (0.001162396465975171 + - (-0.0001120792654142042 + - (9.29759848042302e-6 + - (-6.883087600199417e-7 + - (4.326958021115784e-8 - - 6.309347416082323e-9* - (-14.0009246392473 + - 0.4342944819032517*dum))* - (-12.34863676471927 + - 0.4342944819032517*dum))* - (-10.69634889019124 + - 0.4342944819032517*dum))* - (-9.04406101566321 + - 0.4342944819032517*dum))* - (-7.391773141135174 + - 0.4342944819032517*dum))* - (-5.73948526660714 + 0.4342944819032517*dum))* - (-4.087197392079107 + 0.4342944819032517*dum))* - (-2.434909517551073 + 0.4342944819032517*dum))* - (-0.78262164302304 + 0.4342944819032517*dum))* - (0.869666231504994 + 0.4342944819032517*dum))* - pow(5.,16.40458956729789 + (0.985611314574832 + - (-0.4486531617591206 + (0.07437713380769515 + - (-0.01028351361441756 + - (0.001162396465975171 + - (-0.0001120792654142042 + - (9.29759848042302e-6 + - (-6.883087600199417e-7 + - (4.326958021115784e-8 - - 6.309347416082323e-9* - (-14.0009246392473 + - 0.4342944819032517*dum))* - (-12.34863676471927 + - 0.4342944819032517*dum))* - (-10.69634889019124 + - 0.4342944819032517*dum))* - (-9.04406101566321 + - 0.4342944819032517*dum))* - (-7.391773141135174 + - 0.4342944819032517*dum))* - (-5.73948526660714 + 0.4342944819032517*dum))* - (-4.087197392079107 + 0.4342944819032517*dum))* - (-2.434909517551073 + 0.4342944819032517*dum))* - (-0.78262164302304 + 0.4342944819032517*dum))* - (0.869666231504994 + 0.4342944819032517*dum)); - - return result; -} - -double MLLA_24(const double x) -{ - double result,dum; - - if ((x > 1.) || (x < 0.)) - Error("MLLA_24: invalid x in FragFunction.", PROGRAM_ERROR); - - dum=log(5.e14*x); - result=pow(2.,14.41151551291054 + (1.031272826827779 + - (-0.4887554084149168 + (0.0861742231419955 + - (-0.01267862267956894 + - (0.001524972879202349 + - (-0.0001564836567815242 + - (0.00001381420881469393 + - (-1.088524574431424e-6 + - (7.278270707633613e-8 - - 1.131740588420111e-8* - (-13.1009246392473 + - 0.4342944819032517*dum))* - (-11.54863676471927 + - 0.4342944819032517*dum))* - (-9.99634889019124 + - 0.4342944819032517*dum))* - (-8.44406101566321 + - 0.4342944819032517*dum))* - (-6.891773141135172 + - 0.4342944819032517*dum))* - (-5.339485266607138 + 0.4342944819032517*dum))* - (-3.787197392079105 + 0.4342944819032517*dum))* - (-2.234909517551072 + 0.4342944819032517*dum))* - (-0.6826216430230394 + 0.4342944819032517*dum))* - (0.869666231504994 + 0.4342944819032517*dum))* - pow(5.,15.41151551291054 + (1.031272826827779 + - (-0.4887554084149168 + (0.0861742231419955 + - (-0.01267862267956894 + - (0.001524972879202349 + - (-0.0001564836567815242 + - (0.00001381420881469393 + - (-1.088524574431424e-6 + - (7.278270707633613e-8 - - 1.131740588420111e-8* - (-13.1009246392473 + - 0.4342944819032517*dum))* - (-11.54863676471927 + - 0.4342944819032517*dum))* - (-9.99634889019124 + - 0.4342944819032517*dum))* - (-8.44406101566321 + - 0.4342944819032517*dum))* - (-6.891773141135172 + - 0.4342944819032517*dum))* - (-5.339485266607138 + 0.4342944819032517*dum))* - (-3.787197392079105 + 0.4342944819032517*dum))* - (-2.234909517551072 + 0.4342944819032517*dum))* - (-0.6826216430230394 + 0.4342944819032517*dum))* - (0.869666231504994 + 0.4342944819032517*dum)); - - return result; -} - -double MLLA_23(const double x) -{ - double result,dum; - - if ((x > 1.) || (x < 0.)) - Error("MLLA_23: invalid x in FragFunction.", PROGRAM_ERROR); - - dum=log(5.e13*x); - result=pow(2.,13.41903621081451 + (1.080543174351792 + - (-0.5353344158025766 + (0.1007918200125547 + - (-0.01584522550357778 + - (0.00203634282994057 + - (-0.0002232988627851284 + - (0.00002106422871935973 + - (-1.774021976209115e-6 + - (1.26678984354972e-7 - - 2.109673764365339e-8* - (-12.2009246392473 + - 0.4342944819032517*dum))* - (-10.74863676471927 + - 0.4342944819032517*dum))* - (-9.29634889019124 + - 0.4342944819032517*dum))* - (-7.844061015663205 + - 0.4342944819032517*dum))* - (-6.391773141135174 + - 0.4342944819032517*dum))* - (-4.93948526660714 + 0.4342944819032517*dum))* - (-3.487197392079106 + 0.4342944819032517*dum))* - (-2.034909517551073 + 0.4342944819032517*dum))* - (-0.5826216430230398 + 0.4342944819032517*dum))* - (0.869666231504994 + 0.4342944819032517*dum))* - pow(5.,14.4190362108145 + (1.080543174351792 + - (-0.5353344158025766 + (0.1007918200125547 + - (-0.01584522550357778 + - (0.00203634282994057 + - (-0.0002232988627851284 + - (0.00002106422871935973 + - (-1.774021976209115e-6 + - (1.26678984354972e-7 - - 2.109673764365339e-8* - (-12.2009246392473 + - 0.4342944819032517*dum))* - (-10.74863676471927 + - 0.4342944819032517*dum))* - (-9.29634889019124 + - 0.4342944819032517*dum))* - (-7.844061015663205 + - 0.4342944819032517*dum))* - (-6.391773141135174 + - 0.4342944819032517*dum))* - (-4.93948526660714 + 0.4342944819032517*dum))* - (-3.487197392079106 + 0.4342944819032517*dum))* - (-2.034909517551073 + 0.4342944819032517*dum))* - (-0.5826216430230398 + 0.4342944819032517*dum))* - (0.869666231504994 + 0.4342944819032517*dum)); - - return result; -} - -double MLLA_22(const double x) -{ - double result,dum; - - if ((x > 1.) || (x < 0.)) - Error("MLLA_22: invalid x in FragFunction.", PROGRAM_ERROR); - - dum=log(5.e12*x); - result=pow(2.,12.42700515451375 + (1.13410597810389 + - (-0.5900360565767645 + (0.1191811135998055 + - (-0.02011422129768237 + - (0.002774985316661523 + - (-0.000326719986276957 + - (0.00003308906432045379 + - (-2.992669826664713e-6 + - (2.292869774886544e-7 - - 4.109421051511541e-8* - (-11.3009246392473 + - 0.4342944819032517*dum))* - (-9.94863676471927 + - 0.4342944819032517*dum))* - (-8.59634889019124 + - 0.4342944819032517*dum))* - (-7.244061015663207 + - 0.4342944819032517*dum))* - (-5.891773141135173 + - 0.4342944819032517*dum))* - (-4.539485266607139 + 0.4342944819032517*dum))* - (-3.187197392079106 + 0.4342944819032517*dum))* - (-1.834909517551073 + 0.4342944819032517*dum))* - (-0.4826216430230396 + 0.4342944819032517*dum))* - (0.869666231504994 + 0.4342944819032517*dum))* - pow(5.,13.42700515451375 + (1.13410597810389 + - (-0.5900360565767645 + (0.1191811135998055 + - (-0.02011422129768237 + - (0.002774985316661523 + - (-0.000326719986276957 + - (0.00003308906432045379 + - (-2.992669826664713e-6 + - (2.292869774886544e-7 - - 4.109421051511541e-8* - (-11.3009246392473 + - 0.4342944819032517*dum))* - (-9.94863676471927 + - 0.4342944819032517*dum))* - (-8.59634889019124 + - 0.4342944819032517*dum))* - (-7.244061015663207 + - 0.4342944819032517*dum))* - (-5.891773141135173 + - 0.4342944819032517*dum))* - (-4.539485266607139 + 0.4342944819032517*dum))* - (-3.187197392079106 + 0.4342944819032517*dum))* - (-1.834909517551073 + 0.4342944819032517*dum))* - (-0.4826216430230396 + 0.4342944819032517*dum))* - (0.869666231504994 + 0.4342944819032517*dum)); - - return result; -} - -double Susy_MLLA_25(const double x) -{ - double result,dum; - - if ((x > 1.) || (x < 0.)) - Error("SUSY_MLLA_25: invalid x in FragFunction.", PROGRAM_ERROR); - - dum=log(5.e15*x); - result=pow(2.,17.80939867175655 + (0.2839116910462308 + - (-0.2356852044900653 + (0.02811959068440033 + - (-0.003372920093046873 + - (0.0003286208445235064 + - (-0.00002939777800753709 + - (2.158754018629821e-6 + - (-1.695451594928554e-7 + - 1.096396916569957e-9* - (-12.9950665059705 + - 0.4342944819032517*dum))* - (-11.3649635064041 + - 0.4342944819032517*dum))* - (-9.73486050683771 + - 0.4342944819032517*dum))* - (-8.10475750727131 + - 0.4342944819032517*dum))* - (-6.474654507704915 + 0.4342944819032517*dum))* - (-4.844551508138517 + 0.4342944819032517*dum))* - (-3.214448508572119 + 0.4342944819032517*dum))* - (-1.584345509005722 + 0.4342944819032517*dum))* - (0.04575749056067511 + 0.4342944819032517*dum))* - pow(5.,18.80939867175655 + (0.2839116910462308 + - (-0.2356852044900653 + (0.02811959068440033 + - (-0.003372920093046873 + - (0.0003286208445235064 + - (-0.00002939777800753709 + - (2.158754018629821e-6 + - (-1.695451594928554e-7 + - 1.096396916569957e-9* - (-12.9950665059705 + - 0.4342944819032517*dum))* - (-11.3649635064041 + - 0.4342944819032517*dum))* - (-9.73486050683771 + - 0.4342944819032517*dum))* - (-8.10475750727131 + 0.4342944819032517*dum))* - (-6.474654507704915 + 0.4342944819032517*dum))* - (-4.844551508138517 + 0.4342944819032517*dum))* - (-3.214448508572119 + 0.4342944819032517*dum))* - (-1.584345509005722 + 0.4342944819032517*dum))* - (0.04575749056067511 + 0.4342944819032517*dum)); - - return result; -} - -double Susy_MLLA_24(const double x) -{ - double result,dum; - - if ((x > 1.) || (x < 0.)) - Error("SUSY_MLLA_24: invalid x in FragFunction.", PROGRAM_ERROR); - - dum=log(5.e14*x); - result=pow(2.,16.77113060518843 + (0.2757875825414864 + - (-0.2492517918211629 + (0.03115785196336573 + - (-0.003960507732763939 + - (0.0004075768109015362 + - (-0.00003875082087547734 + - (3.001698672664923e-6 + - (-2.54680759800193e-7 - - 6.061017668092866e-10* - (-12.1950665059705 + - 0.4342944819032517*dum))* - (-10.6649635064041 + - 0.4342944819032517*dum))* - (-9.13486050683771 + - 0.4342944819032517*dum))* - (-7.604757507271312 + - 0.4342944819032517*dum))* - (-6.074654507704915 + 0.4342944819032517*dum))* - (-4.544551508138517 + 0.4342944819032517*dum))* - (-3.01444850857212 + 0.4342944819032517*dum))* - (-1.484345509005722 + 0.4342944819032517*dum))* - (0.04575749056067511 + 0.4342944819032517*dum))* - pow(5.,17.77113060518843 + (0.2757875825414864 + - (-0.2492517918211629 + (0.03115785196336573 + - (-0.003960507732763939 + - (0.0004075768109015362 + - (-0.00003875082087547734 + - (3.001698672664923e-6 + - (-2.54680759800193e-7 - - 6.061017668092866e-10* - (-12.1950665059705 + - 0.4342944819032517*dum))* - (-10.6649635064041 + - 0.4342944819032517*dum))* - (-9.13486050683771 + - 0.4342944819032517*dum))* - (-7.604757507271312 + - 0.4342944819032517*dum))* - (-6.074654507704915 + 0.4342944819032517*dum))* - (-4.544551508138517 + 0.4342944819032517*dum))* - (-3.01444850857212 + 0.4342944819032517*dum))* - (-1.484345509005722 + 0.4342944819032517*dum))* - (0.04575749056067511 + 0.4342944819032517*dum)); - - return result; -} - -double Susy_MLLA_23(const double x) -{ - double result,dum; - - if ((x > 1.) || (x < 0.)) - Error("SUSY_MLLA_23: invalid x in FragFunction.", PROGRAM_ERROR); - - dum=log(5.e13*x); - result=pow(2.,15.72966406841544 + (0.2650394265463622 + - (-0.2643461911608049 + (0.03469445588689251 + - (-0.004691489477251425 + - (0.0005115097120944895 + - (-0.00005190898995160702 + - (4.25132297772461e-6 + - (-3.930251977808645e-7 - - 6.036368834076273e-9* - (-11.3950665059705 + - 0.4342944819032517*dum))* - (-9.96496350640411 + - 0.4342944819032517*dum))* - (-8.53486050683771 + - 0.4342944819032517*dum))* - (-7.104757507271313 + - 0.4342944819032517*dum))* - (-5.674654507704915 + 0.4342944819032517*dum))* - (-4.244551508138518 + 0.4342944819032517*dum))* - (-2.81444850857212 + 0.4342944819032517*dum))* - (-1.384345509005722 + 0.4342944819032517*dum))* - (0.04575749056067511 + 0.4342944819032517*dum))* - pow(5.,16.72966406841544 + (0.2650394265463622 + - (-0.2643461911608049 + (0.03469445588689251 + - (-0.004691489477251425 + - (0.0005115097120944895 + - (-0.00005190898995160702 + - (4.25132297772461e-6 + - (-3.930251977808645e-7 - - 6.036368834076273e-9* - (-11.3950665059705 + - 0.4342944819032517*dum))* - (-9.96496350640411 + - 0.4342944819032517*dum))* - (-8.53486050683771 + - 0.4342944819032517*dum))* - (-7.104757507271313 + - 0.4342944819032517*dum))* - (-5.674654507704915 + 0.4342944819032517*dum))* - (-4.244551508138518 + 0.4342944819032517*dum))* - (-2.81444850857212 + 0.4342944819032517*dum))* - (-1.384345509005722 + 0.4342944819032517*dum))* - (0.04575749056067511 + 0.4342944819032517*dum)); - - return result; -} - -double Susy_MLLA_22(const double x) -{ - double result,dum; - - if ((x > 1.) || (x < 0.)) - Error("SUSY_MLLA_22: invalid x in FragFunction.", PROGRAM_ERROR); - - dum=log(5.e12*x); - result=pow(2.,14.684456999313 + (0.2510136065483903 + - (-0.2812473861506196 + (0.03884100532808183 + - (-0.005612423127059197 + - (0.0006504629731684842 + - (-0.00007081237970893412 + - (6.145415483685166e-6 + - (-6.258855246298706e-7 - - 2.175481457118431e-8* - (-10.5950665059705 + - 0.4342944819032517*dum))* - (-9.26496350640411 + - 0.4342944819032517*dum))* - (-7.934860506837712 + - 0.4342944819032517*dum))* - (-6.604757507271314 + - 0.4342944819032517*dum))* - (-5.274654507704916 + 0.4342944819032517*dum))* - (-3.944551508138518 + 0.4342944819032517*dum))* - (-2.61444850857212 + 0.4342944819032517*dum))* - (-1.284345509005722 + 0.4342944819032517*dum))* - (0.04575749056067511 + 0.4342944819032517*dum))* - pow(5.,15.68445699931301 + (0.2510136065483903 + - (-0.2812473861506196 + (0.03884100532808183 + - (-0.005612423127059197 + - (0.0006504629731684842 + - (-0.00007081237970893412 + - (6.145415483685166e-6 + - (-6.258855246298706e-7 - - 2.175481457118431e-8* - (-10.5950665059705 + - 0.4342944819032517*dum))* - (-9.26496350640411 + - 0.4342944819032517*dum))* - (-7.934860506837712 + - 0.4342944819032517*dum))* - (-6.604757507271314 + - 0.4342944819032517*dum))* - (-5.274654507704916 + 0.4342944819032517*dum))* - (-3.944551508138518 + 0.4342944819032517*dum))* - (-2.61444850857212 + 0.4342944819032517*dum))* - (-1.284345509005722 + 0.4342944819032517*dum))* - (0.04575749056067511 + 0.4342944819032517*dum)); - - return result; -} - -double TDFolded(const double x) -{ - double result,dum; - - if ((x > 1.) || (x < 0.)) - Error("TDFolded: invalid x in FragFunction.", PROGRAM_ERROR); - - dum=log(1.e16*x); - result=pow(10.,16.40245282549585 + (2.006465566761043 + - (-1.2290432682737338 + (0.4053297476358819 + - (-0.10906672734507838 + - (0.02423162048512474 + - (-0.004566321632592419 + - (0.0007455136443033367 + - (-0.00010727374780647999 + - (0.000013791254716212407 + - (-1.6018349553861322e-6 + - (1.6963430526506736e-7 + - (-1.6505676370801003e-8 + - (1.4852680477947195e-9 + - (-1.2429947252576973e-10 + - (9.721275964488186e-12 + - (-7.135988486015182e-13 + - (4.933475574027309e-14 + - (-3.2288896623602718e-15 + - (1.9690047616867213e-16 - - 2.6034108179793842e-17* - (-15.113047072392108 + - 0.43429448190325176*dum))* - (-14.271851635344891 + - 0.43429448190325176*dum))* - (-13.430656198297674 + - 0.43429448190325176*dum))* - (-12.589460761250459 + - 0.43429448190325176*dum))* - (-11.748265324203246 + - 0.43429448190325176*dum))* - (-10.907069887156027 + - 0.43429448190325176*dum))* - (-10.065874450108813 + - 0.43429448190325176*dum))* - (-9.224679013061595 + - 0.43429448190325176*dum))* - (-8.383483576014381 + - 0.43429448190325176*dum))* - (-7.542288138967164 + - 0.43429448190325176*dum))* - (-6.701092701919949 + - 0.43429448190325176*dum))* - (-5.859897264872733 + - 0.43429448190325176*dum))* - (-5.018701827825517 + - 0.43429448190325176*dum))* - (-4.1775063907783005 + - 0.43429448190325176*dum))* - (-3.3363109537310853 + - 0.43429448190325176*dum))* - (-2.4951155166838697 + 0.43429448190325176*dum))* - (-1.6539200796366536 + 0.43429448190325176*dum))* - (-0.812724642589438 + 0.43429448190325176*dum))* - (0.028470794457777927 + 0.43429448190325176*dum))* - (0.8696662315049937 + 0.43429448190325176*dum)); - - return result; -} diff --git a/libs/dint/src/gauleg.cpp b/libs/dint/src/gauleg.cpp deleted file mode 100644 index df634964c..000000000 --- a/libs/dint/src/gauleg.cpp +++ /dev/null @@ -1,534 +0,0 @@ -//////////////////////////////////////////////////////////////////////// -// Gauss Legendre Integration -// -// Based on an implementation from John Burkardt -// http://people.sc.fsu.edu/~jburkardt/cpp_src/legendre_rule_fast/legendre_rule_fast.html -// -// Licensing: -// This code is distributed under the GNU LGPL license. - - -#include -#include - - -void legendre_compute_glr ( int n, double x[], double w[] ); -void legendre_compute_glr0 ( int n, double *p, double *pp ); -void legendre_compute_glr1 ( int n, double *roots, double *ders ); -void legendre_compute_glr2 ( double p, int n, double *roots, double *ders ); - -double ts_mult ( double *u, double h, int n ) - -//****************************************************************************80 -// -// Purpose: -// -// TS_MULT evaluates a polynomial. -// -// Licensing: -// -// This code is distributed under the GNU LGPL license. -// -// Modified: -// -// 17 May 2013 -// -// Author: -// -// Original C++ version by Nick Hale. -// This C++ version by John Burkardt. -// -// Parameters: -// -// Input, double U[N+1], the polynomial coefficients. -// U[0] is ignored. -// -// Input, double H, the polynomial argument. -// -// Input, int N, the number of terms to compute. -// -// Output, double TS_MULT, the value of the polynomial. -// -{ - double hk; - int k; - double ts; - - ts = 0.0; - hk = 1.0; - for ( k = 1; k<= n; k++ ) - { - ts = ts + u[k] * hk; - hk = hk * h; - } - return ts; -} - -double rk2_leg ( double t1, double t2, double x, int n ) - -//****************************************************************************80 -// -// Purpose: -// -// RK2_LEG advances the value of X(T) using a Runge-Kutta method. -// -// Licensing: -// -// This code is distributed under the GNU LGPL license. -// -// Modified: -// -// 22 October 2009 -// -// Author: -// -// Original C++ version by Nick Hale. -// This C++ version by John Burkardt. -// -// Parameters: -// -// Input, double T1, T2, the range of the integration interval. -// -// Input, double X, the value of X at T1. -// -// Input, int N, the number of steps to take. -// -// Output, double RK2_LEG, the value of X at T2. -// -{ - double f; - double h; - int j; - double k1; - double k2; - int m = 10; - double snn1; - double t; - - h = ( t2 - t1 ) / ( double ) m; - snn1 = sqrt ( ( double ) ( n * ( n + 1 ) ) ); - t = t1; - - for ( j = 0; j < m; j++ ) - { - f = ( 1.0 - x ) * ( 1.0 + x ); - k1 = - h * f / ( snn1 * sqrt ( f ) - 0.5 * x * sin ( 2.0 * t ) ); - x = x + k1; - - t = t + h; - - f = ( 1.0 - x ) * ( 1.0 + x ); - k2 = - h * f / ( snn1 * sqrt ( f ) - 0.5 * x * sin ( 2.0 * t ) ); - x = x + 0.5 * ( k2 - k1 ); - } - return x; -} -//****************************************************************************80 - - - -void legendre_compute_glr ( int n, double x[], double w[] ) - -//****************************************************************************80 -// -// Purpose: -// -// LEGENDRE_COMPUTE_GLR: Legendre quadrature by the Glaser-Liu-Rokhlin method. -// -// Licensing: -// -// This code is distributed under the GNU LGPL license. -// -// Modified: -// -// 20 October 2009 -// -// Author: -// -// Original C++ version by Nick Hale. -// This C++ version by John Burkardt. -// -// Reference: -// -// Andreas Glaser, Xiangtao Liu, Vladimir Rokhlin, -// A fast algorithm for the calculation of the roots of special functions, -// SIAM Journal on Scientific Computing, -// Volume 29, Number 4, pages 1420-1438, 2007. -// -// Parameters: -// -// Input, int N, the order. -// -// Output, double X[N], the abscissas. -// -// Output, double W[N], the weights. -// -{ - int i; - double p; - double pp; - double w_sum; -// -// Get the value and derivative of the N-th Legendre polynomial at 0. -// - legendre_compute_glr0 ( n, &p, &pp ); -// -// If N is odd, then zero is a root. -// - if ( n % 2 == 1 ) - { - x[(n-1)/2] = p; - w[(n-1)/2] = pp; - } -// -// If N is even, we have to call a function to find the first root. -// - else - { - legendre_compute_glr2 ( p, n, &x[n/2], &w[n/2] ); - } -// -// Get the complete set of roots and derivatives. -// - legendre_compute_glr1 ( n, x, w ); -// -// Compute the W. -// - for ( i = 0; i < n; i++ ) - { - w[i] = 2.0 / ( 1.0 - x[i] ) / ( 1.0 + x[i] ) / w[i] / w[i]; - } - w_sum = 0.0; - for ( i = 0; i < n; i++ ) - { - w_sum = w_sum + w[i]; - } - for ( i = 0; i < n; i++ ) - { - w[i] = 2.0 * w[i] / w_sum; - } - return; -} -//****************************************************************************80 - -void legendre_compute_glr0 ( int n, double *p, double *pp ) - -//****************************************************************************80 -// -// Purpose: -// -// LEGENDRE_COMPUTE_GLR0 gets a starting value for the fast algorithm. -// -// Licensing: -// -// This code is distributed under the GNU LGPL license. -// -// Modified: -// -// 19 October 2009 -// -// Author: -// -// Original C++ version by Nick Hale. -// This C++ version by John Burkardt. -// -// Reference: -// -// Andreas Glaser, Xiangtao Liu, Vladimir Rokhlin, -// A fast algorithm for the calculation of the roots of special functions, -// SIAM Journal on Scientific Computing, -// Volume 29, Number 4, pages 1420-1438, 2007. -// -// Parameters: -// -// Input, int N, the order of the Legendre polynomial. -// -// Output, double *P, *PP, the value of the N-th Legendre polynomial -// and its derivative at 0. -// -{ - double dk; - int k; - double pm1; - double pm2; - double ppm1; - double ppm2; - - pm2 = 0.0; - pm1 = 1.0; - ppm2 = 0.0; - ppm1 = 0.0; - - for ( k = 0; k < n; k++) - { - dk = ( double ) k; - *p = - dk * pm2 / ( dk + 1.0 ); - *pp = ( ( 2.0 * dk + 1.0 ) * pm1 - dk * ppm2 ) / ( dk + 1.0 ); - pm2 = pm1; - pm1 = *p; - ppm2 = ppm1; - ppm1 = *pp; - } - return; -} -//****************************************************************************80 - -void legendre_compute_glr1 ( int n, double *x, double *w ) - -//****************************************************************************80 -// -// Purpose: -// -// LEGENDRE_COMPUTE_GLR1 gets the complete set of Legendre points and weights. -// -// Discussion: -// -// This routine requires that a starting estimate be provided for one -// root and its derivative. This information will be stored in entry -// (N+1)/2 if N is odd, or N/2 if N is even, of X and W. -// -// Licensing: -// -// This code is distributed under the GNU LGPL license. -// -// Modified: -// -// 19 October 2009 -// -// Author: -// -// Original C++ version by Nick Hale. -// This C++ version by John Burkardt. -// -// Reference: -// -// Andreas Glaser, Xiangtao Liu, Vladimir Rokhlin, -// A fast algorithm for the calculation of the roots of special functions, -// SIAM Journal on Scientific Computing, -// Volume 29, Number 4, pages 1420-1438, 2007. -// -// Parameters: -// -// Input, int N, the order of the Legendre polynomial. -// -// Input/output, double X[N]. On input, a starting value -// has been set in one entry. On output, the roots of the Legendre -// polynomial. -// -// Input/output, double W[N]. On input, a starting value -// has been set in one entry. On output, the derivatives of the Legendre -// polynomial at the zeros. -// -// Local Parameters: -// -// Local, int M, the number of terms in the Taylor expansion. -// -{ - double dk; - double dn; - double h; - int j; - int k; - int l; - int m = 30; - int n2; - static double pi = 3.141592653589793; - int s; - double *u; - double *up; - double xp; - - if ( n % 2 == 1 ) - { - n2 = ( n - 1 ) / 2 - 1; - s = 1; - } - else - { - n2 = n / 2 - 1; - s = 0; - } - - u = new double[m+2]; - up = new double[m+1]; - - dn = ( double ) n; - - for ( j = n2 + 1; j < n - 1; j++ ) - { - xp = x[j]; - - h = rk2_leg ( pi/2.0, -pi/2.0, xp, n ) - xp; - - u[0] = 0.0; - u[1] = 0.0; - u[2] = w[j]; - - up[0] = 0.0; - up[1] = u[2]; - - for ( k = 0; k <= m - 2; k++ ) - { - dk = ( double ) k; - - u[k+3] = - ( - 2.0 * xp * ( dk + 1.0 ) * u[k+2] - + ( dk * ( dk + 1.0 ) - dn * ( dn + 1.0 ) ) * u[k+1] / ( dk + 1.0 ) - ) / ( 1.0 - xp ) / ( 1.0 + xp ) / ( dk + 2.0 ); - - up[k+2] = ( dk + 2.0 ) * u[k+3]; - } - - for ( l = 0; l < 5; l++ ) - { - h = h - ts_mult ( u, h, m ) / ts_mult ( up, h, m-1 ); - } - - x[j+1] = xp + h; - w[j+1] = ts_mult ( up, h, m - 1 ); - } - - for ( k = 0; k <= n2 + s; k++ ) - { - x[k] = - x[n-1-k]; - w[k] = w[n-1-k]; - } - - delete[] u; - delete[] up; - - return; -} -//****************************************************************************80 - -void legendre_compute_glr2 ( double pn0, int n, double *x1, double *d1 ) - -//****************************************************************************80 -// -// Purpose: -// -// LEGENDRE_COMPUTE_GLR2 finds the first real root. -// -// Discussion: -// -// This function is only called if N is even. -// -// Licensing: -// -// This code is distributed under the GNU LGPL license. -// -// Modified: -// -// 19 October 2009 -// -// Author: -// -// Original C++ version by Nick Hale. -// This C++ version by John Burkardt. -// -// Reference: -// -// Andreas Glaser, Xiangtao Liu, Vladimir Rokhlin, -// A fast algorithm for the calculation of the roots of special functions, -// SIAM Journal on Scientific Computing, -// Volume 29, Number 4, pages 1420-1438, 2007. -// -// Parameters: -// -// Input, double PN0, the value of the N-th Legendre polynomial -// at 0. -// -// Input, int N, the order of the Legendre polynomial. -// -// Output, double *X1, the first real root. -// -// Output, double *D1, the derivative at X1. -// -// Local Parameters: -// -// Local, int M, the number of terms in the Taylor expansion. -// -{ - double dk; - double dn; - int k; - int l; - int m = 30; - static double pi = 3.141592653589793; - double t; - double *u; - double *up; - - t = 0.0; - *x1 = rk2_leg ( t, -pi/2.0, 0.0, n ); - - u = new double[m+2]; - up = new double[m+1]; - - dn = ( double ) n; -// -// U[0] and UP[0] are never used. -// U[M+1] is set, but not used, and UP[M] is set and not used. -// What gives? -// - u[0] = 0.0; - u[1] = pn0; - - up[0] = 0.0; - - for ( k = 0; k <= m - 2; k = k + 2 ) - { - dk = ( double ) k; - - u[k+2] = 0.0; - u[k+3] = ( dk * ( dk + 1.0 ) - dn * ( dn + 1.0 ) ) * u[k+1] - / (dk + 1.0) / (dk + 2.0 ); - - up[k+1] = 0.0; - up[k+2] = ( dk + 2.0 ) * u[k+3]; - } - - for ( l = 0; l < 5; l++ ) - { - *x1 = *x1 - ts_mult ( u, *x1, m ) / ts_mult ( up, *x1, m-1 ); - } - *d1 = ts_mult ( up, *x1, m-1 ); - - delete[] u; - delete[] up; - - return; -} - - - - -void Gauleg(const double x1, const double x2, double x[], double w[], - const int n) -{ - - static std::map __legendreAbcissa; - static std::map __legendreWeights; - - if (__legendreAbcissa.find(n) == __legendreAbcissa.end()) - { - __legendreAbcissa[n] = new double[n]; - __legendreWeights[n] = new double[n]; - legendre_compute_glr ( n, __legendreAbcissa[n], __legendreWeights[n]); - } - - - - for ( int i = 0; i < n; i++ ) - { - x[i] = ( ( x1 + x2 ) + ( x2 - x1 ) * __legendreAbcissa[n][i] ) / 2.0; - } - for ( int i = 0; i < n; i++ ) - { - w[i] = ( x2 - x1 ) * __legendreWeights[n][i] / 2.0; - } - return; - -} - diff --git a/libs/dint/src/inject.cpp b/libs/dint/src/inject.cpp deleted file mode 100644 index 7e6a4236d..000000000 --- a/libs/dint/src/inject.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include "dint/cvector.h" -#include "dint/spectrum.h" -#include "dint/const.h" -#include "dint/frag.h" -#include "dint/decay.h" -#include "dint/utilities.h" -#include "dint/inject.h" - -// E.Armengaud - Dec 2005 -// This routine is not used anymore : -// the injection spectrum must now be computed within CRPropa. - -void SetInjectionSpectrum(const PARTICLE part, const double InjEnergy, - const double HInjEnergy, const double deltaE_hadron, - const dCVector* pEnergy, - const dCVector* pEnergyWidth, Spectrum* pQ_0) { - int num_main_bins, maxBin, i; - double criticalEnergy; - - InitializeSpectrum(pQ_0); - num_main_bins = pEnergy->dimension; - - if ((pEnergyWidth->dimension != num_main_bins) || - (pQ_0->numberOfMainBins != num_main_bins)) - Error("PhotonMonoInjection: inconsistent dimensions", PROGRAM_ERROR); - - if (part != NOTHING) { - criticalEnergy = InjEnergy/ELECTRON_MASS; - maxBin = (int)((log10(criticalEnergy*ELECTRON_MASS) - - MAX_ENERGY_EXP)*BINS_PER_DECADE + num_main_bins); - (pQ_0->spectrum)[part][maxBin] = 1.; - - } else { - // In this case, we model the injection spectrum created by pair production - // with a power law of index -7/4 - if (deltaE_hadron == 0.e0) Error("DeltaE_Hadron = 0 !", PROGRAM_ERROR); - double sum=0.; - criticalEnergy = HInjEnergy/ELECTRON_MASS; - for (i = 0; i < num_main_bins; i++) { - if (pEnergy->vector[i] < criticalEnergy) { - (pQ_0->spectrum)[ELECTRON][i] = pow(pEnergy->vector[i],-7./4.)* - (pEnergyWidth->vector)[i]; - sum += (pQ_0->spectrum)[ELECTRON][i]*(pEnergy->vector)[i]; - } - } - sum *= ELECTRON_MASS; - sum = deltaE_hadron/sum/2.; - for (i = 0; i < num_main_bins; i++) { - (pQ_0->spectrum)[ELECTRON][i] *= sum; - (pQ_0->spectrum)[POSITRON][i] = (pQ_0->spectrum)[ELECTRON][i]; - } - - } -} diff --git a/libs/dint/src/io_util.cpp b/libs/dint/src/io_util.cpp deleted file mode 100644 index 7798cf3ae..000000000 --- a/libs/dint/src/io_util.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include "dint/error.h" - -FILE* SafeFOpen(const char* filename, const char* mode) -{ - FILE* file; - if ((file = fopen(filename, mode)) == NULL) - { - printf("SafeFOpen: cannot open %s\n", filename); - exit (IO_ERROR); - } - - return file; -} diff --git a/libs/dint/src/load.cpp b/libs/dint/src/load.cpp deleted file mode 100644 index 6dc1f569c..000000000 --- a/libs/dint/src/load.cpp +++ /dev/null @@ -1,330 +0,0 @@ - -#include "dint/load.h" - -// Modified Apr 2005 : aDirTable argument - -void LoadICSTables(RawTotalRate* ICSTotalRate, RawDiffRate* ICSPhotonRate, - RawDiffRate* ICSScatRate, const int num_main_bins, - string aDirTables) -{ - ReadRawTotalRate(ICSTotalRate, (aDirTables+"/ICSLoss.dat").c_str()); - ModifyRawTotalRate(ICSTotalRate, num_main_bins); - - ReadRawDiffRate(ICSPhotonRate, (aDirTables+"/ICSLP.dat").c_str()); - ModifyRawDiffRate(ICSPhotonRate, num_main_bins); - - ReadRawDiffRate(ICSScatRate, (aDirTables+"/ICSLS.dat").c_str()); - ModifyRawDiffRate(ICSScatRate, num_main_bins); -} - - -void LoadPPTables(RawTotalRate* PPTotalRate, RawDiffRate* PPDiffRate, - const int num_main_bins, string aDirTables) -{ - ReadRawTotalRate(PPTotalRate, (aDirTables+"/PPLoss.dat").c_str()); - ModifyRawTotalRate(PPTotalRate, num_main_bins); - - ReadRawDiffRate(PPDiffRate, (aDirTables+"/PPPL.dat").c_str()); - ModifyRawDiffRate(PPDiffRate, num_main_bins); -} - - -void LoadTPPTables(RawTotalRate* TPPTotalRate, RawDiffRate* TPPDiffRate, - const int num_main_bins, string aDirTables) -{ - ReadRawTotalRate(TPPTotalRate, (aDirTables+"/TPPLoss.dat").c_str()); - ModifyRawTotalRate(TPPTotalRate, num_main_bins); - - ReadRawDiffRate(TPPDiffRate, (aDirTables+"/TPPDiff.dat").c_str()); - ModifyRawDiffRate(TPPDiffRate, num_main_bins); -} - -void LoadDPPTables(RawTotalRate* DPPRate, const int num_main_bins, - string aDirTables) -{ - ReadRawTotalRate(DPPRate, (aDirTables+"/DPP.dat").c_str()); - ModifyRawTotalRate(DPPRate, num_main_bins); -} - -void LoadPPPNucleonTables(RawTotalRate* PPPProtonLossRate, - RawTotalRate* PPPNeutronLossRate, - RawDiffRate* PPPProtonScatRate, - RawDiffRate* PPPProtonNeutronRate, - RawDiffRate* PPPNeutronProtonRate, - const int num_main_bins, - string aDirTables) -{ - FILE* PPPLoss; - - PPPLoss = SafeFOpen((aDirTables+"/PPPLoss.dat").c_str(), "r"); - binfread(PPPProtonLossRate->totalRate[0], sizeof(double), - (PPPProtonLossRate->mainDimension)*(PPPProtonLossRate->bgDimension), - PPPLoss); - binfread(PPPNeutronLossRate->totalRate[0], sizeof(double), - (PPPNeutronLossRate->mainDimension)*(PPPNeutronLossRate->bgDimension), - PPPLoss); - fclose(PPPLoss); - ModifyRawTotalRate(PPPProtonLossRate, num_main_bins); - ModifyRawTotalRate(PPPNeutronLossRate, num_main_bins); - /* this is treated a little differently because the file contains both - tables */ - - - ReadRawDiffRate(PPPProtonScatRate, (aDirTables+"/PPPPrS.dat").c_str()); - ModifyRawDiffRate(PPPProtonScatRate, num_main_bins); - - ReadRawDiffRate(PPPProtonNeutronRate, (aDirTables+"/PPPPrN.dat").c_str()); - ModifyRawDiffRate(PPPProtonNeutronRate, num_main_bins); - - ReadRawDiffRate(PPPNeutronProtonRate, (aDirTables+"/PPPNPr.dat").c_str()); - ModifyRawDiffRate(PPPNeutronProtonRate, num_main_bins); -} - - -void LoadPPPEMTables(RawDiffRate* PPPProtonPhotonRate, - RawDiffRate* PPPProtonElectronRate, - RawDiffRate* PPPProtonPositronRate, - RawDiffRate* PPPNeutronElectronRate, - const int num_main_bins, - string aDirTables) -{ - FILE* PPPNE; - - ReadRawDiffRate(PPPProtonPhotonRate, (aDirTables+"/PPPPrPh.dat").c_str()); - ModifyRawDiffRate(PPPProtonPhotonRate, num_main_bins); - - ReadRawDiffRate(PPPProtonElectronRate, (aDirTables+"/PPPPrE.dat").c_str()); - ModifyRawDiffRate(PPPProtonElectronRate, num_main_bins); - - ReadRawDiffRate(PPPProtonPositronRate, (aDirTables+"/PPPPrPos.dat").c_str()); - - PPPNE = SafeFOpen((aDirTables+"/PPPNE.dat").c_str(), "r"); - if (PPPNeutronElectronRate->numberOfElements != - PPPProtonPositronRate->numberOfElements) - { - Error("LoadPPPTables: inconsistent dimensions", PROGRAM_ERROR); - } - binfread(PPPNeutronElectronRate->diffRate, sizeof(double), - PPPProtonPositronRate->numberOfElements, PPPNE); - fclose(PPPNE); - CopyRawDiffRate(PPPNeutronElectronRate, PPPProtonPositronRate); - ModifyRawDiffRate(PPPProtonPositronRate, num_main_bins); - ModifyRawDiffRate(PPPNeutronElectronRate, num_main_bins); -} - - -void LoadNPPNucleonTables(RawTotalRate* NPPTotalRate, const int num_main_bins, - string aDirTables) -{ - ReadRawTotalRate(NPPTotalRate, (aDirTables+"/NPPLoss.dat").c_str()); - ModifyRawTotalRate(NPPTotalRate, num_main_bins); -} - -void LoadNPPSecondaryTables(RawDiffRate* NPPDiffRate, const int num_main_bins, - string aDirTables) -{ - ReadRawDiffRate(NPPDiffRate, (aDirTables+"/NPPDiff.dat").c_str()); - ModifyRawDiffRate(NPPDiffRate, num_main_bins); -} - -void LoadPPPNeutrinoTables(RawDiffRate* PPPProtonElectronNeutrinoRate, - RawDiffRate* PPPProtonAntiElectronNeutrinoRate, - RawDiffRate* PPPProtonMuonNeutrinoRate, - RawDiffRate* PPPProtonAntiMuonNeutrinoRate, - RawDiffRate* PPPNeutronAntiElectronNeutrinoRate, - RawDiffRate* PPPNeutronMuonNeutrinoRate, - RawDiffRate* PPPNeutronAntiMuonNeutrinoRate, - const int num_main_bins, string aDirTables) -{ - FILE* PPPPrEN; - FILE* PPPNAEN; - FILE* PPPNMN; - FILE* PPPNAMN; - - - /* these 4 rates share the same bound */ - ReadRawDiffRate(PPPProtonAntiMuonNeutrinoRate, (aDirTables+"/PPPPrAMN.dat").c_str()); - - if (PPPProtonElectronNeutrinoRate->numberOfElements != - PPPProtonAntiMuonNeutrinoRate->numberOfElements) - { - Error("LoadPPPTables: inconsistent dimensions", PROGRAM_ERROR); - } - PPPPrEN = SafeFOpen((aDirTables+"/PPPPrEN.dat").c_str(), "r"); - binfread(PPPProtonElectronNeutrinoRate->diffRate, sizeof(double), - PPPProtonAntiMuonNeutrinoRate->numberOfElements, PPPPrEN); - fclose(PPPPrEN); - CopyRawDiffRateBound(PPPProtonElectronNeutrinoRate, - PPPProtonAntiMuonNeutrinoRate); - - if (PPPNeutronAntiElectronNeutrinoRate->numberOfElements != - PPPProtonAntiMuonNeutrinoRate->numberOfElements) - { - Error("LoadPPPTables: inconsistent dimensions", PROGRAM_ERROR); - } - PPPNAEN = SafeFOpen((aDirTables+"/PPPNAEN.dat").c_str(), "r"); - binfread(PPPNeutronAntiElectronNeutrinoRate->diffRate, sizeof(double), - PPPProtonAntiMuonNeutrinoRate->numberOfElements, PPPNAEN); - fclose(PPPNAEN); - CopyRawDiffRateBound(PPPNeutronAntiElectronNeutrinoRate, - PPPProtonAntiMuonNeutrinoRate); - - if (PPPNeutronMuonNeutrinoRate->numberOfElements != - PPPProtonAntiMuonNeutrinoRate->numberOfElements) - { - Error("LoadPPPTables: inconsistent dimensions", PROGRAM_ERROR); - } - PPPNMN = SafeFOpen((aDirTables+"/PPPNMN.dat").c_str(), "r"); - binfread(PPPNeutronMuonNeutrinoRate->diffRate, sizeof(double), - PPPProtonAntiMuonNeutrinoRate->numberOfElements, PPPNMN); - fclose(PPPNMN); - CopyRawDiffRateBound(PPPNeutronMuonNeutrinoRate, - PPPProtonAntiMuonNeutrinoRate); - - ModifyRawDiffRate(PPPProtonAntiMuonNeutrinoRate, num_main_bins); - ModifyRawDiffRate(PPPProtonElectronNeutrinoRate, num_main_bins); - ModifyRawDiffRate(PPPNeutronAntiElectronNeutrinoRate, num_main_bins); - ModifyRawDiffRate(PPPNeutronMuonNeutrinoRate, num_main_bins); - - - - ReadRawDiffRate(PPPProtonAntiElectronNeutrinoRate, - (aDirTables+"/PPPPrAEN.dat").c_str()); - ModifyRawDiffRate(PPPProtonAntiElectronNeutrinoRate, num_main_bins); - - /* these 2 share bound */ - ReadRawDiffRate(PPPProtonMuonNeutrinoRate, (aDirTables+"/PPPPrMN.dat").c_str()); - - if (PPPNeutronAntiMuonNeutrinoRate->numberOfElements != - PPPProtonMuonNeutrinoRate->numberOfElements) - { - Error("LoadPPPTables: inconsistent dimensions", PROGRAM_ERROR); - } - PPPNAMN = SafeFOpen((aDirTables+"/PPPNAMN.dat").c_str(), "r"); - binfread(PPPNeutronAntiMuonNeutrinoRate->diffRate, sizeof(double), - PPPProtonMuonNeutrinoRate->numberOfElements, PPPNAMN); - fclose(PPPNAMN); - CopyRawDiffRateBound(PPPNeutronAntiMuonNeutrinoRate, - PPPProtonMuonNeutrinoRate); - - ModifyRawDiffRate(PPPProtonMuonNeutrinoRate, num_main_bins); - ModifyRawDiffRate(PPPNeutronAntiMuonNeutrinoRate, num_main_bins); -} - -void LoadNeutronDecayNucleonTables(TotalRate* neutronDecayRate, - DiffRate* neutronDecayProtonRate, - const int num_main_bins, - string aDirTables) -{ - ReadTotalRate(neutronDecayRate, (aDirTables+"/neutronDecayLoss.dat").c_str()); - ModifyTotalRate(neutronDecayRate, num_main_bins); - - ReadDiffRate(neutronDecayProtonRate, (aDirTables+"/neutronDecayProton.dat").c_str()); - ModifyDiffRate(neutronDecayProtonRate, num_main_bins); -} - -void LoadNeutronDecaySecondaryTables(DiffRate* neutronDecayElectronRate, - const int num_main_bins, - string aDirTables) -{ - ReadDiffRate(neutronDecayElectronRate, (aDirTables+"/neutronDecayElectron.dat").c_str()); - ModifyDiffRate(neutronDecayElectronRate, num_main_bins); -} - -void LoadNeutrinoTables(const int tauNeutrinoMassSwitch, - TotalRate* NNElNeutTotalRate, - TotalRate* NNMuonNeutTotalRate, - TotalRate* NNTauNeutTotalRate, - DiffRate* NNElNeutScatRate, - DiffRate* NNElNeutMuonNeutRate, - DiffRate* NNElNeutTauNeutRate, - DiffRate* NNElNeutElectronRate, - DiffRate* NNElNeutPhotonRate, - DiffRate* NNElNeutProtonRate, - DiffRate* NNMuonNeutScatRate, - DiffRate* NNMuonNeutElNeutRate, - DiffRate* NNMuonNeutTauNeutRate, - DiffRate* NNMuonNeutElectronRate, - DiffRate* NNMuonNeutPhotonRate, - DiffRate* NNMuonNeutProtonRate, - DiffRate* NNTauNeutScatRate, - DiffRate* NNTauNeutElNeutRate, - DiffRate* NNTauNeutMuonNeutRate, - DiffRate* NNTauNeutElectronRate, - DiffRate* NNTauNeutPhotonRate, - DiffRate* NNTauNeutProtonRate, - const int num_main_bins, - string aDirTables) -{ - if (tauNeutrinoMassSwitch == 0) - { - ReadTotalRate(NNElNeutTotalRate, (aDirTables+"/ENT_0.dat").c_str()); - ReadTotalRate(NNMuonNeutTotalRate, (aDirTables+"/MNT_0.dat").c_str()); - ReadTotalRate(NNTauNeutTotalRate, (aDirTables+"/TNT_0.dat").c_str()); - - ReadDiffRate(NNElNeutScatRate, (aDirTables+"/ENS_0.dat").c_str()); - ReadDiffRate(NNElNeutMuonNeutRate, (aDirTables+"/ENMN_0.dat").c_str()); - ReadDiffRate(NNElNeutTauNeutRate, (aDirTables+"/ENTN_0.dat").c_str()); - ReadDiffRate(NNElNeutElectronRate, (aDirTables+"/ENE_0.dat").c_str()); - ReadDiffRate(NNElNeutPhotonRate, (aDirTables+"/ENPh_0.dat").c_str()); - ReadDiffRate(NNElNeutProtonRate, (aDirTables+"/ENPr_0.dat").c_str()); - ReadDiffRate(NNMuonNeutElNeutRate, (aDirTables+"/MNEN_0.dat").c_str()); - ReadDiffRate(NNMuonNeutScatRate, (aDirTables+"/MNS_0.dat").c_str()); - ReadDiffRate(NNMuonNeutTauNeutRate, (aDirTables+"/MNTN_0.dat").c_str()); - ReadDiffRate(NNMuonNeutElectronRate, (aDirTables+"/MNE_0.dat").c_str()); - ReadDiffRate(NNMuonNeutPhotonRate, (aDirTables+"/MNPh_0.dat").c_str()); - ReadDiffRate(NNMuonNeutProtonRate, (aDirTables+"/MNPr_0.dat").c_str()); - ReadDiffRate(NNTauNeutElNeutRate, (aDirTables+"/TNEN_0.dat").c_str()); - ReadDiffRate(NNTauNeutMuonNeutRate, (aDirTables+"/TNMN_0.dat").c_str()); - ReadDiffRate(NNTauNeutScatRate, (aDirTables+"/TNS_0.dat").c_str()); - ReadDiffRate(NNTauNeutElectronRate, (aDirTables+"/TNE_0.dat").c_str()); - ReadDiffRate(NNTauNeutPhotonRate, (aDirTables+"/TNPh_0.dat").c_str()); - ReadDiffRate(NNTauNeutProtonRate, (aDirTables+"/TNPr_0.dat").c_str()); - } - else - { - ReadTotalRate(NNElNeutTotalRate, (aDirTables+"/ENT_10.dat").c_str()); - ReadTotalRate(NNMuonNeutTotalRate, (aDirTables+"/MNT_10.dat").c_str()); - ReadTotalRate(NNTauNeutTotalRate, (aDirTables+"/TNT_10.dat").c_str()); - ReadDiffRate(NNElNeutScatRate, (aDirTables+"/ENS_10.dat").c_str()); - ReadDiffRate(NNElNeutMuonNeutRate, (aDirTables+"/ENMN_10.dat").c_str()); - ReadDiffRate(NNElNeutTauNeutRate, (aDirTables+"/ENTN_10.dat").c_str()); - ReadDiffRate(NNElNeutElectronRate, (aDirTables+"/ENE_10.dat").c_str()); - ReadDiffRate(NNElNeutPhotonRate, (aDirTables+"/ENPh_10.dat").c_str()); - ReadDiffRate(NNElNeutProtonRate, (aDirTables+"/ENPr_10.dat").c_str()); - ReadDiffRate(NNMuonNeutElNeutRate, (aDirTables+"/MNEN_10.dat").c_str()); - ReadDiffRate(NNMuonNeutScatRate, (aDirTables+"/MNS_10.dat").c_str()); - ReadDiffRate(NNMuonNeutTauNeutRate, (aDirTables+"/MNTN_10.dat").c_str()); - ReadDiffRate(NNMuonNeutElectronRate, (aDirTables+"/MNE_10.dat").c_str()); - ReadDiffRate(NNMuonNeutPhotonRate, (aDirTables+"/MNPh_10.dat").c_str()); - ReadDiffRate(NNMuonNeutProtonRate, (aDirTables+"/MNPr_10.dat").c_str()); - ReadDiffRate(NNTauNeutElNeutRate, (aDirTables+"/TNEN_10.dat").c_str()); - ReadDiffRate(NNTauNeutMuonNeutRate, (aDirTables+"/TNMN_10.dat").c_str()); - ReadDiffRate(NNTauNeutScatRate, (aDirTables+"/TNS_10.dat").c_str()); - ReadDiffRate(NNTauNeutElectronRate, (aDirTables+"/TNE_10.dat").c_str()); - ReadDiffRate(NNTauNeutPhotonRate, (aDirTables+"/TNPh_10.dat").c_str()); - ReadDiffRate(NNTauNeutProtonRate, (aDirTables+"/TNPr_10.dat").c_str()); - } - - ModifyTotalRate(NNElNeutTotalRate, num_main_bins); - ModifyTotalRate(NNMuonNeutTotalRate, num_main_bins); - ModifyTotalRate(NNTauNeutTotalRate, num_main_bins); - ModifyDiffRate(NNElNeutScatRate, num_main_bins); - ModifyDiffRate(NNElNeutMuonNeutRate, num_main_bins); - ModifyDiffRate(NNElNeutTauNeutRate, num_main_bins); - ModifyDiffRate(NNElNeutElectronRate, num_main_bins); - ModifyDiffRate(NNElNeutPhotonRate, num_main_bins); - ModifyDiffRate(NNElNeutProtonRate, num_main_bins); - ModifyDiffRate(NNMuonNeutElNeutRate, num_main_bins); - ModifyDiffRate(NNMuonNeutScatRate, num_main_bins); - ModifyDiffRate(NNMuonNeutTauNeutRate, num_main_bins); - ModifyDiffRate(NNMuonNeutElectronRate, num_main_bins); - ModifyDiffRate(NNMuonNeutPhotonRate, num_main_bins); - ModifyDiffRate(NNMuonNeutProtonRate, num_main_bins); - ModifyDiffRate(NNTauNeutElNeutRate, num_main_bins); - ModifyDiffRate(NNTauNeutMuonNeutRate, num_main_bins); - ModifyDiffRate(NNTauNeutScatRate, num_main_bins); - ModifyDiffRate(NNTauNeutElectronRate, num_main_bins); - ModifyDiffRate(NNTauNeutPhotonRate, num_main_bins); - ModifyDiffRate(NNTauNeutProtonRate, num_main_bins); -} diff --git a/libs/dint/src/math_util.cpp b/libs/dint/src/math_util.cpp deleted file mode 100644 index 545cf262e..000000000 --- a/libs/dint/src/math_util.cpp +++ /dev/null @@ -1,34 +0,0 @@ -double DMax(const double double1, const double double2) -{ - if (double1 >= double2) - return double1; - else - return double2; -} - - -double DMin(const double double1, const double double2) -{ - if (double1 <= double2) - return double1; - else - return double2; -} - - -int IMax(const int integer1, const int integer2) -{ - if (integer1 >= integer2) - return integer1; - else - return integer2; -} - - -int IMin(const int integer1, const int integer2) -{ - if (integer1 <= integer2) - return integer1; - else - return integer2; -} diff --git a/libs/dint/src/prepare.cpp b/libs/dint/src/prepare.cpp deleted file mode 100644 index 50936eef9..000000000 --- a/libs/dint/src/prepare.cpp +++ /dev/null @@ -1,409 +0,0 @@ - -#include -#include -#include -#include -#include "dint/const.h" -#include "dint/cvector.h" -#include "dint/utilities.h" -#include "dint/spectrum.h" -#include "dint/frag.h" -#include "dint/decay.h" - - -void SetEnergyBins(const int min_energy_exp, dCVector* pEnergy, - dCVector* pEnergyWidth) -{ - int i; - double exponent; - double temp; - int num_bins; - double averaging_factor; - double binning_factor; - - num_bins = pEnergy->dimension; - averaging_factor = (pow(10., 1./2./BINS_PER_DECADE) + - pow(10., -1./2./BINS_PER_DECADE))/2.; - binning_factor = pow(10., 1./2./BINS_PER_DECADE) - - pow(10., -1./2./BINS_PER_DECADE); - - if (num_bins != pEnergyWidth->dimension) - { - Error("SetEnergyBins: inconsistent dimensions", PROGRAM_ERROR); - } - - for (i = 0; i < num_bins; i++) - { - exponent = (double)min_energy_exp + (double)i/BINS_PER_DECADE; - temp = pow(10., exponent)/ELECTRON_MASS; - (pEnergy->vector)[i] = temp*averaging_factor; - (pEnergyWidth->vector)[i] = temp*binning_factor; - } -} - -void SetDeltaG(const dCVector* pEnergy, dCVector* pDeltaG) -{ - int i; - int num_main_bins; - - num_main_bins = pEnergy->dimension; - - if (pDeltaG->dimension != num_main_bins) - { - Error("SetDeltaG: inconsistent dimensions", PROGRAM_ERROR); - } - - for (i = 0; i < num_main_bins - 1; i++) - { - (pDeltaG->vector)[i] = (pEnergy->vector)[i+1] - (pEnergy->vector)[i]; - } - (pDeltaG->vector)[num_main_bins-1] = (pEnergy->vector)[num_main_bins-1]* - pow(10., 1./BINS_PER_DECADE); -} - -/* NOTE: this function is not used any more... */ -void GetModeOfInput(FILE* input, int* pInputMethodSwitch) -{ - /* give a choice between manually entering the data and reading it - from a data file */ - printf(" -----------------< Enter Model Parameters >"); - printf("-----------------\n\n"); - printf("1. Read from a file (1)/Manually enter parameters (0): "); - scanf("%i", pInputMethodSwitch); - - if (*pInputMethodSwitch == 1) - /* From data file */ - { - char fileName[20]; - - /* get the name of the file */ - printf("2. Name of parameter file: "); - scanf("%s", fileName); - input = SafeFOpen(fileName, "r"); - } -} - -void BasicParameterInput(FILE* input, const int argc, int* pMinEnergyExp, - int* pNumSmallSteps, - double* pConvergeParameter, - double* pStartingRedshift, - double* pStartingDistanceInMpc) -{ - if (argc == 3) - /* From data file */ - { - printf("\n[Parameters read from the file]\n"); - /* read in parameters */ - fscanf(input, "%i", pMinEnergyExp); - printf("1. Minimum energy: 10^%i eV\n", *pMinEnergyExp); - fscanf(input, "%i", pNumSmallSteps); - printf("2. Number of small steps: %i\n", *pNumSmallSteps); - fscanf(input, "%lf", pConvergeParameter); - printf("3. Delta (convergence parameter): %12.3E\n", - *pConvergeParameter); - fscanf(input, "%lf", pStartingRedshift); - if (*pStartingRedshift != 0.) - { - printf("4. Maximal redshift: %10.3f\n", *pStartingRedshift); - } - fscanf(input, "%lf", pStartingDistanceInMpc); - if (*pStartingDistanceInMpc >= 2.*C/3./H_0*1.e-5) - { - Error("BasicParameterInput: distance larger than horizon", - PROGRAM_ERROR); - } - if (*pStartingDistanceInMpc != 0.) - { - printf("4. Maximal distance (Mpc): %10.3f\n", - *pStartingDistanceInMpc); - } - } - else if (argc == 2) - /* Enter manually */ - { - printf("1. Minimum energy exponent (e.g. 10^8 eV: 8): "); - scanf("%i", pMinEnergyExp); - printf("2. Number of small steps (suggestion: 6): "); - scanf("%i", pNumSmallSteps); - printf("3. Delta (convergence parameter) (suggestion: 1.e-6): "); - scanf("%lf", pConvergeParameter); - printf("4. Maximal redshift "); - printf("(enter 0 if you will type in distance): "); - scanf("%lf", pStartingRedshift); - printf("5. Maximal distance in Mpc "); - printf("(enter 0 if you typed in redshift): "); - scanf("%lf", pStartingDistanceInMpc); - if (*pStartingDistanceInMpc >= 2.*C/3./H_0*1.e-5) - { - Error("BasicParameterInput: distance larger than horizon", - PROGRAM_ERROR); - } - } - - if (*pStartingDistanceInMpc == 0.) - { - *pStartingDistanceInMpc = 2.*C/3./H_0/1.e5*(1. - - pow(1. + *pStartingRedshift, -3./2.)); - printf("\n"); - printf("Maximal distance (Mpc): %12.6f\n", *pStartingDistanceInMpc); - } - if (*pStartingRedshift == 0.) - { - *pStartingRedshift = - pow(1. - 3.*H_0*1.e5*(*pStartingDistanceInMpc)/2./C, -2./3.) - 1.; - printf("\n"); - printf("Maximal redshift: %12.6f\n", *pStartingRedshift); - } -} - -void InteractionParameterInput(FILE* input, const int argc, - int* pSynchrotronSwitch, double* pB_0, - int* pTauNeutrinoMassSwitch, int* pICSSwitch, - int* pPPSwitch, int* pTPPSwitch, - int* pDPPSwitch, int* pPPPSwitch, - int* pNPPSwitch, int* pNeutronDecaySwitch, - int* pNucleonToSecondarySwitch, - int* pNeutrinoNeutrinoSwitch) -{ - if (argc == 3) - /* From data file */ - { - fscanf(input, "%i", pSynchrotronSwitch); - fscanf(input, "%lf", pB_0); - if (*pSynchrotronSwitch == 1) - { - printf("5. Synchrotron loss on -> B_0: %12.3E\n", *pB_0); - } - else - { - *pB_0 = 0; - printf("5. Synchrotron loss off\n"); - } - fscanf(input, "%i", pTauNeutrinoMassSwitch); - if (*pTauNeutrinoMassSwitch == 0) - printf("6. m_tau = m_e = m_nu = 1 eV\n"); - else - printf("6. m_tau = m_nu = 1 eV, m_e = 0.1 eV\n"); - - /* read in interaction switches */ - printf("\n7. "); - fscanf(input, "%i", pICSSwitch); - if (*pICSSwitch != 0) - printf("ICS on... "); - fscanf(input, "%i", pPPSwitch); - if (*pPPSwitch != 0) - printf("PP on... "); - fscanf(input, "%i", pTPPSwitch); - if (*pTPPSwitch != 0) - printf("TPP on... "); - fscanf(input, "%i", pDPPSwitch); - if (*pDPPSwitch != 0) - printf("DPP on... "); - fscanf(input, "%i", pPPPSwitch); - if (*pPPPSwitch != 0) - printf("Photopion production on... "); - fscanf(input, "%i", pNPPSwitch); - if (*pNPPSwitch != 0) - printf("Proton pair production on... "); - fscanf(input, "%i", pNeutronDecaySwitch); - if (*pNeutronDecaySwitch != 0) - printf("Neutron decay on... "); - fscanf(input, "%i", pNucleonToSecondarySwitch); - if (*pNucleonToSecondarySwitch != 0) - printf("Nucleon secondary tables included... "); - fscanf(input, "%i", pNeutrinoNeutrinoSwitch); - if (*pNeutrinoNeutrinoSwitch != 0) - printf("Neutrino-neutrino interaction on... "); - printf("\n"); - } - else if (argc == 2) - /* Enter manually */ - { - printf("6. Synchrotron on/off? (on = 1, off = 0) "); - scanf("%i", pSynchrotronSwitch); - if (*pSynchrotronSwitch == 1) - { - printf(" 6-1. Magnetic field (G): "); - scanf("%lf", pB_0); - } - else - { - *pB_0 = 0; - } - - printf("7. Neutrino mass (0: equally massive (1 eV), 1: tau = nu = 1, e = 0.1 eV): "); - scanf("%i", pTauNeutrinoMassSwitch); - - // printf("\n\nNow turning to individual interactions...\n"); - printf("\n"); - printf("8-1. Inverse Compton scattering (ICS) on? (on = 1, off = 0) "); - scanf("%i", pICSSwitch); - printf("8-2. Pair production (PP) on? "); - scanf("%i", pPPSwitch); - printf("8-3. Triplet pair production (TPP) on? "); - scanf("%i", pTPPSwitch); - printf("8-4. Double pair production (DPP) on? "); - scanf("%i", pDPPSwitch); - printf("8-5. Photopion production on? "); - scanf("%i", pPPPSwitch); - printf("8-6. Proton pair production on? "); - scanf("%i", pNPPSwitch); - printf("8-7. Neutron decay on? "); - scanf("%i", pNeutronDecaySwitch); - printf("8-8. Nucleon secondary tables included? "); - scanf("%i", pNucleonToSecondarySwitch); - printf("8-9. Neutrino-neutrino interaction on? "); - scanf("%i", pNeutrinoNeutrinoSwitch); - } - - /* quick check whether secondary table switch is consistent */ - if (*pNucleonToSecondarySwitch == 1) - { - if ((*pPPPSwitch == 0) && (*pNPPSwitch == 0) && - (*pNeutronDecaySwitch == 0)) - { - printf("WARNING: secondary table on when all interactions off?\n"); - } - } -} - -void ModelParameterInput(FILE* input, const int argc, - int* pSourceTypeSwitch, double* pMinDistance, - double* pBrightPhaseExp, int* pModelTypeSwitch) -{ - if (argc == 3) - /* From data file */ - { - fscanf(input, "%i", pSourceTypeSwitch); - fscanf(input, "%lf", pMinDistance); - fscanf(input, "%lf", pBrightPhaseExp); - if (*pSourceTypeSwitch == 1) - { - printf("8. Source type: diffuse\n"); - printf("8-1. Minimal distance: %12.6f\n", *pMinDistance); - printf("8-2. Bright phase exponent: %12.6f\n", *pBrightPhaseExp); - } - else - printf("8. Source type: single\n"); - - fscanf(input, "%i", pModelTypeSwitch); - if (*pModelTypeSwitch == 0) - printf("9. Injection model: photon monoenergetic injection\n"); - else if (*pModelTypeSwitch == 1) - printf("9. Injection model: electron monoenergetic injection\n"); - else if (*pModelTypeSwitch == 2) - printf("9. Injection model: positron monoenergetic injection\n"); - } - else if (argc == 2) - /* Enter manually */ - { - printf("9. Single source or diffuse sources? "); - printf("(single = 0, diffuse = 1) "); - scanf("%i", pSourceTypeSwitch); - *pMinDistance = 0.; - *pBrightPhaseExp = 1.5; - if (*pSourceTypeSwitch == 1) - { - printf("9-1. Minimal distance: "); - scanf("%lf", pMinDistance); - printf("9-2. Bright phase exponent: "); - scanf("%lf", pBrightPhaseExp); - } - printf("10. Injection model\n"); - printf("(photon = 0, electron = 1,\n"); - printf(" positron = 2; monoenergetic injection ? "); - scanf("%i", pModelTypeSwitch); - } - - printf("\n\nParameter input complete.\n"); -} - -void PrepareSpectra(const int sourceTypeSwitch, const Spectrum* pQ_0, - Spectrum* pSpectrum, Spectrum* pSpectrumNew, - Spectrum* pDerivative) -{ - if (pSpectrumNew->numberOfMainBins != pDerivative->numberOfMainBins) - { - Error("PrepareSpectra: inconsistent dimensions", PROGRAM_ERROR); - } - - // InitializeSpectrum(spectrumOld); - if (sourceTypeSwitch == 0) /* single source */ - SetSpectrum(pSpectrum, pQ_0); - else /* diffuse sources */ - InitializeSpectrum(pSpectrum); - - SetSpectrum(pSpectrumNew, pSpectrum); - InitializeSpectrum(pDerivative); -} - - -void ComputeTotalInitialContent(const dCVector* pEnergy, const Spectrum* pQ_0, - double* initialPhotonEnergy, - double* initialLeptonEnergy, - double* initialNucleonEnergy, - double* initialNeutrinoEnergy, - double* initialTotalEnergy, - double* initialPhotonNumber, - double* initialLeptonNumber, - double* initialNucleonNumber, - double* initialNeutrinoNumber, - double* initialTotalNumber) -{ - int i; - - *initialPhotonEnergy = 0; - *initialLeptonEnergy = 0.; - *initialNucleonEnergy = 0.; - *initialNeutrinoEnergy = 0.; - *initialTotalEnergy = 0.; - *initialPhotonNumber = 0; - *initialLeptonNumber = 0.; - *initialNucleonNumber = 0.; - *initialNeutrinoNumber = 0.; - *initialTotalNumber = 0.; - - for (i = 0; i < pEnergy->dimension; i++) - { - *initialPhotonEnergy += (pQ_0->spectrum)[PHOTON][i]* - (pEnergy->vector)[i]; - *initialPhotonNumber += (pQ_0->spectrum)[PHOTON][i]; - *initialLeptonEnergy += ((pQ_0->spectrum)[ELECTRON][i] + - (pQ_0->spectrum)[POSITRON][i])*(pEnergy->vector)[i]; - *initialLeptonNumber += (pQ_0->spectrum)[ELECTRON][i] + - (pQ_0->spectrum)[POSITRON][i]; - } - *initialNucleonEnergy += GetNucleonEnergy(pQ_0, pEnergy); - *initialNucleonNumber += GetNucleonNumber(pQ_0); - *initialNeutrinoEnergy += GetNeutrinoEnergy(pQ_0, pEnergy); - *initialNeutrinoNumber += GetNeutrinoNumber(pQ_0); - *initialTotalEnergy = *initialPhotonEnergy + *initialLeptonEnergy + - *initialNucleonEnergy + *initialNeutrinoEnergy; - *initialTotalNumber = *initialPhotonNumber + *initialLeptonNumber + - *initialNucleonNumber + *initialNeutrinoNumber; -} - - -void ComputeContinuousEnergyLoss(const int synchrotronSwitch, - const dCVector* synchrotronLoss, - const dCVector* otherLoss, - dCVector* continuousLoss) -{ - int i; - - if ((synchrotronLoss->dimension != otherLoss->dimension) || - (otherLoss->dimension != continuousLoss->dimension)) - { - Error("ComputeContinuousEnergyLoss: inconsistent dimensions", - PROGRAM_ERROR); - } - - for (i = 0; i < continuousLoss->dimension; i++) - { - (continuousLoss->vector)[i] = (otherLoss->vector)[i]; - if (synchrotronSwitch == 1) /* synchrotron on */ - { - (continuousLoss->vector)[i] += (synchrotronLoss->vector)[i]; - } - } -} diff --git a/libs/dint/src/prop_second.cpp b/libs/dint/src/prop_second.cpp deleted file mode 100644 index 5f71f6909..000000000 --- a/libs/dint/src/prop_second.cpp +++ /dev/null @@ -1,1081 +0,0 @@ - -#include "dint/prop_second.h" - -#ifdef DEBUG -void DumpEnergy(const Spectrum* pSpectrum, const dCVector* pEnergy) { - printf("Initial energy: %15.6E\n", GetEnergy(pSpectrum, pEnergy)); - printf("Nucleon fraction: %15.6E\n", - GetNucleonEnergy(pSpectrum, pEnergy)/GetEnergy(pSpectrum, pEnergy)); - printf("electromagnetic fraction: %15.6E\n", - GetEMEnergy(pSpectrum, pEnergy)/GetEnergy(pSpectrum, pEnergy)); -} -#endif - -//-------------------------------------------------------------------------- -// Prop_second : see the file prop_second.h for explanations -//-------------------------------------------------------------------------- - -// Switches to read 1) the folded interaction rates : total pair production and -// total energy losses by photons; 2) the photon background density -//#define EXTRACT_PAIR_PROD_RATE -//#define EXTRACT_PHOTON_TOTAL_RATE -//#define PRINT_PHOTON_BACKGROUND -//#define EXTRACT_LEPTON_RATE - -// Parameters of the redshift table (used for distance-redshift conversion) -#define NBINS_REDSHIFTTABLE 1000 -#define ZMIN_REDSHIFTTABLE 0.0001 -#define ZMAX_REDSHIFTTABLE 100 - -void prop_second(const double dist_observer, - //const double InjEnergy, - //const PARTICLE part, - //const double HInjEnergy, const double deltaE_hadron, - const dCVector* pB_field, - const dCVector* pEnergy, - const dCVector* pEnergyWidth, - Spectrum* apInjectionSpectrum, - Spectrum* pSpectrum, - string aDirTables, - const int aIRFlag, const double aZmax_IR, const int aRadioFlag, - const double aH0 = H_0, const double aOmegaM = OMEGA_M, - const double aOmegaLambda = OMEGA_LAMBDA, - const double aCutcascade_Magfield = 0) { -clock_t start = clock(); - //-------- Declaration of main variables -------- - //---- Interaction table coefficients ---- - RawTotalRate ICSTotalRate; - RawTotalRate PPTotalRate; - RawTotalRate TPPTotalRate; - RawTotalRate DPPRate; - - RawTotalRate PPPProtonLossRate; - RawTotalRate PPPNeutronLossRate; - RawTotalRate NPPTotalRate; - // total (interaction) rates before being folded into the background - - RawDiffRate ICSPhotonRate; - RawDiffRate ICSScatRate; - RawDiffRate PPDiffRate; - RawDiffRate TPPDiffRate; - - RawDiffRate PPPProtonScatRate; - RawDiffRate PPPProtonNeutronRate; - RawDiffRate PPPNeutronProtonRate; - RawDiffRate PPPProtonPhotonRate; - RawDiffRate PPPProtonElectronRate; - RawDiffRate PPPProtonPositronRate; - RawDiffRate PPPNeutronElectronRate; - RawDiffRate NPPDiffRate; - RawDiffRate PPPProtonElectronNeutrinoRate; - RawDiffRate PPPProtonAntiElectronNeutrinoRate; - RawDiffRate PPPProtonMuonNeutrinoRate; - RawDiffRate PPPProtonAntiMuonNeutrinoRate; - RawDiffRate PPPNeutronAntiElectronNeutrinoRate; - RawDiffRate PPPNeutronMuonNeutrinoRate; - RawDiffRate PPPNeutronAntiMuonNeutrinoRate; - // differential rates before being folded into the background - - TotalRate neutronDecayRate; - DiffRate neutronDecayElectronRate; - DiffRate neutronDecayProtonRate; - - TotalRate NNElNeutTotalRate; - TotalRate NNMuonNeutTotalRate; - TotalRate NNTauNeutTotalRate; - // These total rates are net rates; i.e. scattered flux into same bin is subtracted - DiffRate NNElNeutScatRate; - DiffRate NNElNeutMuonNeutRate; - DiffRate NNElNeutTauNeutRate; - DiffRate NNElNeutElectronRate; - DiffRate NNElNeutPhotonRate; - DiffRate NNElNeutProtonRate; - DiffRate NNMuonNeutScatRate; - DiffRate NNMuonNeutElNeutRate; - DiffRate NNMuonNeutTauNeutRate; - DiffRate NNMuonNeutElectronRate; - DiffRate NNMuonNeutPhotonRate; - DiffRate NNMuonNeutProtonRate; - DiffRate NNTauNeutScatRate; - DiffRate NNTauNeutElNeutRate; - DiffRate NNTauNeutMuonNeutRate; - DiffRate NNTauNeutElectronRate; - DiffRate NNTauNeutPhotonRate; - DiffRate NNTauNeutProtonRate; - // rates from neutrino-neutrino interaction - - - //---- Main parameter variables ---- - int B_bin, B_bins; // bin numbers for B-field array - - dCVector deltaG; // dg used in continuous energy loss calculation - - dCVector bgEnergy; - dCVector bgEnergyWidth; - dCVector bgPhotonDensity; - - double distance; // main distance variable (cm) - - int numSmallSteps; // number of small steps in one redshift step - double convergeParameter; // redshift increment - - int synchrotronSwitch; - double B_loc; // local strength of extragalactic magnetic field (gauss) - DiffRate syncRate; - - int sourceTypeSwitch; // source type: single (0) or diffuse (1) - double brightPhaseExp; // bright phase exponent - double startingRedshift; // zsource in FORTRAN - double minDistance; // minimal distance to sources - double bkgFactor; // local background enhancement factor - double totalEnergyInput; // einj0 in FORTRAN - - Spectrum Q_0; // standard injection function - Spectrum spectrumNew; - Spectrum derivative; - - double initialPhotonEnergy; // totpe in FORTRAN - double initialLeptonEnergy; // totee - double initialNucleonEnergy; - double initialNeutrinoEnergy; - double initialTotalEnergy; // tote - double initialPhotonNumber; // totpn - double initialLeptonNumber; // toten - double initialNucleonNumber; - double initialNeutrinoNumber; - double initialTotalNumber; // totn - - int iterationCounter; // niter in FORTRAN - int firstIndex; // ifirst - double leftRedshift; // zi - double deltaRedshift; //zdelt - int lastIndex; // ilast - double propagatingDistance; - // totalx: total propagating distance (pc) - double rightRedshift; // zf - double centralRedshift; // zt - double redshiftRatio; // erat - // double tempCoefficient; // coeff - double distanceStep; // tzdist*tdz (cm) - double rightDistance; // d1 (Mpc) - double leftDistance; // d2 (Mpc) - double evolutionFactor,evolutionFactor1; // zfact - double smallDistanceStep; // dx (pc) - double x; // x (pc) - - // Energy below which the 1D approximation is not a priori correct : - bool lEcFlag ; - int lIndex ; - double lEnergy, t_sync, t_larmor, t_ics = 0 ; - double a_ics = (3.-log10(4.))/4. ; - double b_ics = pow(10.,8.-7.*a_ics) ; - // (used if the flag aCutcascade_Magfield is set) - - // FILE* input; - int tauNeutrinoMassSwitch; - - // interaction switches - int ICSSwitch; - int PPSwitch; - int TPPSwitch; - int DPPSwitch; - - int PPPSwitch; - int NPPSwitch; - int neutronDecaySwitch; - int nucleonToSecondarySwitch; - - int neutrinoNeutrinoSwitch; - - //---- interaction rates folded with photon background ---- - TotalRate leptonTotalRate; - TotalRate photonTotalRate; - TotalRate protonTotalRate; - TotalRate neutronTotalRate; - - DiffRate leptonScatRate; - DiffRate leptonExchRate; - DiffRate leptonPhotonRate; - DiffRate photonLeptonRate; - - DiffRate protonScatRate; - DiffRate protonNeutronRate; - DiffRate neutronProtonRate; - DiffRate protonPhotonRate; - DiffRate protonElectronRate; - DiffRate protonPositronRate; - DiffRate neutronElectronRate; - DiffRate neutronPositronRate; - DiffRate protonElectronNeutrinoRate; - DiffRate protonAntiElectronNeutrinoRate; - DiffRate protonMuonNeutrinoRate; - DiffRate protonAntiMuonNeutrinoRate; - DiffRate neutronAntiElectronNeutrinoRate; - DiffRate neutronMuonNeutrinoRate; - DiffRate neutronAntiMuonNeutrinoRate; - - TotalRate elNeutTotalRate; - TotalRate muonNeutTotalRate; - TotalRate tauNeutTotalRate; - - DiffRate elNeutScatRate; - DiffRate elNeutMuonNeutRate; - DiffRate elNeutTauNeutRate; - DiffRate elNeutElectronRate; - DiffRate elNeutPhotonRate; - DiffRate elNeutProtonRate; - DiffRate muonNeutScatRate; - DiffRate muonNeutElNeutRate; - DiffRate muonNeutTauNeutRate; - DiffRate muonNeutElectronRate; - DiffRate muonNeutPhotonRate; - DiffRate muonNeutProtonRate; - DiffRate tauNeutScatRate; - DiffRate tauNeutElNeutRate; - DiffRate tauNeutMuonNeutRate; - DiffRate tauNeutElectronRate; - DiffRate tauNeutPhotonRate; - DiffRate tauNeutProtonRate; - // rates from neutrino-neutrino interaction - - dCVector synchrotronLoss; // sgdot - dCVector otherLoss; // tgdot - dCVector continuousLoss; // gdot - dCVector protonContinuousLoss; // pgdot - - int loopCounter; - //-------- End of variable declaration -------- - - // numSmallSteps = 100; - convergeParameter = 1.e-8; - - // -------- Redshift Estimation --------------- - // startingRedshift = pow(1. - 3.*H_0*1.e5*dist_observer/2./C, -2./3.) - 1.; - // This was the old analytic redshift computation. - dCVector RedshiftArray ; - dCVector DistanceArray ; - BuildRedshiftTable(aH0, aOmegaM, aOmegaLambda, &RedshiftArray, &DistanceArray) ; - startingRedshift = getRedshift(RedshiftArray, DistanceArray, dist_observer) ; - // printf("distance/Mpc: %15.6E\n", dist_observer); - // printf("particle type: %d\n", part); - // printf("injection energy/eV: %15.6E\n", InjEnergy); - - B_bins = pB_field->dimension; - - synchrotronSwitch = 1; - tauNeutrinoMassSwitch = 1; - ICSSwitch = 1; - PPSwitch = 1; - TPPSwitch = 1; - DPPSwitch = 1; - // PPPSwitch = 1; - PPPSwitch = 0; - NPPSwitch = 0; - // synchrotronSwitch = 0; - // tauNeutrinoMassSwitch = 0; - // ICSSwitch = 0; - // PPSwitch = 0; - // TPPSwitch = 0; - // DPPSwitch = 0; - // PPPSwitch = 1; - PPPSwitch = 0; - NPPSwitch = 0; - // printf("DINT modified!!\n"); -#ifdef EXTRACT_PAIR_PROD_RATE - NPPSwitch = 1; // (allows to compute new pair prod rate) -#endif - - // neutronDecaySwitch = 1; - neutronDecaySwitch = 0; - nucleonToSecondarySwitch = 0; - neutrinoNeutrinoSwitch = 1; - sourceTypeSwitch = 0; - minDistance = 0.; - brightPhaseExp = 0.; - - //-------- Set up energy bins -------- - New_dCVector(&deltaG, NUM_MAIN_BINS); - New_dCVector(&bgEnergy, NUM_BG_BINS); - New_dCVector(&bgEnergyWidth, NUM_BG_BINS); - New_dCVector(&bgPhotonDensity, NUM_BG_BINS); - - // set energy bins - SetDeltaG(pEnergy, &deltaG); - - SetEnergyBins(BG_MIN_ENERGY_EXP, &bgEnergy, &bgEnergyWidth); - - NewSpectrum(&Q_0, NUM_MAIN_BINS); - NewSpectrum(&spectrumNew, NUM_MAIN_BINS); - NewSpectrum(&derivative, NUM_MAIN_BINS); - - New_dCVector(&synchrotronLoss, NUM_MAIN_BINS); - New_dCVector(&otherLoss, NUM_MAIN_BINS); - New_dCVector(&continuousLoss, NUM_MAIN_BINS); - New_dCVector(&protonContinuousLoss, NUM_MAIN_BINS); - - - //---- Select injection model ---- - // SetInjectionSpectrum(part, InjEnergy, HInjEnergy, deltaE_hadron, - // pEnergy, pEnergyWidth, &Q_0); - // SetInjectionSpectrum(part, pEnergy, pEnergyWidth, &Q_0, InjEnergy); - - SetSpectrum(&Q_0, apInjectionSpectrum) ; - // No call anymore to SetInjectionSpectrum, which is not useful anymore. - totalEnergyInput = GetEnergy(&Q_0, pEnergy); -#ifdef DEBUG - DumpEnergy(&Q_0, pEnergy); -#endif - - //-------- Create arrays -------- - // NOTE: I first make them table size; they will be "clipped" after reading in tables - if (ICSSwitch == 1) { - NewRawTotalRate(&ICSTotalRate, EM_NUM_MAIN_BINS, NUM_BG_BINS); - NewRawDiffRate(&ICSPhotonRate, EM_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_IP_ELEMENTS); - NewRawDiffRate(&ICSScatRate, EM_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_IS_ELEMENTS); - } - - if (PPSwitch == 1) { - NewRawTotalRate(&PPTotalRate, EM_NUM_MAIN_BINS, NUM_BG_BINS); - NewRawDiffRate(&PPDiffRate, EM_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_PP_ELEMENTS); - } - - if (TPPSwitch == 1) { - NewRawTotalRate(&TPPTotalRate, EM_NUM_MAIN_BINS, NUM_BG_BINS); - NewRawDiffRate(&TPPDiffRate, EM_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_TPP_ELEMENTS); - } - - if (DPPSwitch == 1) - NewRawTotalRate(&DPPRate, EM_NUM_MAIN_BINS, NUM_BG_BINS); - - if (PPPSwitch == 1) { - NewRawTotalRate(&PPPProtonLossRate, NUC_NUM_MAIN_BINS, NUM_BG_BINS); - NewRawTotalRate(&PPPNeutronLossRate, NUC_NUM_MAIN_BINS, NUM_BG_BINS); - - NewRawDiffRate(&PPPProtonScatRate, NUC_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_PPP_PROTON_SCAT_ELEMENTS); - NewRawDiffRate(&PPPProtonNeutronRate, NUC_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_PPP_PROTON_NEUTRON_ELEMENTS); - NewRawDiffRate(&PPPNeutronProtonRate, NUC_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_PPP_PROTON_NEUTRON_ELEMENTS); - - if (nucleonToSecondarySwitch == 1) { - NewRawDiffRate(&PPPProtonPhotonRate, NUC_NUM_MAIN_BINS, - NUM_BG_BINS, NUM_PPP_PROTON_PHOTON_ELEMENTS); - NewRawDiffRate(&PPPProtonElectronRate, NUC_NUM_MAIN_BINS, - NUM_BG_BINS, NUM_PPP_PROTON_ELECTRON_ELEMENTS); - NewRawDiffRate(&PPPProtonPositronRate, NUC_NUM_MAIN_BINS, - NUM_BG_BINS, NUM_PPP_PROTON_POSITRON_ELEMENTS); - NewRawDiffRate(&PPPNeutronElectronRate, NUC_NUM_MAIN_BINS, - NUM_BG_BINS, NUM_PPP_PROTON_POSITRON_ELEMENTS); - NewRawDiffRate(&PPPProtonElectronNeutrinoRate, NUC_NUM_MAIN_BINS, - NUM_BG_BINS, NUM_PPP_PROTON_ANTI_MUON_NEUTRINO_ELEMENTS); - NewRawDiffRate(&PPPProtonAntiElectronNeutrinoRate, - NUC_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_PPP_PROTON_ANTI_ELECTRON_NEUTRINO_ELEMENTS); - NewRawDiffRate(&PPPProtonMuonNeutrinoRate, NUC_NUM_MAIN_BINS, - NUM_BG_BINS, NUM_PPP_PROTON_MUON_NEUTRINO_ELEMENTS); - NewRawDiffRate(&PPPProtonAntiMuonNeutrinoRate, NUC_NUM_MAIN_BINS, - NUM_BG_BINS, NUM_PPP_PROTON_ANTI_MUON_NEUTRINO_ELEMENTS); - NewRawDiffRate(&PPPNeutronAntiElectronNeutrinoRate, - NUC_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_PPP_PROTON_ANTI_MUON_NEUTRINO_ELEMENTS); - NewRawDiffRate(&PPPNeutronMuonNeutrinoRate, NUC_NUM_MAIN_BINS, - NUM_BG_BINS, NUM_PPP_PROTON_ANTI_MUON_NEUTRINO_ELEMENTS); - NewRawDiffRate(&PPPNeutronAntiMuonNeutrinoRate, NUC_NUM_MAIN_BINS, - NUM_BG_BINS, NUM_PPP_PROTON_MUON_NEUTRINO_ELEMENTS); - } - } - - if (NPPSwitch == 1) { - NewRawTotalRate(&NPPTotalRate, NUC_NUM_MAIN_BINS, NUM_BG_BINS); - - if (nucleonToSecondarySwitch == 1) - NewRawDiffRate(&NPPDiffRate, NUC_NUM_MAIN_BINS, NUM_BG_BINS, - NUM_NPP_ELEMENTS); - } - - // neutron decay does not fit the general category because it is not - // really an interaction (with background) - if (neutronDecaySwitch == 1) { - NewTotalRate(&neutronDecayRate, NUC_NUM_MAIN_BINS); - NewDiffRate(&neutronDecayProtonRate, NUC_NUM_MAIN_BINS); - - if (nucleonToSecondarySwitch == 1) - NewDiffRate(&neutronDecayElectronRate, NUC_NUM_MAIN_BINS); - } - - // neutrino-neutrino rates are already folded w/ neutrino background - if (neutrinoNeutrinoSwitch == 1) { - NewTotalRate(&NNElNeutTotalRate, NEUT_NUM_MAIN_BINS); - NewTotalRate(&NNMuonNeutTotalRate, NEUT_NUM_MAIN_BINS); - NewTotalRate(&NNTauNeutTotalRate, NEUT_NUM_MAIN_BINS); - - NewDiffRate(&NNElNeutScatRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNElNeutMuonNeutRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNElNeutTauNeutRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNElNeutElectronRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNElNeutPhotonRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNElNeutProtonRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNMuonNeutScatRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNMuonNeutElNeutRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNMuonNeutTauNeutRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNMuonNeutElectronRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNMuonNeutPhotonRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNMuonNeutProtonRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNTauNeutScatRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNTauNeutElNeutRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNTauNeutMuonNeutRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNTauNeutElectronRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNTauNeutPhotonRate, NEUT_NUM_MAIN_BINS); - NewDiffRate(&NNTauNeutProtonRate, NEUT_NUM_MAIN_BINS); - } - - //---- read in coefficient tables; clipping is done here if necessary ---- - if (ICSSwitch == 1) - LoadICSTables(&ICSTotalRate, &ICSPhotonRate, &ICSScatRate, - NUM_MAIN_BINS, aDirTables); - if (PPSwitch == 1) - LoadPPTables(&PPTotalRate, &PPDiffRate, NUM_MAIN_BINS, aDirTables); - if (TPPSwitch == 1) - LoadTPPTables(&TPPTotalRate, &TPPDiffRate, NUM_MAIN_BINS, aDirTables); - if (DPPSwitch == 1) - LoadDPPTables(&DPPRate, NUM_MAIN_BINS, aDirTables); - if (PPPSwitch == 1) { - LoadPPPNucleonTables(&PPPProtonLossRate, &PPPNeutronLossRate, - &PPPProtonScatRate, &PPPProtonNeutronRate, &PPPNeutronProtonRate, - NUM_MAIN_BINS, aDirTables); - - if (nucleonToSecondarySwitch == 1) { - LoadPPPEMTables(&PPPProtonPhotonRate, &PPPProtonElectronRate, - &PPPProtonPositronRate, &PPPNeutronElectronRate, - NUM_MAIN_BINS, aDirTables); - LoadPPPNeutrinoTables(&PPPProtonElectronNeutrinoRate, - &PPPProtonAntiElectronNeutrinoRate, &PPPProtonMuonNeutrinoRate, - &PPPProtonAntiMuonNeutrinoRate, - &PPPNeutronAntiElectronNeutrinoRate, - &PPPNeutronMuonNeutrinoRate, &PPPNeutronAntiMuonNeutrinoRate, - NUM_MAIN_BINS, aDirTables); - } - } - if (NPPSwitch == 1) { - LoadNPPNucleonTables(&NPPTotalRate, NUM_MAIN_BINS, aDirTables); - - if (nucleonToSecondarySwitch == 1) - LoadNPPSecondaryTables(&NPPDiffRate, NUM_MAIN_BINS, aDirTables); - } - - if (neutronDecaySwitch == 1) { - LoadNeutronDecayNucleonTables(&neutronDecayRate, - &neutronDecayProtonRate, NUM_MAIN_BINS, aDirTables); - - if (nucleonToSecondarySwitch == 1) - LoadNeutronDecaySecondaryTables(&neutronDecayElectronRate, - NUM_MAIN_BINS, aDirTables); - } - - if (neutrinoNeutrinoSwitch == 1) - LoadNeutrinoTables(tauNeutrinoMassSwitch, &NNElNeutTotalRate, - &NNMuonNeutTotalRate, &NNTauNeutTotalRate, &NNElNeutScatRate, - &NNElNeutMuonNeutRate, &NNElNeutTauNeutRate, - &NNElNeutElectronRate, &NNElNeutPhotonRate, &NNElNeutProtonRate, - &NNMuonNeutScatRate, &NNMuonNeutElNeutRate, - &NNMuonNeutTauNeutRate, &NNMuonNeutElectronRate, - &NNMuonNeutPhotonRate, &NNMuonNeutProtonRate, &NNTauNeutScatRate, - &NNTauNeutElNeutRate, &NNTauNeutMuonNeutRate, - &NNTauNeutElectronRate, &NNTauNeutPhotonRate, - &NNTauNeutProtonRate, NUM_MAIN_BINS, aDirTables); - -#ifdef DEBUG - printf("Starting computations...\n\n"); -#endif - -clock_t start_comp = clock(); - - //---- Initialize distance ---- - distance = 0.; // distance variable: dist in FORTRAN - - PrepareSpectra(sourceTypeSwitch, &Q_0, pSpectrum, &spectrumNew, - &derivative); - // NOTE: suspect derivative is never used??? - - // if (sourceTypeSwitch == 0) // single source - // DumpSpectrum(pEnergy, pEnergyWidth, &Q_0, "InitialSpectrumDump.dat"); - - ComputeTotalInitialContent(pEnergy, &Q_0, &initialPhotonEnergy, - &initialLeptonEnergy, &initialNucleonEnergy, - &initialNeutrinoEnergy, &initialTotalEnergy, - &initialPhotonNumber, &initialLeptonNumber, - &initialNucleonNumber, &initialNeutrinoNumber, - &initialTotalNumber); - - //--------- START of actual computation -------- - //---- initialize indices and parameters ---- - iterationCounter = 1; - firstIndex = 0; - leftRedshift = startingRedshift; - deltaRedshift = 1. - (pEnergy->vector)[2]/(pEnergy->vector)[3]; - lastIndex = 0; - propagatingDistance = 0.; - - - NewTotalRate(&leptonTotalRate, NUM_MAIN_BINS); - NewTotalRate(&photonTotalRate, NUM_MAIN_BINS); - - NewTotalRate(&protonTotalRate, NUM_MAIN_BINS); - NewTotalRate(&neutronTotalRate, NUM_MAIN_BINS); - - - NewDiffRate(&leptonScatRate, NUM_MAIN_BINS); - NewDiffRate(&leptonExchRate, NUM_MAIN_BINS); - NewDiffRate(&leptonPhotonRate, NUM_MAIN_BINS); - NewDiffRate(&photonLeptonRate, NUM_MAIN_BINS); - - NewDiffRate(&protonScatRate, NUM_MAIN_BINS); - NewDiffRate(&protonNeutronRate, NUM_MAIN_BINS); - NewDiffRate(&neutronProtonRate, NUM_MAIN_BINS); - NewDiffRate(&protonPhotonRate, NUM_MAIN_BINS); - NewDiffRate(&protonElectronRate, NUM_MAIN_BINS); - NewDiffRate(&protonPositronRate, NUM_MAIN_BINS); - NewDiffRate(&neutronElectronRate, NUM_MAIN_BINS); - NewDiffRate(&neutronPositronRate, NUM_MAIN_BINS); - NewDiffRate(&protonElectronNeutrinoRate, NUM_MAIN_BINS); - NewDiffRate(&protonAntiElectronNeutrinoRate, NUM_MAIN_BINS); - NewDiffRate(&protonMuonNeutrinoRate, NUM_MAIN_BINS); - NewDiffRate(&protonAntiMuonNeutrinoRate, NUM_MAIN_BINS); - NewDiffRate(&neutronAntiElectronNeutrinoRate, NUM_MAIN_BINS); - NewDiffRate(&neutronMuonNeutrinoRate, NUM_MAIN_BINS); - NewDiffRate(&neutronAntiMuonNeutrinoRate, NUM_MAIN_BINS); - - - NewTotalRate(&elNeutTotalRate, NUM_MAIN_BINS); - NewTotalRate(&muonNeutTotalRate, NUM_MAIN_BINS); - NewTotalRate(&tauNeutTotalRate, NUM_MAIN_BINS); - - NewDiffRate(&elNeutScatRate, NUM_MAIN_BINS); - NewDiffRate(&elNeutMuonNeutRate, NUM_MAIN_BINS); - NewDiffRate(&elNeutTauNeutRate, NUM_MAIN_BINS); - NewDiffRate(&elNeutElectronRate, NUM_MAIN_BINS); - NewDiffRate(&elNeutPhotonRate, NUM_MAIN_BINS); - NewDiffRate(&elNeutProtonRate, NUM_MAIN_BINS); - NewDiffRate(&muonNeutElNeutRate, NUM_MAIN_BINS); - NewDiffRate(&muonNeutScatRate, NUM_MAIN_BINS); - NewDiffRate(&muonNeutTauNeutRate, NUM_MAIN_BINS); - NewDiffRate(&muonNeutElectronRate, NUM_MAIN_BINS); - NewDiffRate(&muonNeutPhotonRate, NUM_MAIN_BINS); - NewDiffRate(&muonNeutProtonRate, NUM_MAIN_BINS); - NewDiffRate(&tauNeutElNeutRate, NUM_MAIN_BINS); - NewDiffRate(&tauNeutMuonNeutRate, NUM_MAIN_BINS); - NewDiffRate(&tauNeutScatRate, NUM_MAIN_BINS); - NewDiffRate(&tauNeutElectronRate, NUM_MAIN_BINS); - NewDiffRate(&tauNeutPhotonRate, NUM_MAIN_BINS); - NewDiffRate(&tauNeutProtonRate, NUM_MAIN_BINS); - /* I created all folded rates because I didn't want to pass all the - switches to the subsequent functions, and these allocations are - not so expensive anyway */ - - //-------- This is where propagation takes place -------- - do { - - // this firstIndex & lastIndex pair is used to bin redshift finer - // near the end of propagation (z close to 0) - ComputeRedshifts(sourceTypeSwitch, leftRedshift, &deltaRedshift, - &rightRedshift, ¢ralRedshift, &lastIndex); - - //---- compute various distance parameters ---- - redshiftRatio = (1. + rightRedshift)/(1. + leftRedshift); - // tempCoefficient = pow(OMEGA_M*pow(1. + centralRedshift,3.)+ - // OMEGA_LAMBDA, -1./2.)/(1.+centralRedshift); - // tempCoefficient = pow(1. + centralRedshift, -5./2.); - // distanceStep = (leftRedshift - rightRedshift)*tempCoefficient*C/ - // (H_0*1.e5/1.e6/DISTANCE_UNIT); - - // (cosmological parameters added July 2005) - leftDistance = getDistance(RedshiftArray,DistanceArray,leftRedshift) ; - rightDistance = getDistance(RedshiftArray,DistanceArray,rightRedshift) ; - distanceStep = leftDistance - rightDistance ; - distance += distanceStep; - // rightDistance = distance - distanceStep/2.; - // leftDistance = distance + distanceStep/2.; - // rightDistance = 2./3.*C/1.e5/H_0*(1. - pow(1. + rightRedshift, -1.5)); - // leftDistance = 2./3.*C/1.e5/H_0*(1. - pow(1. + leftRedshift, -1.5)); - - evolutionFactor1 = pow((1. + centralRedshift)/(1. + startingRedshift), - brightPhaseExp+3.); // redshift evolution - numSmallSteps = (int)(ceil(distanceStep/DISTANCE_UNIT/DMAX)); - smallDistanceStep = distanceStep/DISTANCE_UNIT/numSmallSteps; - x = 0.; - // printf("small stepsize: %15.6E\n", smallDistanceStep); - - //---- compute the photon background at given redshift ---- - LoadPhotonBackground(centralRedshift, &bgEnergy, &bgEnergyWidth, - &bgPhotonDensity, aIRFlag, aZmax_IR, aRadioFlag, - aH0, aOmegaM, aOmegaLambda); - - // if (rightRedshift < 1.e-5) - // DumpBgSpectrum(&bgEnergy, &bgEnergyWidth, &bgPhotonDensity,"~/"); - - //---- initialize rates ---- - InitializeLeptonCoefficients(&leptonTotalRate, &leptonScatRate, - &leptonExchRate, &leptonPhotonRate); - InitializePhotonCoefficients(&photonTotalRate, &photonLeptonRate); - InitializeNucleonCoefficients(&protonTotalRate, &neutronTotalRate, - &protonScatRate, &protonNeutronRate, - &neutronProtonRate, &protonPhotonRate, - &protonElectronRate, &protonPositronRate, - &neutronElectronRate, &neutronPositronRate, - &protonElectronNeutrinoRate, - &protonAntiElectronNeutrinoRate, - &protonMuonNeutrinoRate, &protonAntiMuonNeutrinoRate, - &neutronAntiElectronNeutrinoRate, &neutronMuonNeutrinoRate, - &neutronAntiMuonNeutrinoRate); - InitializeNeutrinoCoefficients(&elNeutTotalRate, &muonNeutTotalRate, - &tauNeutTotalRate, &elNeutScatRate, &elNeutMuonNeutRate, - &elNeutTauNeutRate, &elNeutElectronRate, - &elNeutPhotonRate, &elNeutProtonRate, - &muonNeutElNeutRate, &muonNeutScatRate, - &muonNeutTauNeutRate, &muonNeutElectronRate, - &muonNeutPhotonRate, &muonNeutProtonRate, - &tauNeutElNeutRate, &tauNeutMuonNeutRate, - &tauNeutScatRate, &tauNeutElectronRate, - &tauNeutPhotonRate, &tauNeutProtonRate); - - Initialize_dCVector(&continuousLoss); - - Initialize_dCVector(&otherLoss); - Initialize_dCVector(&protonContinuousLoss); - - //---- fold interaction rates w/ photon background ---- - if (ICSSwitch == 1) - FoldICS(&bgPhotonDensity, &ICSTotalRate, &ICSPhotonRate, - &ICSScatRate, &leptonTotalRate, &leptonPhotonRate, - &leptonScatRate); - if (TPPSwitch == 1) - FoldTPP(&bgPhotonDensity, pEnergy, &TPPTotalRate, &TPPDiffRate, - &leptonTotalRate, &leptonScatRate, &leptonExchRate, - &otherLoss); - if (PPSwitch == 1) - FoldPP(&bgPhotonDensity, &PPTotalRate, &PPDiffRate, - &photonTotalRate, &photonLeptonRate); - if (DPPSwitch == 1) - FoldDPP(&bgPhotonDensity, &DPPRate, &photonTotalRate, - &photonLeptonRate); - if (PPPSwitch == 1) { - FoldPPPNucleon(&bgPhotonDensity, &PPPProtonLossRate, - &PPPNeutronLossRate, &PPPProtonScatRate, &PPPProtonNeutronRate, - &PPPNeutronProtonRate, &protonTotalRate, &neutronTotalRate, - &protonScatRate, &protonNeutronRate, &neutronProtonRate); - - if (nucleonToSecondarySwitch == 1) - FoldPPPSecondary(&bgPhotonDensity, &PPPProtonPhotonRate, - &PPPProtonElectronRate, &PPPProtonPositronRate, - &PPPNeutronElectronRate, &PPPProtonElectronNeutrinoRate, - &PPPProtonAntiElectronNeutrinoRate, - &PPPProtonMuonNeutrinoRate, &PPPProtonAntiMuonNeutrinoRate, - &PPPNeutronAntiElectronNeutrinoRate, - &PPPNeutronMuonNeutrinoRate, - &PPPNeutronAntiMuonNeutrinoRate, &protonPhotonRate, - &protonElectronRate, &protonPositronRate, - &neutronElectronRate, &neutronPositronRate, - &protonElectronNeutrinoRate, - &protonAntiElectronNeutrinoRate, - &protonMuonNeutrinoRate, &protonAntiMuonNeutrinoRate, - &neutronAntiElectronNeutrinoRate, &neutronMuonNeutrinoRate, - &neutronAntiMuonNeutrinoRate); - } - - -#ifdef EXTRACT_PHOTON_TOTAL_RATE - // Add - E.A. Dec. 2005 - // Extract photon total energy loss rate - for (int i=0; idimension; i++) cout << (pEnergy->vector)[i] << " " - << (photonTotalRate.totalRate)[i] - << endl; - exit(0) ; -#endif -#ifdef EXTRACT_LEPTON_RATE - for (int i=0; idimension; i++) cout << (pEnergy->vector)[i] << " " - << (leptonTotalRate.totalRate)[i] - << endl; - exit(0) ; -#endif - - if (NPPSwitch == 1) { - - FoldNPPNucleon(&bgPhotonDensity, pEnergy, &NPPTotalRate, - &protonContinuousLoss); - -#ifdef EXTRACT_PAIR_PROD_RATE - // Slight add - E.A. July 2005 . - // To extract the pair production tables of protons on photon backgrounds. - // (need to switch NPPSwitch!) - for (int i=0; idimension; i++) cout << (pEnergy->vector)[i] << " " - << (protonContinuousLoss.vector)[i] - << endl; - exit(0) ; -#endif - - if (nucleonToSecondarySwitch == 1) - FoldNPPSecondary(&bgPhotonDensity, &NPPDiffRate, - &protonPositronRate, &protonElectronRate); - } - - if (neutrinoNeutrinoSwitch == 1) - MapNeutRates(centralRedshift, lastIndex, tauNeutrinoMassSwitch, - &NNElNeutTotalRate, &NNMuonNeutTotalRate, &NNTauNeutTotalRate, - &NNElNeutScatRate, &NNElNeutMuonNeutRate, - &NNElNeutTauNeutRate, &NNElNeutElectronRate, - &NNElNeutPhotonRate, &NNElNeutProtonRate, - &NNMuonNeutElNeutRate, &NNMuonNeutScatRate, - &NNMuonNeutTauNeutRate, &NNMuonNeutElectronRate, - &NNMuonNeutPhotonRate, &NNMuonNeutProtonRate, - &NNTauNeutElNeutRate, &NNTauNeutMuonNeutRate, - &NNTauNeutScatRate, &NNTauNeutElectronRate, - &NNTauNeutPhotonRate, &NNTauNeutProtonRate, &elNeutTotalRate, - &muonNeutTotalRate, &tauNeutTotalRate, &elNeutScatRate, - &elNeutMuonNeutRate, &elNeutTauNeutRate, &elNeutElectronRate, - &elNeutPhotonRate, &elNeutProtonRate, &muonNeutElNeutRate, - &muonNeutScatRate, &muonNeutTauNeutRate, &muonNeutElectronRate, - &muonNeutPhotonRate, &muonNeutProtonRate, &tauNeutElNeutRate, - &tauNeutMuonNeutRate, &tauNeutScatRate, &tauNeutElectronRate, - &tauNeutPhotonRate, &tauNeutProtonRate); - - //---- main iteration (convergence) block ---- - - for (loopCounter = 0; loopCounter < numSmallSteps; loopCounter++) { - - if (synchrotronSwitch == 1) { // synchrotron == true (on) - - NewDiffRate(&syncRate, NUM_MAIN_BINS); - - B_bin = (int)((double)(B_bins)*(propagatingDistance+x)/1.e6/ - dist_observer); - B_loc=(pB_field->vector)[B_bin]; - InitializeSynchrotron(B_loc, pEnergy, pEnergyWidth, - &synchrotronLoss, &syncRate, - aDirTables); - } - //---- compute continuous energy loss for electrons ---- - ComputeContinuousEnergyLoss(synchrotronSwitch, &synchrotronLoss, - &otherLoss, &continuousLoss); - - evolutionFactor = evolutionFactor1; - if ((leftDistance - x/1.e6) < minDistance) - evolutionFactor = 0.; - if ((leftDistance - x/1.e6) < SOURCE_CLUSTER_DISTANCE) - evolutionFactor = SOURCE_CLUSTER_FACTOR*evolutionFactor1; - if ((leftDistance - x/1.e6) < CLUSTER_DISTANCE) - bkgFactor = CLUSTER_FACTOR; - else - bkgFactor = 1.; - - AdvanceNucNeutStep(sourceTypeSwitch, PPPSwitch, NPPSwitch, - neutronDecaySwitch, nucleonToSecondarySwitch, - neutrinoNeutrinoSwitch, smallDistanceStep, - evolutionFactor, convergeParameter, bkgFactor, &Q_0, - &elNeutProtonRate, - &muonNeutProtonRate, &tauNeutProtonRate, &protonTotalRate, - &neutronTotalRate, &neutronDecayRate, &protonScatRate, - &protonNeutronRate, &neutronProtonRate, - &neutronDecayProtonRate, &protonMuonNeutrinoRate, - &neutronAntiMuonNeutrinoRate, &protonAntiMuonNeutrinoRate, - &neutronMuonNeutrinoRate, &protonElectronNeutrinoRate, - &neutronAntiElectronNeutrinoRate, - &protonAntiElectronNeutrinoRate, &neutronDecayElectronRate, - &elNeutTotalRate, &muonNeutTotalRate, &tauNeutTotalRate, - &elNeutScatRate, &elNeutMuonNeutRate, &elNeutTauNeutRate, - &muonNeutElNeutRate, &muonNeutScatRate, &muonNeutTauNeutRate, - &tauNeutElNeutRate, &tauNeutMuonNeutRate, &tauNeutScatRate, - &protonContinuousLoss, &deltaG, pSpectrum, &spectrumNew); - - SetNucleonSpectrum(pSpectrum, &spectrumNew); - SetNeutrinoSpectrum(pSpectrum, &spectrumNew); - - AdvanceEMStep(sourceTypeSwitch, PPSwitch, ICSSwitch, - TPPSwitch, DPPSwitch, synchrotronSwitch, PPPSwitch, - NPPSwitch, neutronDecaySwitch, nucleonToSecondarySwitch, - neutrinoNeutrinoSwitch, smallDistanceStep, evolutionFactor, - convergeParameter, bkgFactor, &Q_0, &photonLeptonRate, - &protonElectronRate, &neutronPositronRate, - &protonPositronRate, &neutronElectronRate, - &neutronDecayElectronRate, &elNeutElectronRate, - &muonNeutElectronRate, &tauNeutElectronRate, - &protonPhotonRate, &elNeutPhotonRate, &muonNeutPhotonRate, - &tauNeutPhotonRate, &leptonTotalRate, &leptonScatRate, - &leptonExchRate, &continuousLoss, &deltaG, &photonTotalRate, - &leptonPhotonRate, &syncRate, pSpectrum, &spectrumNew); - - SetEMSpectrum(pSpectrum, &spectrumNew); - // update spectrum - - if (aCutcascade_Magfield != 0 && B_loc != 0 ) { - // Estimate the effect of B field on the 1D approximation (added E.A. June 2006) - lEcFlag = 0 ; - lIndex = 0; - while (!lEcFlag) { - lEnergy = (pEnergy->vector)[lIndex] ; - // Time scales are computed in parsec - t_sync = 3.84e6/(lEnergy*B_loc*B_loc*ELECTRON_MASS) ; - t_larmor = (1.1e-21)*ELECTRON_MASS*lEnergy/(B_loc*aCutcascade_Magfield) ; - if (lEnergy <= 1.e15/ELECTRON_MASS) { - t_ics = 4.e2*1.e15/(ELECTRON_MASS*lEnergy) ; - } else if (lEnergy <= 1.e18/ELECTRON_MASS) { - t_ics = 4.e2*lEnergy*ELECTRON_MASS/1.e15 ; - } else if (lEnergy <= 1.e22/ELECTRON_MASS) { - t_ics = b_ics*pow(lEnergy*ELECTRON_MASS/1.e15,a_ics) ; - } else t_ics = 1.e8*lEnergy*ELECTRON_MASS/1.e22 ; - if (t_larmor >= t_sync || t_larmor >= t_ics) lEcFlag = 1 ; - // defines the "critical" energy : the e+/- spectrum is set to 0 for Espectrum)[ELECTRON][lIndex]=0 ; - (pSpectrum->spectrum)[POSITRON][lIndex]=0 ; - lIndex++ ; - } - } - - if (synchrotronSwitch == 1) // synchrotron == true (on) - DeleteDiffRate(&syncRate); - - x += smallDistanceStep; - iterationCounter++; - } - - - propagatingDistance += x; // increment distance - - //---- redshift bins down ---- - RedshiftDown(lastIndex, redshiftRatio, pEnergy, pSpectrum, - &spectrumNew); - - // printf("\nz = %g -> %g", leftRedshift, rightRedshift); - // printf("; d/Mpc = %g -> %g:\n", leftDistance, rightDistance); - // printf("%g, %g:\n", propagatingDistance, distance); - CheckEnergy(sourceTypeSwitch, brightPhaseExp, startingRedshift, - rightRedshift, pSpectrum, pEnergy, initialTotalEnergy); - - //---- prepare for new step ---- - leftRedshift = rightRedshift; - } while (lastIndex != 1); - -clock_t end_comp = clock(); - - //---- I am done with the rates ---- - DeleteDiffRate(&leptonScatRate); - DeleteDiffRate(&leptonExchRate); - DeleteDiffRate(&leptonPhotonRate); - DeleteDiffRate(&photonLeptonRate); - DeleteDiffRate(&protonScatRate); - DeleteDiffRate(&protonNeutronRate); - DeleteDiffRate(&neutronProtonRate); - DeleteDiffRate(&protonPhotonRate); - DeleteDiffRate(&protonElectronRate); - DeleteDiffRate(&protonPositronRate); - DeleteDiffRate(&neutronElectronRate); - DeleteDiffRate(&neutronPositronRate); - DeleteDiffRate(&protonElectronNeutrinoRate); - DeleteDiffRate(&protonAntiElectronNeutrinoRate); - DeleteDiffRate(&protonMuonNeutrinoRate); - DeleteDiffRate(&protonAntiMuonNeutrinoRate); - DeleteDiffRate(&neutronAntiElectronNeutrinoRate); - DeleteDiffRate(&neutronMuonNeutrinoRate); - DeleteDiffRate(&neutronAntiMuonNeutrinoRate); - - DeleteDiffRate(&elNeutScatRate); - DeleteDiffRate(&elNeutMuonNeutRate); - DeleteDiffRate(&elNeutTauNeutRate); - DeleteDiffRate(&elNeutElectronRate); - DeleteDiffRate(&elNeutPhotonRate); - DeleteDiffRate(&elNeutProtonRate); - DeleteDiffRate(&muonNeutElNeutRate); - DeleteDiffRate(&muonNeutScatRate); - DeleteDiffRate(&muonNeutTauNeutRate); - DeleteDiffRate(&muonNeutElectronRate); - DeleteDiffRate(&muonNeutPhotonRate); - DeleteDiffRate(&muonNeutProtonRate); - DeleteDiffRate(&tauNeutElNeutRate); - DeleteDiffRate(&tauNeutMuonNeutRate); - DeleteDiffRate(&tauNeutScatRate); - DeleteDiffRate(&tauNeutElectronRate); - DeleteDiffRate(&tauNeutPhotonRate); - DeleteDiffRate(&tauNeutProtonRate); - - DeleteTotalRate(&leptonTotalRate); - DeleteTotalRate(&photonTotalRate); - DeleteTotalRate(&protonTotalRate); - DeleteTotalRate(&neutronTotalRate); - DeleteTotalRate(&elNeutTotalRate); - DeleteTotalRate(&muonNeutTotalRate); - DeleteTotalRate(&tauNeutTotalRate); - - - if (ICSSwitch == 1) { - DeleteRawDiffRate(&ICSPhotonRate); - DeleteRawDiffRate(&ICSScatRate); - DeleteRawTotalRate(&ICSTotalRate); - } - if (PPSwitch == 1) { - DeleteRawDiffRate(&PPDiffRate); - DeleteRawTotalRate(&PPTotalRate); - } - if (TPPSwitch == 1) { - DeleteRawDiffRate(&TPPDiffRate); - DeleteRawTotalRate(&TPPTotalRate); - } - if (PPPSwitch == 1) { - DeleteRawDiffRate(&PPPProtonScatRate); - DeleteRawDiffRate(&PPPProtonNeutronRate); - DeleteRawDiffRate(&PPPNeutronProtonRate); - - DeleteRawTotalRate(&PPPProtonLossRate); - DeleteRawTotalRate(&PPPNeutronLossRate); - - if (nucleonToSecondarySwitch == 1) { - DeleteRawDiffRate(&PPPProtonPhotonRate); - DeleteRawDiffRate(&PPPProtonElectronRate); - DeleteRawDiffRate(&PPPProtonPositronRate); - DeleteRawDiffRate(&PPPNeutronElectronRate); - DeleteRawDiffRate(&PPPProtonElectronNeutrinoRate); - DeleteRawDiffRate(&PPPProtonAntiElectronNeutrinoRate); - DeleteRawDiffRate(&PPPProtonMuonNeutrinoRate); - DeleteRawDiffRate(&PPPProtonAntiMuonNeutrinoRate); - DeleteRawDiffRate(&PPPNeutronAntiElectronNeutrinoRate); - DeleteRawDiffRate(&PPPNeutronMuonNeutrinoRate); - DeleteRawDiffRate(&PPPNeutronAntiMuonNeutrinoRate); - } - } - if (NPPSwitch == 1) { - if (nucleonToSecondarySwitch == 1) - DeleteRawDiffRate(&NPPDiffRate); - DeleteRawTotalRate(&NPPTotalRate); - } - if (DPPSwitch == 1) - DeleteRawTotalRate(&DPPRate); - - if (neutronDecaySwitch == 1) { - if (nucleonToSecondarySwitch == 1) - DeleteDiffRate(&neutronDecayElectronRate); - DeleteDiffRate(&neutronDecayProtonRate); - DeleteTotalRate(&neutronDecayRate); - } - - - if (neutrinoNeutrinoSwitch == 1) { - DeleteDiffRate(&NNElNeutScatRate); - DeleteDiffRate(&NNElNeutMuonNeutRate); - DeleteDiffRate(&NNElNeutTauNeutRate); - DeleteDiffRate(&NNElNeutElectronRate); - DeleteDiffRate(&NNElNeutPhotonRate); - DeleteDiffRate(&NNElNeutProtonRate); - DeleteDiffRate(&NNMuonNeutElNeutRate); - DeleteDiffRate(&NNMuonNeutScatRate); - DeleteDiffRate(&NNMuonNeutTauNeutRate); - DeleteDiffRate(&NNMuonNeutElectronRate); - DeleteDiffRate(&NNMuonNeutPhotonRate); - DeleteDiffRate(&NNMuonNeutProtonRate); - DeleteDiffRate(&NNTauNeutElNeutRate); - DeleteDiffRate(&NNTauNeutMuonNeutRate); - DeleteDiffRate(&NNTauNeutScatRate); - DeleteDiffRate(&NNTauNeutElectronRate); - DeleteDiffRate(&NNTauNeutPhotonRate); - DeleteDiffRate(&NNTauNeutProtonRate); - - DeleteTotalRate(&NNElNeutTotalRate); - DeleteTotalRate(&NNMuonNeutTotalRate); - DeleteTotalRate(&NNTauNeutTotalRate); - } - - // FinalPrintOutToTheScreen(distance, startingRedshift, propagatingDistance); - - DeleteSpectrum(&Q_0); - DeleteSpectrum(&spectrumNew); - DeleteSpectrum(&derivative); - - Delete_dCVector(&synchrotronLoss); - Delete_dCVector(&continuousLoss); - Delete_dCVector(&otherLoss); - Delete_dCVector(&protonContinuousLoss); - - Delete_dCVector(&deltaG); - Delete_dCVector(&bgEnergy); - Delete_dCVector(&bgEnergyWidth); - Delete_dCVector(&bgPhotonDensity); - - Delete_dCVector(&RedshiftArray) ; - Delete_dCVector(&DistanceArray) ; -clock_t end = clock(); - -clock_t total = end -start; -clock_t comp = end_comp -start_comp; - -#ifdef DEBUG -printf("Dint Comptime: %f\n", float(comp)/float(total)); -#endif -} - -void BuildRedshiftTable(double aH0, double aOmegaM, double aOmegaLambda, - dCVector* pRedshiftArray, dCVector* pDistanceArray) { - - // Routine added Jan 2006 - E.A. - - // aH0 in km/s/Mpc - // C is in cm/s, distances in Mpc - int lNbBins = NBINS_REDSHIFTTABLE ; - double lZmin = ZMIN_REDSHIFTTABLE ; - double lZmax = ZMAX_REDSHIFTTABLE ; - New_dCVector(pRedshiftArray, lNbBins) ; - New_dCVector(pDistanceArray, lNbBins) ; - - pRedshiftArray->vector[0] = 0 ; - for (int i=0; i < lNbBins - 1; i++) { - double kk = i/(lNbBins-2.) ; - pRedshiftArray->vector[i+1] = lZmin*pow(lZmax/lZmin,kk) ; - } - dCVector lpEvolutionFactor ; - New_dCVector(&lpEvolutionFactor, lNbBins) ; - lpEvolutionFactor.vector[0] = 1 ; - pDistanceArray->vector[0] = 0 ; - for (int i=1; i < lNbBins; i++) { - double lZ = pRedshiftArray->vector[i] ; - lpEvolutionFactor.vector[i] = 1./((1.+lZ)*sqrt(aOmegaLambda+aOmegaM*pow(1.+lZ,3))) ; - pDistanceArray->vector[i] = pDistanceArray->vector[i-1]+ - (lZ-pRedshiftArray->vector[i-1])*0.5* - (lpEvolutionFactor.vector[i-1]+lpEvolutionFactor.vector[i])*C/(aH0*1.e5) ; - } - Delete_dCVector(&lpEvolutionFactor) ; - -} - -double getRedshift(dCVector RedshiftArray, dCVector DistanceArray, double distance) { - - // Routine added Jan 2006 - E.A. - - unsigned int i0 = 0 ; - while (DistanceArray.vector[i0+1] <= distance) i0 += 1 ; - double lRedshift = RedshiftArray.vector[i0] + (RedshiftArray.vector[i0+1]-RedshiftArray.vector[i0]) - *(distance-DistanceArray.vector[i0]) - /(DistanceArray.vector[i0+1]-DistanceArray.vector[i0]) ; - if ( distance <= 0 ) lRedshift = 0 ; - - return lRedshift ; -} - -double getDistance(dCVector RedshiftArray, dCVector DistanceArray, double redshift) { - - // Routine added Jan 2006 - E.A. - - unsigned int i0 = 0 ; - while (RedshiftArray.vector[i0+1] <= redshift) i0 += 1 ; - double lDistance = DistanceArray.vector[i0] + (DistanceArray.vector[i0+1]-DistanceArray.vector[i0]) - *(redshift-RedshiftArray.vector[i0]) - /(RedshiftArray.vector[i0+1]-RedshiftArray.vector[i0]) ; - if ( redshift <= 0 ) lDistance = 0 ; - - // At that level lDistance is in Mpc --> we convert it into cm. - lDistance *= 1.e6 ; // in pc - lDistance *= DISTANCE_UNIT ; // in cm - - return lDistance ; -} - diff --git a/libs/dint/src/rate.cpp b/libs/dint/src/rate.cpp deleted file mode 100644 index c62e781db..000000000 --- a/libs/dint/src/rate.cpp +++ /dev/null @@ -1,909 +0,0 @@ -#include -#include "dint/rate.h" -#include "dint/vector.h" -#include "dint/utilities.h" - - -/* this is actually the class constructor for RawTotalRate */ -void NewRawTotalRate(RawTotalRate* pRate, const int num_main_bins, - const int num_bg_bins) -{ - pRate->mainDimension = num_main_bins; - pRate->bgDimension = num_bg_bins; - pRate->totalRate = New_dMatrix(num_main_bins, num_bg_bins); - - InitializeRawTotalRate(pRate); -} - -void DeleteRawTotalRate(RawTotalRate* pRate) -{ - Delete_dMatrix(pRate->totalRate); -} - -void InitializeRawTotalRate(RawTotalRate* pRate) -{ - int i; - int j; - - for (i = 0; i < pRate->mainDimension; i++) - { - for (j = 0; j < pRate->bgDimension; j++) - { - pRate->totalRate[i][j] = 0.; - } - } -} - -void CopyRawTotalRate(RawTotalRate* pLRate, const RawTotalRate* pRRate) -{ - int i; - int j; - - pLRate->mainDimension = pRRate->mainDimension; - pLRate->bgDimension = pRRate->bgDimension; - - Delete_dMatrix(pLRate->totalRate); - - pLRate->totalRate = New_dMatrix(pRRate->mainDimension, - pRRate->bgDimension); - - for (i = 0; i < pRRate->mainDimension; i++) - { - for (j = 0; j < pRRate->bgDimension; j++) - { - pLRate->totalRate[i][j] = pRRate->totalRate[i][j]; - } - } - /* deep copy */ -} - -void ClipRawTotalRate(RawTotalRate* pRate, const int newSize) -{ - int i; - int j; - int clip; - RawTotalRate tempRate; - - printf("Clipping RawTotalRate. From %5i... ", pRate->mainDimension); - /* let user know */ - - clip = pRate->mainDimension - newSize; - NewRawTotalRate(&tempRate, newSize, pRate->bgDimension); - - for (i = 0; i < newSize; i++) - { - int iOld = i + clip; - for (j = 0; j < pRate->bgDimension; j++) - { -#ifdef DEBUG - CheckIndex(0, pRate->mainDimension, iOld, "ClipRawTotalRate"); -#endif - tempRate.totalRate[i][j] = pRate->totalRate[iOld][j]; - } - } - - CopyRawTotalRate(pRate, &tempRate); - DeleteRawTotalRate(&tempRate); - - printf("to %5i.\n", pRate->mainDimension); -} - -void EnlargeRawTotalRate(RawTotalRate* pRate, const int newSize) -{ - int i; - int j; - RawTotalRate tempRate; - int numAddedCells; - - - numAddedCells = newSize - pRate->mainDimension; - NewRawTotalRate(&tempRate, newSize, pRate->bgDimension); - - for (i = 0; i < newSize; i++) - { - int iOld = i - numAddedCells; - for (j = 0; j < pRate->bgDimension; j++) - { - if (iOld >= 0) /* range where original matrix is */ - { -#ifdef DEBUG - CheckIndex(0, pRate->mainDimension, iOld, - "EnlargeRawTotalRate"); -#endif - tempRate.totalRate[i][j] = pRate->totalRate[iOld][j]; - } - else /* enlarged area is filled with 0 for convenience */ - { - tempRate.totalRate[i][j] = 0.; - } - } - } - - CopyRawTotalRate(pRate, &tempRate); - DeleteRawTotalRate(&tempRate); -} - -void ModifyRawTotalRate(RawTotalRate* pRate, const int newSize) -{ - if (pRate->mainDimension > newSize) - { - ClipRawTotalRate(pRate, newSize); - } - else if (pRate->mainDimension < newSize) - { - EnlargeRawTotalRate(pRate, newSize); - } - else - { - /* do nothing */ - } -} - -void ReadRawTotalRate(RawTotalRate* pRate, const char* filename) -{ - FILE* file; - - file = SafeFOpen(filename, "r"); - binfread((pRate->totalRate)[0], sizeof(double), (pRate->mainDimension)* - (pRate->bgDimension), file); - fclose(file); -} - - - -/* this is actually the class constructor for RawDiffRate */ -void NewRawDiffRate(RawDiffRate* pRate, const int num_main_bins, - const int num_bg_bins, const int num_elements) -{ - pRate->mainDimension = num_main_bins; - pRate->bgDimension = num_bg_bins; - pRate->numberOfElements = num_elements; - pRate->bound = New_i3Tensor(num_main_bins, num_bg_bins, 2); - pRate->diffRate = New_dVector(num_elements); - - InitializeRawDiffRate(pRate); -} - -void DeleteRawDiffRate(RawDiffRate* pRate) -{ - Delete_dVector(pRate->diffRate); - Delete_i3Tensor(pRate->bound); -} - -void InitializeRawDiffRate(RawDiffRate* pRate) -{ - int i; - int j; - - for (i = 0; i < pRate->mainDimension; i++) - { - for (j = 0; j < pRate->bgDimension; j++) - { - pRate->bound[i][j][0] = -1; - pRate->bound[i][j][1] = -1; - } - } - /* note how the bounds are invalidated */ - - for (i = 0; i < pRate->numberOfElements; i++) - { - pRate->diffRate[i] = 0.; - } -} - -void CheckRawDiffRate(RawDiffRate* pRate) -{ - int i; - int j; - int counter; - - for (counter = 0, i = 0; i < pRate->mainDimension; i++) - { - for (j = 0; j < pRate->bgDimension; j++) - { - if (pRate->bound[i][j][0] != -1) - { - counter += pRate->bound[i][j][1] - pRate->bound[i][j][0] + 1; - } - } - } - - if (counter != pRate->numberOfElements) - { - Error("CheckRawDiffRate: inconsistent rate", PROGRAM_ERROR); - } -} - -#ifdef DEBUG -double RawDiffRateElement(const RawDiffRate* pRate, const int i, const int j, - const int k) -{ - int n; - int p; - int offset; - - - if ((i < 0) || (j < 0) || (i >= pRate->mainDimension) || - (j >= pRate->bgDimension)) - { - printf("i: %3i, j: %3i\n", i, j); - Error("RawDiffRateElement: i or j out of bounds", PROGRAM_ERROR); - } - if ((pRate->bound)[i][j][0] == -1) /* out of range */ - { - printf("i: %3i, j: %3i\n", i, j); - Error("RawDiffRateElement: i or j out of range", PROGRAM_ERROR); - } - else - { - if ((k < (pRate->bound)[i][j][0]) || (k > (pRate->bound)[i][j][1])) - { - printf("i, j, k: %3i %3i %3i\n", k); - Error("RawDiffRateElement: k out of range", PROGRAM_ERROR); - } - } - - offset = 0; - for (n = 0; n < i; n++) - { - for (p = 0; p < pRate->bgDimension; p++) - { - if ((pRate->bound)[n][p][0] != -1) - { - offset += ((pRate->bound)[n][p][1] - (pRate->bound)[n][p][0] + - 1); - } - } - } - for (p = 0; p < j; p++) - { - offset += ((pRate->bound)[i][p][1] - (pRate->bound)[i][p][0] + 1); - } - offset += -(pRate->bound)[i][j][0] + k; - if (offset >= pRate->numberOfElements || offset < 0) - { - printf("offset: %7i, number of elements: %7i\n", offset, - pRate->numberOfElements); - Error("RawDiffRateElement: main index out of range", PROGRAM_ERROR); - } - - return (pRate->diffRate)[offset]; -} -#endif - -void CopyRawDiffRate(RawDiffRate* pLRate, const RawDiffRate* pRRate) -{ - int i; - int j; - - pLRate->mainDimension = pRRate->mainDimension; - pLRate->bgDimension = pRRate->bgDimension; - pLRate->numberOfElements = pRRate->numberOfElements; - - Delete_dVector(pLRate->diffRate); - Delete_i3Tensor(pLRate->bound); - - pLRate->bound = New_i3Tensor(pRRate->mainDimension, pRRate->bgDimension, - 2); - pLRate->diffRate = New_dVector(pRRate->numberOfElements); - - for (i = 0; i < pRRate->mainDimension; i++) - { - for (j = 0; j < pRRate->bgDimension; j++) - { - pLRate->bound[i][j][0] = pRRate->bound[i][j][0]; - pLRate->bound[i][j][1] = pRRate->bound[i][j][1]; - } - } - for (i = 0; i < pRRate->numberOfElements; i++) - { - pLRate->diffRate[i] = pRRate->diffRate[i]; - } -} - -void CopyRawDiffRateBound(RawDiffRate* pLRate, const RawDiffRate* pRRate) -{ - int i; - int j; - - if ((pLRate->mainDimension != pRRate->mainDimension) || - (pLRate->bgDimension != pRRate->bgDimension) || - (pLRate->numberOfElements != pRRate->numberOfElements)) - { - Error("CopyRawDiffRateBound: inconsistent dimensions", PROGRAM_ERROR); - } - - for (i = 0; i < pLRate->mainDimension; i++) - { - for (j = 0; j < pLRate->bgDimension; j++) - { - pLRate->bound[i][j][0] = pRRate->bound[i][j][0]; - pLRate->bound[i][j][1] = pRRate->bound[i][j][1]; - } - } -} - -void ClipRawDiffRate(RawDiffRate* pRate, const int newSize) -{ - int clip; - int newNumberOfElements; - RawDiffRate tempRate; - int i; - int j; - int k; - int counter; - int newCounter; - - - printf("Clipping RawDiffRate. From %8i... ", pRate->numberOfElements); - - clip = pRate->mainDimension - newSize; - - for (newNumberOfElements = 0, i = clip; i < pRate->mainDimension; i++) - { - for (j = 0; j < pRate->bgDimension; j++) - { - if ((pRate->bound[i][j][0] != -1) && - (pRate->bound[i][j][1] >= clip)) - /* not empty AND within range */ - { - int newLowerBound; - newLowerBound = IMax(pRate->bound[i][j][0], clip); - /* new lower bound cannot be smaller than the lower clip */ - newNumberOfElements += pRate->bound[i][j][1] - - newLowerBound + 1; - } - } - } - /* determine new number of elements */ - - NewRawDiffRate(&tempRate, newSize, pRate->bgDimension, - newNumberOfElements); - - for (i = 0; i < newSize; i++) - { - int iOld = i + clip; /* (old) index for old rate */ - for (j = 0; j < pRate->bgDimension; j++) - { -#ifdef DEBUG - CheckIndex(0, pRate->mainDimension, iOld, "ClipRawDiffRate"); -#endif - if ((pRate->bound[iOld][j][0] != -1) && - (pRate->bound[iOld][j][1] >= clip)) - { - tempRate.bound[i][j][0] = - IMax(pRate->bound[iOld][j][0], clip) - clip; - tempRate.bound[i][j][1] = - pRate->bound[iOld][j][1] - clip; - } - else - { - tempRate.bound[i][j][0] = -1; - tempRate.bound[i][j][1] = -1; - } - } - } - /* set the bounds */ - - /* fast-forward the index */ - for (counter = 0, newCounter = 0, i = 0; i < pRate->mainDimension; i++) - { - int iNew = i - clip; /* (new) index for new rate */ - for (j = 0; j < pRate->bgDimension; j++) - { - if (pRate->bound[i][j][0] != -1) - { - for (k = pRate->bound[i][j][0]; - k <= pRate->bound[i][j][1]; k++, counter++) - { - int kNew = k - clip; /* (new) k index */ - -#ifdef DEBUG - CheckIndex(0, pRate->numberOfElements, counter, - "ClipRawDiffRate"); -#endif - /* i must be within clips */ - if (i >= clip) - { - /* its own bound must not be empty && - k must be within range: - comparison w/ upper bound is not necessary - because it is automatically satisfied */ -#ifdef DEBUG - CheckIndex(0, tempRate.mainDimension, iNew, - "ClipRawDiffRate"); -#endif - if ((tempRate.bound[iNew][j][0] != -1) && - (kNew >= tempRate.bound[iNew][j][0])) - { -#ifdef DEBUG - CheckIndex(0, tempRate.numberOfElements, - newCounter, "ClipRawDiffRate"); -#endif - tempRate.diffRate[newCounter] = - pRate->diffRate[counter]; - newCounter++; - } - } - } - } - } - } - if ((counter != pRate->numberOfElements) || - (newCounter != tempRate.numberOfElements)) - { - Error("ClipRawDiffRate: counting does not match", PROGRAM_ERROR); - } - /* redundant checking, but comes cheap so why not */ - - CopyRawDiffRate(pRate, &tempRate); - /* this is where real copy takes place */ - DeleteRawDiffRate(&tempRate); - - printf("to %8i.\n", pRate->numberOfElements); -} - -void EnlargeRawDiffRate(RawDiffRate* pRate, const int newSize) -{ - int i; - int j; - int numAddedCells; - RawDiffRate tempRate; - - numAddedCells = newSize - pRate->mainDimension; - - NewRawDiffRate(&tempRate, newSize, pRate->bgDimension, - pRate->numberOfElements); - - for (i = 0; i < newSize; i++) - { - int iOld = i - numAddedCells; - for (j = 0; j < pRate->bgDimension; j++) - { - if (iOld >= 0) /* area where the original tensor is */ - { - if (pRate->bound[iOld][j][0] != -1) - { -#ifdef DEBUG - CheckIndex(0, pRate->mainDimension, iOld, - "EnlargeRawDiffRate"); -#endif - tempRate.bound[i][j][0] = pRate->bound[iOld][j][0] + - numAddedCells; - tempRate.bound[i][j][1] = pRate->bound[iOld][j][1] + - numAddedCells; - } - else - { - tempRate.bound[i][j][0] = -1; - tempRate.bound[i][j][1] = -1; - } - } - else /* outside the original tensor */ - { - tempRate.bound[i][j][0] = -1; - tempRate.bound[i][j][1] = -1; - } - } - } - - for (i = 0; i < pRate->numberOfElements; i++) - { - tempRate.diffRate[i] = pRate->diffRate[i]; - /* the rate itself does not change */ - } - - CopyRawDiffRate(pRate, &tempRate); - DeleteRawDiffRate(&tempRate); -} - -void ModifyRawDiffRate(RawDiffRate* pRate, const int newSize) -{ - if (pRate->mainDimension > newSize) - { - ClipRawDiffRate(pRate, newSize); - } - else if (pRate->mainDimension < newSize) - { - EnlargeRawDiffRate(pRate, newSize); - } - else - { - /* do nothing */ - } -} - -void ReadRawDiffRate(RawDiffRate* pRate, const char* filename) -{ - FILE* file; - - file = SafeFOpen(filename, "r"); - binfread((pRate->bound)[0][0], sizeof(int), (pRate->mainDimension)* - (pRate->bgDimension)*2, file); - binfread(pRate->diffRate, sizeof(double), pRate->numberOfElements, file); - fclose(file); - - CheckRawDiffRate(pRate); -} - - - -void NewTotalRate(TotalRate* pRate, const int num_main_bins) -{ - pRate->mainDimension = num_main_bins; - pRate->totalRate = New_dVector(num_main_bins); - - InitializeTotalRate(pRate); -} - -void DeleteTotalRate(TotalRate* pRate) -{ - Delete_dVector(pRate->totalRate); -} - -void InitializeTotalRate(TotalRate* pRate) -{ - int i; - - for (i = 0; i < pRate->mainDimension; i++) - { - pRate->totalRate[i] = 0.; - } -} - -void CopyTotalRate(TotalRate* pLRate, const TotalRate* pRRate) -{ - int i; - - pLRate->mainDimension = pRRate->mainDimension; - - Delete_dVector(pLRate->totalRate); - pLRate->totalRate = New_dVector(pRRate->mainDimension); - - for (i = 0; i < pRRate->mainDimension; i++) - { - pLRate->totalRate[i] = pRRate->totalRate[i]; - } -} - -void ClipTotalRate(TotalRate* pRate, const int newSize) -{ - int i; - int clip; - TotalRate tempRate; - - - printf("Clipping TotalRate. From %5i... ", pRate->mainDimension); - /* let user know */ - - clip = pRate->mainDimension - newSize; - NewTotalRate(&tempRate, newSize); - - for (i = 0; i < newSize; i++) - { - int iOld = i + clip; -#ifdef DEBUG - CheckIndex(0, pRate->mainDimension, iOld, "ClipTotalRate"); -#endif - tempRate.totalRate[i] = pRate->totalRate[iOld]; - } - - CopyTotalRate(pRate, &tempRate); - DeleteTotalRate(&tempRate); - - printf("to %5i.\n", pRate->mainDimension); -} - -void EnlargeTotalRate(TotalRate* pRate, const int newSize) -{ - int i; - int numAddedCells; - TotalRate tempRate; - - numAddedCells = newSize - pRate->mainDimension; - - NewTotalRate(&tempRate, newSize); - - for (i = 0; i < newSize; i++) - { - int iOld = i - numAddedCells; - if (iOld >= 0) - { -#ifdef DEBUG - CheckIndex(0, pRate->mainDimension, iOld, "EnlargeTotalRate"); -#endif - tempRate.totalRate[i] = pRate->totalRate[iOld]; - } - else - { - tempRate.totalRate[i] = 0.; - } - } - - CopyTotalRate(pRate, &tempRate); - DeleteTotalRate(&tempRate); -} - -void ModifyTotalRate(TotalRate* pRate, const int newSize) -{ - if (pRate->mainDimension > newSize) - { - ClipTotalRate(pRate, newSize); - } - else if (pRate->mainDimension < newSize) - { - EnlargeTotalRate(pRate, newSize); - } - else - { - /* do nothing */ - } -} - -void ReadTotalRate(TotalRate* pRate, const char* filename) -{ - FILE* file; - - file = SafeFOpen(filename, "r"); - binfread(pRate->totalRate, sizeof(double), (pRate->mainDimension), file); - fclose(file); -} - - - -void NewDiffRate(DiffRate* pRate, const int num_main_bins) -{ - pRate->mainDimension = num_main_bins; - pRate->bound = New_iMatrix(num_main_bins, 2); - pRate->diffRate = New_dMatrix(num_main_bins, num_main_bins); - - InitializeDiffRate(pRate); -} - - -void DeleteDiffRate(DiffRate* pRate) -{ - Delete_dMatrix(pRate->diffRate); - Delete_iMatrix(pRate->bound); -} - - -void InitializeDiffRate(DiffRate* pRate) -{ - int i; - int j; - - for (i = 0; i < pRate->mainDimension; i++) - { - pRate->bound[i][0] = pRate->mainDimension - 1; - pRate->bound[i][1] = 0; - /* note that the invalidation here is different from RawDiffRate */ - for (j = 0; j < pRate->mainDimension; j++) - { - pRate->diffRate[i][j] = 0.; - } - } -} - -void CopyDiffRate(DiffRate* pLRate, const DiffRate* pRRate) -{ - int i; - int j; - - pLRate->mainDimension = pRRate->mainDimension; - - Delete_dMatrix(pLRate->diffRate); - Delete_iMatrix(pLRate->bound); - - pLRate->bound = New_iMatrix(pRRate->mainDimension, 2); - pLRate->diffRate = New_dMatrix(pRRate->mainDimension, - pRRate->mainDimension); - - for (i = 0; i < pRRate->mainDimension; i++) - { - pLRate->bound[i][0] = pRRate->bound[i][0]; - pLRate->bound[i][1] = pRRate->bound[i][1]; - for (j = 0; j < pRRate->mainDimension; j++) - { - pLRate->diffRate[i][j] = pRRate->diffRate[i][j]; - } - } -} - -void CopyDiffRateBound(DiffRate* pLRate, const DiffRate* pRRate) -{ - int i; - - if (pLRate->mainDimension != pRRate->mainDimension) - { - Error("CopyDiffRateBound: inconsistent dimensions", PROGRAM_ERROR); - } - - for (i = 0; i < pLRate->mainDimension; i++) - { - pLRate->bound[i][0] = pRRate->bound[i][0]; - pLRate->bound[i][1] = pRRate->bound[i][1]; - } -} - -void SetStandardDiffRateBound(DiffRate* pRate) -{ - int i; - - InvalidateDiffRateBound(pRate); - - for (i = 0; i < pRate->mainDimension; i++) - { - if ((pRate->bound[i][0] != pRate->mainDimension - 1) || - (pRate->bound[i][1] != 0)) - { - pRate->bound[i][0] = 0; - pRate->bound[i][1] = i; - } - } -} - -void ClipDiffRate(DiffRate* pRate, const int newSize) -{ - int clip; - DiffRate tempRate; - int i; - int j; - - printf("Clipping DiffRate. From %5i... ", pRate->mainDimension); - - clip = pRate->mainDimension - newSize; - - NewDiffRate(&tempRate, newSize); - - for (i = 0; i < newSize; i++) - { - int iOld = i + clip; /* (old) index for old rate */ - -#ifdef DEBUG - CheckIndex(0, pRate->mainDimension, iOld, "ClipDiffRate"); -#endif - if ((pRate->bound[iOld][0] != pRate->mainDimension - 1) || - (pRate->bound[iOld][1] != 0)) - /* bound is valid */ - { - if (pRate->bound[iOld][1] >= clip) - { - tempRate.bound[i][0] = IMax(pRate->bound[iOld][0], clip) - - clip; - tempRate.bound[i][1] = pRate->bound[iOld][1] - clip; - } - else - { - tempRate.bound[i][0] = newSize - 1; - tempRate.bound[i][1] = 0; - } - } - else /* bound is invalid to begin with */ - { - tempRate.bound[i][0] = newSize - 1; - tempRate.bound[i][1] = 0; - } - - for (j = 0; j < newSize; j++) - { - int jOld = j + clip; /* (old) j-index */ - -#ifdef DEBUG - CheckIndex(0, pRate->mainDimension, jOld, "ClipDiffRate"); -#endif - tempRate.diffRate[i][j] = pRate->diffRate[iOld][jOld]; - } - } - - CopyDiffRate(pRate, &tempRate); - DeleteDiffRate(&tempRate); - - printf("to %5i.\n", pRate->mainDimension); -} - -void EnlargeDiffRate(DiffRate* pRate, const int newSize) -{ - int i; - int j; - int numAddedCells; - DiffRate tempRate; - - numAddedCells = newSize - pRate->mainDimension; - - NewDiffRate(&tempRate, newSize); - - for (i = 0; i < newSize; i++) - { - int iOld = i - numAddedCells; - if (iOld >= 0) - { -#ifdef DEBUG - CheckIndex(0, pRate->mainDimension, iOld, "EnlargeDiffRate"); -#endif - if ((pRate->bound[iOld][0] != pRate->mainDimension - 1) || - (pRate->bound[iOld][1] != 0)) - /* old bound is valid */ - { - tempRate.bound[i][0] = pRate->bound[iOld][0] + numAddedCells; - tempRate.bound[i][1] = pRate->bound[iOld][1] + numAddedCells; - } - else /* old bound is invalild */ - { - tempRate.bound[i][0] = newSize - 1; - tempRate.bound[i][1] = 0; - } - } - else - { - tempRate.bound[i][0] = newSize - 1; - tempRate.bound[i][1] = 0; - } - - for (j = 0; j < newSize; j++) - { - int jOld = j - numAddedCells; - if (iOld >= 0 && jOld >= 0) - { -#ifdef DEBUG - CheckIndex(0, pRate->mainDimension, jOld, "EnlargeDiffRate"); -#endif - tempRate.diffRate[i][j] = pRate->diffRate[iOld][jOld]; - } - else - { - tempRate.diffRate[i][j] = 0.; - } - } - } - - CopyDiffRate(pRate, &tempRate); - DeleteDiffRate(&tempRate); -} - -void ModifyDiffRate(DiffRate* pRate, const int newSize) -{ - if (pRate->mainDimension > newSize) - { - ClipDiffRate(pRate, newSize); - } - else if (pRate->mainDimension < newSize) - { - EnlargeDiffRate(pRate, newSize); - } - else - { - /* do nothing */ - } -} - -void ReadDiffRate(DiffRate* pRate, const char* filename) -{ - FILE* file; - - file = SafeFOpen(filename, "r"); - binfread((pRate->bound)[0], sizeof(int), (pRate->mainDimension)*2, file); - binfread((pRate->diffRate)[0], sizeof(double), (pRate->mainDimension)* - (pRate->mainDimension), file); - fclose(file); - - InvalidateDiffRateBound(pRate); - /* make sure invalid bounds are properly invalidated */ -} - -void InvalidateDiffRateBound(DiffRate* pRate) -{ - int i; - - for (i = 0; i < pRate->mainDimension; i++) - { - if ((pRate->bound[i][0] == -1) || ((pRate->bound[i][0] == - pRate->mainDimension - 1) && (pRate->bound[i][0] == 0))) - /* picks up invalid bound data however they are formatted */ - { - pRate->bound[i][0] = pRate->mainDimension - 1; - pRate->bound[i][1] = 0; - } - } -} - diff --git a/libs/dint/src/spectrum.cpp b/libs/dint/src/spectrum.cpp deleted file mode 100644 index b01801762..000000000 --- a/libs/dint/src/spectrum.cpp +++ /dev/null @@ -1,212 +0,0 @@ -#include -#include -#include "dint/spectrum.h" -#include "dint/vector.h" -#include "dint/cvector.h" -#include "dint/const.h" -#include "dint/utilities.h" - - -void NewSpectrum(Spectrum* pSpectrum, const int num_bins) { - pSpectrum->numberOfMainBins = num_bins; - pSpectrum->spectrum = New_dMatrix(NUM_SPECIES, num_bins); - - InitializeSpectrum(pSpectrum); // always initialize! -} - -void DeleteSpectrum(Spectrum* pSpectrum) { - Delete_dMatrix(pSpectrum->spectrum); -} - -void InitializeSpectrum(Spectrum* pSpectrum) { - for (int i=0; inumberOfMainBins; j++) - pSpectrum->spectrum[i][j] = 0.; - } -} - -void InitializeEMSpectrum(Spectrum* pSpectrum) { - for (int i=0; i<3; i++) { - for (int j=0; jnumberOfMainBins; j++) - pSpectrum->spectrum[i][j] = 0.; - } -} - -void InitializeNucleonSpectrum(Spectrum* pSpectrum) { - for (int i=3; i<5; i++) { - for (int j=0; jnumberOfMainBins; j++) - pSpectrum->spectrum[i][j] = 0.; - } -} - -void InitializeNeutrinoSpectrum(Spectrum* pSpectrum) { - for (int i=5; inumberOfMainBins; j++) - pSpectrum->spectrum[i][j] = 0.; - } -} - -void AddSpectrum(Spectrum *a, const Spectrum *b) { - for (int i = 0; i < NUM_SPECIES; i++) { - for (int j = 0; j < a->numberOfMainBins; j++) - a->spectrum[i][j] += b->spectrum[i][j]; - } -} - -void SetSpectrum(Spectrum* pSpectrum1, const Spectrum* pSpectrum2) { - if (pSpectrum1->numberOfMainBins != pSpectrum2->numberOfMainBins) - Error("SetSpectrum: inconsistent dimensions", PROGRAM_ERROR); - - for (int i=0; inumberOfMainBins; j++) - pSpectrum1->spectrum[i][j] = pSpectrum2->spectrum[i][j]; - } -} - -void SetEMSpectrum(Spectrum* pSpectrum1, const Spectrum* pSpectrum2) { - if (pSpectrum1->numberOfMainBins != pSpectrum2->numberOfMainBins) - Error("SetEMSpectrum: inconsistent dimension", PROGRAM_ERROR); - - for (int i=0; i<3; i++) { - for (int j=0; jnumberOfMainBins; j++) - pSpectrum1->spectrum[i][j] = pSpectrum2->spectrum[i][j]; - } -} - -void SetNucleonSpectrum(Spectrum* pSpectrum1, const Spectrum* pSpectrum2) { - if (pSpectrum1->numberOfMainBins != pSpectrum2->numberOfMainBins) - Error("SetSpectrum: inconsistent dimension", PROGRAM_ERROR); - - for (int i=3; i<5; i++) { - for (int j=0; jnumberOfMainBins; j++) - pSpectrum1->spectrum[i][j] = pSpectrum2->spectrum[i][j]; - } -} - -void SetNeutrinoSpectrum(Spectrum* pSpectrum1, const Spectrum* pSpectrum2) { - if (pSpectrum1->numberOfMainBins != pSpectrum2->numberOfMainBins) - Error("SetSpectrum: inconsistent dimension", PROGRAM_ERROR); - - for (int i=5; inumberOfMainBins; j++) - pSpectrum1->spectrum[i][j] = pSpectrum2->spectrum[i][j]; - } -} - -double GetNumber(const Spectrum* pSpectrum) { - double number = 0.; - - for (int i=0; inumberOfMainBins; j++) - number += pSpectrum->spectrum[i][j]; - } - return number; -} - -double GetEMNumber(const Spectrum* pSpectrum) { - double number = 0.; - - for (int i=0; i<3; i++) { - for (int j=0; jnumberOfMainBins; j++) - number += pSpectrum->spectrum[i][j]; - } - return number; -} - -double GetNucleonNumber(const Spectrum* pSpectrum) { - double number = 0.; - - for (int i=3; i<5; i++) { - for (int j=0; jnumberOfMainBins; j++) - number += pSpectrum->spectrum[i][j]; - } - return number; -} - -double GetNeutrinoNumber(const Spectrum* pSpectrum) { - double number = 0.; - - for (int i=5; inumberOfMainBins; j++) - number += pSpectrum->spectrum[i][j]; - } - return number; -} - -double GetEnergy(const Spectrum* pSpectrum, const dCVector* pEnergy) { - double totalEnergy = 0.; - - if (pSpectrum->numberOfMainBins != pEnergy->dimension) - Error("GetEnergy: inconsistent dimensions", PROGRAM_ERROR); - - for (int i=0; inumberOfMainBins; j++) - totalEnergy += (pSpectrum->spectrum)[i][j]*(pEnergy->vector)[j]; - } - return totalEnergy; -} - -double GetEMEnergy(const Spectrum* pSpectrum, const dCVector* pEnergy) { - double totalEnergy = 0.; - - if (pSpectrum->numberOfMainBins != pEnergy->dimension) - Error("GetEnergy: inconsistent dimensions", PROGRAM_ERROR); - - for (int i=0; i<3; i++) { - for (int j=0; jnumberOfMainBins; j++) - totalEnergy += (pSpectrum->spectrum)[i][j]*(pEnergy->vector)[j]; - } - return totalEnergy; -} - -double GetNucleonEnergy(const Spectrum* pSpectrum, const dCVector* pEnergy) { - double totalEnergy = 0.; - - if (pSpectrum->numberOfMainBins != pEnergy->dimension) - Error("GetEnergy: inconsistent dimensions", PROGRAM_ERROR); - - for (int i=3; i<5; i++) { - for (int j=0; jnumberOfMainBins; j++) - totalEnergy += (pSpectrum->spectrum)[i][j]*(pEnergy->vector)[j]; - } - return totalEnergy; -} - -double GetNeutrinoEnergy(const Spectrum* pSpectrum, const dCVector* pEnergy) { - double totalEnergy = 0.; - - if (pSpectrum->numberOfMainBins != pEnergy->dimension) - Error("GetEnergy: inconsistent dimensions", PROGRAM_ERROR); - - for (int i=5; inumberOfMainBins; j++) - totalEnergy += (pSpectrum->spectrum)[i][j]*(pEnergy->vector)[j]; - } - return totalEnergy; -} - -void DumpSpectrum(const dCVector* pEnergy, const dCVector* pEnergyWidth, - const Spectrum* pSpectrum, const char* filename) { - FILE* dumpFile; - char f1[80] = "datafiles/"; - - if ((pEnergy->dimension != pEnergyWidth->dimension) || - (pEnergyWidth->dimension != pSpectrum->numberOfMainBins)) - Error("DumpSpectrum: inconsistent dimensions", PROGRAM_ERROR); - - strncat(f1, filename, 79 - strlen(filename)); - dumpFile = SafeFOpen(f1, "w"); - // this is to send the dump file to a different directory (datafiles) - // by Guenter (7/20/1998) - - for (int i=0; inumberOfMainBins; j++) { - fprintf(dumpFile, "%15.4E %15.4E\n", - ELECTRON_MASS*(pEnergy->vector)[j], - (pSpectrum->spectrum)[i][j]/(pEnergyWidth->vector)[j]* - (pEnergy->vector)[j]*(pEnergy->vector)[j]); - // proper unit conversion for energy - } - } - fclose(dumpFile); -} diff --git a/libs/dint/src/sync.cpp b/libs/dint/src/sync.cpp deleted file mode 100644 index 72a74699b..000000000 --- a/libs/dint/src/sync.cpp +++ /dev/null @@ -1,128 +0,0 @@ - -#include "dint/sync.h" - -void LoadSyncTable(dCVector* syncTable, string aDirTables) -{ - FILE* syncData; - double temporary; - int i; - - syncData = SafeFOpen((aDirTables+"/syncTable.dat").c_str(), "r"); - for (i = 0; i < syncTable->dimension; i++) { - fscanf(syncData, "%lf %lf", &temporary, &((syncTable->vector)[i])); - } - fclose(syncData) ; // added June 2005 - E.A. - -} - - -void InitializeSynchrotron(const double B_0, const dCVector* pEnergy, - const dCVector* pEnergyWidth, - dCVector* synchrotronLoss, DiffRate* syncRate, - string aDirTables) -/* this function calculates the synchrotron loss rate for the electron - and the synchrotron radiation spectrum for photons - The radom direction of the magnetic field requires me to do an - average over the pitch angle, and it results in an extra factor of - 2/3, and slightly modifies the functional form of F(x) from the - purely perpendicular case */ -/* The above comment is from the stand alone version. Compared to this version the constants seem to be fixed to correct for a perpendicular field as input. JK, 2011*/ -{ - const int SYNC_TABLE_SIZE = 161; - int i; - double offset; /* parameter to compute bounds correctly */ - dCVector syncTable; - double x0; - - double ECrit; - double EMin; - double EMax; - int jMin; - int jMax; - int j; - double xx; - double function; - int iTable; - double eLower; - double eUpper; - int num_main_bins; - - num_main_bins = pEnergy->dimension; - - if ((num_main_bins != pEnergyWidth->dimension) || - (num_main_bins != syncRate->mainDimension) || - (num_main_bins != synchrotronLoss->dimension)) - { - Error("InitializeSynchrotron: inconsistent dimensions", PROGRAM_ERROR); - } - - New_dCVector(&syncTable, SYNC_TABLE_SIZE); - - /* read in table */ - - LoadSyncTable(&syncTable, aDirTables); - - /* calculate the rates */ - offset = BINS_PER_DECADE*(log10(ELECTRON_MASS) - MAX_ENERGY_EXP) + - num_main_bins + 0.5; - x0 = B_0*5.86667629e-4*DISTANCE_UNIT; - /* x0: eB/m_e in inverse pc */ - - for (i = 0; i < num_main_bins; i++) - { - /* electron loss rate */ - (synchrotronLoss->vector)[i] = -B_0*B_0*(pEnergy->vector)[i]* - (pEnergy->vector)[i]*2.*4.86037e4*VOLUME_UNIT; - - /* calculate the radiation spectrum */ - ECrit = 3./2.*B_0/4.414034e13*(pEnergy->vector)[i]* - (pEnergy->vector)[i]; - /* ECrit: critical energy in electron mass */ - - EMin = 2./3./((pEnergy->vector)[i]*(pEnergy->vector)[i]* - (pEnergy->vector)[i])*ECrit; - EMax = 5.*ECrit; - /* EMin/EMax: useful range for x (in electron mass) */ - - /* set up the range for photons -> determine bounds */ - jMin = IMax((int)(BINS_PER_DECADE*log10(EMin) + offset), 0); - jMax = IMin((int)(BINS_PER_DECADE*log10(EMax) + offset), - num_main_bins - 1); - if (jMax >= 0) /* normal case */ - { - (syncRate->bound)[i][0] = jMin; - (syncRate->bound)[i][1] = jMax; - - for (j = (syncRate->bound)[i][0]; - j <= (syncRate->bound)[i][1]; j++) - { - xx = (pEnergy->vector)[j]/ECrit; - - if (log10(xx) < -7.) - { - function = pow(xx, 1./3.)*2.1809736; - /* use an approximation for x below 10^-7 */ - } - else - { - /* compute F(x) at given photon energy by linear - extrapolation in logarithm */ - iTable = (int)(log10(xx)*20. + 140); - eLower = (double)(iTable - 140)/20.; - eUpper = (double)(iTable - 139)/20.; - /* numbers 140, 139, and 20 are properties of table */ - function = exp(log(syncTable.vector[iTable]) + (log10(xx) - - eLower)/(eUpper - eLower)* - (log(syncTable.vector[iTable+1]) - - log(syncTable.vector[iTable]))); - } - (syncRate->diffRate)[i][j] = 2.756644477e-1/137.036*x0* - function/(pEnergy->vector)[j]*(pEnergyWidth->vector)[j]; - /* 2.7566...: sqtr(3)/(2pi), 1/137: e^2, x0: eB/m_e */ - } - } - } - - Delete_dCVector(&syncTable) ; - -} diff --git a/libs/dint/src/vector.cpp b/libs/dint/src/vector.cpp deleted file mode 100644 index 58e9700d4..000000000 --- a/libs/dint/src/vector.cpp +++ /dev/null @@ -1,224 +0,0 @@ - -#include -#include - -#include "dint/vector.h" -#include "dint/error.h" - - -dVector New_dVector(const int n) -{ - dVector vector; - - vector = (double*)malloc((size_t)(n*sizeof(double))); - if (vector == NULL) - { - Error("New_dVector: allocation failure", ARRAY_ERROR); - } - - return vector; -} - -iVector New_iVector(const int n) -{ - iVector vector; - - vector = (int*)malloc((size_t)(n*sizeof(int))); - if (vector == NULL) - { - Error("New_iVector: allocation failure", ARRAY_ERROR); - } - - return vector; -} - - -dMatrix New_dMatrix(const int n1, const int n2) -{ - int i; - dMatrix matrix; - - matrix = (double**)malloc((size_t)(n1*sizeof(double*))); - if (matrix == NULL) - { - Error("New_dMatrix: allocation failure level 1", ARRAY_ERROR); - } - - matrix[0] = (double*)malloc((size_t)(n1*n2*sizeof(double))); - if (matrix[0] == NULL) - { - Error("New_dMatrix: allocation failure level 2", ARRAY_ERROR); - } - - for (i = 1; i < n1; i++) - { - matrix[i] = matrix[i-1] + n2; - } - - return matrix; -} - - -iMatrix New_iMatrix(const int n1, const int n2) -{ - int i; - iMatrix matrix; - - matrix = (int**)malloc((size_t)(n1*sizeof(int*))); - if (matrix == NULL) - { - Error("New_iMatrix: allocation failure level 1", ARRAY_ERROR); - } - - matrix[0] = (int*)malloc((size_t)(n1*n2*sizeof(int))); - if (matrix[0] == NULL) - { - Error("New_iMatrix: allocation failure level 2", ARRAY_ERROR); - } - - for (i = 1; i < n1; i++) - { - matrix[i] = matrix[i-1] + n2; - } - - return matrix; -} - - -d3Tensor New_d3Tensor(const int n1, const int n2, const int n3) -{ - int i; - int j; - d3Tensor tensor; - - tensor = (double***)malloc((size_t)(n1*sizeof(double**))); - if (tensor == NULL) - { - Error("d3Tensor: allocation failure level 1", ARRAY_ERROR); - } - - tensor[0] = (double**)malloc((size_t)(n1*n2*sizeof(double*))); - if (tensor[0] == NULL) - { - Error("d3Tensor: allocation failure level 2", ARRAY_ERROR); - } - - tensor[0][0] = (double*)malloc((size_t)(n1*n2*n3*sizeof(double))); - if (tensor[0][0] == NULL) - { - Error("d3Tensor: allocation failure level 3", ARRAY_ERROR); - } - - for (j = 1; j < n2; j++) - { - tensor[0][j] = tensor[0][j-1] + n3; - } - for (i = 1; i < n1; i++) - { - tensor[i] = tensor[i-1] + n2; - tensor[i][0] = tensor[i-1][0] + n2*n3; - for (j = 1; j < n2; j++) - { - tensor[i][j] = tensor[i][j-1] + n3; - } - } - - return tensor; -} - - -i3Tensor New_i3Tensor(const int n1, const int n2, const int n3) -{ - int i; - int j; - i3Tensor tensor; - - tensor = (int***)malloc((size_t)(n1*sizeof(int**))); - if (tensor == NULL) - { - Error("New_i3Tensor: allocation failure level 1", ARRAY_ERROR); - } - - tensor[0] = (int**)malloc((size_t)(n1*n2*sizeof(int*))); - if (tensor[0] == NULL) - { - Error("New_i3Tensor: allocation failure level 2", ARRAY_ERROR); - } - - tensor[0][0] = (int*)malloc((size_t)(n1*n2*n3*sizeof(int))); - if (tensor[0][0] == NULL) - { - Error("New_i3Tensor: allocation failure level 3", ARRAY_ERROR); - } - - - for (j = 1; j < n2; j++) - { - tensor[0][j] = tensor[0][j-1] + n3; - } - for (i = 1; i < n1; i++) - { - tensor[i] = tensor[i-1] + n2; - tensor[i][0] = tensor[i-1][0] + n2*n3; - for (j = 1; j < n2; j++) - { - tensor[i][j] = tensor[i][j-1] + n3; - } - } - - return tensor; -} - - -void Delete_dVector(dVector vector) -{ - free(vector); - vector = NULL; -} - - -void Delete_iVector(iVector vector) -{ - free(vector); - vector = NULL; -} - - -void Delete_dMatrix(dMatrix matrix) -{ - free(matrix[0]); - matrix[0] = NULL; - free(matrix); - matrix = NULL; -} - - -void Delete_iMatrix(iMatrix matrix) -{ - free(matrix[0]); - matrix[0] = NULL; - free(matrix); - matrix = NULL; -} - - -void Delete_d3Tensor(d3Tensor tensor) -{ - free(tensor[0][0]); - tensor[0][0] = NULL; - free(tensor[0]); - tensor[0] = NULL; - free(tensor); - tensor = NULL; -} - - -void Delete_i3Tensor(i3Tensor tensor) -{ - free(tensor[0][0]); - tensor[0][0] = NULL; - free(tensor[0]); - tensor[0] = NULL; - free(tensor); - tensor = NULL; -} diff --git a/python/2_headers.i b/python/2_headers.i index 0ac86dc21..28254ab07 100644 --- a/python/2_headers.i +++ b/python/2_headers.i @@ -173,7 +173,6 @@ using namespace crpropa; // for usage of namespace in header files, necessary %include "crpropa/Units.h" %include "crpropa/Common.h" %include "crpropa/Cosmology.h" -%include "crpropa/PhotonPropagation.h" %template(RandomSeed) std::vector; %template(RandomSeedThreads) std::vector< std::vector >; %include "crpropa/Random.h" @@ -554,8 +553,6 @@ using namespace crpropa; // for usage of namespace in header files, necessary %include "crpropa/module/HDF5Output.h" %include "crpropa/module/OutputShell.h" -%include "crpropa/module/EMCascade.h" -%include "crpropa/module/PhotonEleCa.h" %include "crpropa/module/PhotonOutput1D.h" %include "crpropa/module/NuclearDecay.h" %include "crpropa/module/ElectronPairProduction.h" @@ -570,6 +567,8 @@ using namespace crpropa; // for usage of namespace in header files, necessary %include "crpropa/module/EMInverseComptonScattering.h" %include "crpropa/module/SynchrotronRadiation.h" %include "crpropa/module/AdiabaticCooling.h" +%include "crpropa/module/MomentumDiffusion.h" +%include "crpropa/module/CandidateSplitting.h" %template(IntSet) std::set; %include "crpropa/module/Tools.h" diff --git a/src/Candidate.cpp b/src/Candidate.cpp index 32c1e5815..8028d66a2 100644 --- a/src/Candidate.cpp +++ b/src/Candidate.cpp @@ -103,11 +103,11 @@ void Candidate::setProperty(const std::string &name, const Variant &value) { } void Candidate::setTagOrigin (std::string tagOrigin) { - this -> tagOrigin = tagOrigin ; + this->tagOrigin = tagOrigin; } std::string Candidate::getTagOrigin () const { - return tagOrigin ; + return tagOrigin; } const Variant &Candidate::getProperty(const std::string &name) const { @@ -141,6 +141,10 @@ void Candidate::addSecondary(int id, double energy, double w, std::string tagOri secondary->setRedshift(redshift); secondary->setTrajectoryLength(trajectoryLength); secondary->setWeight(weight * w); + secondary->setTagOrigin(tagOrigin); + for (PropertyMap::const_iterator it = properties.begin(); it != properties.end(); ++it) { + secondary->setProperty(it->first, it->second); + } secondary->source = source; secondary->previous = previous; secondary->created = previous; @@ -148,15 +152,18 @@ void Candidate::addSecondary(int id, double energy, double w, std::string tagOri secondary->current.setId(id); secondary->current.setEnergy(energy); secondary->parent = this; - secondary->setTagOrigin (tagOrigin); secondaries.push_back(secondary); } void Candidate::addSecondary(int id, double energy, Vector3d position, double w, std::string tagOrigin) { ref_ptr secondary = new Candidate; secondary->setRedshift(redshift); - secondary->setTrajectoryLength(trajectoryLength - (current.getPosition() - position).getR() ); + secondary->setTrajectoryLength(trajectoryLength - (current.getPosition() - position).getR()); secondary->setWeight(weight * w); + secondary->setTagOrigin(tagOrigin); + for (PropertyMap::const_iterator it = properties.begin(); it != properties.end(); ++it) { + secondary->setProperty(it->first, it->second); + } secondary->source = source; secondary->previous = previous; secondary->created = previous; @@ -166,7 +173,6 @@ void Candidate::addSecondary(int id, double energy, Vector3d position, double w, secondary->current.setPosition(position); secondary->created.setPosition(position); secondary->parent = this; - secondary->setTagOrigin (tagOrigin); secondaries.push_back(secondary); } diff --git a/src/PhotonPropagation.cpp b/src/PhotonPropagation.cpp deleted file mode 100644 index b7d7ea06c..000000000 --- a/src/PhotonPropagation.cpp +++ /dev/null @@ -1,504 +0,0 @@ -#include "crpropa/PhotonPropagation.h" -#include "crpropa/Common.h" -#include "crpropa/Units.h" -#include "crpropa/Cosmology.h" -#include "crpropa/ProgressBar.h" - -#include "EleCa/Propagation.h" -#include "EleCa/Particle.h" -#include "EleCa/Common.h" - -#include "dint/prop_second.h" -#include "dint/DintEMCascade.h" -#include "kiss/string.h" -#include "kiss/logger.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace crpropa { - -void ElecaPropagation( - const std::string &inputfile, - const std::string &outputfile, - bool showProgress, - double lowerEnergyThreshold, - double magneticFieldStrength, - const std::string &background) { - - KISS_LOG_WARNING << "EleCa propagation is deprecated and is no longer supported. Please use the EM* (EMPairProduction, EMInverseComptonScattering, ...) modules instead.\n"; - - std::ifstream infile(inputfile.c_str()); - std::streampos startPosition = infile.tellg(); - - infile.seekg(0, std::ios::end); - std::streampos endPosition = infile.tellg(); - infile.seekg(startPosition); - - - ProgressBar progressbar(endPosition); - if (showProgress) { - progressbar.start("Run ElecaPropagation"); - } - - if (!infile.good()) - throw std::runtime_error( - "ElecaPropagation: could not open file " + inputfile); - - bool PhotonOutput1D; - std::string line; - std::getline(infile, line); - if (line == "#ID E D pID pE iID iE iD") { - PhotonOutput1D = true; - } else if (line == "# D ID E ID0 E0 ID1 E1 X1") { - PhotonOutput1D = false; - } else { - throw std::runtime_error("ElecaPropagation: Wrong header of input file. Use PhotonOutput1D or Event1D with additional columns enabled."); - } - - eleca::setSeed(); - eleca::Propagation propagation; - propagation.SetEthr(lowerEnergyThreshold / eV ); - propagation.ReadTables(getDataPath("EleCa/eleca.dat")); - propagation.InitBkgArray(background); - - propagation.SetB(magneticFieldStrength / gauss); - - std::ofstream output(outputfile.c_str()); - output << "# ID\tE\tiID\tiE\tgeneration\n"; - output << "# ID Id of particle (photon, electron, positron)\n"; - output << "# E Energy [EeV]\n"; - output << "# iID Id of source particle\n"; - output << "# iE Energy [EeV] of source particle\n"; - output << "# Generation number of interactions during propagation before particle is created\n"; - - while (infile.good()) { - if (infile.peek() != '#') { - double D, E, E0, E1, X1; - int ID, ID0, ID1; - if (PhotonOutput1D) { - infile >> ID >> E >> X1 >> ID1 >> E1 >> ID0 >> E0 >> D; - } else { - infile >> D >> ID >> E >> ID0 >> E0 >> ID1 >> E1 >> X1; - } - if (showProgress) { - progressbar.setPosition(infile.tellg()); - } - - if (infile) { - - double z = eleca::Mpc2z(X1); - eleca::Particle p0(ID, E * 1e18, z); - - std::vector ParticleAtMatrix; - std::vector ParticleAtGround; - ParticleAtMatrix.push_back(p0); - - while (ParticleAtMatrix.size() > 0) { - - eleca::Particle p1 = ParticleAtMatrix.back(); - ParticleAtMatrix.pop_back(); - - if (p1.IsGood()) { - propagation.Propagate(p1, ParticleAtMatrix, - ParticleAtGround); - } - } - - for (int i = 0; i < ParticleAtGround.size(); ++i) { - eleca::Particle &p = ParticleAtGround[i]; - if (p.GetType() != 22) - continue; - char buffer[256]; - size_t bufferPos = 0; - bufferPos += std::sprintf(buffer + bufferPos, "%i\t", p.GetType()); - bufferPos += std::sprintf(buffer + bufferPos, "%.4E\t", p.GetEnergy() / 1E18 ); - bufferPos += std::sprintf(buffer + bufferPos, "%i\t", ID0); - bufferPos += std::sprintf(buffer + bufferPos, "%.4E\t", E0 ); - bufferPos += std::sprintf(buffer + bufferPos, "%i", p.Generation()); - bufferPos += std::sprintf(buffer + bufferPos, "\n"); - - output.write(buffer, bufferPos); - } - } - } - - infile.ignore(std::numeric_limits::max(), '\n'); - } - infile.close(); - output.close(); -} - -typedef struct _Secondary { - double D, E, E0, E1, X1; - int ID, ID0, ID1; -} _Secondary; - -bool _SecondarySortPredicate(const _Secondary& s1, const _Secondary& s2) { - return s1.X1 < s2.X1; -} - -void FillInSpectrum(Spectrum *a, const _Secondary &s) { - double logE = log10(s.E) + 18; // log10(E/eV) - int iBin = floor((logE - MIN_ENERGY_EXP) / 0.1); // bin number from 0 - NUM_MAIN_BINS-1 - if (iBin >= NUM_MAIN_BINS) { - std::cout << "DintPropagation: Energy too high " << logE << std::endl; - return; - } - if (iBin < 0) { - std::cout << "DintPropagation: Energy too low " << logE << std::endl; - return; - } - if (s.ID == 22) - a->spectrum[PHOTON][iBin] += 1.; - else if (s.ID == 11) - a->spectrum[ELECTRON][iBin] += 1.; - else if (s.ID == -11) - a->spectrum[POSITRON][iBin] += 1.; - else - std::cout << "DintPropagation: Unhandled particle ID " << s.ID << std::endl; -} - -void DintPropagation( - const std::string &inputfile, - const std::string &outputfile, - int IRBFlag, - int RadioFlag, - double magneticFieldStrength, - double aCutcascade_Magfield) { - - KISS_LOG_WARNING << "DINT propagation is deprecated and is no longer supported. Please use the EM* (EMPairProduction, EMInverseComptonScattering, ...) modules instead.\n"; - - // initialize the energy grids for DINT - dCVector energyGrid, energyWidth; - New_dCVector(&energyGrid, NUM_MAIN_BINS); - New_dCVector(&energyWidth, NUM_MAIN_BINS); - SetEnergyBins(MIN_ENERGY_EXP, &energyGrid, &energyWidth); - - std::ofstream outfile(outputfile.c_str()); - if (!outfile.good()) - throw std::runtime_error( - "DintPropagation: could not open file " + outputfile); - - std::ifstream infile(inputfile.c_str()); - if (!infile.good()) - throw std::runtime_error( - "DintPropagation: could not open file " + inputfile); - - bool PhotonOutput1D; - std::string line; - std::getline(infile, line); - if (line == "#ID E D pID pE iID iE iD") { - PhotonOutput1D = true; - } else if (line == "# D ID E ID0 E0 ID1 E1 X1") { - PhotonOutput1D = false; - } else { - throw std::runtime_error("DintPropagation: Wrong header of input file. Use PhotonOutput1D or Event1D with additional columns enabled."); - } - - // initialize the spectrum - Spectrum finalSpectrum; - NewSpectrum(&finalSpectrum, NUM_MAIN_BINS); - InitializeSpectrum(&finalSpectrum); - - std::string dataPath = getDataPath("dint"); - double B = magneticFieldStrength / gauss; - double h = H0() * Mpc / 1000; - DintEMCascade dint(IRBFlag, RadioFlag, dataPath, B, h, omegaM(), omegaL()); - - const size_t nBuffer = 7.5E7; // maximum number of simultaneously processed particles, keep memory requirement < 1GB - const double dMargin = 0.1; // distance bin width in [Mpc] - - while (infile.good()) { - // read up to nBuffer secondaries from input file - std::vector<_Secondary> secondaries; - secondaries.reserve(nBuffer); - while (infile.good() && (secondaries.size() < nBuffer)) { - if (infile.peek() != '#') { - _Secondary s; - if (PhotonOutput1D) { - infile >> s.ID >> s.E >> s.X1 >> s.ID1 >> s.E1 >> s.ID0 >> s.E0 >> s.D; - } else { - infile >> s.D >> s.ID >> s.E >> s.ID0 >> s.E0 >> s.ID1 >> s.E1 >> s.X1; - } - s.X1 = comoving2LightTravelDistance(s.X1 * Mpc) / Mpc; // DintEMCascade expects light travel distance - if (infile) - secondaries.push_back(s); - } - infile.ignore(std::numeric_limits::max(), '\n'); - } - - if (secondaries.empty()) - break; // all secondaries processed, nothing left to do - - // sort by distance - std::sort(secondaries.begin(), secondaries.end(), - _SecondarySortPredicate); - - Spectrum inputSpectrum, outputSpectrum; - NewSpectrum(&inputSpectrum, NUM_MAIN_BINS); - NewSpectrum(&outputSpectrum, NUM_MAIN_BINS); - InitializeSpectrum(&inputSpectrum); - - // process secondaries - while ((secondaries.size() > 0 ) && (secondaries.back().X1 > 0)) { - double Dmax = secondaries.back().X1; // upper bound of distance bin - double Dmin = max(Dmax - dMargin, 0.); // lower bound of distance bin - - // add all secondaries within the current distance bin - while ((secondaries.size() > 0) && (secondaries.back().X1 > Dmin)) { - FillInSpectrum(&inputSpectrum, secondaries.back()); - secondaries.pop_back(); - } - - // propagate to next closest particle or to D=0 - double D = 0; - if (secondaries.size() > 0) - D = secondaries.back().X1; - - // propagate distance step and make the output the new input spectrum - InitializeSpectrum(&outputSpectrum); - dint.propagate(Dmax, D, &inputSpectrum, &outputSpectrum, aCutcascade_Magfield); - SetSpectrum(&inputSpectrum, &outputSpectrum); - } - - // add remaining secondaries at D=0 to output spectrum - while (secondaries.size() > 0) { - FillInSpectrum(&inputSpectrum, secondaries.back()); - secondaries.pop_back(); - } - - AddSpectrum(&finalSpectrum, &inputSpectrum); - DeleteSpectrum(&outputSpectrum); - DeleteSpectrum(&inputSpectrum); - } - - // output - outfile << "# logE photons electrons positrons\n"; - outfile << "# - logE: energy bin center \n"; - outfile << "# - photons, electrons, positrons: total flux weights\n"; - for (int j = 0; j < finalSpectrum.numberOfMainBins; j++) { - double logEc = MIN_ENERGY_EXP + 0.05 + j * 1. / BINS_PER_DECADE; - outfile << std::setw(5) << logEc; - for (int i = 0; i < 3; i++) { - outfile << std::setw(13) << finalSpectrum.spectrum[i][j]; - } - outfile << "\n"; - } - outfile.close(); - - DeleteSpectrum(&finalSpectrum); - Delete_dCVector(&energyGrid); - Delete_dCVector(&energyWidth); -} - - - -bool _ParticlesAtGroundSortPredicate(const eleca::Particle& p1, const eleca::Particle& p2) { - return p1.Getz() < p2.Getz(); -} - -void DintElecaPropagation( - const std::string &inputfile, - const std::string &outputfile, - bool showProgress, - double crossOverEnergy, - double magneticFieldStrength, - double aCutcascade_Magfield) { - - KISS_LOG_WARNING << "EleCa+DINT propagation is deprecated and is no longer supported. Please use the EM* (EMPairProduction, EMInverseComptonScattering, ...) modules instead.\n"; - - //////////////////////////////////////////////////////////////////////// - //Initialize EleCa - std::ifstream infile(inputfile.c_str()); - std::streampos startPosition = infile.tellg(); - - infile.seekg(0, std::ios::end); - std::streampos endPosition = infile.tellg(); - infile.seekg(startPosition); - - ProgressBar progressbar(endPosition); - if (showProgress) { - progressbar.start("Run EleCa propagation"); - } - - if (!infile.good()) - throw std::runtime_error( - "EleCaPropagation: could not open file " + inputfile); - - bool PhotonOutput1D; - std::string line; - std::getline(infile, line); - if (line == "#ID E D pID pE iID iE iD") { - PhotonOutput1D = true; - } else if (line == "# D ID E ID0 E0 ID1 E1 X1") { - PhotonOutput1D = false; - } else { - throw std::runtime_error("DintElecaPropagation: Wrong header of input file. Use PhotonOutput1D or Event1D with additional columns enabled."); - } - - eleca::setSeed(); - eleca::Propagation propagation; - propagation.SetEthr(crossOverEnergy / eV ); - propagation.ReadTables(getDataPath("EleCa/eleca.dat")); - propagation.InitBkgArray("ALL"); - propagation.SetB(magneticFieldStrength / gauss); - std::vector ParticleAtGround; - - //////////////////////////////////////////////////////////////////////// - //Initialize DINT - dCVector energyGrid, energyWidth; - // Initialize the energy grids for dint - New_dCVector(&energyGrid, NUM_MAIN_BINS); - New_dCVector(&energyWidth, NUM_MAIN_BINS); - SetEnergyBins(MIN_ENERGY_EXP, &energyGrid, &energyWidth); - - std::ofstream outfile(outputfile.c_str()); - if (!outfile.good()) - throw std::runtime_error( - "DintPropagation: could not open file " + outputfile); - - Spectrum finalSpectrum; - NewSpectrum(&finalSpectrum, NUM_MAIN_BINS); - InitializeSpectrum(&finalSpectrum); - - std::string dataPath = getDataPath("dint"); - double h = H0() * Mpc / 1000; - double ol = omegaL(); - double om = omegaM(); - DintEMCascade dint(4, 4, dataPath, magneticFieldStrength/gauss, h, om, ol); - - //////////////////////////////////////////////////////////////////////// - // Loop over infile - - while (infile.good()) { - /// Eleca Propagation - if (infile.peek() == '#') { - infile.ignore(std::numeric_limits::max(), '\n'); - continue; - } - - double D, E, E0, E1, X1; - int ID, ID0, ID1; - if (PhotonOutput1D) { - infile >> ID >> E >> X1 >> ID1 >> E1 >> ID0 >> E0 >> D; - } else { - infile >> D >> ID >> E >> ID0 >> E0 >> ID1 >> E1 >> X1; - } - if (showProgress) { - progressbar.setPosition(infile.tellg()); - } - if (infile) { // stop at last line - double z = eleca::Mpc2z(X1); - eleca::Particle p0(ID, E * 1e18, z); - - std::vector ParticleAtMatrix; - ParticleAtMatrix.push_back(p0); - - while (ParticleAtMatrix.size() > 0) { - eleca::Particle p1 = ParticleAtMatrix.back(); - ParticleAtMatrix.pop_back(); - - if (p1.IsGood()) { - propagation.Propagate(p1, ParticleAtMatrix, - ParticleAtGround, false); - } - } - } - - // The vector is larger than ~1GB, or the infile is completely read - better call DINT. - if (ParticleAtGround.size() > 1000000 || !infile) { - const double dMargin = 0.1 * Mpc; - - std::sort(ParticleAtGround.begin(), ParticleAtGround.end(), _ParticlesAtGroundSortPredicate); - - Spectrum inputSpectrum, outputSpectrum; - NewSpectrum(&inputSpectrum, NUM_MAIN_BINS); - NewSpectrum(&outputSpectrum, NUM_MAIN_BINS); - - InitializeSpectrum(&inputSpectrum); - // process secondaries - while (ParticleAtGround.size() > 0) { - double currentDistance = redshift2LightTravelDistance(ParticleAtGround.back().Getz()); // dint expects light travel distance - bool lastStep = (currentDistance == 0.); - // add secondaries at the current distance to spectrum - while ((ParticleAtGround.size() > 0) && (redshift2LightTravelDistance(ParticleAtGround.back().Getz()) >= (currentDistance - dMargin))) { - if (redshift2LightTravelDistance(ParticleAtGround.back().Getz()) > 0. || lastStep) { - double criticalEnergy = ParticleAtGround.back().GetEnergy() / (ELECTRON_MASS); // units of dint - int maxBin = (int) ((log10(criticalEnergy * ELECTRON_MASS) - MIN_ENERGY_EXP) * BINS_PER_DECADE + 0.5 + 1); // +1 line before to avoid conversion error to int for negative values (int(-0.7) = 0) - maxBin -= 1; // remove the additional 1 from line before - if (maxBin >= NUM_MAIN_BINS) { - std::cout << "DintPropagation: Energy too high " << - ParticleAtGround.back().GetEnergy() << " eV" << - std::endl; - ParticleAtGround.pop_back(); - continue; - } - if (maxBin < 0) { - std::cout << "DintPropagation: Energy too low " << - ParticleAtGround.back().GetEnergy() << " eV" << std::endl; - ParticleAtGround.pop_back(); - continue; - } - int Id = ParticleAtGround.back().GetType(); - if (Id == 22) - inputSpectrum.spectrum[PHOTON][maxBin] += 1.; - else if (Id == 11) - inputSpectrum.spectrum[ELECTRON][maxBin] += 1.; - else if (Id == -11) - inputSpectrum.spectrum[POSITRON][maxBin] += 1.; - else { - std::cout << "DintPropagation: Unhandled particle ID " << Id - << std::endl; - } - ParticleAtGround.pop_back(); - } else - break; - } - - double D = 0; - // only propagate to next particle - if (ParticleAtGround.size() > 0) - D = redshift2LightTravelDistance(ParticleAtGround.back().Getz()); - - InitializeSpectrum(&outputSpectrum); - dint.propagate(currentDistance / Mpc, D / Mpc, &inputSpectrum, - &outputSpectrum, aCutcascade_Magfield); - SetSpectrum(&inputSpectrum, &outputSpectrum); - } // while (secondaries.size() > 0) - - AddSpectrum(&finalSpectrum, &inputSpectrum); - - DeleteSpectrum(&outputSpectrum); - DeleteSpectrum(&inputSpectrum); - } // dint call - } - - infile.close(); - - // output - outfile << "# logE photons electrons positrons\n"; - outfile << "# - logE: energy bin center \n"; - outfile << "# - photons, electrons, positrons: total flux weights\n"; - for (int j = 0; j < finalSpectrum.numberOfMainBins; j++) { - double logEc = MIN_ENERGY_EXP + 0.05 + j * 1. / BINS_PER_DECADE; - outfile << std::setw(5) << logEc; - for (int i = 0; i < 3; i++) { - outfile << std::setw(13) << finalSpectrum.spectrum[i][j]; - } - outfile << "\n"; - } - outfile.close(); - - DeleteSpectrum(&finalSpectrum); - Delete_dCVector(&energyGrid); - Delete_dCVector(&energyWidth); -} - -} // namespace crpropa diff --git a/src/Source.cpp b/src/Source.cpp index e9f496970..840ff1c39 100644 --- a/src/Source.cpp +++ b/src/Source.cpp @@ -817,38 +817,14 @@ void SourceIsotropicEmission::setDescription() { SourceDirectedEmission::SourceDirectedEmission(Vector3d mu, double kappa): mu(mu), kappa(kappa) { if (kappa <= 0) throw std::runtime_error("The concentration parameter kappa should be larger than 0."); - double alpha = atan2(mu.y,mu.x); - double delta = asin(mu.z); - setCa(alpha); - setSa(alpha); - setCd(delta); - setSd(delta); setDescription(); } void SourceDirectedEmission::prepareCandidate(Candidate &candidate) const { Random &random = Random::instance(); - //generate sample from von Mises Fisher distribution following - // http://people.csail.mit.edu/jstraub/download/straub2017vonMisesFisherInference.pdf - //sample normalized direction vector from unit Gaussian distribution - Vector3d v(random.randNorm(0., 1.),random.randNorm(0., 1.),0.); - v = v.getUnitVector(); - - //sample uniform random number - double xi = random.rand(); - - double u = 1. + 1. / kappa * log(xi + (1. - xi) * exp(-2. * kappa)); - - //sample vector from von-Mises distribution - Vector3d n = sqrt(1. - u * u) * v; - n.z += u; - - //we are in the frame m = (0,0,1) - //so rotate to target frame - v = Vector3d(ca * sd * n.x - sa * n.y + ca * cd * n.z, - sa * sd * n.x + ca * n.y + sa * cd * n.z, - - cd * n.x + sd * n.z); + Vector3d muvec = mu / mu.getR(); + Vector3d v = random.randFisherVector(muvec, kappa); v = v.getUnitVector(); candidate.source.setDirection(v); @@ -862,42 +838,6 @@ void SourceDirectedEmission::prepareCandidate(Candidate &candidate) const { candidate.setWeight(weight); } -void SourceDirectedEmission::setCa(double alpha) { - ca = cos(alpha); - return; -} - -void SourceDirectedEmission::setSa(double alpha) { - sa = sin(alpha); - return; -} - -void SourceDirectedEmission::setCd(double delta) { - cd = cos(delta); - return; -} - -void SourceDirectedEmission::setSd(double delta) { - sd = sin(delta); - return; -} - -double SourceDirectedEmission::getCa() const { - return ca; -} - -double SourceDirectedEmission::getSa() const { - return sa; -} - -double SourceDirectedEmission::getCd() const { - return cd; -} - -double SourceDirectedEmission::getSd() const { - return sd; -} - void SourceDirectedEmission::setDescription() { std::stringstream ss; ss << "SourceDirectedEmission: Random directed emission following the von-Mises-Fisher distribution with mean direction "; diff --git a/src/Variant.cpp b/src/Variant.cpp index 436f3a23d..f2f2bbfcb 100644 --- a/src/Variant.cpp +++ b/src/Variant.cpp @@ -3,960 +3,1122 @@ // http://vispa.physik.rwth-aachen.de/ - // Licensed under a LGPL-2 or later license - //------------------------------------------------------------- + #include "crpropa/Variant.h" -#include -namespace crpropa -{ +namespace crpropa { + -Variant::Variant() : - type(TYPE_NONE) -{ +Variant::Variant() : type(TYPE_NONE) { } -Variant::~Variant() -{ - clear(); +Variant::Variant(Type t) : type(TYPE_NONE) { + check(t); } -Variant::Variant(const Variant& a) : - type(TYPE_NONE) -{ - copy(a); +Variant::Variant(const Variant& v) : type(TYPE_NONE) { + copy(v); } -Variant::Variant(const char *s) -{ - data._String = new std::string(s); +Variant::Variant(const char* s) { + data._t_string = new std::string(s); type = TYPE_STRING; } - -void Variant::clear() -{ - if (type == TYPE_STRING) - { - if(data._String) - { - delete data._String; - data._String = NULL; - } - - } - - type = TYPE_NONE; +Variant::~Variant() { + clear(); } -void Variant::check(const Type t) const -{ - if (type != t) - throw bad_conversion(type, t); +const char* Variant::getTypeName() const { + return getTypeName(type); } -void Variant::check(const Type t) -{ - if (type == TYPE_NONE) - { - std::memset(&data, 0, sizeof(data)); - switch (t) - { - case TYPE_STRING: - data._String = new std::string; - break; - default: - break; - } - type = t; - } - else if (type != t) - { - throw bad_conversion(type, t); - } -} - -const std::type_info& Variant::getTypeInfo() const -{ - if (type == TYPE_BOOL) - { - const std::type_info &ti = typeid(data._Bool); - return ti; - } - else if (type == TYPE_CHAR) - { - const std::type_info &ti = typeid(data._Char); - return ti; - } - else if (type == TYPE_UCHAR) - { - const std::type_info &ti = typeid(data._UChar); - return ti; - } - else if (type == TYPE_INT16) - { - const std::type_info &ti = typeid(data._Int16); - return ti; - } - else if (type == TYPE_UINT16) - { - const std::type_info &ti = typeid(data._UInt16); - return ti; - } - else if (type == TYPE_INT32) - { - const std::type_info &ti = typeid(data._Int32); - return ti; - } - else if (type == TYPE_UINT32) - { - const std::type_info &ti = typeid(data._UInt32); - return ti; - } - else if (type == TYPE_INT64) - { - const std::type_info &ti = typeid(data._Int64); - return ti; - } - else if (type == TYPE_UINT64) - { - const std::type_info &ti = typeid(data._UInt64); - return ti; - } - else if (type == TYPE_FLOAT) - { - const std::type_info &ti = typeid(data._Float); - return ti; - } - else if (type == TYPE_DOUBLE) - { - const std::type_info &ti = typeid(data._Double); - return ti; - } - else if (type == TYPE_STRING) - { - const std::type_info &ti = typeid(*data._String); - return ti; - } - else - { - const std::type_info &ti = typeid(0); - return ti; - } - -} - -const char *Variant::getTypeName(Type type) -{ - if (type == TYPE_NONE) - { +const char* Variant::getTypeName(Type t) { + if (t == TYPE_NONE) return "none"; - } - else if (type == TYPE_BOOL) - { + else if (t == TYPE_BOOL) return "bool"; - } - else if (type == TYPE_CHAR) - { + else if (t == TYPE_CHAR) return "char"; - } - else if (type == TYPE_UCHAR) - { + else if (t == TYPE_UCHAR) return "uchar"; - } - else if (type == TYPE_INT16) - { + else if (t == TYPE_INT16) return "int16"; - } - else if (type == TYPE_UINT16) - { + else if (t == TYPE_UINT16) return "uint16"; - } - else if (type == TYPE_INT32) - { + else if (t == TYPE_INT32) return "int32"; - } - else if (type == TYPE_UINT32) - { + else if (t == TYPE_UINT32) return "uint32"; - } - else if (type == TYPE_INT64) - { + else if (t == TYPE_INT64) return "int64"; - } - else if (type == TYPE_UINT64) - { + else if (t == TYPE_UINT64) return "uint64"; - } - else if (type == TYPE_FLOAT) - { + else if (t == TYPE_FLOAT) return "float"; - } - else if (type == TYPE_DOUBLE) - { + else if (t == TYPE_DOUBLE) return "double"; - } - else if (type == TYPE_STRING) - { + else if (t == TYPE_LONGDOUBLE) + return "ldouble"; + else if (t == TYPE_COMPLEXF) + return "complex_f"; + else if (t == TYPE_COMPLEXD) + return "complex_d"; + else if (t == TYPE_STRING) return "string"; - } + else if (t == TYPE_VECTOR3F) + return "Vector3f"; + else if (t == TYPE_VECTOR3D) + return "Vector3d"; + else if (t == TYPE_VECTOR3C) + return "Vector3c"; + else if (t == TYPE_VECTOR) + return "vector"; else - { return "unknown"; +} + +const std::type_info& Variant::getTypeInfo() const { + if (type == TYPE_BOOL) { + const std::type_info& ti = typeid(data._t_bool); + return ti; + } else if (type == TYPE_CHAR) { + const std::type_info& ti = typeid(data._t_char); + return ti; + } else if (type == TYPE_UCHAR) { + const std::type_info& ti = typeid(data._t_uchar); + return ti; + } else if (type == TYPE_INT16) { + const std::type_info& ti = typeid(data._t_int16); + return ti; + } else if (type == TYPE_UINT16) { + const std::type_info& ti = typeid(data._t_uint16); + return ti; + } else if (type == TYPE_INT32) { + const std::type_info& ti = typeid(data._t_int32); + return ti; + } else if (type == TYPE_UINT32) { + const std::type_info& ti = typeid(data._t_uint32); + return ti; + } else if (type == TYPE_INT64) { + const std::type_info& ti = typeid(data._t_int64); + return ti; + } else if (type == TYPE_UINT64) { + const std::type_info& ti = typeid(data._t_uint64); + return ti; + } else if (type == TYPE_FLOAT) { + const std::type_info& ti = typeid(data._t_float); + return ti; + } else if (type == TYPE_DOUBLE) { + const std::type_info& ti = typeid(data._t_double); + return ti; + } else if (type == TYPE_LONGDOUBLE) { + const std::type_info& ti = typeid(data._t_ldouble); + return ti; + } else if (type == TYPE_STRING) { + const std::type_info& ti = typeid(*data._t_string); + return ti; + } else if (type == TYPE_COMPLEXF) { // pointer needed? + const std::type_info& ti = typeid(*data._t_complex_f); + return ti; + } else if (type == TYPE_COMPLEXD) { + const std::type_info& ti = typeid(*data._t_complex_d); + return ti; + } else if (type == TYPE_VECTOR3D) { + const std::type_info& ti = typeid(data._t_vector3d); + return ti; + } else if (type == TYPE_VECTOR3F) { + const std::type_info& ti = typeid(data._t_vector3f); + return ti; + } else if (type == TYPE_VECTOR) { + const std::type_info& ti = typeid(*data._t_vector); + return ti; + } else { + const std::type_info& ti = typeid(0); + return ti; } } -Variant::Type Variant::toType(const std::string &name) -{ +Variant::Type Variant::toType(const std::string& name) { if (name == "none") - { return TYPE_NONE; - } else if (name == "bool") - { return TYPE_BOOL; - } - else if (name == "char") - { + else if (name == "char") return TYPE_CHAR; - } else if (name == "uchar") - { return TYPE_UCHAR; - } else if (name == "int16") - { return TYPE_INT16; - } else if (name == "uint16") - { return TYPE_UINT16; - } else if (name == "int32") - { return TYPE_INT32; - } else if (name == "uint32") - { return TYPE_UINT32; - } else if (name == "int64") - { return TYPE_INT64; - } else if (name == "uint64") - { return TYPE_UINT64; - } else if (name == "float") - { return TYPE_FLOAT; - } else if (name == "double") - { return TYPE_DOUBLE; - } - else if (name == "string") - { + else if (name == "long double") + return TYPE_LONGDOUBLE; + else if (name == "complex_f") + return TYPE_COMPLEXF; + else if (name == "complex_d") + return TYPE_COMPLEXD; + else if (name == "string") return TYPE_STRING; - } + else if (name == "Vector3f") + return TYPE_VECTOR3F; + else if (name == "Vector3d") + return TYPE_VECTOR3D; + else if (name == "Vector3c") + return TYPE_VECTOR3C; + else if (name == "vector") + return TYPE_VECTOR; else - { return TYPE_NONE; - } } -bool Variant::operator ==(const Variant &a) const -{ - if (type != a.type) - return false; - if (type == TYPE_BOOL) - { - return (data._Bool == a.data._Bool); - } - else if (type == TYPE_CHAR) - { - return (data._Char == a.data._Char); - } - else if (type == TYPE_UCHAR) - { - return (data._UChar == a.data._UChar); - } - else if (type == TYPE_INT16) - { - return (data._Int16 == a.data._Int16); - } - else if (type == TYPE_UINT16) - { - return (data._UInt16 == a.data._UInt16); +bool Variant::toBool() const { + switch (type) { + case TYPE_BOOL: + return data._t_bool; + break; + case TYPE_CHAR: + return data._t_char != 0; + break; + case TYPE_UCHAR: + return data._t_uchar != 0; + break; + case TYPE_INT16: + return data._t_int16 != 0; + break; + case TYPE_UINT16: + return data._t_uint16 != 0; + break; + case TYPE_INT32: + return data._t_int32 != 0; + break; + case TYPE_UINT32: + return data._t_uint32 != 0; + break; + case TYPE_INT64: + return data._t_int64 != 0; + break; + case TYPE_UINT64: + return data._t_uint64 != 0; + break; + case TYPE_STRING: { + std::string upperstr(*data._t_string); + std::transform(upperstr.begin(), upperstr.end(), upperstr.begin(), (int(*) (int)) toupper); + if (upperstr == "YES" || upperstr == "TRUE" || upperstr == "1") + return true; + else if (upperstr == "NO" || upperstr == "FALSE" || upperstr == "0") + return false; + else + throw bad_conversion(type, TYPE_BOOL); + } + break; + case TYPE_COMPLEXF: { + if (data._t_complex_f->real() == 0 && data._t_complex_f->imag() == 0) + return true; + else + return false; + } + break; + case TYPE_COMPLEXD: { + if (data._t_complex_d->real() == 0 && data._t_complex_d->imag() == 0) + return true; + else + return false; + } + break; + case TYPE_VECTOR: + return data._t_vector->size() != 0; + break; + case TYPE_FLOAT: + case TYPE_DOUBLE: + case TYPE_LONGDOUBLE: + default: + throw bad_conversion(type, TYPE_BOOL); + break; } - else if (type == TYPE_INT32) - { - return (data._Int32 == a.data._Int32); + + return false; +} + +float Variant::toFloat() const { + switch (type) { + case TYPE_BOOL: + return data._t_bool ? (float) 1.0 : (float) 0.0; + break; + case TYPE_CHAR: + return static_cast(data._t_char); + break; + case TYPE_UCHAR: + return static_cast(data._t_uchar); + break; + case TYPE_INT16: + return static_cast(data._t_int16); + break; + case TYPE_INT32: + return static_cast(data._t_int32); + break; + case TYPE_INT64: + return static_cast(data._t_int64); + break; + case TYPE_UINT16: + return static_cast(data._t_uint16); + break; + case TYPE_UINT32: + return static_cast(data._t_uint32); + break; + case TYPE_UINT64: + return static_cast(data._t_uint64); + break; + case TYPE_FLOAT: + return static_cast(data._t_float); + break; + case TYPE_DOUBLE: + return static_cast(data._t_double); + break; + case TYPE_LONGDOUBLE: + return static_cast(data._t_ldouble); + break; + case TYPE_STRING: + return static_cast(std::atof(data._t_string->c_str())); + break; + case TYPE_COMPLEXF: { + if (data._t_complex_f->imag() == 0) + return static_cast(data._t_complex_f->real()); + else + throw bad_conversion(type, TYPE_COMPLEXF); + } + break; + case TYPE_COMPLEXD: { + if (data._t_complex_d->imag() == 0) + return static_cast(data._t_complex_d->real()); + else + throw bad_conversion(type, TYPE_COMPLEXD); + } + break; + default: + throw bad_conversion(type, TYPE_FLOAT); + break; } - else if (type == TYPE_UINT32) - { - return (data._UInt32 == a.data._UInt32); + + return 0.; +} + +double Variant::toDouble() const { + switch (type) { + case TYPE_BOOL: + return data._t_bool ? (double) 1.0 : (double) 0.0; + break; + case TYPE_CHAR: + return static_cast(data._t_char); + break; + case TYPE_UCHAR: + return static_cast(data._t_uchar); + break; + case TYPE_INT16: + return static_cast(data._t_int16); + break; + case TYPE_INT32: + return static_cast(data._t_int32); + break; + case TYPE_INT64: + return static_cast(data._t_int64); + break; + case TYPE_UINT16: + return static_cast(data._t_uint16); + break; + case TYPE_UINT32: + return static_cast(data._t_uint32); + break; + case TYPE_UINT64: + return static_cast(data._t_uint64); + break; + case TYPE_FLOAT: + return static_cast(data._t_float); + break; + case TYPE_DOUBLE: + return static_cast(data._t_double); + break; + case TYPE_LONGDOUBLE: + return static_cast(data._t_ldouble); + break; + case TYPE_COMPLEXF: { + if (data._t_complex_f->imag() == 0) + return static_cast(data._t_complex_f->real()); + else + throw bad_conversion(type, TYPE_COMPLEXF); + } + break; + case TYPE_COMPLEXD: { + if (data._t_complex_d->imag() == 0) + return static_cast(data._t_complex_d->real()); + else + throw bad_conversion(type, TYPE_COMPLEXD); + } + break; + case TYPE_STRING: + return static_cast(std::atof(data._t_string->c_str())); + break; + default: + throw bad_conversion(type, TYPE_DOUBLE); + break; } - else if (type == TYPE_INT64) - { - return (data._Int64 == a.data._Int64); + + return 0.; +} + +long double Variant::toLongDouble() const { + switch (type) { + case TYPE_BOOL: + return data._t_bool ? (long double) 1.0 : (long double) 0.0; + break; + case TYPE_CHAR: + return static_cast(data._t_char); + break; + case TYPE_UCHAR: + return static_cast(data._t_uchar); + break; + case TYPE_INT16: + return static_cast(data._t_int16); + break; + case TYPE_INT32: + return static_cast(data._t_int32); + break; + case TYPE_INT64: + return static_cast(data._t_int64); + break; + case TYPE_UINT16: + return static_cast(data._t_uint16); + break; + case TYPE_UINT32: + return static_cast(data._t_uint32); + break; + case TYPE_UINT64: + return static_cast(data._t_uint64); + break; + case TYPE_FLOAT: + return static_cast(data._t_float); + break; + case TYPE_DOUBLE: + return static_cast(data._t_double); + break; + case TYPE_LONGDOUBLE: + return static_cast(data._t_ldouble); + break; + case TYPE_COMPLEXF: { + if (data._t_complex_f->imag() == 0) + return static_cast(data._t_complex_f->real()); + else + throw bad_conversion(type, TYPE_COMPLEXF); + } + break; + case TYPE_COMPLEXD: { + if (data._t_complex_d->imag() == 0) + return static_cast(data._t_complex_d->real()); + else + throw bad_conversion(type, TYPE_COMPLEXD); + } + break; + case TYPE_STRING: + return static_cast(std::atof(data._t_string->c_str())); + break; + default: + throw bad_conversion(type, TYPE_LONGDOUBLE); + break; } - else if (type == TYPE_UINT64) - { - return (data._UInt64 == a.data._UInt64); + + return 0.; +} + +std::complex Variant::toComplexFloat() const { + switch (type) { + case TYPE_COMPLEXF: + return static_cast>(*data._t_complex_f); + break; + case TYPE_COMPLEXD: + return static_cast>(*data._t_complex_d); + break; + default: + throw bad_conversion(type, TYPE_COMPLEXF); + break; } - else if (type == TYPE_FLOAT) - { - return (data._Float == a.data._Float); +} + +std::complex Variant::toComplexDouble() const { + switch (type) { + case TYPE_COMPLEXF: + return static_cast>(*data._t_complex_f); + break; + case TYPE_COMPLEXD: + return static_cast>(*data._t_complex_d); + break; + default: + throw bad_conversion(type, TYPE_COMPLEXD); + break; } - else if (type == TYPE_DOUBLE) - { - return (data._Double == a.data._Double); +} + +Vector3f Variant::toVector3f() const { + switch (type) { + case TYPE_VECTOR3F: + return static_cast(*data._t_vector3f); + break; + case TYPE_VECTOR3D: + return static_cast(*data._t_vector3d); + break; + default: + throw bad_conversion(type, TYPE_VECTOR3F); + break; } - else if (type == TYPE_STRING) - { - return (*data._String == *a.data._String); +} + +Vector3d Variant::toVector3d() const { + switch (type) { + case TYPE_VECTOR3F: + return static_cast(*data._t_vector3f); + break; + case TYPE_VECTOR3D: + return static_cast(*data._t_vector3d); + break; + default: + throw bad_conversion(type, TYPE_VECTOR3D); + break; } - else - { - throw std::runtime_error("compare operator not implemented"); +} + +Vector3> Variant::toVector3c() const { + switch (type) { + case TYPE_VECTOR3C: + return static_cast(*data._t_vector3c); + break; + default: + throw bad_conversion(type, TYPE_VECTOR3C); + break; } } -std::string Variant::toString() const -{ +std::string Variant::toString(const std::string& delimiter) const { if (type == TYPE_STRING) - return *data._String; + return *data._t_string; - std::stringstream sstr; - if (type == TYPE_BOOL) - { - sstr << data._Bool; - } - else if (type == TYPE_CHAR) - { - sstr << data._Char; - } - else if (type == TYPE_UCHAR) - { - sstr << data._UChar; - } - else if (type == TYPE_INT16) - { - sstr << data._Int16; - } - else if (type == TYPE_UINT16) - { - sstr << data._UInt16; - } - else if (type == TYPE_INT32) - { - sstr << data._Int32; - } - else if (type == TYPE_UINT32) - { - sstr << data._UInt32; - } - else if (type == TYPE_INT64) - { - sstr << data._Int64; - } - else if (type == TYPE_UINT64) - { - sstr << data._UInt64; - } - else if (type == TYPE_FLOAT) - { - sstr << std::scientific << data._Float; - } - else if (type == TYPE_DOUBLE) - { - sstr << std::scientific << data._Double; + std::stringstream ss; + + if (type == TYPE_BOOL) { + ss << data._t_bool; + } else if (type == TYPE_CHAR) { + ss << data._t_char; + } else if (type == TYPE_UCHAR) { + ss << data._t_uchar; + } else if (type == TYPE_INT16) { + ss << data._t_int16; + } else if (type == TYPE_UINT16) { + ss << data._t_uint16; + } else if (type == TYPE_INT32) { + ss << data._t_int32; + } else if (type == TYPE_UINT32) { + ss << data._t_uint32; + } else if (type == TYPE_INT64) { + ss << data._t_int64; + } else if (type == TYPE_UINT64) { + ss << data._t_uint64; + } else if (type == TYPE_FLOAT) { + ss << std::scientific << data._t_float; + } else if (type == TYPE_DOUBLE) { + ss << std::scientific << data._t_double; + } else if (type == TYPE_LONGDOUBLE) { + ss << std::scientific << data._t_ldouble; + } else if (type == TYPE_COMPLEXF) { + ss << std::scientific << data._t_complex_f->real() << delimiter; + ss << std::scientific << data._t_complex_f->imag(); + } else if (type == TYPE_COMPLEXD) { + ss << std::scientific << data._t_complex_d->real() << delimiter; + ss << std::scientific << data._t_complex_d->imag(); + } else if (type == TYPE_VECTOR3F) { + ss << *data._t_vector3f; + } else if (type == TYPE_VECTOR3D) { + ss << *data._t_vector3d; + } else if (type == TYPE_VECTOR) { + ss << *data._t_vector; } - return sstr.str(); -} - -Variant Variant::fromString(const std::string &str, Type type) -{ - std::stringstream sstr(str); - switch (type) - { - case TYPE_BOOL: - { - std::string upperstr(str); - std::transform(upperstr.begin(), upperstr.end(), upperstr.begin(), - (int(*)(int))toupper);if -( upperstr == "YES") - return Variant(true); - else if (upperstr == "NO") - return Variant(false); - if (upperstr == "TRUE") - return Variant(true); - else if (upperstr == "FALSE") - return Variant(false); - if (upperstr == "1") + return ss.str(); +} + +Variant::vector_t Variant::toVector() const { + if (type == TYPE_VECTOR) + return *data._t_vector; + else + throw bad_conversion(type, TYPE_VECTOR); +} + +Variant Variant::fromString(const std::string& s, Type t) { + std::stringstream ss(s); + + if (t == TYPE_BOOL) { + std::string upperstr(s); + std::transform(upperstr.begin(), upperstr.end(), upperstr.begin(), (int (*)(int)) toupper); + if (upperstr == "YES" || upperstr == "TRUE" || upperstr == "1") return Variant(true); - else if (upperstr == "0") + else if (upperstr == "NO" || upperstr == "FALSE" || upperstr == "0") return Variant(false); - throw bad_conversion(type, TYPE_BOOL); - } - case TYPE_CHAR: - { + throw bad_conversion(t, TYPE_BOOL); + } else if (t == TYPE_CHAR) { char c; - sstr >> c; + ss >> c; return Variant(c); - } - case TYPE_UCHAR: - { + } else if (t == TYPE_UCHAR) { unsigned char c; - sstr >> c; + ss >> c; return Variant(c); - } - case TYPE_INT16: - { + } else if (t == TYPE_INT16) { int16_t c; - sstr >> c; - return Variant(c); - } - case TYPE_UINT16: - { - uint16_t c; - sstr >> c; + ss >> c; return Variant(c); - } - case TYPE_INT32: - { + } else if (t == TYPE_INT32) { int32_t c; - sstr >> c; - return Variant(c); - } - case TYPE_UINT32: - { - uint32_t c; - sstr >> c; + ss >> c; return Variant(c); - } - case TYPE_INT64: - { + } else if (t == TYPE_INT64) { int64_t c; - sstr >> c; + ss >> c; return Variant(c); - } - case TYPE_UINT64: - { + } else if (t == TYPE_UINT16) { + uint16_t c; + ss >> c; + return Variant(c); + } else if (t == TYPE_UINT32) { + uint32_t c; + ss >> c; + return Variant(c); + } else if (t == TYPE_UINT64) { uint64_t c; - sstr >> c; + ss >> c; return Variant(c); - } - case TYPE_FLOAT: - { + } else if (t == TYPE_FLOAT) { float c; - sstr >> c; + ss >> c; return Variant(c); - } - case TYPE_DOUBLE: - { + } else if (t == TYPE_DOUBLE) { double c; - sstr >> c; + ss >> c; return Variant(c); + } else if (t == TYPE_LONGDOUBLE) { + long double c; + ss >> c; + return Variant(c); + } else if (t == TYPE_STRING) { + return Variant(s); + } else if (t == TYPE_COMPLEXF) { + float _vr, _vi; + ss >> _vr >> _vi; + complex_f v(_vr, _vi); + return Variant(v); + } else if (t == TYPE_COMPLEXD) { + double _vr, _vi; + ss >> _vr >> _vi; + complex_d v(_vr, _vi); + return Variant(v); + } else if (t == TYPE_VECTOR3F) { + Vector3f v; + float _val; + ss >> _val; + v.setX(_val); + ss >> _val; + v.setY(_val); + ss >> _val; + v.setZ(_val); + return Variant(v); + } else if (t == TYPE_VECTOR3D) { + Vector3d v; + double _val; + ss >> _val; + v.setX(_val); + ss >> _val; + v.setY(_val); + ss >> _val; + v.setZ(_val); + return Variant(v); + } else if (t == TYPE_VECTOR3C) { + Vector3c v; + std::complex _val; + ss >> _val; + v.setX(_val); + ss >> _val; + v.setY(_val); + ss >> _val; + v.setZ(_val); + return Variant(v); + } else if (t == TYPE_VECTOR) { + // std::regex useless("(|)|[|]| "); + vector_t v; + while (ss.good()) { + std::string s; + v.push_back(s); + } + } else { + std::string msg; + msg += "fromString not implemented for type "; + msg += getTypeName(t); + throw std::runtime_error("Variant: " + msg); } - case TYPE_STRING: - { - return Variant(str); - } - default: - throw std::runtime_error("pxl::Variant::fromString: unknown type"); - } - } -bool Variant::operator !=(const Variant &a) const -{ - if (type != a.type) - return true; +void Variant::clear(Type t) { + if (t == TYPE_STRING) + safeDelete(data._t_string); + else if (t == TYPE_VECTOR3F) + safeDelete(data._t_vector3f); + else if (t == TYPE_VECTOR3D) + safeDelete(data._t_vector3d); + else if (t == TYPE_VECTOR3C) + safeDelete(data._t_vector3c); + else if (t == TYPE_COMPLEXF) + safeDelete(data._t_complex_f); + else if (t == TYPE_COMPLEXD) + safeDelete(data._t_complex_d); + else if (t == TYPE_VECTOR) + safeDelete(data._t_vector); - switch (type) - { - case TYPE_BOOL: - return (data._Bool != a.data._Bool); - case TYPE_CHAR: - return (data._Char != a.data._Char); - case TYPE_UCHAR: - return (data._UChar != a.data._UChar); - case TYPE_INT16: - return (data._Int16 != a.data._Int16); - case TYPE_UINT16: - return (data._UInt16 == a.data._UInt16); - case TYPE_INT32: - return (data._Int32 == a.data._Int32); - case TYPE_UINT32: - return (data._UInt32 == a.data._UInt32); - case TYPE_INT64: - return (data._Int64 == a.data._Int64); - case TYPE_UINT64: - return (data._UInt64 == a.data._UInt64); - case TYPE_FLOAT: - return (data._Float == a.data._Float); - case TYPE_DOUBLE: - return (data._Double == a.data._Double); - case TYPE_STRING: - return (*data._String == *a.data._String); - default: - throw std::runtime_error("compare operator not implemented"); - } + // set the type to TYPE_NONE which will be used for checks + type = TYPE_NONE; + check(t); } +void Variant::copy(const Variant& v) { + Type t = v.type; -void Variant::copy(const Variant &a) -{ - Type t = a.type; - if (t == TYPE_BOOL) - { - operator =(a.data._Bool); - } + if (t == TYPE_BOOL) + operator = (v.data._t_bool); else if (t == TYPE_CHAR) - { - operator =(a.data._Char); - } + operator = (v.data._t_char); else if (t == TYPE_UCHAR) - { - operator =(a.data._UChar); - } + operator = (v.data._t_uchar); else if (t == TYPE_INT16) - { - operator =(a.data._Int16); - } + operator = (v.data._t_int16); else if (t == TYPE_UINT16) - { - operator =(a.data._UInt16); - } + operator = (v.data._t_uint16); else if (t == TYPE_INT32) - { - operator =(a.data._Int32); - } + operator = (v.data._t_int32); else if (t == TYPE_UINT32) - { - operator =(a.data._UInt32); - } + operator = (v.data._t_uint32); else if (t == TYPE_INT64) - { - operator =(a.data._Int64); - } + operator = (v.data._t_int64); else if (t == TYPE_UINT64) - { - operator =(a.data._UInt64); - } + operator = (v.data._t_uint64); else if (t == TYPE_FLOAT) - { - operator =(a.data._Float); - } + operator = (v.data._t_float); else if (t == TYPE_DOUBLE) - { - operator =(a.data._Double); - } + operator = (v.data._t_double); + else if (t == TYPE_LONGDOUBLE) + operator = (v.data._t_ldouble); else if (t == TYPE_STRING) - { - operator =(*a.data._String); - } + operator = (*v.data._t_string); + else if (t == TYPE_COMPLEXF) + operator = (*v.data._t_complex_f); + else if (t == TYPE_COMPLEXD) + operator = (*v.data._t_complex_d); + else if (t == TYPE_VECTOR3F) + operator = (*v.data._t_vector3f); + else if (t == TYPE_VECTOR3D) + operator = (*v.data._t_vector3d); + else if (t == TYPE_VECTOR3C) + operator = (*v.data._t_vector3c); + else if (t == TYPE_VECTOR) + operator = (*v.data._t_vector); else - { type = TYPE_NONE; +} + +void Variant::check(const Type t) const { + if (type != t) { + throw bad_conversion(type, t); } } -bool Variant::toBool() const -{ - switch (type) - { - case TYPE_BOOL: - return data._Bool; - break; - case TYPE_CHAR: - return data._Char != 0; - break; - case TYPE_UCHAR: - return data._UChar != 0; - break; - case TYPE_INT16: - return data._Int16 != 0; - break; - case TYPE_UINT16: - return data._UInt16 != 0; - break; - case TYPE_INT32: - return data._Int32 != 0; - break; - case TYPE_UINT32: - return data._UInt32 != 0; - break; - case TYPE_INT64: - return data._Int64 != 0; - break; - case TYPE_UINT64: - return data._UInt64 != 0; - break; - case TYPE_STRING: - { - std::string upperstr(*data._String); - std::transform(upperstr.begin(), upperstr.end(), upperstr.begin(), - (int(*)(int))toupper);if -( upperstr == "YES") - return true; - else if (upperstr == "NO") - return false; - if (upperstr == "TRUE") - return true; - else if (upperstr == "FALSE") - return false; - if (upperstr == "1") - return true; - else if (upperstr == "0") - return false; +void Variant::check(const Type t) { + if (type == TYPE_NONE) { + memset(&data, 0, sizeof(data)); + if (t == TYPE_VECTOR3F) + data._t_vector3f = new Vector3f(); + else if (t == TYPE_VECTOR3D) + data._t_vector3d = new Vector3d(); + else if (t == TYPE_VECTOR3C) + data._t_vector3c = new Vector3c(); + else if (t == TYPE_COMPLEXF) + data._t_complex_f = new complex_f(); + else if (t == TYPE_COMPLEXD) + data._t_complex_d = new complex_d(); + else if (t == TYPE_STRING) + data._t_string = new std::string(); + else if (t == TYPE_VECTOR) + data._t_vector = new vector_t(); else - throw bad_conversion(type, TYPE_BOOL); + type = t; + } else if (type != t) { + throw bad_conversion(type, t); } - break; - case TYPE_FLOAT: - case TYPE_DOUBLE: - case TYPE_NONE: - throw bad_conversion(type, TYPE_BOOL); - break; +} + +bool Variant::isValid() const { + return (type != TYPE_NONE); +} + +size_t Variant::size() const { + if (type == TYPE_VECTOR) { + return data._t_vector->size(); + } else { + std::string msg; + msg += "size() not implemented for type "; + msg += getTypeName(type); + throw std::runtime_error("Variant: " + msg); } - return false; } -#define INT_CASE(from_var, from_type, to_type, to) \ - case Variant::from_type:\ - if (data._##from_var < std::numeric_limits::min() || data._##from_var > std::numeric_limits::max())\ - throw bad_conversion(type, to_type);\ - else\ - return static_cast(data._##from_var);\ - break;\ - -#define INT_FUNCTION(to_type, fun, to) \ -to Variant::fun() const { \ - switch (type) { \ - case Variant::TYPE_BOOL: \ - return data._Bool ? 1 : 0; \ - break; \ - INT_CASE(Char, TYPE_CHAR, to_type, to) \ - INT_CASE(UChar, TYPE_UCHAR, to_type, to) \ - INT_CASE(Int16, TYPE_INT16, to_type, to) \ - INT_CASE(UInt16, TYPE_UINT16, to_type, to) \ - INT_CASE(Int32, TYPE_INT32, to_type, to) \ - INT_CASE(UInt32, TYPE_UINT32, to_type, to) \ - INT_CASE(Int64, TYPE_INT64, to_type, to) \ - INT_CASE(UInt64, TYPE_UINT64, to_type, to) \ - INT_CASE(Float, TYPE_FLOAT, to_type, to) \ - INT_CASE(Double, TYPE_DOUBLE, to_type, to) \ - case Variant::TYPE_STRING: \ - { \ - long l = atol(data._String->c_str()); \ - if (l < std::numeric_limits::min() || l > std::numeric_limits::max()) \ - throw bad_conversion(type, to_type); \ - else \ - return l; \ - } \ - break; \ - case Variant::TYPE_NONE: \ - throw bad_conversion(type, TYPE_INT16); \ - break;\ - }\ - return 0;\ -} - -INT_FUNCTION( TYPE_CHAR, toChar, char) -INT_FUNCTION( TYPE_UCHAR, toUChar, unsigned char) -INT_FUNCTION( TYPE_INT16, toInt16, int16_t) -INT_FUNCTION( TYPE_UINT16, toUInt16, uint16_t) -INT_FUNCTION( TYPE_INT32, toInt32, int32_t) -INT_FUNCTION( TYPE_UINT32, toUInt32, uint32_t) -INT_FUNCTION( TYPE_INT64, toInt64, int64_t) -INT_FUNCTION( TYPE_UINT64, toUInt64, uint64_t) - -std::ostream& operator <<(std::ostream& os, const Variant &v) -{ - switch (v.getType()) - { - case Variant::TYPE_BOOL: - os << v.asBool(); - break; - case Variant::TYPE_CHAR: - os << v.asChar(); - break; - case Variant::TYPE_UCHAR: - os << v.asUChar(); - break; - case Variant::TYPE_INT16: - os << v.asInt16(); - break; - case Variant::TYPE_UINT16: - os << v.asUInt16(); - break; - case Variant::TYPE_INT32: - os << v.asInt32(); - break; - case Variant::TYPE_UINT32: - os << v.asUInt32(); - break; - case Variant::TYPE_INT64: - os << v.asInt64(); - break; - case Variant::TYPE_UINT64: - os << v.asUInt64(); - break; - case Variant::TYPE_FLOAT: - os << v.asFloat(); - break; - case Variant::TYPE_DOUBLE: - os << v.asDouble(); - break; - case Variant::TYPE_STRING: - os << v.asString(); - break; - default: - break; +size_t Variant::getSizeOf() const { + switch (type) { + case TYPE_BOOL: + return sizeof(data._t_bool); + break; + case TYPE_CHAR: + return sizeof(data._t_char); + break; + case TYPE_UCHAR: + return sizeof(data._t_uchar); + break; + case TYPE_INT16: + return sizeof(data._t_int16); + break; + case TYPE_UINT16: + return sizeof(data._t_uint16); + break; + case TYPE_INT32: + return sizeof(data._t_int32); + break; + case TYPE_UINT32: + return sizeof(data._t_uint32); + break; + case TYPE_INT64: + return sizeof(data._t_int64); + break; + case TYPE_UINT64: + return sizeof(data._t_uint64); + break; + case TYPE_FLOAT: + return sizeof(data._t_float); + break; + case TYPE_DOUBLE: + return sizeof(data._t_double); + break; + case TYPE_LONGDOUBLE: + return sizeof(data._t_ldouble); + break; + case TYPE_COMPLEXF: + return sizeof(data._t_complex_f); + break; + case TYPE_COMPLEXD: + return sizeof(data._t_complex_d); + break; + case TYPE_VECTOR3F: + return sizeof(data._t_vector3f); + break; + case TYPE_VECTOR3D: + return sizeof(data._t_vector3d); + break; + case TYPE_VECTOR3C: + return sizeof(data._t_vector3c); + break; + case TYPE_STRING: { + size_t len = strlen(data._t_string->c_str() + 1); + return len; + } + break; + case TYPE_NONE: + return 0; + break; + default: + throw std::runtime_error("Function getSize() cannot handle this type."); } - return os; } +size_t Variant::getSize() const { + return getSizeOf(); +} +void Variant::resize(size_t i) { + check(TYPE_VECTOR); + return data._t_vector->resize(i); +} -float Variant::toFloat() const -{ - if (type == TYPE_CHAR) - { - return static_cast(data._Char); - } - else if (type == TYPE_UCHAR) - { - return static_cast(data._UChar); - } - else if (type == TYPE_INT16) - { - return static_cast(data._Int16); - } - else if (type == TYPE_UINT16) - { - return static_cast(data._UInt16); - } - else if (type == TYPE_INT32) - { - return static_cast(data._Int32); - } - else if (type == TYPE_UINT32) - { - return static_cast(data._UInt32); - } - else if (type == TYPE_INT64) - { - return static_cast(data._Int64); - } - else if (type == TYPE_UINT64) - { - return static_cast(data._UInt64); - } - else if (type == TYPE_FLOAT) - { - return static_cast(data._Float); - } - else if (type == TYPE_DOUBLE) - { - return static_cast(data._Double); - } - else if (type == TYPE_STRING) - { - return static_cast(std::atof(data._String->c_str())); - } - else if (type == TYPE_BOOL) - { - return data._Bool ? 1.0f : 0.0f; - } - else - { - return 0.0; +size_t Variant::copyToBuffer(void* buffer) { + if (type == TYPE_BOOL) { + memcpy(buffer, &data._t_bool, sizeof(bool)); + return sizeof(data._t_bool); + } else if (type == TYPE_CHAR) { + memcpy(buffer, &data._t_char, sizeof(char)); + return sizeof(data._t_char); + } else if (type == TYPE_UCHAR) { + memcpy(buffer, &data._t_uchar, sizeof(unsigned char)); + return sizeof(data._t_uchar); + } else if (type == TYPE_INT16) { + memcpy(buffer, &data._t_int16, sizeof(int16_t)); + return sizeof(data._t_int16); + } else if (type == TYPE_UINT16) { + memcpy(buffer, &data._t_uint16, sizeof(uint16_t)); + return sizeof(data._t_uint16); + } else if (type == TYPE_INT32) { + memcpy(buffer, &data._t_int32, sizeof(int32_t)); + return sizeof(data._t_int32); + } else if (type == TYPE_UINT32) { + memcpy(buffer, &data._t_uint32, sizeof(uint32_t)); + return sizeof(data._t_uint32); + } else if (type == TYPE_INT64) { + memcpy(buffer, &data._t_int64, sizeof(int64_t)); + return sizeof(data._t_int64); + } else if (type == TYPE_UINT64) { + memcpy(buffer, &data._t_uint64, sizeof(uint64_t)); + return sizeof(data._t_uint64); + } else if (type == TYPE_FLOAT) { + memcpy(buffer, &data._t_float, sizeof(float)); + return sizeof(data._t_float); + } else if (type == TYPE_DOUBLE) { + memcpy(buffer, &data._t_double, sizeof(double)); + return sizeof(data._t_double); + } else if (type == TYPE_LONGDOUBLE) { + memcpy(buffer, &data._t_ldouble, sizeof(long double)); + return sizeof(data._t_ldouble); + } else if (type == TYPE_STRING) { + size_t len = data._t_string->size(); + memcpy(buffer, data._t_string->c_str(), len); + return len; + } else if (type == TYPE_NONE) { + return 0; + } else { + throw std::runtime_error("This type cannot be handled by copyToBuffer()."); } } -double Variant::toDouble() const -{ - if (type == TYPE_CHAR) - { - return static_cast(data._Char); - } - else if (type == TYPE_UCHAR) - { - return static_cast(data._UChar); - } - else if (type == TYPE_INT16) - { - return static_cast(data._Int16); - } - else if (type == TYPE_UINT16) - { - return static_cast(data._UInt16); - } - else if (type == TYPE_INT32) - { - return static_cast(data._Int32); - } - else if (type == TYPE_UINT32) - { - return static_cast(data._UInt32); - } - else if (type == TYPE_INT64) - { - return static_cast(data._Int64); - } - else if (type == TYPE_UINT64) - { - return static_cast(data._UInt64); - } - else if (type == TYPE_FLOAT) - { - return static_cast(data._Float); - } - else if (type == TYPE_DOUBLE) - { - return static_cast(data._Double); - } - else if (type == TYPE_STRING) - { - return std::atof(data._String->c_str()); - } - else if (type == TYPE_BOOL) - { - return data._Bool ? 1.0 : 0.0; +Variant& Variant::operator=(const Variant &v) { + copy(v); + return *this; +} + +bool Variant::operator==(const Variant& v) const { + if (type != v.type) + return false; + + if (type == TYPE_BOOL) { + return (data._t_bool == v.data._t_bool); + } else if (type == TYPE_CHAR) { + return (data._t_char == v.data._t_char); + } else if (type == TYPE_UCHAR) { + return (data._t_uchar == v.data._t_uchar); + } else if (type == TYPE_INT16) { + return (data._t_int16 == v.data._t_int16); + } else if (type == TYPE_UINT16) { + return (data._t_uint16 == v.data._t_uint16); + } else if (type == TYPE_INT32) { + return (data._t_int32 == v.data._t_int32); + } else if (type == TYPE_UINT32) { + return (data._t_uint32 == v.data._t_uint32); + } else if (type == TYPE_INT64) { + return (data._t_int64 == v.data._t_int64); + } else if (type == TYPE_UINT64) { + return (data._t_uint64 == v.data._t_uint64); + } else if (type == TYPE_FLOAT) { + return (data._t_float == v.data._t_float); + } else if (type == TYPE_DOUBLE) { + return (data._t_double == v.data._t_double); + } else if (type == TYPE_LONGDOUBLE) { + return (data._t_ldouble == v.data._t_ldouble); + } else if (type == TYPE_STRING) { + return (*data._t_string == *v.data._t_string); + } else if (type == TYPE_COMPLEXF) { + return (*data._t_complex_f == *v.data._t_complex_f); + } else if (type == TYPE_COMPLEXD) { + return (*data._t_complex_d == *v.data._t_complex_d); + } else if (type == TYPE_VECTOR3F) { + return (*data._t_vector3f == *v.data._t_vector3f); + } else if (type == TYPE_VECTOR3D) { + return (*data._t_vector3d == *v.data._t_vector3d); + } else if (type == TYPE_VECTOR3C) { + return (*data._t_vector3c == *v.data._t_vector3c); + } else if (type == TYPE_VECTOR) { + return (*data._t_vector == *v.data._t_vector); + } else { + throw std::runtime_error("compare operator not implemented"); } +} + +bool Variant::operator!=(const Variant& v) const { + if (type != v.type) + return true; + + if (*this == v) + return false; else - { - return 0.0; - } + return true; } +bool Variant::operator!=(const char* v) const { + check(TYPE_STRING); + return data._t_string->compare(v) != 0; +} -#define MEMCPYRET(VAR) \ - memcpy(buffer, &VAR, sizeof( VAR) );\ - return sizeof( VAR ); +Variant& Variant::operator[](size_t i) { + check(TYPE_VECTOR); + return (*data._t_vector)[i]; +} -size_t Variant::copyToBuffer(void* buffer) -{ - if (type == TYPE_CHAR) - { - MEMCPYRET( data._Char ) - } - else if (type == TYPE_UCHAR) - { - MEMCPYRET( data._UChar ) - } - else if (type == TYPE_INT16) - { - MEMCPYRET(data._Int16); - } - else if (type == TYPE_UINT16) - { - MEMCPYRET(data._UInt16); - } - else if (type == TYPE_INT32) - { - MEMCPYRET(data._Int32); - } - else if (type == TYPE_UINT32) - { - MEMCPYRET(data._UInt32); - } - else if (type == TYPE_INT64) - { - MEMCPYRET(data._Int64); - } - else if (type == TYPE_UINT64) - { - MEMCPYRET(data._UInt64); - } - else if (type == TYPE_FLOAT) - { - MEMCPYRET(data._Float); - } - else if (type == TYPE_DOUBLE) - { - MEMCPYRET(data._Double); - } - else if (type == TYPE_STRING) - { - size_t len = data._String->size(); - memcpy(buffer, data._String->c_str(), len); - return len; - } - else if (type == TYPE_BOOL) - { - MEMCPYRET(data._Bool); - } - else if (type == TYPE_NONE) - { - return 0; - } - throw std::runtime_error("This is serious: Type not handled in copyToBuffer()!"); -}; - -size_t Variant::getSize() const -{ - if (type == TYPE_CHAR) - { - return sizeof(data._Char); - } - else if (type == TYPE_UCHAR) - { - return sizeof(data._UChar); - } - else if (type == TYPE_INT16) - { - return sizeof(data._Int16); - } - else if (type == TYPE_UINT16) - { - return sizeof(data._UInt16); - } - else if (type == TYPE_INT32) - { - return sizeof(data._Int32); - } - else if (type == TYPE_UINT32) - { - return sizeof(data._UInt32); - } - else if (type == TYPE_INT64) - { - return sizeof(data._Int64); - } - else if (type == TYPE_UINT64) - { - return sizeof(data._UInt64); - } - else if (type == TYPE_FLOAT) - { - return sizeof(data._Float); - } - else if (type == TYPE_DOUBLE) - { - return sizeof(data._Double); - } - else if (type == TYPE_STRING) - { - size_t len = strlen(data._String->c_str()+1); - return len; - } - else if (type == TYPE_BOOL) - { - return sizeof(data._Bool); - } - else if (type == TYPE_NONE) - { - return 0; +const Variant& Variant::operator[](size_t i) const { + check(TYPE_VECTOR); + return (*data._t_vector)[i]; +} + +Variant::operator std::vector&() { + check(TYPE_VECTOR); + return *data._t_vector; +} + +Variant::operator const std::vector&() const { + check(TYPE_VECTOR); + return *data._t_vector; +} + + + +#define INT_CASE(from_var, from_type, to_type, to) \ + case Variant::from_type: { \ + if (data._t_##from_var ::min() || data._t_##from_var> std::numeric_limits::max()) \ + throw bad_conversion(type, to_type); \ + else \ + return static_cast(data._t_##from_var); \ + } \ + break; \ + +#define INT_FUNCTION(to_type, fun, to) \ + to Variant::fun() const { \ + switch (type) { \ + case Variant::TYPE_BOOL: \ + return data._t_bool ? 1 : 0; \ + break; \ + INT_CASE(char, TYPE_CHAR, to_type, to) \ + INT_CASE(uchar, TYPE_UCHAR, to_type, to) \ + INT_CASE(int16, TYPE_INT16, to_type, to) \ + INT_CASE(uint16, TYPE_UINT16, to_type, to) \ + INT_CASE(int32, TYPE_INT32, to_type, to) \ + INT_CASE(uint32, TYPE_UINT32, to_type, to) \ + INT_CASE(int64, TYPE_INT64, to_type, to) \ + INT_CASE(uint64, TYPE_UINT64, to_type, to) \ + INT_CASE(float, TYPE_FLOAT, to_type, to) \ + INT_CASE(double, TYPE_DOUBLE, to_type, to) \ + INT_CASE(ldouble, TYPE_LONGDOUBLE, to_type, to) \ + case Variant::TYPE_STRING: { \ + long l = atol(data._t_string->c_str()); \ + if (l ::min() || l > std::numeric_limits::max()) \ + throw bad_conversion(type, to_type); \ + else \ + return l; \ + } \ + break; \ + case Variant::TYPE_COMPLEXF: \ + case Variant::TYPE_COMPLEXD: \ + case Variant::TYPE_VECTOR3F: \ + case Variant::TYPE_VECTOR3D: \ + case Variant::TYPE_VECTOR3C: \ + case Variant::TYPE_VECTOR: \ + case Variant::TYPE_NONE: \ + throw bad_conversion(type, to_type); \ + break; \ + } \ + return 0; \ + } + +INT_FUNCTION(TYPE_CHAR, toChar, char) +INT_FUNCTION(TYPE_UCHAR, toUChar, unsigned char) +INT_FUNCTION(TYPE_INT16, toInt16, int16_t) +INT_FUNCTION(TYPE_UINT16, toUInt16, uint16_t) +INT_FUNCTION(TYPE_INT32, toInt32, int32_t) +INT_FUNCTION(TYPE_UINT32, toUInt32, uint32_t) +INT_FUNCTION(TYPE_INT64, toInt64, int64_t) +INT_FUNCTION(TYPE_UINT64, toUInt64, uint64_t) + + + +std::ostream& operator <<(std::ostream& os, const Variant& v) { + switch (v.getType()) { + case Variant::TYPE_BOOL: + os << v.asBool(); + break; + case Variant::TYPE_CHAR: + os << v.asChar(); + break; + case Variant::TYPE_UCHAR: + os << v.asUChar(); + break; + case Variant::TYPE_INT16: + os << v.asInt16(); + break; + case Variant::TYPE_UINT16: + os << v.asUInt16(); + break; + case Variant::TYPE_INT32: + os << v.asInt32(); + break; + case Variant::TYPE_UINT32: + os << v.asUInt32(); + break; + case Variant::TYPE_INT64: + os << v.asInt64(); + break; + case Variant::TYPE_UINT64: + os << v.asUInt64(); + break; + case Variant::TYPE_FLOAT: + os << v.asFloat(); + break; + case Variant::TYPE_DOUBLE: + os << v.asDouble(); + break; + case Variant::TYPE_LONGDOUBLE: + os << v.asLongDouble(); + break; + case Variant::TYPE_COMPLEXF: + os << v.asComplexFloat(); + break; + case Variant::TYPE_COMPLEXD: + os << v.asComplexDouble(); + break; + case Variant::TYPE_STRING: + os << v.asString(); + break; + case Variant::TYPE_VECTOR3F: + os << v.asVector3f(); + break; + case Variant::TYPE_VECTOR3D: + os << v.asVector3d(); + break; + case Variant::TYPE_VECTOR3C: + os << v.asVector3c(); + break; + default: + break; } - throw std::runtime_error("This is serious: Type not handled in getSize()!"); -}; + + return os; +} -} // namespace pxl +} // namespace crpropa diff --git a/src/advectionField/AdvectionField.cpp b/src/advectionField/AdvectionField.cpp index 45fd60d41..65f089a62 100644 --- a/src/advectionField/AdvectionField.cpp +++ b/src/advectionField/AdvectionField.cpp @@ -177,6 +177,255 @@ std::string SphericalAdvectionField::getDescription() const { return s.str(); } +//---------------------------------------------------------------- + +OneDimensionalCartesianShock::OneDimensionalCartesianShock(double compressionRatio, double vUp, double lShock){ + setComp(compressionRatio); + setVup(vUp); + setShockwidth(lShock); + } + +Vector3d OneDimensionalCartesianShock::getField(const Vector3d &position) const { + double x = position.x; + double vDown = vUp / compressionRatio; + + double a = (vUp + vDown) * 0.5; + double b = (vUp - vDown) * 0.5; + + Vector3d v(0.); + v.x = a - b * tanh(x / lShock); + return v; + +} + +double OneDimensionalCartesianShock::getDivergence(const Vector3d &position) const { + double x = position.x; + double vDown = vUp / compressionRatio; + + double a = (vUp + vDown) * 0.5; + double b = (vUp - vDown) * 0.5; + return -b / lShock * (1 - tanh(x / lShock) * tanh(x / lShock)); +} + +void OneDimensionalCartesianShock::setComp(double r) { + compressionRatio = r; + return; +} + +void OneDimensionalCartesianShock::setVup(double v) { + vUp = v; + return; +} +void OneDimensionalCartesianShock::setShockwidth(double w) { + lShock = w; + return; +} + +double OneDimensionalCartesianShock::getComp() const { + return compressionRatio; +} + +double OneDimensionalCartesianShock::getVup() const { + return vUp; +} + +double OneDimensionalCartesianShock::getShockwidth() const { + return lShock; +} + +std::string OneDimensionalCartesianShock::getDescription() const { + std::stringstream s; + s << "Shock width: " << lShock / km << " km, "; + s << "Vup: " << vUp / km * sec << " km/s, "; + s << "Compression: " << compressionRatio; + return s.str(); +} + +//---------------------------------------------------------------- + +OneDimensionalSphericalShock::OneDimensionalSphericalShock(double rShock, double vUp, double compressionRatio, double lShock, bool coolUpstream ){ + setComp(compressionRatio); + setVup(vUp); + setShockwidth(lShock); + setShockRadius(rShock); + setCooling(coolUpstream); + } + +Vector3d OneDimensionalSphericalShock::getField(const Vector3d &position) const { + double r = position.getR(); + Vector3d e_r = position.getUnitVector(); + + double vDown = vUp / compressionRatio; + double a = (vUp + vDown) * 0.5; + double b = (vUp - vDown) * 0.5; + + double v; + if (coolUpstream == true){ + + if (r <= rShock) + v = a - b * tanh((r-rShock) / lShock); + else + v = (a - b * tanh((r-rShock) / lShock)) * (rShock / r) * (rShock / r); + + } + else + v = (a - b * tanh((r-rShock) / lShock)) * (rShock / r) * (rShock / r); + + return v * e_r; + } + +double OneDimensionalSphericalShock::getDivergence(const Vector3d &position) const { + double r = position.getR(); + + double vDown = vUp / compressionRatio; + double a = (vUp + vDown) * 0.5; + double b = (vUp - vDown) * 0.5; + + double c = tanh((r-rShock) / lShock); + + if (coolUpstream == true){ + if (r <= rShock) + return 2 * a / r - 2 * b / r * c - b / lShock * (1 - c * c); + else + return -(rShock / r) * (rShock / r) * b / lShock * (1 - c * c); + } + else + return -(rShock / r) * (rShock / r) * b / lShock * (1 - c * c); + +} + +void OneDimensionalSphericalShock::setComp(double r) { + compressionRatio = r; + return; +} + +void OneDimensionalSphericalShock::setVup(double v) { + vUp = v; + return; +} +void OneDimensionalSphericalShock::setShockwidth(double w) { + lShock = w; + return; +} + +void OneDimensionalSphericalShock::setShockRadius(double r) { + rShock = r; + return; +} + +void OneDimensionalSphericalShock::setCooling(bool c) { + coolUpstream = c; + return; +} + +double OneDimensionalSphericalShock::getComp() const { + return compressionRatio; +} + +double OneDimensionalSphericalShock::getVup() const { + return vUp; +} + +double OneDimensionalSphericalShock::getShockwidth() const { + return lShock; +} + +double OneDimensionalSphericalShock::getShockRadius() const { + return rShock; +} + +bool OneDimensionalSphericalShock::getCooling() const { + return coolUpstream; +} + +std::string OneDimensionalSphericalShock::getDescription() const { + std::stringstream s; + s << "Shock width: " << lShock / km << " km, "; + s << "Shock radius: " << rShock / km << " km, "; + s << "Vup: " << vUp / km * sec << " km/s, "; + s << "Comp: " << compressionRatio; + + return s.str(); +} + +//---------------------------------------------------------------- + +ObliqueAdvectionShock::ObliqueAdvectionShock(double compressionRatio, double vXUp, double vY, double lShock) { + setComp(compressionRatio); + setVup(vXUp); + setVy(vY); + setShockwidth(lShock); + } + +Vector3d ObliqueAdvectionShock::getField(const Vector3d &position) const { + double x = position.x; + double vXDown = vXUp / compressionRatio; + + double a = (vXUp + vXDown) * 0.5; + double b = (vXUp - vXDown) * 0.5; + + Vector3d v(0.); + v.x = a - b * tanh(x / lShock); + v.y = vY; + + return v; + } + +double ObliqueAdvectionShock::getDivergence(const Vector3d &position) const { + double x = position.x; + double vXDown = vXUp / compressionRatio; + // vy = const + + double a = (vXUp + vXDown) * 0.5; + double b = (vXUp - vXDown) * 0.5; + + return -b / lShock * (1 - tanh(x / lShock) * tanh(x / lShock)); + } + +void ObliqueAdvectionShock::setComp(double r) { + compressionRatio = r; + return; +} + +void ObliqueAdvectionShock::setVup(double v) { + vXUp = v; + return; +} + +void ObliqueAdvectionShock::setVy(double v) { + vY = v; + return; +} +void ObliqueAdvectionShock::setShockwidth(double w) { + lShock = w; + return; +} + +double ObliqueAdvectionShock::getComp() const { + return compressionRatio; +} + +double ObliqueAdvectionShock::getVup() const { + return vXUp; +} + +double ObliqueAdvectionShock::getVy() const { + return vY; +} + +double ObliqueAdvectionShock::getShockwidth() const { + return lShock; +} + +std::string ObliqueAdvectionShock::getDescription() const { + std::stringstream s; + s << "Shock width: " << lShock / km << " km, "; + s << "Vx_up: " << vXUp / km * sec << " km/s, "; + s << "Vy: " << vY / km * sec << " km/s, "; + s << "Comp: " << compressionRatio; + + return s.str(); +} //----------------------------------------------------------------- diff --git a/src/module/CandidateSplitting.cpp b/src/module/CandidateSplitting.cpp new file mode 100644 index 000000000..de7604864 --- /dev/null +++ b/src/module/CandidateSplitting.cpp @@ -0,0 +1,118 @@ +#include "crpropa/module/CandidateSplitting.h" + +namespace crpropa { + +CandidateSplitting::CandidateSplitting() { + // no particle splitting if EnergyBins and NSplit are not specified + setNsplit(0); + setMinimalWeight(1.); +} + +CandidateSplitting::CandidateSplitting(int nSplit, double Emin, double Emax, double nBins, double minWeight, bool log) { + setNsplit(nSplit); + setEnergyBins(Emin, Emax, nBins, log); + setMinimalWeight(minWeight); +} + +CandidateSplitting::CandidateSplitting(double spectralIndex, double Emin, int nBins) { + // to use with Diffusive Shock Acceleration + if (spectralIndex > 0){ + throw std::runtime_error( + "CandidateSplitting: spectralIndex > 0 !"); + } + + setNsplit(2); // always split in 2, calculate bins in energy for given spectrum: + double dE = pow(1. / 2, 1. / (spectralIndex + 1)); + setEnergyBinsDSA(Emin, dE, nBins); + setMinimalWeight(1. / pow(2, nBins)); +} + +void CandidateSplitting::process(Candidate *c) const { + double currE = c->current.getEnergy(); + double prevE = c->previous.getEnergy(); + + if (c->getWeight() <= minWeight){ + // minimal weight reached, no splitting + return; + } + if (currE < Ebins[0] || nSplit == 0 ){ + // current energy is smaller than first bin -> no splitting + // or, number of splits = 0 + return; + } + for (size_t i = 0; i < Ebins.size(); ++i){ + + if( prevE < Ebins[i] ){ + // previous energy is in energy bin [i-1, i] + if(currE < Ebins[i]){ + //assuming that dE greater than 0, prevE and E in same energy bin -> no splitting + return; + } + // current energy is in energy bin [i,i+1] or higher -> particle splitting for each crossing + for (size_t j = i; j < Ebins.size(); ++j ){ + + // adapted from Acceleration Module: + c->updateWeight(1. / nSplit); // * 1/n_split + + for (int i = 1; i < nSplit; i++) { + + ref_ptr new_candidate = c->clone(false); + new_candidate->parent = c; + new_candidate->previous.setEnergy(currE); // so that new candidate is not split again in next step! + c->addSecondary(new_candidate); + } + if (j < Ebins.size()-1 && currE < Ebins[j+1]){ + // candidate is in energy bin [j, j+1] -> no further splitting + return; + } + } + return; + } + } +} + +void CandidateSplitting::setEnergyBins(double Emin, double Emax, double nBins, bool log) { + Ebins.resize(0); + if (Emin > Emax){ + throw std::runtime_error( + "CandidateSplitting: Emin > Emax!"); + } + double dE = (Emax-Emin)/nBins; + for (size_t i = 0; i < nBins; ++i) { + if (log == true) { + Ebins.push_back(Emin * pow(Emax / Emin, i / (nBins - 1.0))); + } else { + Ebins.push_back(Emin + i * dE); + } + } +} + +void CandidateSplitting::setEnergyBinsDSA(double Emin, double dE, int n) { + Ebins.resize(0); + for (size_t i = 1; i < n + 1; ++i) { + Ebins.push_back(Emin * pow(dE, i)); + } +} + +const std::vector& CandidateSplitting::getEnergyBins() const { + return Ebins; +} + +void CandidateSplitting::setNsplit(int n) { + nSplit = n; +} + +void CandidateSplitting::setMinimalWeight(double w) { + minWeight = w; +} + +int CandidateSplitting::getNsplit() const { + return nSplit; +} + +double CandidateSplitting::getMinimalWeight() const { + return minWeight; +} + +} // end namespace crpropa + diff --git a/src/module/EMCascade.cpp b/src/module/EMCascade.cpp deleted file mode 100644 index 924192e3c..000000000 --- a/src/module/EMCascade.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include "crpropa/module/EMCascade.h" -#include "crpropa/Cosmology.h" -#include "crpropa/Units.h" - -#include "dint/DintEMCascade.h" -#include "kiss/logger.h" - -#include -#include -#include -#include -#include -#include - -namespace crpropa { - -EMCascade::EMCascade() : nE(170), logEmin(7), logEmax(24), dlogE(0.1) { - KISS_LOG_WARNING << "EMCascade is deprecated and is no longer supported. Please use the EM* (EMPairProduction, EMInverseComptonScattering, ...) modules instead.\n"; - setDistanceBinning(1000 * Mpc, 1000); -} - -void EMCascade::setDistanceBinning(double Dmax, int nD) { - this->Dmax = Dmax; - this->nD = nD; - this->dD = Dmax / nD; - init(); -} - -void EMCascade::init() { - photonHist.reserve(nD * nE); - photonHist.assign(nD * nE, 0); - electronHist.reserve(nD * nE); - electronHist.assign(nD * nE, 0); - positronHist.reserve(nD * nE); - positronHist.assign(nD * nE, 0); -} - -std::string EMCascade::getDescription() const { - std::stringstream s; - s << "EMCascade"; - return s.str(); -} - -void EMCascade::process(Candidate *candidate) const { - int id = candidate->current.getId(); - if ((id != 22) and (id != 11) and (id != -11)) - return; - - candidate->setActive(false); - - double logE = log10(candidate->current.getEnergy() / eV); - double D = candidate->current.getPosition().getR(); // distance to (0,0,0) - - if ((logE < logEmin) or (logE > logEmax)) - return; - if (D > Dmax) - return; - - int iE = (logE - logEmin) / dlogE; - int iD = D / dD; - int i = (iD * nE) + iE; - -#pragma omp critical - { - if (id == 22) - photonHist[i] += 1; - else if (id == 11) - electronHist[i] += 1; - else - positronHist[i] += 1; - } -} - -void EMCascade::save(const std::string &filename) { - std::ofstream outfile(filename.c_str()); - if (!outfile) { - std::stringstream s; - s << "EMCascade: could not open " << filename; - throw std::runtime_error(s.str()); - } - outfile << "# D/Mpc log10(E/eV) nPhotons nElectrons nPositrons\n"; - for (int i = 0; i < (nD * nE); i++) { - div_t divresult = div(i, nE); - double D = (divresult.quot + 0.5) * dD / Mpc; - double logE = logEmin + (divresult.rem + 0.5) * dlogE; - outfile << D << "\t"; - outfile << logE << "\t"; - outfile << photonHist[i] << "\t"; - outfile << electronHist[i] << "\t"; - outfile << positronHist[i] << "\n"; - } - outfile.close(); -} - -void EMCascade::load(const std::string &filename) { - std::ifstream infile(filename.c_str()); - if (!infile) { - std::stringstream s; - s << "EMCascade: could not open " << filename; - throw std::runtime_error(s.str()); - } - - infile.ignore(std::numeric_limits::max(), '\n'); // skip header - double D, lE, h1, h2, h3; - for (int i = 0; i < (nD * nE); i++) { - infile >> D >> lE >> h1 >> h2 >> h3; - if (!infile.good()) - throw std::runtime_error("EMCascde: error reading file"); - photonHist[i] += h1; - electronHist[i] += h2; - positronHist[i] += h3; - } - infile.close(); -} - -void EMCascade::runCascade(const std::string &filename, int IRBFlag, - int RadioFlag, double Bfield, double cutCascade) { - - // set up DINT - std::string dataPath = getDataPath("dint"); - double B = Bfield / gauss; - double h = H0() * Mpc / 1000; - DintEMCascade dint(IRBFlag, RadioFlag, dataPath, B, h, omegaM(), omegaL()); - - Spectrum inputSpectrum, outputSpectrum; - NewSpectrum(&inputSpectrum, nE); - NewSpectrum(&outputSpectrum, nE); - InitializeSpectrum(&outputSpectrum); - - // step-wise cascade calculation - for (int iD = nD - 1; iD >= 0; iD--) { - // make output of previous step the new input and reset output - SetSpectrum(&inputSpectrum, &outputSpectrum); - InitializeSpectrum(&outputSpectrum); - - // add new particles to input - double count = 0; - for (int iE = 0; iE < nE; iE++) { - int i = (iD * nE) + iE; - inputSpectrum.spectrum[PHOTON][iE] += photonHist[i]; - inputSpectrum.spectrum[ELECTRON][iE] += electronHist[i]; - inputSpectrum.spectrum[POSITRON][iE] += positronHist[i]; - count += inputSpectrum.spectrum[PHOTON][iE]; - count += inputSpectrum.spectrum[ELECTRON][iE]; - count += inputSpectrum.spectrum[POSITRON][iE]; - } - // skip step if input spectrum empty - if (count == 0) - continue; - - // start and stop distance [Mpc,light travel] from bin center to bin center - double D1 = comoving2LightTravelDistance( (iD + 0.5) * dD ); - double D0 = comoving2LightTravelDistance( std::max((iD - 0.5) * dD, 0.) ); - - // propagate distance step - dint.propagate(D1/Mpc, D0/Mpc, &inputSpectrum, &outputSpectrum, cutCascade); - } - - // write output - std::ofstream outfile(filename.c_str()); - if (!outfile) { - std::stringstream s; - s << "EMCascade: could not open " << filename; - throw std::runtime_error(s.str()); - } - outfile << "# log10(E/eV) photons electrons positrons\n"; - for (int iE = 0; iE < nE; iE++) { - outfile << std::setw(5) << logEmin + (iE + 0.5) * dlogE; - for (int s = 0; s < 3; s++) - outfile << std::setw(13) << outputSpectrum.spectrum[s][iE]; - outfile << "\n"; - } - outfile.close(); - - // clear the histogram - photonHist.assign(nD * nE, 0); - electronHist.assign(nD * nE, 0); - positronHist.assign(nD * nE, 0); - - DeleteSpectrum(&outputSpectrum); - DeleteSpectrum(&inputSpectrum); -} - -} // namespace crpropa diff --git a/src/module/MomentumDiffusion.cpp b/src/module/MomentumDiffusion.cpp new file mode 100644 index 000000000..dc9b795c5 --- /dev/null +++ b/src/module/MomentumDiffusion.cpp @@ -0,0 +1,71 @@ +#include "crpropa/module/MomentumDiffusion.h" + +using namespace crpropa; + +ConstantMomentumDiffusion::ConstantMomentumDiffusion(double Dpp) { + setLimit(0.1); + setDpp(Dpp); +} + +ConstantMomentumDiffusion::ConstantMomentumDiffusion(double Dpp, double limit) { + setLimit(limit); + setDpp(Dpp); +} + +void ConstantMomentumDiffusion::process(Candidate *c) const { + double rig = c->current.getRigidity(); + if (std::isinf(rig)) { + return; // Only charged particles + } + + double p = c->current.getEnergy() / c_light; // Note we use E=p/c (relativistic limit) + double dt = c->getCurrentStep() / c_light; + + double eta = Random::instance().randNorm(); + double domega = eta * sqrt(dt); + + double AScal = calculateAScalar(p); + double BScal = calculateBScalar(); + + double dp = AScal * dt + BScal * domega; + c->current.setEnergy((p + dp) * c_light); + + c->limitNextStep(limit * p / AScal * c_light); +} + +double ConstantMomentumDiffusion::calculateAScalar(double p) const { + double a = + 2. / p * Dpp; + return a; +} + +double ConstantMomentumDiffusion::calculateBScalar() const { + double b = sqrt(2 * Dpp); + return b; +} + +void ConstantMomentumDiffusion::setDpp(double d) { + if (d < 0 ) + throw std::runtime_error( + "ConstantMomentumDiffusion: Dpp must be non-negative"); + Dpp = d; +} + +void ConstantMomentumDiffusion::setLimit(double l) { + limit = l; +} + +double ConstantMomentumDiffusion::getDpp() const { + return Dpp; +} + +double ConstantMomentumDiffusion::getLimit() const { + return limit; +} + +std::string ConstantMomentumDiffusion::getDescription() const { + std::stringstream s; + s << "limit: " << limit << "\n"; + s << "Dpp: " << Dpp / (meter * meter / second) << " m^2/s"; + + return s.str(); +} diff --git a/src/module/Output.cpp b/src/module/Output.cpp index b72641455..dd3978869 100644 --- a/src/module/Output.cpp +++ b/src/module/Output.cpp @@ -43,13 +43,12 @@ void Output::setOutputType(OutputType outputtype) { set(CurrentEnergyColumn, true); set1D(true); } else if (outputtype == Event1D) { - // D, ID, E, ID0, E0, tag + // D, ID, E, ID0, E0 set(TrajectoryLengthColumn, true); set(CurrentIdColumn, true); set(CurrentEnergyColumn, true); set(SourceIdColumn, true); set(SourceEnergyColumn, true); - set(CandidateTagColumn, true); set1D(true); } else if (outputtype == Trajectory3D) { // D, ID, E, X, Y, Z, Px, Py, Pz @@ -60,7 +59,7 @@ void Output::setOutputType(OutputType outputtype) { set(CurrentDirectionColumn, true); set1D(false); } else if (outputtype == Event3D) { - // D, ID, E, X, Y, Z, Px, Py, Pz, ID0, E0, X0, Y0, Z0, P0x, P0y, P0z, tag + // D, ID, E, X, Y, Z, Px, Py, Pz, ID0, E0, X0, Y0, Z0, P0x, P0y, P0z set(TrajectoryLengthColumn, true); set(CurrentIdColumn, true); set(CurrentEnergyColumn, true); @@ -70,7 +69,6 @@ void Output::setOutputType(OutputType outputtype) { set(SourceEnergyColumn, true); set(SourcePositionColumn, true); set(SourceDirectionColumn, true); - set(CandidateTagColumn, true); set1D(false); } else if (outputtype == Everything) { enableAll(); diff --git a/src/module/PhotonEleCa.cpp b/src/module/PhotonEleCa.cpp deleted file mode 100644 index 97425fcab..000000000 --- a/src/module/PhotonEleCa.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "crpropa/module/PhotonEleCa.h" -#include "crpropa/Units.h" - -#include "EleCa/Propagation.h" -#include "EleCa/Particle.h" -#include "EleCa/Common.h" -#include "kiss/logger.h" - -#include - -namespace crpropa { - -PhotonEleCa::PhotonEleCa(const std::string background, - const std::string &outputFilename) : - propagation(new eleca::Propagation), saveOnlyPhotonEnergies(false) { - KISS_LOG_WARNING << "EleCa propagation is deprecated and is no longer supported. Please use the EM* (EMPairProduction, EMInverseComptonScattering, ...) modules instead.\n"; - propagation->ReadTables(getDataPath("EleCa/eleca.dat")); - propagation->InitBkgArray(background); - output.open(outputFilename.c_str()); -} - -PhotonEleCa::~PhotonEleCa() { -} - -void PhotonEleCa::process(Candidate *candidate) const { - if (candidate->current.getId() != 22) - return; // do nothing if not a photon - - double z = candidate->getRedshift(); - if (z == 0) - z = eleca::Mpc2z( - (candidate->current.getPosition() - observer).getR() / Mpc); - eleca::Particle p0(candidate->current.getId(), - candidate->current.getEnergy() / eV, z); - std::vector ParticleAtMatrix; - std::vector ParticleAtGround; - ParticleAtMatrix.push_back(p0); - - while (ParticleAtMatrix.size() > 0) { - - eleca::Particle p1 = ParticleAtMatrix.back(); - ParticleAtMatrix.pop_back(); - - if (p1.IsGood()) { - propagation->Propagate(p1, ParticleAtMatrix, ParticleAtGround); - } - } - -#pragma omp critical - { - if (saveOnlyPhotonEnergies) { - for (int i = 0; i < ParticleAtGround.size(); ++i) { - eleca::Particle &p = ParticleAtGround[i]; - if (p.GetType() != 22) - continue; - output << p.GetEnergy() << "\n"; - } - } else { - propagation->WriteOutput(output, p0, ParticleAtGround); - } - } - - candidate->setActive(false); - return; -} - -void PhotonEleCa::setObserver(const Vector3d &position) { - observer = position; -} - -void PhotonEleCa::setSaveOnlyPhotonEnergies(bool photonsOnly) { - saveOnlyPhotonEnergies = photonsOnly; -} - -std::string PhotonEleCa::getDescription() const { - std::stringstream s; - s << "PhotonEleCa"; - return s.str(); -} - -} // namespace crpropa diff --git a/src/module/TextOutput.cpp b/src/module/TextOutput.cpp index 89590c5a7..07bd5ea3c 100644 --- a/src/module/TextOutput.cpp +++ b/src/module/TextOutput.cpp @@ -257,18 +257,14 @@ void TextOutput::process(Candidate *c) const { } for(std::vector::const_iterator iter = properties.begin(); - iter != properties.end(); ++iter) - { + iter != properties.end(); ++iter) { Variant v; - if (c->hasProperty((*iter).name)) - { + if (c->hasProperty((*iter).name)) { v = c->getProperty((*iter).name); - } - else - { + } else { v = (*iter).defaultValue; } - p += std::sprintf(buffer + p, "%s", v.toString().c_str()); + p += std::sprintf(buffer + p, "%s", v.toString("\t").c_str()); p += std::sprintf(buffer + p, "\t"); } buffer[p - 1] = '\n'; diff --git a/test/testCandidateSplitting.cpp b/test/testCandidateSplitting.cpp new file mode 100644 index 000000000..dafdd23f6 --- /dev/null +++ b/test/testCandidateSplitting.cpp @@ -0,0 +1,90 @@ +#include "crpropa/Units.h" +#include "crpropa/Common.h" +#include "crpropa/ParticleID.h" +#include "crpropa/module/CandidateSplitting.h" + +#include "gtest/gtest.h" +#include +#include + +namespace crpropa { + +TEST(testCandidateSplitting, SimpleTest) { + int nSplit = 2; + int nBins = 4; + double minWeight = pow(1. / nSplit, 2); + double Emin = 1; // dimensionless for testing + double Emax = 10; + + CandidateSplitting split_lin(nSplit, Emin, Emax, nBins, minWeight); + double dE = (Emax - Emin) / nBins; + EXPECT_DOUBLE_EQ(split_lin.getEnergyBins()[0], Emin); + EXPECT_DOUBLE_EQ(split_lin.getEnergyBins()[1], Emin + dE); + + EXPECT_EQ(split_lin.getNsplit(), nSplit); + EXPECT_DOUBLE_EQ(split_lin.getMinimalWeight(), minWeight); + + CandidateSplitting split_log(nSplit, Emin, Emax, nBins, minWeight, true); + double dE_log = pow(Emax / Emin, 1. / (nBins - 1.0)); + EXPECT_DOUBLE_EQ(split_log.getEnergyBins()[0], Emin); + EXPECT_DOUBLE_EQ(split_log.getEnergyBins()[1], Emin * dE_log); + + double spectralIndex = -2.; + CandidateSplitting split_dsa(spectralIndex, Emin, nBins); + double dE_dsa = pow(1. / 2, 1. / (spectralIndex + 1)); + EXPECT_DOUBLE_EQ(split_dsa.getEnergyBins()[0], Emin * dE_dsa); + EXPECT_DOUBLE_EQ(split_dsa.getEnergyBins()[nBins - 1], Emin * pow(dE_dsa, nBins)); +} + + +TEST(testCandidateSplitting, CheckSplits) { + int nSplit = 2; + int nBins = 3; + double Emin = 1; // dimensionless for testing + double Emax = 10; + double minWeight = pow(1. / nSplit, 4); + + CandidateSplitting splitting(nSplit, Emin, Emax, nBins, minWeight); + Candidate c(nucleusId(1,1),0.5); + double weight = 1.0; + double serial = c.getSerialNumber(); + + splitting.process(&c); // no split + EXPECT_DOUBLE_EQ(c.getWeight(), weight); + EXPECT_DOUBLE_EQ(c.getNextSerialNumber(), serial); + + c.current.setEnergy(2); + splitting.process(&c); // 1. split + weight = weight/nSplit; + EXPECT_DOUBLE_EQ(c.getWeight(), weight); + EXPECT_DOUBLE_EQ(c.getNextSerialNumber(), serial + 1); + c.previous.setEnergy(2); + + c.current.setEnergy(6); + splitting.process(&c); // 2. split + weight = weight/nSplit; + EXPECT_DOUBLE_EQ(c.getWeight(), weight); + EXPECT_DOUBLE_EQ(c.getNextSerialNumber(), serial + 2); + c.previous.setEnergy(6); + + c.current.setEnergy(0.5); + splitting.process(&c); // no split, cooling + EXPECT_DOUBLE_EQ(c.getWeight(), weight); + EXPECT_DOUBLE_EQ(c.getNextSerialNumber(), serial + 2); + c.previous.setEnergy(0.5); + + c.current.setEnergy(6); + splitting.process(&c); // 3. & 4. split, crosses two boundaries + weight = weight/nSplit/nSplit; + EXPECT_DOUBLE_EQ(c.getWeight(), weight); + EXPECT_DOUBLE_EQ(c.getNextSerialNumber(), serial + 4); + c.previous.setEnergy(6); + + c.current.setEnergy(8); + splitting.process(&c); // no split, minimal weight reached + EXPECT_DOUBLE_EQ(c.getWeight(), weight); + EXPECT_DOUBLE_EQ(c.getNextSerialNumber(), serial + 4); + c.previous.setEnergy(8); +} + +} //namespace crpropa diff --git a/test/testCore.cpp b/test/testCore.cpp index 72e4a6c78..1f33d38d8 100644 --- a/test/testCore.cpp +++ b/test/testCore.cpp @@ -5,6 +5,8 @@ Common functions */ +#include + #include "crpropa/Candidate.h" #include "crpropa/base64.h" #include "crpropa/Common.h" @@ -16,6 +18,7 @@ #include "crpropa/GridTools.h" #include "crpropa/Geometry.h" #include "crpropa/EmissionMap.h" +#include "crpropa/Vector3.h" #include #include "gtest/gtest.h" @@ -522,6 +525,10 @@ TEST(Grid1f, SimpleTest) { //nearest neighbour interpolated grid.setInterpolationType(NEAREST_NEIGHBOUR); EXPECT_FLOAT_EQ(7., grid.interpolate(some_grid_point)); + + //Test if grid is set to zero outside of volume for clipVolume=true + grid.setClipVolume(true); + EXPECT_FLOAT_EQ(0, grid.interpolate(Vector3d(100, 0, 12))); } TEST(Grid1f, GridPropertiesConstructor) { @@ -599,6 +606,35 @@ TEST(Grid1f, ClosestValue) { EXPECT_FLOAT_EQ(2, grid.closestValue(Vector3d(0.2, 0.1, 1.3))); EXPECT_FLOAT_EQ(3, grid.closestValue(Vector3d(0.3, 1.2, 0.2))); EXPECT_FLOAT_EQ(7, grid.closestValue(Vector3d(1.7, 1.8, 0.4))); + + //Test if grid is set to zero outside of volume for clipVolume=true + EXPECT_NE(0, grid.interpolate(Vector3d(0, 0, 12))); + grid.setClipVolume(true); + double b = grid.interpolate(Vector3d(0, 0, 12)); + EXPECT_FLOAT_EQ(0, b); +} + +TEST(Grid1f, clipVolume) { + // Check volume clipping for gridproperties constructor + size_t N = 2; + Vector3d origin = Vector3d(0.); + double spacing = 2; + GridProperties properties(origin, N, spacing); + Grid1f grid(properties); + grid.get(0, 0, 0) = 1; + grid.get(0, 0, 1) = 2; + grid.get(0, 1, 0) = 3; + grid.get(0, 1, 1) = 4; + grid.get(1, 0, 0) = 5; + grid.get(1, 0, 1) = 6; + grid.get(1, 1, 0) = 7; + grid.get(1, 1, 1) = 8; + + //Test if grid is set to zero outside of volume for clipVolume=true + EXPECT_NE(0, grid.interpolate(Vector3d(0, 0, 12))); + grid.setClipVolume(true); + double b = grid.interpolate(Vector3d(0, 0, 10)); + EXPECT_FLOAT_EQ(0, b); } TEST(Grid3f, Interpolation) { @@ -731,6 +767,13 @@ TEST(Grid3f, Periodicity) { EXPECT_FLOAT_EQ(b.x, b2.x); EXPECT_FLOAT_EQ(b.y, b2.y); EXPECT_FLOAT_EQ(b.z, b2.z); + + //Test if grid is set to zero outside of volume for clipVolume=true + grid.setClipVolume(true); + Vector3f b3 = grid.interpolate(pos + Vector3d(0, 0, -2) * size); + EXPECT_FLOAT_EQ(0., b3.x); + EXPECT_FLOAT_EQ(0., b3.y); + EXPECT_FLOAT_EQ(0., b3.z); } TEST(Grid3f, Reflectivity) { @@ -807,6 +850,13 @@ TEST(Grid3f, Reflectivity) { EXPECT_FLOAT_EQ(b.x, b2.x); EXPECT_FLOAT_EQ(b.y, b2.y); EXPECT_FLOAT_EQ(b.z, b2.z); + + //Test if grid is set to zero outside of volume for clipVolume=true + grid.setClipVolume(true); + Vector3f b3 = grid.interpolate(pos + Vector3d(0, 0, -2) * size); + EXPECT_FLOAT_EQ(0., b3.x); + EXPECT_FLOAT_EQ(0., b3.y); + EXPECT_FLOAT_EQ(0., b3.z); } TEST(Grid3f, DumpLoad) { @@ -929,8 +979,7 @@ TEST(EmissionMap, merge) { } -TEST(Variant, copyToBuffer) -{ +TEST(Variant, copyToBuffer) { double a = 23.42; Variant v(a); double b; @@ -938,8 +987,7 @@ TEST(Variant, copyToBuffer) EXPECT_EQ(a, b); } -TEST(Variant, stringConversion) -{ +TEST(Variant, stringConversion) { Variant v, w; { int32_t a = 12; @@ -958,25 +1006,66 @@ TEST(Variant, stringConversion) w = Variant::fromString(v.toString(), v.getType()); EXPECT_EQ(a, w.asInt64()); } + + { + Vector3d a(1, 2, 3); + Variant v = Variant::fromVector3d(a); + Vector3d u = v.asVector3d(); + EXPECT_EQ(a.getX(), u.getX()); + EXPECT_EQ(a.getY(), u.getY()); + EXPECT_EQ(a.getZ(), u.getZ()); + } + + { + std::complex a1(1, 1); + std::complex a2(2, 0); + Vector3> a(a1, a1, a2); + Variant v = Variant::fromVector3c(a); + Vector3> u = v.asVector3c(); + EXPECT_EQ(a1, u.getX()); + EXPECT_EQ(a1, u.getY()); + EXPECT_EQ(a2, u.getZ()); + } + + { + std::complex a(1, 2); + Variant v = Variant::fromComplexDouble(a); + std::complex u = v.asComplexDouble(); + EXPECT_EQ(u.real(), 1); + EXPECT_EQ(u.imag(), 2); + } + + { + std::vector a; + a.push_back(Variant::fromDouble(1)); + a.push_back(Variant::fromDouble(2)); + a.push_back(Variant::fromDouble(3)); + a.push_back(Variant::fromDouble(4)); + Variant v = Variant::fromVector(a); + std::vector u = v.asVector(); + EXPECT_EQ(a[0], Variant::fromDouble(u[0])); + EXPECT_EQ(a[1], Variant::fromDouble(u[1])); + EXPECT_EQ(a[2], Variant::fromDouble(u[2])); + EXPECT_EQ(a[3], Variant::fromDouble(u[3])); + } + + } -TEST(Geometry, Plane) -{ +TEST(Geometry, Plane) { Plane p(Vector3d(0,0,1), Vector3d(0,0,1)); EXPECT_DOUBLE_EQ(-1., p.distance(Vector3d(0, 0, 0))); EXPECT_DOUBLE_EQ(9., p.distance(Vector3d(1, 1, 10))); } -TEST(Geometry, Sphere) -{ +TEST(Geometry, Sphere) { Sphere s(Vector3d(0,0,0), 1.); EXPECT_DOUBLE_EQ(-1., s.distance(Vector3d(0, 0, 0))); EXPECT_DOUBLE_EQ(9., s.distance(Vector3d(10, 0, 0))); } -TEST(Geometry, ParaxialBox) -{ +TEST(Geometry, ParaxialBox) { ParaxialBox b(Vector3d(0,0,0), Vector3d(3,4,5)); EXPECT_NEAR(-.1, b.distance(Vector3d(0.1, 0.1, 0.1)), 1E-10); EXPECT_NEAR(-.1, b.distance(Vector3d(0.1, 3.8, 0.1)), 1E-10); diff --git a/test/testDINT.cpp b/test/testDINT.cpp deleted file mode 100644 index cc0229342..000000000 --- a/test/testDINT.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "dint/gauleg.h" - -#include "gtest/gtest.h" -#include - -namespace crpropa { - -class GaussLegendreIntegrationTest : public testing::Test { -protected: - size_t N; - double *x; - double *w; - double x1, x2; - double analytical, res; - virtual void SetUp() { - N = 16384; - x = new double[N]; - w = new double[N]; - } - - virtual void TearDown() { - delete[] x; - delete[] w; - } -}; - -TEST_F(GaussLegendreIntegrationTest, exp) { - x1 = -1; - x2 = 1; - - res = 0; - Gauleg(x1, x2, x, w, N); - for (int i =0; i < N; i++) - res+= w[i] * exp(x[i]); - - analytical = exp(x2) - exp(x1); - EXPECT_NEAR(res, analytical, 1E-10); -} - -TEST_F(GaussLegendreIntegrationTest, x2) { - x1 = -10; - x2 = 1; - - res = 0; - Gauleg(x1, x2, x, w, N); - for (int i =0; i < N; i++) - res+= w[i] * x[i] * x[i]; - - analytical = 1./3 * (x2*x2*x2 - x1*x1*x1); - EXPECT_NEAR(res, analytical, 1E-10); -} - -TEST_F(GaussLegendreIntegrationTest, x3) { - x1 = -4; - x2 = 7; - - res = 0; - Gauleg(x1, x2, x, w, N); - for (int i =0; i < N; i++) - res+= w[i] * x[i] * x[i] * x[i]; - - analytical = 1./4 * (x2*x2*x2*x2 - x1*x1*x1*x1); - EXPECT_NEAR(res, analytical, 1E-10); -} - -TEST_F(GaussLegendreIntegrationTest, cosx) { - x1 = -2; - x2 = 3; - - res = 0; - Gauleg(x1, x2, x, w, N); - for (int i =0; i < N; i++) - res+= w[i] * cos(x[i] * 1234); - - analytical = 1./1234 * (sin(x2 * 1234 ) - sin(x1 * 1234)); - EXPECT_NEAR(res, analytical, 1E-10); -} - -TEST_F(GaussLegendreIntegrationTest, sinx) { - x1 = -M_PI; - x2 = M_PI; - - res = 0; - Gauleg(x1, x2, x, w, N); - for (int i =0; i < N; i++) - res+= w[i] * sin(x[i]); - - analytical = 0; - EXPECT_NEAR(res, analytical, 1E-10); -} - -int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} - -} // namespace crpropa diff --git a/test/testMomentumDiffusion.py b/test/testMomentumDiffusion.py new file mode 100644 index 000000000..9c555d523 --- /dev/null +++ b/test/testMomentumDiffusion.py @@ -0,0 +1,75 @@ +# coding=utf-8 +import sys + +try: + import unittest +except: + print("***********************************************************") + print("* WARNING!! Couldn't import python unittesting framework! *") + print("* No python tests have been executed *") + print("***********************************************************") + sys.exit(0) + +try: + import numpy as np +except: + print("***********************************************************") + print("* WARNING!! Couldn't import numpy framework! *") + print("* No python tests have been executed *") + print("***********************************************************") + sys.exit(-1) + +try: + import crpropa + from crpropa import nG, kpc, pc, GeV, TeV, PeV, c_light +except Exception as e: + print("*** CRPropa import failed") + print(type(e), str(e)) + sys.exit(-2) + + +class MomentumDiffusion(unittest.TestCase): + + Dpp = 10 + limit = 0.3 + + momDif = crpropa.ConstantMomentumDiffusion(Dpp) + momDif.setLimit(limit) + + def test_Simple(self): + self.assertEqual(self.momDif.getDpp(), self.Dpp) + self.assertEqual(self.momDif.getLimit(), self.limit) + + def test_Limits(self): + Dpp2 = 10 + limit2 = 0.4 + + momDif = crpropa.ConstantMomentumDiffusion(Dpp2, limit2) + self.assertEqual(momDif.getDpp(), Dpp2) + self.assertEqual(momDif.getLimit(), limit2) + + def test_Helper(self): + """Test to check the calculation of the helper functions + Dpp + B + A + """ + E = 10*TeV + c = crpropa.Candidate(crpropa.nucleusId(1,1)) + c.current.setEnergy(E) + p = c.current.getEnergy() / c_light + + bscal = self.momDif.calculateBScalar() + self.assertEqual(np.sqrt(2*self.Dpp), bscal) + ascal = self.momDif.calculateAScalar(p, Dpp) + self.assertAlmostEqual(2/p*self.Dpp, ascal) + + def test_NeutralParticle(self): + E = 10*TeV + c = crpropa.Candidate(crpropa.nucleusId(1,0)) + c.current.setEnergy(E) + c.setNextStep(10) + self.momDif.process(c) + + self.assertEqual(c.current.getEnergy(), E) #acts only on charged particles + self.assertEqual(c.getNextStep(), 10) diff --git a/test/testOutput.cpp b/test/testOutput.cpp index 92a3d7902..d1920d959 100644 --- a/test/testOutput.cpp +++ b/test/testOutput.cpp @@ -64,7 +64,7 @@ TEST(TextOutput, printHeader_Event1D) { output.process(&c); std::string captured = testing::internal::GetCapturedStdout(); - EXPECT_EQ(captured.substr(0, captured.find("\n")), "#\tD\tID\tE\tID0\tE0\ttag"); + EXPECT_EQ(captured.substr(0, captured.find("\n")), "#\tD\tID\tE\tID0\tE0"); } TEST(TextOutput, printHeader_Trajectory3D) { @@ -89,7 +89,7 @@ TEST(TextOutput, printHeader_Event3D) { EXPECT_EQ( captured.substr(0, captured.find("\n")), - "#\tD\tID\tE\tX\tY\tZ\tPx\tPy\tPz\tID0\tE0\tX0\tY0\tZ0\tP0x\tP0y\tP0z\ttag"); + "#\tD\tID\tE\tX\tY\tZ\tPx\tPy\tPz\tID0\tE0\tX0\tY0\tZ0\tP0x\tP0y\tP0z"); } TEST(TextOutput, printHeader_Custom) { @@ -99,6 +99,7 @@ TEST(TextOutput, printHeader_Custom) { output.enable(Output::SerialNumberColumn); output.disable(Output::TrajectoryLengthColumn); output.set(Output::RedshiftColumn, false); + output.enable(Output::CandidateTagColumn); ::testing::internal::CaptureStdout(); output.process(&c); diff --git a/test/testSimulationExecution.py b/test/testSimulationExecution.py index 1db919033..7e67c9dc8 100644 --- a/test/testSimulationExecution.py +++ b/test/testSimulationExecution.py @@ -37,8 +37,11 @@ def runTest(self): sim.add(crp.NuclearDecay()) sim.add(crp.ElectronPairProduction(CMB)) sim.add(crp.ElectronPairProduction(IRB)) + sim.add(crp.EMPairProduction(CMB)) + sim.add(crp.EMPairProduction(IRB)) + sim.add(crp.EMInverseComptonScattering(CMB)) + sim.add(crp.EMInverseComptonScattering(IRB)) sim.add(crp.MinimumEnergy(1 * crp.EeV)) - sim.add(crp.EMCascade()) # observer obs = crp.Observer()