Muon Stopping Power and Range

Each example consists of a main code to be linked with the Muon Range Library. The examples calculate the range or energy loss in materials, the material thickness that would cause a given energy decrement, or simply output a formatted stopping power and range table.

Example Codes

After package installation, the example codes can be found in /usr/share/doc/murange/examples/.

Table of Contents

Example 1

The following example code creates an element, a range table for the element, a muon object, and outputs the range at muon momentum 200 MeV/c and 1 GeV kinetic energy,

using namespace std;

#include <iostream>
#include <murange.hpp>

int main() {

  // Iron (Fe)
  Material *Fe = new Element("Fe");

  // range table for element Fe
  Range *rFe = new Range(Fe);

  // muon with momentum 200 MeV/c
  Muon *mu = new Muon();
  mu->SetMomentum(200);

  // method 1
  cout << rFe->GetRange(mu) << " MeV/cm2" << endl;

  // method 2
  cout << rFe->GetRange(1000) << " MeV/cm2" << endl;

  delete mu;
  delete rFe;
  delete Fe;

  return EXIT_SUCCESS;
}

The outcome of this example is,

$ g++ -o GetRange-example GetRange-example.cpp -lmurange
$ ./GetRange-example
56.7843 MeV/cm2
640.323 MeV/cm2

Example 2

The following example code creates a material (Stainless Steel 316L) and prints to standard output a stopping power and range table,

using namespace std;

#include <iostream>
#include <murange.hpp>

int main() {

  // Stainless Steel 316L
  Material *mat = new Mixture(502);
  Range *rng = new Range(mat);

  // print stopping power and range table
  rng->PrintRangeTable();

  delete rng;
  delete mat;

  return EXIT_SUCCESS;
}

The outcome of this example is,

Example 3

The following example code creates an element (Deuterium, gaseous), a range table for the element, a muon object with 30 GeV kinetic energy, and outputs the energy loss and outgoing energy after passage through 5 g/cm² D gas at 5 atm,

using namespace std;

#include <iostream>
#include <murange.hpp>

int main() {

  // Deuterium (D)
  Material *D = new Element("D");

  // set density to 5 atm
  D->SetDensity(5,"atm");

  // range table for gaseous D
  Range *rD = new Range(D);

  // muon with kinetic energy 30 GeV
  Muon *mu = new Muon(30000);

  // method 1
  D->SetThickness(5);
  cout << rD->GetOutgoingEnergy(mu) << " MeV energy loss" << endl;
  cout << mu->GetKEnergy() << " MeV" << endl;
  cout << endl;

  // method 2
  mu->SetKEnergy(30000);
  cout << rD->GetOutgoingEnergy(mu,5) << " MeV energy loss" << endl;
  cout << mu->GetKEnergy() << " MeV" << endl;
  cout << endl;

  // method 3
  cout << rD->GetOutgoingEnergy(30000,5) << " MeV energy loss" << endl;

  delete mu;
  delete rD;
  delete D;

  return EXIT_SUCCESS;
}

The outcome of this example is,

$ g++ -o GetOutgoingEnergy-example GetOutgoingEnergy-example.cpp -lmurange
$ ./GetOutgoingEnergy-example
14.9812 MeV energy loss
29985 MeV

14.9812 MeV energy loss
29985 MeV

14.9812 MeV energy loss

Example 4

The following example code creates a mixture (Co-Cr ASTM-F75), a range table for the mixture, a muon object with 10 MeV kinetic energy, and outputs the energy loss and ingoing energy before passage through 1 g/cm² liquid Deuterium,

using namespace std;

#include <iostream>
#include <murange.hpp>

int main() {

  // muon with kinetic energy 10 MeV
  Muon *mu = new Muon(10);

  // Cobalt-Chromium (ASTM-F75)
  Material *CoCr = new Mixture(532);

  // range table for Cobalt-Chromium
  Range *rCoCr = new Range(CoCr);

  // method 1
  CoCr->SetThickness(1);
  cout << rCoCr->GetIngoingEnergy(mu) << " MeV energy loss" << endl;
  cout << mu->GetKEnergy() << " MeV" << endl;
  cout << endl;

  // method 2
  mu->SetKEnergy(10);
  cout << rCoCr->GetIngoingEnergy(mu,1) << " MeV energy loss" << endl;
  cout << mu->GetKEnergy() << " MeV" << endl;
  cout << endl;

  // method 3
  cout << rCoCr->GetIngoingEnergy(10,1) << " MeV energy loss" << endl;

  delete rCoCr;
  delete CoCr;
  delete mu;

  return EXIT_SUCCESS;
}

The outcome of this example is,

$ g++ -o GetIngoingEnergy-example GetIngoingEnergy-example.cpp -lmurange
$ ./GetIngoingEnergy-example
4.59922 MeV energy loss
14.5992 MeV

4.59922 MeV energy loss
14.5992 MeV

4.59922 MeV energy loss

Example 5

The following example code creates an mixture (Concrete), a range table for the mixture, a muon object with 300 MeV kinetic energy, and outputs the material thickness needed to reduce the kinetic energy to 200 MeV.

