RotationScaleMerge: a merge with no rocking-curve runs reports itself instead of dividing by zero
With more than one thread, Combine() split its runs into per-thread chunks of ceil(n_run / nt) with nt = min(nthreads, n_run); with no runs at all (a lattice that integrated nothing) nt was 0 and the process died on SIGFPE in Step 5. The empty case now takes the serial path, and the merge ends in the ordinary exception. Test: RotationScaleMerge_NoReflectionsIsAnErrorNotACrash (fails without the fix, on the host path). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HVeDQqN9qRD57vnShzTC37
This commit is contained in:
1 parent
297ef9dc78
commit
9499d77606
2 files changed
+20
-1
No files matched your search
@@ -4843,7 +4843,9 @@ void RotationScaleMerge::Combine() {
|
||||
size_t n_used = 0;
|
||||
std::vector<std::vector<Obs>> part; // the fulls of consecutive runs, in run order
|
||||
|
||||
if (observation_dump || nthreads <= 1) {
|
||||
// No runs at all (a lattice that integrated nothing) takes the serial path too: the chunking below
|
||||
// divides by the number of threads it would use, which is then 0.
|
||||
if (observation_dump || nthreads <= 1 || n_run == 0) {
|
||||
// Serial (diagnostic dump needs a single writer).
|
||||
std::ostringstream dump;
|
||||
if (observation_dump) {
|
||||
|
||||
@@ -281,3 +281,20 @@ TEST_CASE("TrimBlankSweepEnds_WeakCrystalKeepsItsEnds", "[RotationScale]") {
|
||||
CHECK(sweep.front().reflections.size() == 200);
|
||||
CHECK(sweep.back().reflections.size() == 200);
|
||||
}
|
||||
|
||||
// A lattice that integrated nothing hands the merge frames without a single reflection. On more than one
|
||||
// thread the 3D combine split its rocking-curve runs into per-thread chunks by dividing by the number of
|
||||
// threads it would use - 0 with no runs - and the process died on SIGFPE instead of reporting the empty merge.
|
||||
TEST_CASE("RotationScaleMerge_NoReflectionsIsAnErrorNotACrash", "[RotationScale]") {
|
||||
DiffractionExperiment x(DetJF(1));
|
||||
x.Goniometer(GoniometerAxis("omega", 0.0f, 0.2f, Coord(1, 0, 0), std::nullopt));
|
||||
x.BeamX_pxl(512).BeamY_pxl(256).DetectorDistance_mm(150).IncidentEnergy_keV(WVL_1A_IN_KEV);
|
||||
x.SetUnitCell(UnitCell(50, 60, 70, 90, 90, 90));
|
||||
std::vector<IntegrationOutcome> outcomes(20);
|
||||
for (auto &o : outcomes)
|
||||
o.geom = x.GetDiffractionGeometry();
|
||||
Logger logger("RotationScaleMerge_NoReflections");
|
||||
RotationScaleMerge rsm(x, outcomes, x.GetUnitCell(), 3, 4, logger);
|
||||
rsm.Ingest();
|
||||
REQUIRE_THROWS_AS(rsm.Run(false, true, false), JFJochException);
|
||||
}
|
||||
Reference in new issue
Block a user