LCOV - code coverage report
Current view: top level - test - testPropagation.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 337 340 99.1 %
Date: 2024-04-29 14:43:01 Functions: 18 19 94.7 %

          Line data    Source code
       1             : #include "crpropa/Candidate.h"
       2             : #include "crpropa/ParticleID.h"
       3             : #include "crpropa/module/SimplePropagation.h"
       4             : #include "crpropa/module/PropagationBP.h"
       5             : #include "crpropa/module/PropagationCK.h"
       6             : #include "crpropa/magneticField/turbulentField/PlaneWaveTurbulence.h"
       7             : 
       8             : #include "gtest/gtest.h"
       9             : 
      10             : #include <string>
      11             : #include <iostream>
      12             : 
      13             : namespace crpropa {
      14             : 
      15           1 : TEST(testSimplePropagation, step) {
      16           1 :         double minStep = 20;
      17           1 :         double maxStep = 100;
      18           1 :         SimplePropagation propa(minStep, maxStep);
      19             : 
      20           1 :         ParticleState p;
      21           1 :         p.setPosition(Vector3d(0, 0, 0));
      22           1 :         p.setDirection(Vector3d(0, 1, 0));
      23             : 
      24           1 :         Candidate c(p);
      25           1 :         c.setNextStep(10);
      26             : 
      27           1 :         propa.process(&c);
      28             : 
      29           1 :         EXPECT_EQ(minStep, c.getCurrentStep());
      30           1 :         EXPECT_EQ(maxStep, c.getNextStep());
      31           2 :         EXPECT_EQ(Vector3d(0,  0, 0), c.created.getPosition());
      32           2 :         EXPECT_EQ(Vector3d(0,  1, 0), c.created.getDirection());
      33           2 :         EXPECT_EQ(Vector3d(0,  0, 0), c.previous.getPosition());
      34           2 :         EXPECT_EQ(Vector3d(0,  1, 0), c.previous.getDirection());
      35           2 :         EXPECT_EQ(Vector3d(0, 20, 0), c.current.getPosition());
      36           2 :         EXPECT_EQ(Vector3d(0,  1, 0), c.current.getDirection());
      37           2 : }
      38             : 
      39             : 
      40           1 : TEST(testPropagationCK, zeroField) {
      41           1 :         PropagationCK propa(new UniformMagneticField(Vector3d(0, 0, 0)));
      42             : 
      43             :         double minStep = 0.1 * kpc;
      44           1 :         propa.setMinimumStep(minStep);
      45             : 
      46           1 :         ParticleState p;
      47           1 :         p.setId(nucleusId(1, 1));
      48           1 :         p.setEnergy(100 * EeV);
      49           1 :         p.setPosition(Vector3d(0, 0, 0));
      50           1 :         p.setDirection(Vector3d(0, 1, 0));
      51           1 :         Candidate c(p);
      52           1 :         c.setNextStep(0);
      53             : 
      54           1 :         propa.process(&c);
      55             : 
      56           1 :         EXPECT_DOUBLE_EQ(minStep, c.getCurrentStep());  // perform minimum step
      57           1 :         EXPECT_DOUBLE_EQ(5 * minStep, c.getNextStep());  // acceleration by factor 5
      58           1 : }
      59             : 
      60             : #ifndef CRPROPA_TESTS_SKIP_EXCEPTIONS
      61           1 : TEST(testPropagationCK, exceptions) {
      62             :         // minStep should be smaller than maxStep
      63           2 :         EXPECT_THROW(PropagationCK propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)), 0.42, 10 , 0), std::runtime_error);
      64             :         // Too large tolerance: tolerance should be between 0 and 1
      65           2 :         EXPECT_THROW(PropagationCK propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)), 42., 10 * kpc , 20 * kpc), std::runtime_error);
      66             : 
      67           2 :         PropagationCK propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)));
      68             : 
      69             :         // set maximum step, so that it can be tested what happens if a larger minStep is set.
      70           1 :         propa.setMaximumStep(1 * Mpc);
      71             : 
      72             :         // this tests _that_ the expected exception is thrown
      73           1 :         EXPECT_THROW(propa.setTolerance(2.), std::runtime_error);
      74           1 :         EXPECT_THROW(propa.setMinimumStep(-1.), std::runtime_error);
      75           1 :         EXPECT_THROW(propa.setMinimumStep(2 * Mpc), std::runtime_error);
      76             : 
      77             :         // set minimum step, so that it can be tested what happens if a smaller maxStep is set.
      78           1 :         propa.setMinimumStep(0.5 * Mpc);
      79             : 
      80           1 :         EXPECT_THROW(propa.setMaximumStep(0.1 * Mpc), std::runtime_error);
      81           1 : }
      82             : #endif
      83             : 
      84           1 : TEST(testPropagationCK, constructor) {
      85             :         // Test construction and parameters
      86           1 :         ref_ptr<MagneticField> bField = new UniformMagneticField(Vector3d(0, 0, 1 * nG));
      87             : 
      88           1 :         double minStep = 1.;
      89           1 :         double maxStep = 100.;
      90           1 :         double tolerance = 0.01;
      91             : 
      92           1 :         PropagationCK propa(bField, tolerance, minStep, maxStep);
      93             : 
      94           1 :         EXPECT_EQ(minStep, propa.getMinimumStep());
      95           1 :         EXPECT_EQ(maxStep, propa.getMaximumStep());
      96           1 :         EXPECT_EQ(tolerance, propa.getTolerance());
      97           2 :         EXPECT_EQ(bField, propa.getField());
      98             : 
      99             :         // Update parameters
     100           1 :         minStep = 10.;
     101           1 :         maxStep = 10.;
     102           1 :         propa.setTolerance(0.0001);
     103           1 :         bField = new UniformMagneticField(Vector3d(10 * nG, 0, 1 * nG));
     104             : 
     105           1 :         propa.setTolerance(tolerance);
     106           1 :         propa.setMinimumStep(minStep);
     107           1 :         propa.setMaximumStep(maxStep);
     108           1 :         propa.setField(bField);
     109             : 
     110           1 :         EXPECT_EQ(minStep, propa.getMinimumStep());
     111           1 :         EXPECT_EQ(maxStep, propa.getMaximumStep());
     112           1 :         EXPECT_EQ(tolerance, propa.getTolerance());
     113           2 :         EXPECT_EQ(bField, propa.getField());
     114             : 
     115             :         // The propagation should be initialized with the default constructor
     116           2 :         PropagationCK propaCKField(bField);
     117           1 :         EXPECT_EQ(propaCKField.getMaximumStep(), 1 * Gpc);
     118           2 : }
     119             : 
     120             : 
     121             : // Test if the step size is reduced correctly if the error is too large with respect to the tolerance: r > 1
     122           1 : TEST(testPropagationCK, reduceStep) {
     123           1 :         PropagationCK propa(new UniformMagneticField(Vector3d(0, 0, 100 * nG)));
     124             : 
     125             :         double minStep = 0.1 * kpc;
     126             :         double maxStep = 1 * Gpc;
     127           1 :         propa.setMinimumStep(minStep);
     128           1 :         propa.setMaximumStep(maxStep);
     129             :         // small tolerance leads to large values of r
     130           1 :         propa.setTolerance(1e-15);
     131             : 
     132           1 :         ParticleState p;
     133           1 :         p.setId(nucleusId(1, 1));
     134           1 :         p.setEnergy(100 * TeV);
     135           1 :         p.setPosition(Vector3d(0, 0, 0));
     136           1 :         p.setDirection(Vector3d(0, 1, 0));
     137           1 :         Candidate c(p);
     138             :         // large step leads to large errors and thus in combination with the low tolerance to high values of r
     139           1 :         c.setNextStep(maxStep);
     140             : 
     141           1 :         propa.process(&c);
     142             : 
     143             :         // adaptive algorithm should propagate particle with minimum step size due to the low value for the tolerance
     144           1 :         EXPECT_DOUBLE_EQ(minStep, c.getCurrentStep());  // perform minimum step because of large r due to small tolerance
     145           1 :         EXPECT_DOUBLE_EQ(minStep, c.getNextStep());  // stay at minimum step because of large r due to small tolerance
     146           1 : }
     147             : 
     148             : 
     149             : // Test if the step size is increased correctly if the error is small with respect to the tolerance: r < 1
     150           1 : TEST(testPropagationCK, increaseStep) {
     151           1 :         PropagationCK propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)));
     152             : 
     153             :         double minStep = 0.001 * pc;
     154             :         double maxStep = 3.125 * pc;
     155           1 :         propa.setMinimumStep(minStep);
     156           1 :         propa.setMaximumStep(maxStep);
     157             :         // large tolerance leads to small values of r. Consequently, the step size can be increased.
     158           1 :         propa.setTolerance(0.9);
     159             : 
     160           1 :         ParticleState p;
     161           1 :         p.setId(nucleusId(1, 1));
     162           1 :         p.setEnergy(100 * EeV);
     163           1 :         p.setPosition(Vector3d(0, 0, 0));
     164           1 :         p.setDirection(Vector3d(0, 1, 0));
     165           1 :         Candidate c(p);
     166             : 
     167             :         // each step the step size can be increased by a factor of 5.
     168           6 :         for (int i = 1; i < 6; i++){
     169           5 :                 propa.process(&c);
     170           5 :                 EXPECT_DOUBLE_EQ(minStep*pow(5, i) / pc, c.getNextStep()/pc);
     171             :         }
     172             :         // after 5 steps the maxStep is reached. The current step is, however, less.
     173           1 :         EXPECT_DOUBLE_EQ(maxStep/pc/5., c.getCurrentStep()/pc);
     174           1 :         EXPECT_DOUBLE_EQ(maxStep/pc, c.getNextStep()/pc);
     175           1 : }
     176             : 
     177             : 
     178           1 : TEST(testPropagationCK, proton) {
     179           1 :         PropagationCK propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)));
     180             : 
     181             :         double minStep = 0.1 * kpc;
     182           1 :         propa.setMinimumStep(minStep);
     183             : 
     184           1 :         ParticleState p;
     185           1 :         p.setId(nucleusId(1, 1));
     186           1 :         p.setEnergy(100 * EeV);
     187           1 :         p.setPosition(Vector3d(0, 0, 0));
     188           1 :         p.setDirection(Vector3d(0, 1, 0));
     189           1 :         Candidate c(p);
     190           1 :         c.setNextStep(0);
     191             : 
     192           1 :         propa.process(&c);
     193             : 
     194           1 :         EXPECT_DOUBLE_EQ(minStep, c.getCurrentStep());  // perform minimum step
     195           1 :         EXPECT_DOUBLE_EQ(5 * minStep, c.getNextStep());  // acceleration by factor 5
     196           1 : }
     197             : 
     198             : 
     199             : // Test the numerical results for parallel magnetic field lines along the z-axis
     200           1 : TEST(testPropagationCK, gyration) {
     201           1 :         PropagationCK propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)));
     202             : 
     203             :         double step = 10. * Mpc;  // gyroradius is 108.1 Mpc
     204           1 :         propa.setMaximumStep(step);
     205           1 :         propa.setMinimumStep(step);
     206             : 
     207             : 
     208           1 :         ParticleState p;
     209           1 :         p.setId(nucleusId(1, 1));
     210           1 :         p.setEnergy(100 * EeV);
     211           1 :         p.setPosition(Vector3d(0, 0, 0));
     212           1 :         p.setDirection(Vector3d(1, 1, 1));
     213           1 :         Candidate c(p);
     214           1 :         c.setNextStep(0);
     215           1 :         propa.process(&c);
     216             : 
     217           1 :         double dirX = c.current.getDirection().x;
     218           1 :         double dirY = c.current.getDirection().y;
     219           1 :         double dirZ = c.current.getDirection().z;
     220           1 :         double posZ = c.current.getPosition().z;
     221             : 
     222             :         // Test if the analytical solution is achieved for the components of the momentum with the CK method as expected in
     223             :         // the background magnetic field.
     224             :         double precision = 1e-7;
     225             :         double expected = 2 / 3.;
     226           1 :         EXPECT_NEAR(expected, dirX * dirX + dirY * dirY, expected * precision);  // constant momentum in the plane perpendicular to background magnetic field field
     227             :         expected = 1 / 3.;
     228           1 :         EXPECT_NEAR(expected, dirZ * dirZ, expected * precision);  // constant momentum parallel to the background magnetic field
     229             :         expected = step * step / 3.;
     230           1 :         EXPECT_NEAR(expected, posZ * posZ, expected * precision);  // constant velocity parallel to the background magnetic field
     231             : 
     232             :         // Nine new steps to have finally propagated the particle ten times
     233          10 :         for (int i = 0; i < 9; i++){
     234           9 :                 propa.process(&c);
     235             :         }
     236             : 
     237           1 :         dirX = c.current.getDirection().x;
     238           1 :         dirY = c.current.getDirection().y;
     239           1 :         dirZ = c.current.getDirection().z;
     240           1 :         posZ = c.current.getPosition().z;
     241             : 
     242             :         // Compare the numerical solutions after ten steps with the analytical solution of the trajectories
     243             :         expected = 2 / 3.;
     244           1 :         EXPECT_NEAR(expected, dirX * dirX + dirY * dirY, expected * precision);  // constant momentum in the plane perpendicular to background magnetic field field
     245             :         expected = 1 / 3.;
     246           1 :         EXPECT_NEAR(expected, dirZ * dirZ, expected * precision);  // constant momentum parallel to the background magnetic field
     247             :         expected = 100 * step * step / 3.;
     248           1 :         EXPECT_NEAR(expected, posZ * posZ, expected * precision);  // constant velocity parallel to the background magnetic field
     249           1 : }
     250             : 
     251             : 
     252           1 : TEST(testPropagationCK, neutron) {
     253           1 :         PropagationCK propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)));
     254           1 :         propa.setMinimumStep(1 * kpc);
     255           1 :         propa.setMaximumStep(42 * Mpc);
     256             : 
     257           1 :         ParticleState p;
     258           1 :         p.setId(nucleusId(1, 0));
     259           1 :         p.setEnergy(100 * EeV);
     260           1 :         p.setPosition(Vector3d(0, 0, 0));
     261           1 :         p.setDirection(Vector3d(0, 1, 0));
     262           1 :         Candidate c(p);
     263             : 
     264           1 :         propa.process(&c);
     265             : 
     266           1 :         EXPECT_DOUBLE_EQ(1 * kpc, c.getCurrentStep());
     267           1 :         EXPECT_DOUBLE_EQ(42 * Mpc, c.getNextStep());
     268           2 :         EXPECT_EQ(Vector3d(0, 1 * kpc, 0), c.current.getPosition());
     269           2 :         EXPECT_EQ(Vector3d(0, 1, 0), c.current.getDirection());
     270           1 : }
     271             : 
     272             : 
     273           1 : TEST(testPropagationBP, zeroField) {
     274           1 :         PropagationBP propa(new UniformMagneticField(Vector3d(0, 0, 0)), 1 * kpc);
     275             : 
     276             :         double minStep = 0.1 * kpc;
     277           1 :         propa.setMinimumStep(minStep);
     278           1 :         propa.setTolerance(0.42);
     279             : 
     280           1 :         ParticleState p;
     281           1 :         p.setId(nucleusId(1, 1));
     282           1 :         p.setEnergy(100 * EeV);
     283           1 :         p.setPosition(Vector3d(0, 0, 0));
     284           1 :         p.setDirection(Vector3d(0, 1, 0));
     285           1 :         Candidate c(p);
     286           1 :         c.setNextStep(0);
     287             : 
     288           1 :         propa.process(&c);
     289             : 
     290           1 :         EXPECT_DOUBLE_EQ(minStep, c.getCurrentStep());  // perform minimum step
     291           1 :         EXPECT_DOUBLE_EQ(5 * minStep, c.getNextStep());  // acceleration by factor 5
     292           1 : }
     293             : 
     294             : #ifndef CRPROPA_TESTS_SKIP_EXCEPTIONS
     295           1 : TEST(testPropagationBP, exceptions) {
     296             :         // minStep should be smaller than maxStep
     297           2 :         EXPECT_THROW(PropagationBP propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)), 0.42, 10 , 0), std::runtime_error);
     298             :         // Too large tolerance: tolerance should be between 0 and 1
     299           2 :         EXPECT_THROW(PropagationBP propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)), 42., 10 * kpc , 20 * kpc), std::runtime_error);
     300             : 
     301           2 :         PropagationBP propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)));
     302             : 
     303             :         // set maximum step, so that it can be tested what happens if a larger minStep is set.
     304           1 :         propa.setMaximumStep(1 * Mpc);
     305             : 
     306             :         // this tests _that_ the expected exception is thrown
     307           1 :         EXPECT_THROW(propa.setTolerance(2.), std::runtime_error);
     308           1 :         EXPECT_THROW(propa.setMinimumStep(-1.), std::runtime_error);
     309           1 :         EXPECT_THROW(propa.setMinimumStep(2 * Mpc), std::runtime_error);
     310             : 
     311             :         // set minimum step, so that it can be tested what happens if a smaller maxStep is set.
     312           1 :         propa.setMinimumStep(0.5 * Mpc);
     313             : 
     314           1 :         EXPECT_THROW(propa.setMaximumStep(0.1 * Mpc), std::runtime_error);
     315           1 : }
     316             : #endif
     317             : 
     318             : 
     319           1 : TEST(testPropagationBP, constructor) {
     320             :         // Test construction and parameters
     321           1 :         ref_ptr<MagneticField> bField = new UniformMagneticField(Vector3d(0, 0, 1 * nG));
     322             : 
     323           1 :         double minStep = 1.;
     324           1 :         double maxStep = 100.;
     325           1 :         double tolerance = 0.01;
     326             : 
     327           1 :         PropagationBP propa(bField, tolerance, minStep, maxStep);
     328             : 
     329           1 :         EXPECT_EQ(minStep, propa.getMinimumStep());
     330           1 :         EXPECT_EQ(maxStep, propa.getMaximumStep());
     331           1 :         EXPECT_EQ(tolerance, propa.getTolerance());
     332           2 :         EXPECT_EQ(bField, propa.getField());
     333             : 
     334             :         // Update parameters
     335           1 :         minStep = 10.;
     336           1 :         maxStep = 10.;
     337           1 :         propa.setTolerance(0.0001);
     338           1 :         bField = new UniformMagneticField(Vector3d(10 * nG, 0, 1 * nG));
     339             : 
     340           1 :         propa.setTolerance(tolerance);
     341           1 :         propa.setMinimumStep(minStep);
     342           1 :         propa.setMaximumStep(maxStep);
     343           1 :         propa.setField(bField);
     344             : 
     345           1 :         EXPECT_EQ(minStep, propa.getMinimumStep());
     346           1 :         EXPECT_EQ(maxStep, propa.getMaximumStep());
     347           1 :         EXPECT_EQ(tolerance, propa.getTolerance());
     348           2 :         EXPECT_EQ(bField, propa.getField());
     349             : 
     350             :         // Test the fixed step size version of the Boris push
     351           1 :         minStep = 10. * kpc;
     352           2 :         PropagationBP propaBP(bField, minStep);
     353           1 :         EXPECT_EQ(propaBP.getMaximumStep(), propaBP.getMaximumStep());
     354             : 
     355             :         // The propagation should be initialized with the default constructor
     356           2 :         PropagationBP propaBPField(bField);
     357           1 :         EXPECT_EQ(propaBPField.getMaximumStep(), 1 * kpc);
     358           2 : }
     359             : 
     360             : 
     361             : // Test if the step size is reduced correctly if the error is too large with respect to the tolerance: r > 1
     362           1 : TEST(testPropagationBP, reduceStep) {
     363           1 :         PropagationBP propa(new UniformMagneticField(Vector3d(0, 0, 100 * nG)), 1 * kpc);
     364             : 
     365             :         double minStep = 0.1 * kpc;
     366             :         double maxStep = 1 * Gpc;
     367           1 :         propa.setMinimumStep(minStep);
     368           1 :         propa.setMaximumStep(maxStep);
     369             :         // small tolerance leads to large values of r
     370           1 :         propa.setTolerance(1e-15);
     371             : 
     372           1 :         ParticleState p;
     373           1 :         p.setId(nucleusId(1, 1));
     374           1 :         p.setEnergy(100 * TeV);
     375           1 :         p.setPosition(Vector3d(0, 0, 0));
     376           1 :         p.setDirection(Vector3d(0, 1, 0));
     377           1 :         Candidate c(p);
     378             :         // large step leads to large errors and thus in combination with the low tolerance to high values of r
     379           1 :         c.setNextStep(maxStep);
     380             : 
     381           1 :         propa.process(&c);
     382             : 
     383             :         // adaptive algorithm should propagate particle with minimum step size due to the low value for the tolerance
     384           1 :         EXPECT_DOUBLE_EQ(minStep, c.getCurrentStep());  // perform minimum step because of large r due to small tolerance
     385           1 :         EXPECT_DOUBLE_EQ(minStep, c.getNextStep());  // stay at minimum step because of large r due to small tolerance
     386           1 : }
     387             : 
     388             : 
     389             : // Test if the step size is increased correctly if the error is small with respect to the tolerance: r < 1
     390           1 : TEST(testPropagationBP, increaseStep) {
     391           1 :         PropagationBP propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)), 1 * kpc);
     392             : 
     393             :         double minStep = 0.001 * pc;
     394             :         double maxStep = 3.125 * pc;
     395           1 :         propa.setMinimumStep(minStep);
     396           1 :         propa.setMaximumStep(maxStep);
     397             :         // large tolerance leads to small values of r. Consequently, the step size can be increased.
     398           1 :         propa.setTolerance(0.9);
     399             : 
     400           1 :         ParticleState p;
     401           1 :         p.setId(nucleusId(1, 1));
     402           1 :         p.setEnergy(100 * EeV);
     403           1 :         p.setPosition(Vector3d(0, 0, 0));
     404           1 :         p.setDirection(Vector3d(0, 1, 0));
     405           1 :         Candidate c(p);
     406             : 
     407             :         // each step the step size can be increased by a factor of 5.
     408           6 :         for (int i = 1; i < 6; i++){
     409           5 :                 propa.process(&c);
     410           5 :                 EXPECT_DOUBLE_EQ(minStep*pow(5, i) / pc, c.getNextStep()/pc);
     411             :         }
     412             :         // after 5 steps the maxStep is reached. The current step is, however, less.
     413           1 :         EXPECT_DOUBLE_EQ(maxStep/pc/5., c.getCurrentStep()/pc);
     414           1 :         EXPECT_DOUBLE_EQ(maxStep/pc, c.getNextStep()/pc);
     415           1 : }
     416             : 
     417             : 
     418           1 : TEST(testPropagationBP, proton) {
     419           1 :         PropagationBP propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)));
     420             : 
     421             :         double step = 0.01 * kpc;
     422           1 :         propa.setMinimumStep(step);
     423           1 :         propa.setMaximumStep(10*step);
     424           1 :         propa.setTolerance(0.00001);
     425             : 
     426           1 :         ParticleState p;
     427           1 :         p.setId(nucleusId(1, 1));
     428           1 :         p.setEnergy(100 * EeV);
     429           1 :         p.setPosition(Vector3d(0, 0, 0));
     430           1 :         p.setDirection(Vector3d(0, 1, 0));
     431           1 :         Candidate c(p);
     432           1 :         c.setNextStep(0);
     433             : 
     434           1 :         propa.process(&c);
     435             : 
     436           1 :         EXPECT_DOUBLE_EQ(step, c.getCurrentStep());  // perform step
     437           1 :         EXPECT_DOUBLE_EQ(5 * step, c.getNextStep());  // acceleration by factor 5
     438           1 : }
     439             : 
     440             : 
     441             : // Test the numerical results for parallel magnetic field lines along the z-axis
     442           1 : TEST(testPropagationBP, gyration) {
     443           1 :         PropagationBP propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)));
     444             : 
     445             :         double step = 10. * Mpc;  // gyroradius is 108.1 Mpc
     446           1 :         propa.setMaximumStep(step);
     447           1 :         propa.setMinimumStep(step);
     448             : 
     449             : 
     450           1 :         ParticleState p;
     451           1 :         p.setId(nucleusId(1, 1));
     452           1 :         p.setEnergy(100 * EeV);
     453           1 :         p.setPosition(Vector3d(0, 0, 0));
     454           1 :         p.setDirection(Vector3d(1, 1, 1));
     455           1 :         Candidate c(p);
     456           1 :         c.setNextStep(0);
     457           1 :         propa.process(&c);
     458             : 
     459           1 :         double dirX = c.current.getDirection().x;
     460           1 :         double dirY = c.current.getDirection().y;
     461           1 :         double dirZ = c.current.getDirection().z;
     462           1 :         double posZ = c.current.getPosition().z;
     463             : 
     464             :         // Test if the analytical solution is achieved for the components of the momentum with the Boris push as expected in
     465             :         // the background magnetic field.
     466           1 :         EXPECT_DOUBLE_EQ(2 / 3., dirX * dirX + dirY * dirY);  // constant momentum in the perpendicular plane to background magnetic field field
     467           1 :         EXPECT_DOUBLE_EQ(1 / 3., dirZ * dirZ);  // constant momentum parallel to the background magnetic field
     468           1 :         EXPECT_DOUBLE_EQ( step * step / 3., posZ * posZ);  // constant velocity parallel to the background magnetic field
     469             : 
     470             :         // Nine new steps to have finally propagated the particle ten times
     471          10 :         for (int i = 0; i < 9; i++){
     472           9 :                 propa.process(&c);
     473             :         }
     474             : 
     475           1 :         dirX = c.current.getDirection().x;
     476           1 :         dirY = c.current.getDirection().y;
     477           1 :         dirZ = c.current.getDirection().z;
     478           1 :         posZ = c.current.getPosition().z;
     479             : 
     480             :         // Compare the numerical solutions after ten steps with the analytical solution of the trajectories
     481           1 :         EXPECT_DOUBLE_EQ(2 / 3., dirX * dirX + dirY * dirY);  // constant momentum in the perpendicular plane to background magnetic field field
     482           1 :         EXPECT_DOUBLE_EQ(1 / 3., dirZ * dirZ);  // constant momentum parallel to the background magnetic field
     483           1 :         EXPECT_DOUBLE_EQ(100 * step * step / 3., posZ * posZ);  // constant velocity parallel to the background magnetic field
     484           1 : }
     485             : 
     486             : 
     487             : // Test the that the optimization for fixed step sizes works
     488           1 : TEST(testPropagationBP, fixedStepOptimization) {
     489             :         // particle 1 with fixed step sizes
     490             :         double fixed_step = pc;
     491           2 :         PropagationBP propa1(new PlaneWaveTurbulence(TurbulenceSpectrum(gauss, pc, 100*pc), 10, 1), fixed_step);
     492           1 :         ParticleState p1;
     493           1 :         p1.setId(nucleusId(1, 1));
     494           1 :         p1.setEnergy(100 * EeV);
     495           1 :         p1.setPosition(Vector3d(0, 0, 0));
     496           1 :         p1.setDirection(Vector3d(1, 1, 1));
     497           1 :         Candidate c1(p1);
     498           1 :         c1.setNextStep(0);
     499             :         // Nine new steps to have finally propagated the particle ten times
     500          10 :         for (int i = 0; i < 9; i++){
     501           9 :                 propa1.process(&c1);
     502             :         }
     503             : 
     504             :         // particle 2 with different min and max steps. The tolerance is chosen such that particle 2 will be
     505             :         // propagated with the same step as particle 1, however not using the optimization for fixed step sizes
     506             :         double tolerance = 1;
     507           2 :         PropagationBP propa2(new PlaneWaveTurbulence(TurbulenceSpectrum(gauss, pc, 100*pc), 10, 1), tolerance, fixed_step, 1.1*fixed_step);
     508           1 :         ParticleState p2;
     509           1 :         p2.setId(nucleusId(1, 1));
     510           1 :         p2.setEnergy(100 * EeV);
     511           1 :         p2.setPosition(Vector3d(0, 0, 0));
     512           1 :         p2.setDirection(Vector3d(1, 1, 1));
     513           1 :         Candidate c2(p2);
     514           1 :         c1.setNextStep(0);
     515             :         // Nine new steps to have finally propagated the particle ten times
     516          10 :         for (int i = 0; i < 9; i++){
     517           9 :                 propa2.process(&c2);
     518             :         }
     519             : 
     520           1 :         EXPECT_DOUBLE_EQ(c1.current.getDirection().x, c2.current.getDirection().x);
     521           1 :         EXPECT_DOUBLE_EQ(c1.current.getDirection().y, c2.current.getDirection().y);
     522           1 :         EXPECT_DOUBLE_EQ(c1.current.getDirection().z, c2.current.getDirection().z);
     523           1 :         EXPECT_DOUBLE_EQ(c1.current.getPosition().x, c2.current.getPosition().x);
     524           1 :         EXPECT_DOUBLE_EQ(c1.current.getPosition().y, c2.current.getPosition().y);
     525           1 :         EXPECT_DOUBLE_EQ(c1.current.getPosition().z, c2.current.getPosition().z);
     526           1 : }
     527             : 
     528             : 
     529           1 : TEST(testPropagationBP, neutron) {
     530           1 :         PropagationBP propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)));
     531             : 
     532           1 :         propa.setMinimumStep(1 * kpc);
     533           1 :         propa.setMaximumStep(1 * kpc);
     534             : 
     535           1 :         ParticleState p;
     536           1 :         p.setId(nucleusId(1, 0));
     537           1 :         p.setEnergy(100 * EeV);
     538           1 :         p.setPosition(Vector3d(0, 0, 0));
     539           1 :         p.setDirection(Vector3d(0, 1, 0));
     540           1 :         Candidate c(p);
     541             : 
     542           1 :         propa.process(&c);
     543             : 
     544           1 :         EXPECT_DOUBLE_EQ(1 * kpc, c.getCurrentStep());
     545           1 :         EXPECT_DOUBLE_EQ(1 * kpc, c.getNextStep());
     546           2 :         EXPECT_EQ(Vector3d(0, 1 * kpc, 0), c.current.getPosition());
     547           2 :         EXPECT_EQ(Vector3d(0, 1, 0), c.current.getDirection());
     548           1 : }
     549             : 
     550             : 
     551           0 : int main(int argc, char **argv) {
     552           0 :         ::testing::InitGoogleTest(&argc, argv);
     553           0 :         return RUN_ALL_TESTS();
     554             : }
     555             : 
     556             : } // namespace crpropa

Generated by: LCOV version 1.14