Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kinetics parameters using Iterated Fission Probability #3133

Draft
wants to merge 15 commits into
base: develop
Choose a base branch
from

Conversation

JoffreyDorville
Copy link
Contributor

@JoffreyDorville JoffreyDorville commented Sep 16, 2024

Description

Calculation of adjoint-weighted kinetics parameters (effective generation time and effective delayed neutron fraction) using the Iterated Fission Probability (IFP) method.

This implementation uses the same approach as the IFP implementation in Serpent 2 documented in [1].

To generate results for both effective generation time and effective delayed neutron fraction, IFP settings need to be set:

settings.iterated_fission_probability = {
    "parameter": "both",
    "n_generation": 5
}

and a specific tally has to be set:

tally = openmc.Tally(name="ifp-scores")
tally.scores = [
    "ifp-time-numerator",
    "ifp-beta-numerator",
    "ifp-denominator"
]

Testing is still in progress. I will update the draft to PR once I have finished the remaining tests.

References

[1] J. Leppänen, M. Aufiero, E. Fridman, R. Rachamin, and S. van der Marck, “Calculation of effective point kinetics parameters in the Serpent 2 Monte Carlo code,” Annals of Nuclear Energy, vol. 65, pp. 272–279, Mar. 2014, doi:10.1016/j.anucene.2013.10.032

Checklist

  • I have performed a self-review of my own code
  • I have run clang-format (version 15) on any C++ source files (if applicable)
  • I have followed the style guidelines for Python source files (if applicable)
  • I have made corresponding changes to the documentation (if applicable)
  • I have added tests that prove my fix is effective or that my feature works (if applicable)

@zhangzeqin1997
Copy link

I have tested this feature, and everything works well at the moment. I would like to inquire if there are any plans to add output for the individual delayed neutron group fractions and decay constants, similar to how it is done in MCNP.

Copy link
Contributor

@paulromano paulromano left a comment

Choose a reason for hiding this comment

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

Thanks for this PR @JoffreyDorville and apologies it's taken me some time to get you some feedback on this. Here is a set of initial comments. In addition to the line comments/questions below, I'll add two other comments:

  • It would be nice if some of the logic/functionality here could be isolated into its own source file (ifp.h/ifp.cpp).
  • I see quite a few blocks of code that seem repeated (for example, in bank.cpp and eigenvalue.cpp). If there's any way to encapsulate them in a function so that they don't need to be repeated, that would help reduce the total number of lines.

Comment on lines +123 to +124
extern IFPParameter
ifp_parameter; //!< Parameter to calculate for Iterated Fission Probability
Copy link
Contributor

Choose a reason for hiding this comment

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

I see right now this is determined based on user input in the Settings object. I think it would be better if this was determined automatically based on what scores show up in tallies (i.e., if the user specified "ifp-time-numerator" as a score, then activate the logic to collect the information needed accordingly), which leaves less for the user to think about.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The code now detects automatically the correct value for ifp_parameter based on the user defined tallies. It also detects whether settings::ifp should be true or not. I removed the iterated_fission_probability settings so that the user only declares the number of generations via ifp_n_generation instead. If the user does not declare this value and IFP tallies are requested, the code will use a default value of 10 generations.

src/physics.cpp Outdated
Comment on lines 215 to 216
vector<int> updated_ifp_delayed_groups;
vector<double> updated_ifp_lifetimes;
Copy link
Contributor

Choose a reason for hiding this comment

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

This will result in memory allocation in the middle of a particle's transport, which is never desirable 1) because it can degrade threading efficiency and 2) it doesn't fit GPU programming models well. Is there any way we can avoid the memory allocation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With the refactoring, these vectors are only declared inside the "if (settings::ifp)" loop now. This should no longer impact the non-IFP user.

For the IFP context, I need to use vectors in the current implementation as the number of generations is only known at runtime (user input). There are options to use arrays instead with some limitations but this is not what I chose for this implementation.

src/particle.cpp Outdated
@@ -233,13 +234,15 @@ void Particle::event_advance()
coord(j).r += distance * coord(j).u;
}
this->time() += distance / this->speed();
this->lifetime() += distance / this->speed();
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that lifetime looks identical to time here, can you explain what the difference between the two is?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The main difference between time() and lifetime() is that when a particle is created via Particle::from_source, lifetime() will be reset to 0 while time() will be set to the source time. This means that time() will not necessarily be equal to 0 when Particle::from_source is called if we already did multiple batches. In my case, I really need a timer that is reset every time a particle is created.

@JoffreyDorville
Copy link
Contributor Author

I isolated every IFP functionality within ifp.cpp/ifp.h as suggested. The code reads definitely better now, especially in eigenvalue.cpp. There is a balance to find when encapsulating parts of the IFP code in their own functions that we can discuss. Interestingly, it ended up in more lines of code, but the readability and maintainability should be better now.

@realmisch
Copy link

Hello everyone, I've done some testing with support from @sallustius in using the IFP tallies and modifying the implementation to permit using a DelayedGroupFilter since the delayed group index is already calculated during transport. With this modification, I've been able to calculate the group-wise delayed fraction constants and do 6-group point kinetics solely from OpenMC results. The results have been in agreement with Serpent's IFP results for the same geometry and simulation settings.

@JoffreyDorville how would you like to proceed with adding this capability to your branch?

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.

4 participants