Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Momentum Diffusion #444

Merged
merged 7 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,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
Expand Down Expand Up @@ -680,6 +681,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)
Expand Down
606 changes: 606 additions & 0 deletions doc/pages/example_notebooks/Diffusion/MomentumDiffusion.ipynb

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions doc/pages/galactic_cosmic_rays.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ changes, which can be modeled following the next examples.
.. toctree::
example_notebooks/Diffusion/AdiabaticCooling.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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
1 change: 1 addition & 0 deletions include/CRPropa.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#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"
Expand Down
60 changes: 60 additions & 0 deletions include/crpropa/module/MomentumDiffusion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#ifndef CRPROPA_MOMENTUMDIFFUSION_H
#define CRPROPA_MOMENTUMDIFFUSION_H

#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <cstdlib>
#include <stdexcept>

#include <crpropa/Module.h>
#include <crpropa/Units.h>
#include <crpropa/Random.h>

#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);

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
1 change: 1 addition & 0 deletions python/2_headers.i
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@ 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<int>;
Expand Down
66 changes: 66 additions & 0 deletions src/module/MomentumDiffusion.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "crpropa/module/MomentumDiffusion.h"

using namespace crpropa;

ConstantMomentumDiffusion::ConstantMomentumDiffusion(double Dpp) {
setLimit(0.1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it make sense to allow the user to control the limit, as done in the other modules?

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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add spaces:
getEnergy() / c_light

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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add spaces between parenthesis and c_light.


c->limitNextStep(limit * p / AScal * c_light);
}

double ConstantMomentumDiffusion::calculateAScalar(double p) const {
double a = + 2./p * Dpp;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow CRPropa convention and add white spaces around /

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";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add white spaces, following CRPropa's convention.


return s.str();
}
67 changes: 67 additions & 0 deletions test/testMomentumDiffusion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# 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_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)