using namespace std;

#include <iostream>
#include <murange.hpp>

int main() {

  // Concrete (Ordinary)
  Material *mat = new Mixture(518);

  // range table for concrete
  Range *r = new Range(mat);

  // muon with kinetic energy 300 MeV
  Muon *mu = new Muon(300.);

  // method 1
  double s = r->GetMaterialThickness(mu,-100.);
  cout << "material thickness " << s << " g/cm2, or " << s/mat->GetDensity() << " cm concrete" << endl;
  cout << "initial KE " << mu->GetKEnergy() << " MeV, energy loss " << r->GetOutgoingEnergy(mu,s) <<
    " MeV, final KE " << mu->GetKEnergy() << " MeV" << endl;

  // method 2
  s = r->GetMaterialThickness(300.,-100.);
  cout << "material thickness " << s << " g/cm2, or " << s/mat->GetDensity() << " cm concrete" << endl;

  delete mu;
  delete r;
  delete mat;

  return EXIT_SUCCESS;
}

The outcome of this example is,

$ g++ -o GetMaterialThickness-example GetMaterialThickness-example.cpp -lmurange
$ ./GetMaterialThickness-example
material thickness 57.4584 g/cm2, or 24.9819 cm concrete
initial KE 300 MeV, energy loss 100 MeV, final KE 200 MeV
material thickness 57.4584 g/cm2, or 24.9819 cm concrete

Example 6

The following example code calculates the range of a 30 GeV muon in Carbon Tetrafluoride (CF4) at 1 atm and 100 Torr,

using namespace std;

#include <iostream>
#include <murange.hpp>

int main() {

  // muon with kinetic energy 30 GeV
  Muon *mu = new Muon(30e3);

  // range table for CF4
  Material *CF4 = new Compound(326);
  Range *rCF4 = new Range(CF4);

  cout << "Range of" << mu->GetKEnergy()/1000 << " GeV muon in CF4 at 1 atm: " <<
    rCF4->GetRange(mu) << " MeV/cm2" << endl;

  // change the density to 100 Torr
  CF4->SetDensity(100,"Torr");

  // new range table for CF4
  delete rCF4;
  rCF4 = new Range(CF4);

  cout << "Range of" << mu->GetKEnergy()/1000 << " GeV muon in CF4 at 100 Torr: " <<
    rCF4->GetRange(mu) << " MeV/cm2" << endl;

  delete rCF4;
  delete CF4;
  delete mu;

  return EXIT_SUCCESS;
}

The outcome of this example is,

$ g++ -o cf4-range cf4-range.cpp -lmurange
$ ./cf4-range
Range of 30 GeV muon in CF4 at 1 atm: 12171.4 MeV/cm2
Range of 30 GeV muon in CF4 at 1 Torr: 11934.8 MeV/cm2

This demonstrates the density dependence of the electronic stopping power.

Example 7

The following example code creates an element (Si), a range table and sets the muon kinetic energy randomly, from 10 to 100 MeV, then calculates the energy loss in 1-10 g/cm² Si, iterated over tries times. The OpenMP time function is used to estimate the performance [Mtrials/s],

using namespace std;

#include <iostream>
#include <ctime>
#include <murange.hpp>

#include <omp.h>

int main(int argc, char **argv) {

  // number of tries
  unsigned long tries = atol(argv[1]);

  srand(time(NULL));

  // start time
  double start_time = omp_get_wtime();

  // Si range table
  Material *Si = new Element("Si");
  Range *rSi = new Range(Si);

  for ( int i = 0 ; i < tries ; i++ ) {
    // kinetic energy between 10 and 100 MeV
    double ke = (rand()%(90000000)+10000000)/1000000.;
    // thickness between 1 and 10 g/cm2
    double s = (rand()%(90000000)+10000000)/10000000.;
    rSi->GetOutgoingEnergy(ke,s);
  }

  // stop time
  double stop_time = omp_get_wtime();

  double performance = (double)tries / (time_stop-time_start) / 1000000.;

  fprintf(stderr,"\nnumber of tries: %ld\n",tries);
  fprintf(stderr,"execution time: %g s\n",time_stop-time_start);
  fprintf(stderr,"performance: %g Mtrials/s\n\n",performance);

  delete rSi;
  delete Si;

  return EXIT_SUCCESS;;
}

The outcome of this example is,

$ g++ -o performance performance.cpp -fopenmp -lmurange
$ ./performance 100000000

number of tries: 100000000
execution time: 18.8887 s
performance: 5.29418 Mtrials/s

The plot shows the performance as a function of number of trials, a useful measure when performing Monte Carlo simulations.

A similar OpenMP version of the above code, with 8 threads, gives,

$ g++ -o performance-omp performance-omp.cpp -fopenmp -lmurange
$ ./performance-omp 8 100000000
using OpenMP with 8/16 threads

number of tries: 100000000
execution time: 3.22482 s
performance: 31.0095 Mtrials/s

and performance plot,