Skip to content

Commit 68e894c

Browse files
authored
Fix a bug in time cutoff behavior (#3526)
1 parent c5a7173 commit 68e894c

4 files changed

Lines changed: 37 additions & 47 deletions

File tree

src/particle.cpp

Lines changed: 33 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -44,34 +44,30 @@ namespace openmc {
4444

4545
double 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
}

src/physics_mg.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ void create_fission_sites(Particle& p)
137137
SourceSite site;
138138
site.r = p.r();
139139
site.particle = ParticleType::neutron;
140+
site.time = p.time();
140141
site.wgt = 1. / weight;
141142
site.parent_id = p.id();
142143
site.progeny_id = p.n_progeny()++;
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
tally 1:
2-
2.000000E+03
3-
4.000000E+05
2+
1.383148E+02
3+
1.913099E+03
44
0.000000E+00
55
0.000000E+00

tests/unit_tests/test_mesh.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ def test_mesh_material_volumes_serialize():
620620
assert new_volumes.by_element(3) == [(2, 1.0)]
621621

622622

623-
def test_raytrace_mesh_infinite_loop():
623+
def test_raytrace_mesh_infinite_loop(run_in_tmpdir):
624624
# Create a model with one large spherical cell
625625
sphere = openmc.Sphere(r=100, boundary_type='vacuum')
626626
cell = openmc.Cell(region=-sphere)

0 commit comments

Comments
 (0)