Skip to content

Commit b061c20

Browse files
authored
Merge pull request #39 from zxkjack123/point-detector-contrib
Fix point detector scoring: activate tallies, set ParticleRay state, fix Python reader
2 parents 3cc9446 + e519b94 commit b061c20

5 files changed

Lines changed: 49 additions & 1 deletion

File tree

include/openmc/tallies/tally_scoring.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,15 @@ void score_point_tally_impl(
158158
p.wgt_last() = p.wgt();
159159
p.wgt() *= attenuation;
160160

161+
// Set position state so PointFilter::get_all_bins can match:
162+
// r() = detector position (for bin matching),
163+
// r_last() = source/scatter position (for 1/r^2 weight)
164+
p.r_last() = r;
165+
p.r() = det;
166+
167+
// Set E_last so EnergyFilter::get_all_bins bins correctly
168+
p.E_last() = E;
169+
161170
double flux = p.wgt_last() * pdf;
162171
score_tracklength_tally_general(p, flux, model::active_point_tallies);
163172
}

openmc/filter.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,28 @@ def bins(self, bins):
834834
cv.check_length(f'bins[{i}][0]', item[0], 3, 3)
835835
cv.check_type(f'bins[{i}][1]', item[1], Real)
836836
self._bins = bins
837+
838+
@classmethod
839+
def from_hdf5(cls, group, **kwargs):
840+
filter_id = int(group.name.split('/')[-1].lstrip('filter '))
841+
flat = group['bins'][()]
842+
# Reconstruct tuple structure: every 4 values = (x, y, z, r0)
843+
bins = []
844+
for i in range(0, len(flat), 4):
845+
pos = (float(flat[i]), float(flat[i+1]), float(flat[i+2]))
846+
r0 = float(flat[i+3])
847+
bins.append((pos, r0))
848+
out = cls(bins, filter_id=filter_id)
849+
out._num_bins = group['n_bins'][()]
850+
return out
851+
852+
def get_pandas_dataframe(self, data_size, stride, **kwargs):
853+
import pandas as pd
854+
labels = [f"({p[0]}, {p[1]}, {p[2]}) R0={r}" for (p, r) in self.bins]
855+
filter_bins = np.repeat(labels, stride)
856+
tile_factor = data_size // len(filter_bins)
857+
filter_bins = np.tile(filter_bins, tile_factor)
858+
return pd.DataFrame({self.short_name.lower(): filter_bins})
837859

838860
def to_xml_element(self):
839861
"""Return XML Element representing the Filter.

openmc/tallies.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
_FILTER_CLASSES = (Filter, CrossFilter, AggregateFilter)
5454

5555
# Valid types of estimators
56-
ESTIMATOR_TYPES = {'tracklength', 'collision', 'analog'}
56+
ESTIMATOR_TYPES = {'tracklength', 'collision', 'analog', 'next-event'}
5757

5858

5959
class Tally(IDManagerMixin):

src/state_point.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ extern "C" int openmc_statepoint_write(const char* filename, bool* write_source)
214214
write_dataset(tally_group, "estimator", "tracklength");
215215
} else if (tally->estimator_ == TallyEstimator::COLLISION) {
216216
write_dataset(tally_group, "estimator", "collision");
217+
} else if (tally->estimator_ == TallyEstimator::NEXT_EVENT) {
218+
write_dataset(tally_group, "estimator", "next-event");
217219
}
218220

219221
write_dataset(tally_group, "n_realizations", tally->n_realizations_);

src/tallies/tally.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "openmc/tallies/filter_meshmaterial.h"
3232
#include "openmc/tallies/filter_meshsurface.h"
3333
#include "openmc/tallies/filter_particle.h"
34+
#include "openmc/tallies/filter_point.h"
3435
#include "openmc/tallies/filter_sph_harm.h"
3536
#include "openmc/tallies/filter_surface.h"
3637
#include "openmc/tallies/filter_time.h"
@@ -1199,6 +1200,8 @@ void setup_active_tallies()
11991200
model::active_meshsurf_tallies.clear();
12001201
model::active_surface_tallies.clear();
12011202
model::active_pulse_height_tallies.clear();
1203+
model::active_point_tallies.clear();
1204+
model::active_point_detectors.clear();
12021205
model::time_grid.clear();
12031206

12041207
for (auto i = 0; i < model::tallies.size(); ++i) {
@@ -1240,6 +1243,16 @@ void setup_active_tallies()
12401243
case TallyType::PULSE_HEIGHT:
12411244
model::active_pulse_height_tallies.push_back(i);
12421245
break;
1246+
1247+
case TallyType::POINT:
1248+
model::active_point_tallies.push_back(i);
1249+
// Populate the set of unique detector positions from PointFilter
1250+
if (auto pf = tally.get_filter<PointFilter>()) {
1251+
for (const auto& [pos, r0] : pf->detectors()) {
1252+
model::active_point_detectors.insert(pos);
1253+
}
1254+
}
1255+
break;
12431256
}
12441257
}
12451258
}
@@ -1263,6 +1276,8 @@ void free_memory_tally()
12631276
model::active_meshsurf_tallies.clear();
12641277
model::active_surface_tallies.clear();
12651278
model::active_pulse_height_tallies.clear();
1279+
model::active_point_tallies.clear();
1280+
model::active_point_detectors.clear();
12661281
model::time_grid.clear();
12671282

12681283
model::tally_map.clear();

0 commit comments

Comments
 (0)