@@ -44,34 +44,30 @@ namespace openmc {
4444
4545double Particle::speed () const
4646{
47- // Determine mass in eV/c^2
48- double mass;
49- switch (this ->type ()) {
50- case ParticleType::neutron:
51- mass = MASS_NEUTRON_EV;
52- break ;
53- case ParticleType::photon:
54- mass = 0.0 ;
55- break ;
56- case ParticleType::electron:
57- case ParticleType::positron:
58- mass = MASS_ELECTRON_EV;
59- break ;
60- }
61-
62- if (this ->E () < 1.0e-9 * mass) {
63- // If the energy is much smaller than the mass, revert to non-relativistic
64- // formula. The 1e-9 criterion is specifically chosen as the point below
65- // which the error from using the non-relativistic formula is less than the
66- // round-off eror when using the relativistic formula (see analysis at
67- // https://gist.github.com/paulromano/da3b473fe3df33de94b265bdff0c7817)
68- return C_LIGHT * std::sqrt (2 * this ->E () / mass);
47+ if (settings::run_CE) {
48+ // Determine mass in eV/c^2
49+ double mass;
50+ switch (this ->type ()) {
51+ case ParticleType::neutron:
52+ mass = MASS_NEUTRON_EV;
53+ break ;
54+ case ParticleType::photon:
55+ mass = 0.0 ;
56+ break ;
57+ case ParticleType::electron:
58+ case ParticleType::positron:
59+ mass = MASS_ELECTRON_EV;
60+ break ;
61+ }
62+ // Equivalent to C * sqrt(1-(m/(m+E))^2) without problem at E<<m:
63+ return C_LIGHT * std::sqrt (this ->E () * (this ->E () + 2 * mass)) /
64+ (this ->E () + mass);
6965 } else {
70- // Calculate inverse of Lorentz factor
71- const double inv_gamma = mass / ( this ->E () + mass) ;
72-
73- // Calculate speed via v = c * sqrt(1 - γ^-2)
74- return C_LIGHT * std::sqrt ( 1 - inv_gamma * inv_gamma );
66+ auto & macro_xs = data::mg. macro_xs_ [ this -> material ()];
67+ int macro_t = this ->mg_xs_cache (). t ;
68+ int macro_a = macro_xs. get_angle_index ( this -> u ());
69+ return 1.0 / macro_xs. get_xs (MgxsType::INVERSE_VELOCITY, this -> g (), nullptr ,
70+ nullptr , nullptr , macro_t , macro_a );
7571 }
7672}
7773
@@ -241,32 +237,25 @@ void Particle::event_advance()
241237 collision_distance () = -std::log (prn (current_seed ())) / macro_xs ().total ;
242238 }
243239
244- // Select smaller of the two distances
245- double distance = std::min (boundary ().distance (), collision_distance ());
240+ double speed = this ->speed ();
241+ double time_cutoff = settings::time_cutoff[static_cast <int >(type ())];
242+ double distance_cutoff =
243+ (time_cutoff < INFTY) ? (time_cutoff - time ()) * speed : INFTY;
244+
245+ // Select smaller of the three distances
246+ double distance =
247+ std::min ({boundary ().distance (), collision_distance (), distance_cutoff});
246248
247249 // Advance particle in space and time
248250 // Short-term solution until the surface source is revised and we can use
249251 // this->move_distance(distance)
250252 for (int j = 0 ; j < n_coord (); ++j) {
251253 coord (j).r () += distance * coord (j).u ();
252254 }
253- double dt = distance / this -> speed () ;
255+ double dt = distance / speed;
254256 this ->time () += dt;
255257 this ->lifetime () += dt;
256258
257- // Kill particle if its time exceeds the cutoff
258- bool hit_time_boundary = false ;
259- double time_cutoff = settings::time_cutoff[static_cast <int >(type ())];
260- if (time () > time_cutoff) {
261- double dt = time () - time_cutoff;
262- time () = time_cutoff;
263- lifetime () = time_cutoff;
264-
265- double push_back_distance = speed () * dt;
266- this ->move_distance (-push_back_distance);
267- hit_time_boundary = true ;
268- }
269-
270259 // Score track-length tallies
271260 if (!model::active_tracklength_tallies.empty ()) {
272261 score_tracklength_tally (*this , distance);
@@ -284,7 +273,7 @@ void Particle::event_advance()
284273 }
285274
286275 // Set particle weight to zero if it hit the time boundary
287- if (hit_time_boundary ) {
276+ if (distance == distance_cutoff ) {
288277 wgt () = 0.0 ;
289278 }
290279}
0 commit comments