Skip to content

Conversation

@ChasingNeutrons
Copy link
Collaborator

I have added a very Serpent-like feature: one can specify a minimum average flight distance before collision. The collision is then rejection sampled and can be real or virtual. This is mostly useful because it allows using surface tracking with the collision estimator to score in low density regions.

The operation is quite simple and comes mostly from the database. An 'avgDist' is input, which creates a cross section. During tracking, the maximum of the majorant/total and this cross section is used for tracking. This is then stored in cache and use for tallying as well. Beyond that, there are a few small changes to surface tracking routines.

Allows obtaining CFE tallies in void when using ST or HT. User specifies
a minimum average distance to collision.
Copy link
Member

@valeriaRaffuzzi valeriaRaffuzzi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks very good overall! It doesn't look like anything should break or be biased anywhere :) Just a suggestion on a different logic that avoids some repetition and avoids having NaN distances.


STLoop: do

invSigmaTrack = ONE / self % xsData % getTrackingXS(p, p % matIdx(), MATERIAL_XS)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like that you're inviting a division by ZERO and a NaN distance in the common case of vacuum material and unspecified collisionXS. What about this modified logic? If we're not bothered by the trackXS == ZERO. We could also have a tolerance and the check becomes trackXS < TOL where TOL can be 1.0e-12 or so?

      trackXS = self % xsData % getTrackingXS(p, p % matIdx(), MATERIAL_XS)

      if (trackXS == ZERO) then

          dist = INFINITY
          invSigmaTrack = INFINITY
          sigmaT = ZERO

      else

          invSigmaTrack = ONE / trackXS
          dist = -log( p % pRNG % get()) * invSigmaTrack

          ! Should never happen! Catches NaN distances
          if (dist /= dist) call fatalError(Here, "Distance is NaN")

          ! Obtain the local cross-section
          sigmaT = self % xsData % getTrackMatXS(p, p % matIdx())

      end if

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I shouldn't invite the NaN. It is maybe a bit complicated because it isn't clear whether the check you propose is identical to checking for a void material. This might then imply adding a change in logic to getTrackMatXS, which is a bit messy.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, to be more clear: if trackXS /= ZERO in a void (as we have imposed a minimum average distance) this requires getting sigmaT for a void. This implies changing updateTrackMatXS

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair, I hadn't thought of this last case! You can still have a if VOID sigmaT = ZERO in the tracking logic.

dist = -log( p % pRNG % get()) * invSigmaTrack

! Obtain the local cross-section
sigmaT = self % xsData % getTrackMatXS(p, p % matIdx())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks better now, but I am not against adding an extra VOID check here to be extra safe!

@valeriaRaffuzzi valeriaRaffuzzi merged commit 40ad750 into CambridgeNuclear:main Oct 8, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants