mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 05:35:49 -04:00
Merge 188f7a5167 into d3bc1669d3
This commit is contained in:
commit
b29ce5aa91
18 changed files with 155 additions and 277 deletions
|
|
@ -32,9 +32,7 @@ the ``ifp_n_generation`` settings in the Python API::
|
|||
|
||||
settings.ifp_n_generation = 5
|
||||
|
||||
``ifp_n_generation`` should be greater than 0, but should also be lower than
|
||||
or equal to the number of inactive batches declared for the calculation.
|
||||
The respect of these constraints is verified by OpenMC before any calculation.
|
||||
``ifp_n_generation`` should be greater than 0.
|
||||
|
||||
OpenMC will automatically detect the type of data that needs to be stored based
|
||||
on the tally scores selected by the user. This guarantees that only information
|
||||
|
|
|
|||
|
|
@ -5,21 +5,12 @@
|
|||
#include "openmc/particle.h"
|
||||
#include "openmc/particle_data.h"
|
||||
#include "openmc/settings.h"
|
||||
#include "openmc/simulation.h"
|
||||
|
||||
#include <algorithm> // for copy
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//! Check the value of the IFP parameter for beta effective or both.
|
||||
//!
|
||||
//! \return true if "BetaEffective" or "Both", false otherwise.
|
||||
bool is_beta_effective_or_both();
|
||||
|
||||
//! Check the value of the IFP parameter for generation time or both.
|
||||
//!
|
||||
//! \return true if "GenerationTime" or "Both", false otherwise.
|
||||
bool is_generation_time_or_both();
|
||||
|
||||
//! Resize IFP vectors
|
||||
//!
|
||||
//! \param[in,out] delayed_groups List of delayed group numbers
|
||||
|
|
@ -28,10 +19,10 @@ bool is_generation_time_or_both();
|
|||
template<typename T, typename U>
|
||||
void resize_ifp_data(vector<T>& delayed_groups, vector<U>& lifetimes, int64_t n)
|
||||
{
|
||||
if (is_beta_effective_or_both()) {
|
||||
if (simulation::ifp_delayed_on) {
|
||||
delayed_groups.resize(n);
|
||||
}
|
||||
if (is_generation_time_or_both()) {
|
||||
if (simulation::ifp_lifetime_on) {
|
||||
lifetimes.resize(n);
|
||||
}
|
||||
}
|
||||
|
|
@ -85,10 +76,12 @@ void resize_simulation_ifp_banks();
|
|||
//! Retrieve IFP data from the IFP fission banks.
|
||||
//!
|
||||
//! \param[in] i_bank Index in the fission banks
|
||||
//! \param[in,out] delayed_groups Delayed group numbers
|
||||
//! \param[in,out] lifetimes Lifetimes lists
|
||||
void copy_ifp_data_from_fission_banks(
|
||||
int i_bank, vector<int>& delayed_groups, vector<double>& lifetimes);
|
||||
//! \param[in] j_bank Index in the ifp banks
|
||||
//! \param[in,out] delayed_groups_bank Delayed group numbers
|
||||
//! \param[in,out] lifetimes_bank Lifetimes lists
|
||||
void copy_ifp_data_from_fission_banks(int i_bank, int j_bank,
|
||||
vector<vector<int>>& delayed_groups_bank,
|
||||
vector<vector<double>>& lifetimes_bank);
|
||||
|
||||
#ifdef OPENMC_MPI
|
||||
|
||||
|
|
|
|||
|
|
@ -24,14 +24,6 @@ enum class SSWCellType {
|
|||
To,
|
||||
};
|
||||
|
||||
// Type of IFP parameters
|
||||
enum class IFPParameter {
|
||||
None,
|
||||
Both,
|
||||
BetaEffective,
|
||||
GenerationTime,
|
||||
};
|
||||
|
||||
struct CollisionTrackConfig {
|
||||
bool mcpl_write {false}; //!< Write collision tracks using MCPL?
|
||||
std::unordered_set<int>
|
||||
|
|
@ -69,8 +61,7 @@ extern bool
|
|||
delayed_photon_scaling; //!< Scale fission photon yield to include delayed
|
||||
extern "C" bool entropy_on; //!< calculate Shannon entropy?
|
||||
extern "C" bool
|
||||
event_based; //!< use event-based mode (instead of history-based)
|
||||
extern bool ifp_on; //!< Use IFP for kinetics parameters?
|
||||
event_based; //!< use event-based mode (instead of history-based)
|
||||
extern bool legendre_to_tabular; //!< convert Legendre distributions to tabular?
|
||||
extern bool material_cell_offsets; //!< create material cells offsets?
|
||||
extern "C" bool output_summary; //!< write summary.h5?
|
||||
|
|
@ -146,8 +137,6 @@ extern array<double, 4>
|
|||
time_cutoff; //!< Time cutoff in [s] for each particle type
|
||||
extern int
|
||||
ifp_n_generation; //!< Number of generation for Iterated Fission Probability
|
||||
extern IFPParameter
|
||||
ifp_parameter; //!< Parameter to calculate for Iterated Fission Probability
|
||||
extern int
|
||||
legendre_to_tabular_points; //!< number of points to convert Legendres
|
||||
extern int max_order; //!< Maximum Legendre order for multigroup data
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ namespace simulation {
|
|||
extern int ct_current_file; //!< current collision track file index
|
||||
extern "C" int current_batch; //!< current batch
|
||||
extern "C" int current_gen; //!< current fission generation
|
||||
extern bool ifp_delayed_on; //!< Store delayed group IFP data?
|
||||
extern bool ifp_lifetime_on; //!< Store lifetime IFP data?
|
||||
extern "C" bool initialized; //!< has simulation been initialized?
|
||||
extern "C" double keff; //!< average k over batches
|
||||
extern "C" double keff_std; //!< standard deviation of average k
|
||||
|
|
|
|||
|
|
@ -147,6 +147,9 @@ public:
|
|||
//! Whether this tally is currently being updated
|
||||
bool active_ {false};
|
||||
|
||||
//! Offset batch to activate this tally after.
|
||||
int offset_ {0};
|
||||
|
||||
//! Number of realizations
|
||||
int n_realizations_ {0};
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ void sort_bank(SharedArray<SourceSite>& bank, bool is_fission_bank)
|
|||
sorted_bank = bank.data() + bank.size();
|
||||
}
|
||||
|
||||
if (settings::ifp_on && is_fission_bank) {
|
||||
if (is_fission_bank) {
|
||||
allocate_temporary_vector_ifp(
|
||||
sorted_ifp_delayed_group_bank, sorted_ifp_lifetime_bank);
|
||||
}
|
||||
|
|
@ -135,15 +135,15 @@ void sort_bank(SharedArray<SourceSite>& bank, bool is_fission_bank)
|
|||
"bank size during sorting.");
|
||||
}
|
||||
sorted_bank[idx] = site;
|
||||
if (settings::ifp_on && is_fission_bank) {
|
||||
if (is_fission_bank) {
|
||||
copy_ifp_data_from_fission_banks(
|
||||
i, sorted_ifp_delayed_group_bank[idx], sorted_ifp_lifetime_bank[idx]);
|
||||
i, idx, sorted_ifp_delayed_group_bank, sorted_ifp_lifetime_bank);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy sorted bank into the fission bank
|
||||
std::copy(sorted_bank, sorted_bank + bank.size(), bank.data());
|
||||
if (settings::ifp_on && is_fission_bank) {
|
||||
if (is_fission_bank) {
|
||||
copy_ifp_data_to_fission_banks(
|
||||
sorted_ifp_delayed_group_bank.data(), sorted_ifp_lifetime_bank.data());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,10 +135,8 @@ void synchronize_bank()
|
|||
// Temporary banks for IFP
|
||||
vector<vector<int>> temp_delayed_groups;
|
||||
vector<vector<double>> temp_lifetimes;
|
||||
if (settings::ifp_on) {
|
||||
resize_ifp_data(
|
||||
temp_delayed_groups, temp_lifetimes, 3 * simulation::work_per_rank);
|
||||
}
|
||||
resize_ifp_data(
|
||||
temp_delayed_groups, temp_lifetimes, 3 * simulation::work_per_rank);
|
||||
|
||||
// ==========================================================================
|
||||
// SAMPLE N_PARTICLES FROM FISSION BANK AND PLACE IN TEMP_SITES
|
||||
|
|
@ -164,10 +162,8 @@ void synchronize_bank()
|
|||
for (int64_t i = tooth_start; i < tooth_end; i++) {
|
||||
int64_t idx = std::floor(tooth) - start;
|
||||
temp_sites[index_temp] = simulation::fission_bank[idx];
|
||||
if (settings::ifp_on) {
|
||||
copy_ifp_data_from_fission_banks(
|
||||
idx, temp_delayed_groups[index_temp], temp_lifetimes[index_temp]);
|
||||
}
|
||||
copy_ifp_data_from_fission_banks(
|
||||
idx, index_temp, temp_delayed_groups, temp_lifetimes);
|
||||
++index_temp;
|
||||
|
||||
// Next tooth
|
||||
|
|
@ -206,10 +202,8 @@ void synchronize_bank()
|
|||
|
||||
// IFP number of generation
|
||||
int ifp_n_generation;
|
||||
if (settings::ifp_on) {
|
||||
broadcast_ifp_n_generation(
|
||||
ifp_n_generation, temp_delayed_groups, temp_lifetimes);
|
||||
}
|
||||
broadcast_ifp_n_generation(
|
||||
ifp_n_generation, temp_delayed_groups, temp_lifetimes);
|
||||
|
||||
int64_t index_local = 0;
|
||||
vector<MPI_Request> requests;
|
||||
|
|
@ -225,7 +219,7 @@ void synchronize_bank()
|
|||
simulation::work_index.begin(), simulation::work_index.end(), start);
|
||||
|
||||
// Resize IFP send buffers
|
||||
if (settings::ifp_on && mpi::n_procs > 1) {
|
||||
if (mpi::n_procs > 1) {
|
||||
resize_ifp_data(send_delayed_groups, send_lifetimes,
|
||||
ifp_n_generation * 3 * simulation::work_per_rank);
|
||||
}
|
||||
|
|
@ -243,15 +237,12 @@ void synchronize_bank()
|
|||
mpi::source_site, neighbor, mpi::rank, mpi::intracomm,
|
||||
&requests.back());
|
||||
|
||||
if (settings::ifp_on) {
|
||||
// Send IFP data
|
||||
if (is_beta_effective_or_both())
|
||||
send_ifp_info(index_local, n, ifp_n_generation, neighbor, requests,
|
||||
temp_delayed_groups, send_delayed_groups);
|
||||
if (is_generation_time_or_both())
|
||||
send_ifp_info(index_local, n, ifp_n_generation, neighbor, requests,
|
||||
temp_lifetimes, send_lifetimes);
|
||||
}
|
||||
if (simulation::ifp_delayed_on)
|
||||
send_ifp_info(index_local, n, ifp_n_generation, neighbor, requests,
|
||||
temp_delayed_groups, send_delayed_groups);
|
||||
if (simulation::ifp_lifetime_on)
|
||||
send_ifp_info(index_local, n, ifp_n_generation, neighbor, requests,
|
||||
temp_lifetimes, send_lifetimes);
|
||||
}
|
||||
|
||||
// Increment all indices
|
||||
|
|
@ -290,7 +281,7 @@ void synchronize_bank()
|
|||
}
|
||||
|
||||
// Resize IFP receive buffers
|
||||
if (settings::ifp_on && mpi::n_procs > 1) {
|
||||
if (mpi::n_procs > 1) {
|
||||
resize_ifp_data(recv_delayed_groups, recv_lifetimes,
|
||||
ifp_n_generation * simulation::work_per_rank);
|
||||
}
|
||||
|
|
@ -314,15 +305,12 @@ void synchronize_bank()
|
|||
MPI_Irecv(&simulation::source_bank[index_local], static_cast<int>(n),
|
||||
mpi::source_site, neighbor, neighbor, mpi::intracomm, &requests.back());
|
||||
|
||||
if (settings::ifp_on) {
|
||||
// Receive IFP data
|
||||
if (is_beta_effective_or_both())
|
||||
receive_ifp_data(index_local, n, ifp_n_generation, neighbor, requests,
|
||||
recv_delayed_groups, deserialization_info);
|
||||
if (is_generation_time_or_both())
|
||||
receive_ifp_data(index_local, n, ifp_n_generation, neighbor, requests,
|
||||
recv_lifetimes, deserialization_info);
|
||||
}
|
||||
if (simulation::ifp_delayed_on)
|
||||
receive_ifp_data(index_local, n, ifp_n_generation, neighbor, requests,
|
||||
recv_delayed_groups, deserialization_info);
|
||||
if (simulation::ifp_lifetime_on)
|
||||
receive_ifp_data(index_local, n, ifp_n_generation, neighbor, requests,
|
||||
recv_lifetimes, deserialization_info);
|
||||
|
||||
} else {
|
||||
// If the source sites are on this processor, we can simply copy them
|
||||
|
|
@ -332,10 +320,8 @@ void synchronize_bank()
|
|||
std::copy(&temp_sites[index_temp], &temp_sites[index_temp + n],
|
||||
&simulation::source_bank[index_local]);
|
||||
|
||||
if (settings::ifp_on) {
|
||||
copy_partial_ifp_data_to_source_banks(
|
||||
index_temp, n, index_local, temp_delayed_groups, temp_lifetimes);
|
||||
}
|
||||
copy_partial_ifp_data_to_source_banks(
|
||||
index_temp, n, index_local, temp_delayed_groups, temp_lifetimes);
|
||||
}
|
||||
|
||||
// Increment all indices
|
||||
|
|
@ -351,21 +337,17 @@ void synchronize_bank()
|
|||
int n_request = requests.size();
|
||||
MPI_Waitall(n_request, requests.data(), MPI_STATUSES_IGNORE);
|
||||
|
||||
if (settings::ifp_on) {
|
||||
if (is_beta_effective_or_both())
|
||||
deserialize_ifp_info(ifp_n_generation, recv_delayed_groups,
|
||||
simulation::ifp_source_delayed_group_bank, deserialization_info);
|
||||
if (is_generation_time_or_both())
|
||||
deserialize_ifp_info(ifp_n_generation, recv_lifetimes,
|
||||
simulation::ifp_source_lifetime_bank, deserialization_info);
|
||||
}
|
||||
if (simulation::ifp_delayed_on)
|
||||
deserialize_ifp_info(ifp_n_generation, recv_delayed_groups,
|
||||
simulation::ifp_source_delayed_group_bank, deserialization_info);
|
||||
if (simulation::ifp_lifetime_on)
|
||||
deserialize_ifp_info(ifp_n_generation, recv_lifetimes,
|
||||
simulation::ifp_source_lifetime_bank, deserialization_info);
|
||||
|
||||
#else
|
||||
std::copy(temp_sites.data(), temp_sites.data() + settings::n_particles,
|
||||
simulation::source_bank.begin());
|
||||
if (settings::ifp_on) {
|
||||
copy_complete_ifp_data_to_source_banks(temp_delayed_groups, temp_lifetimes);
|
||||
}
|
||||
copy_complete_ifp_data_to_source_banks(temp_delayed_groups, temp_lifetimes);
|
||||
#endif
|
||||
|
||||
simulation::time_bank_sendrecv.stop();
|
||||
|
|
|
|||
76
src/ifp.cpp
76
src/ifp.cpp
|
|
@ -10,33 +10,15 @@
|
|||
|
||||
namespace openmc {
|
||||
|
||||
bool is_beta_effective_or_both()
|
||||
{
|
||||
if (settings::ifp_parameter == IFPParameter::BetaEffective ||
|
||||
settings::ifp_parameter == IFPParameter::Both) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_generation_time_or_both()
|
||||
{
|
||||
if (settings::ifp_parameter == IFPParameter::GenerationTime ||
|
||||
settings::ifp_parameter == IFPParameter::Both) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ifp(const Particle& p, int64_t idx)
|
||||
{
|
||||
if (is_beta_effective_or_both()) {
|
||||
if (simulation::ifp_delayed_on) {
|
||||
const auto& delayed_groups =
|
||||
simulation::ifp_source_delayed_group_bank[p.current_work()];
|
||||
simulation::ifp_fission_delayed_group_bank[idx] =
|
||||
_ifp(p.delayed_group(), delayed_groups);
|
||||
}
|
||||
if (is_generation_time_or_both()) {
|
||||
if (simulation::ifp_lifetime_on) {
|
||||
const auto& lifetimes =
|
||||
simulation::ifp_source_lifetime_bank[p.current_work()];
|
||||
simulation::ifp_fission_lifetime_bank[idx] = _ifp(p.lifetime(), lifetimes);
|
||||
|
|
@ -51,15 +33,16 @@ void resize_simulation_ifp_banks()
|
|||
simulation::ifp_fission_lifetime_bank, 3 * simulation::work_per_rank);
|
||||
}
|
||||
|
||||
void copy_ifp_data_from_fission_banks(
|
||||
int i_bank, vector<int>& delayed_groups, vector<double>& lifetimes)
|
||||
void copy_ifp_data_from_fission_banks(int i_bank, int j_bank,
|
||||
vector<vector<int>>& delayed_groups_bank,
|
||||
vector<vector<double>>& lifetimes_bank)
|
||||
{
|
||||
if (is_beta_effective_or_both()) {
|
||||
delayed_groups = simulation::ifp_fission_delayed_group_bank[i_bank];
|
||||
}
|
||||
if (is_generation_time_or_both()) {
|
||||
lifetimes = simulation::ifp_fission_lifetime_bank[i_bank];
|
||||
}
|
||||
if (simulation::ifp_delayed_on)
|
||||
delayed_groups_bank[j_bank] =
|
||||
simulation::ifp_fission_delayed_group_bank[i_bank];
|
||||
|
||||
if (simulation::ifp_lifetime_on)
|
||||
lifetimes_bank[j_bank] = simulation::ifp_fission_lifetime_bank[i_bank];
|
||||
}
|
||||
|
||||
#ifdef OPENMC_MPI
|
||||
|
|
@ -67,28 +50,27 @@ void broadcast_ifp_n_generation(int& n_generation,
|
|||
const vector<vector<int>>& delayed_groups,
|
||||
const vector<vector<double>>& lifetimes)
|
||||
{
|
||||
if (mpi::rank == 0) {
|
||||
if (is_beta_effective_or_both()) {
|
||||
if (simulation::ifp_delayed_on) {
|
||||
if (mpi::rank == 0)
|
||||
n_generation = static_cast<int>(delayed_groups[0].size());
|
||||
} else {
|
||||
MPI_Bcast(&n_generation, 1, MPI_INT, 0, mpi::intracomm);
|
||||
} else if (simulation::ifp_lifetime_on) {
|
||||
if (mpi::rank == 0)
|
||||
n_generation = static_cast<int>(lifetimes[0].size());
|
||||
}
|
||||
MPI_Bcast(&n_generation, 1, MPI_INT, 0, mpi::intracomm);
|
||||
}
|
||||
MPI_Bcast(&n_generation, 1, MPI_INT, 0, mpi::intracomm);
|
||||
}
|
||||
|
||||
void copy_partial_ifp_data_to_source_banks(int64_t idx, int n, int64_t i_bank,
|
||||
const vector<vector<int>>& delayed_groups,
|
||||
const vector<vector<double>>& lifetimes)
|
||||
{
|
||||
if (is_beta_effective_or_both()) {
|
||||
if (simulation::ifp_delayed_on)
|
||||
std::copy(&delayed_groups[idx], &delayed_groups[idx + n],
|
||||
&simulation::ifp_source_delayed_group_bank[i_bank]);
|
||||
}
|
||||
if (is_generation_time_or_both()) {
|
||||
if (simulation::ifp_lifetime_on)
|
||||
std::copy(&lifetimes[idx], &lifetimes[idx + n],
|
||||
&simulation::ifp_source_lifetime_bank[i_bank]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -96,40 +78,36 @@ void copy_complete_ifp_data_to_source_banks(
|
|||
const vector<vector<int>>& delayed_groups,
|
||||
const vector<vector<double>>& lifetimes)
|
||||
{
|
||||
if (is_beta_effective_or_both()) {
|
||||
if (simulation::ifp_delayed_on)
|
||||
std::copy(delayed_groups.data(),
|
||||
delayed_groups.data() + settings::n_particles,
|
||||
simulation::ifp_source_delayed_group_bank.begin());
|
||||
}
|
||||
if (is_generation_time_or_both()) {
|
||||
if (simulation::ifp_lifetime_on)
|
||||
std::copy(lifetimes.data(), lifetimes.data() + settings::n_particles,
|
||||
simulation::ifp_source_lifetime_bank.begin());
|
||||
}
|
||||
}
|
||||
|
||||
void allocate_temporary_vector_ifp(
|
||||
vector<vector<int>>& delayed_groups, vector<vector<double>>& lifetimes)
|
||||
{
|
||||
if (is_beta_effective_or_both()) {
|
||||
if (simulation::ifp_delayed_on)
|
||||
delayed_groups.resize(simulation::fission_bank.size());
|
||||
}
|
||||
if (is_generation_time_or_both()) {
|
||||
|
||||
if (simulation::ifp_lifetime_on)
|
||||
lifetimes.resize(simulation::fission_bank.size());
|
||||
}
|
||||
}
|
||||
|
||||
void copy_ifp_data_to_fission_banks(const vector<int>* const delayed_groups_ptr,
|
||||
const vector<double>* lifetimes_ptr)
|
||||
{
|
||||
if (is_beta_effective_or_both()) {
|
||||
if (simulation::ifp_delayed_on)
|
||||
std::copy(delayed_groups_ptr,
|
||||
delayed_groups_ptr + simulation::fission_bank.size(),
|
||||
simulation::ifp_fission_delayed_group_bank.data());
|
||||
}
|
||||
if (is_generation_time_or_both()) {
|
||||
|
||||
if (simulation::ifp_lifetime_on)
|
||||
std::copy(lifetimes_ptr, lifetimes_ptr + simulation::fission_bank.size(),
|
||||
simulation::ifp_fission_lifetime_bank.data());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
|
|
|
|||
|
|
@ -250,9 +250,7 @@ void create_fission_sites(Particle& p, int i_nuclide, const Reaction& rx)
|
|||
break;
|
||||
}
|
||||
// Iterated Fission Probability (IFP) method
|
||||
if (settings::ifp_on) {
|
||||
ifp(p, idx);
|
||||
}
|
||||
ifp(p, idx);
|
||||
} else {
|
||||
site.wgt_born = p.wgt_born();
|
||||
site.wgt_ww_born = p.wgt_ww_born();
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ bool create_fission_neutrons {true};
|
|||
bool delayed_photon_scaling {true};
|
||||
bool entropy_on {false};
|
||||
bool event_based {false};
|
||||
bool ifp_on {false};
|
||||
bool legendre_to_tabular {true};
|
||||
bool material_cell_offsets {true};
|
||||
bool output_summary {true};
|
||||
|
|
@ -114,7 +113,6 @@ ElectronTreatment electron_treatment {ElectronTreatment::TTB};
|
|||
array<double, 4> energy_cutoff {0.0, 1000.0, 0.0, 0.0};
|
||||
array<double, 4> time_cutoff {INFTY, INFTY, INFTY, INFTY};
|
||||
int ifp_n_generation {-1};
|
||||
IFPParameter ifp_parameter {IFPParameter::None};
|
||||
int legendre_to_tabular_points {C_NONE};
|
||||
int max_order {0};
|
||||
int n_log_bins {8000};
|
||||
|
|
@ -567,14 +565,8 @@ void read_settings_xml(pugi::xml_node root)
|
|||
// Probability (IFP) method
|
||||
if (check_for_node(root, "ifp_n_generation")) {
|
||||
ifp_n_generation = std::stoi(get_node_value(root, "ifp_n_generation"));
|
||||
if (ifp_n_generation <= 0) {
|
||||
if (ifp_n_generation <= 0)
|
||||
fatal_error("'ifp_n_generation' must be greater than 0.");
|
||||
}
|
||||
// Avoid tallying 0 if IFP logs are not complete when active cycles start
|
||||
if (ifp_n_generation > n_inactive) {
|
||||
fatal_error("'ifp_n_generation' must be lower than or equal to the "
|
||||
"number of inactive cycles.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -330,6 +330,8 @@ namespace simulation {
|
|||
int ct_current_file;
|
||||
int current_batch;
|
||||
int current_gen;
|
||||
bool ifp_delayed_on {false};
|
||||
bool ifp_lifetime_on {false};
|
||||
bool initialized {false};
|
||||
double keff {1.0};
|
||||
double keff_std;
|
||||
|
|
@ -459,9 +461,7 @@ void allocate_banks()
|
|||
init_fission_bank(3 * simulation::work_per_rank);
|
||||
|
||||
// Allocate IFP bank
|
||||
if (settings::ifp_on) {
|
||||
resize_simulation_ifp_banks();
|
||||
}
|
||||
resize_simulation_ifp_banks();
|
||||
}
|
||||
|
||||
if (settings::surf_source_write) {
|
||||
|
|
@ -510,7 +510,21 @@ void initialize_batch()
|
|||
simulation::time_inactive.stop();
|
||||
simulation::time_active.start();
|
||||
for (auto& t : model::tallies) {
|
||||
t->active_ = true;
|
||||
if (t->offset_ == 0)
|
||||
t->active_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Activate tallies which have activation offset.
|
||||
for (auto& t : model::tallies) {
|
||||
if (t->offset_ > 0) {
|
||||
if (!settings::restart_run) {
|
||||
if (simulation::current_batch == settings::n_inactive + 1 + t->offset_)
|
||||
t->active_ = true;
|
||||
} else if (simulation::current_batch == simulation::restart_batch + 1) {
|
||||
if (simulation::restart_batch >= settings::n_inactive + t->offset_)
|
||||
t->active_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -193,64 +193,6 @@ Tally::Tally(pugi::xml_node node)
|
|||
fatal_error(fmt::format("No scores specified on tally {}.", id_));
|
||||
}
|
||||
|
||||
// Set IFP if needed
|
||||
if (!settings::ifp_on) {
|
||||
// Determine if this tally has an IFP score
|
||||
bool has_ifp_score = false;
|
||||
for (int score : scores_) {
|
||||
if (score == SCORE_IFP_TIME_NUM || score == SCORE_IFP_BETA_NUM ||
|
||||
score == SCORE_IFP_DENOM) {
|
||||
has_ifp_score = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for errors
|
||||
if (has_ifp_score) {
|
||||
if (settings::run_mode == RunMode::EIGENVALUE) {
|
||||
if (settings::ifp_n_generation < 0) {
|
||||
settings::ifp_n_generation = DEFAULT_IFP_N_GENERATION;
|
||||
warning(fmt::format(
|
||||
"{} generations will be used for IFP (default value). It can be "
|
||||
"changed using the 'ifp_n_generation' settings.",
|
||||
settings::ifp_n_generation));
|
||||
}
|
||||
if (settings::ifp_n_generation > settings::n_inactive) {
|
||||
fatal_error("'ifp_n_generation' must be lower than or equal to the "
|
||||
"number of inactive cycles.");
|
||||
}
|
||||
settings::ifp_on = true;
|
||||
} else if (settings::run_mode == RunMode::FIXED_SOURCE) {
|
||||
fatal_error(
|
||||
"Iterated Fission Probability can only be used in an eigenvalue "
|
||||
"calculation.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set IFP parameters if needed
|
||||
if (settings::ifp_on) {
|
||||
for (int score : scores_) {
|
||||
switch (score) {
|
||||
case SCORE_IFP_TIME_NUM:
|
||||
if (settings::ifp_parameter == IFPParameter::None) {
|
||||
settings::ifp_parameter = IFPParameter::GenerationTime;
|
||||
} else if (settings::ifp_parameter == IFPParameter::BetaEffective) {
|
||||
settings::ifp_parameter = IFPParameter::Both;
|
||||
}
|
||||
break;
|
||||
case SCORE_IFP_BETA_NUM:
|
||||
case SCORE_IFP_DENOM:
|
||||
if (settings::ifp_parameter == IFPParameter::None) {
|
||||
settings::ifp_parameter = IFPParameter::BetaEffective;
|
||||
} else if (settings::ifp_parameter == IFPParameter::GenerationTime) {
|
||||
settings::ifp_parameter = IFPParameter::Both;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if tally is compatible with particle type
|
||||
if (!settings::photon_transport) {
|
||||
for (int score : scores_) {
|
||||
|
|
@ -686,7 +628,23 @@ void Tally::set_scores(const vector<std::string>& scores)
|
|||
case SCORE_IFP_TIME_NUM:
|
||||
case SCORE_IFP_BETA_NUM:
|
||||
case SCORE_IFP_DENOM:
|
||||
if (score == SCORE_IFP_TIME_NUM)
|
||||
simulation::ifp_lifetime_on = true;
|
||||
if (score == SCORE_IFP_BETA_NUM)
|
||||
simulation::ifp_delayed_on = true;
|
||||
if (settings::run_mode == RunMode::FIXED_SOURCE)
|
||||
fatal_error(
|
||||
"Iterated Fission Probability can only be used in an eigenvalue "
|
||||
"calculation.");
|
||||
if (settings::ifp_n_generation < 0) {
|
||||
settings::ifp_n_generation = DEFAULT_IFP_N_GENERATION;
|
||||
warning(fmt::format(
|
||||
"{} generations will be used for IFP (default value). It can be "
|
||||
"changed using the 'ifp_n_generation' settings.",
|
||||
settings::ifp_n_generation));
|
||||
}
|
||||
estimator_ = TallyEstimator::COLLISION;
|
||||
offset_ = settings::ifp_n_generation;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -941,61 +941,34 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index,
|
|||
break;
|
||||
|
||||
case SCORE_IFP_TIME_NUM:
|
||||
if (settings::ifp_on) {
|
||||
if (p.type().is_neutron() && p.fission()) {
|
||||
if (is_generation_time_or_both()) {
|
||||
const auto& lifetimes =
|
||||
simulation::ifp_source_lifetime_bank[p.current_work()];
|
||||
if (lifetimes.size() == settings::ifp_n_generation) {
|
||||
score = lifetimes[0] * p.wgt_last();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p.type().is_neutron() && p.fission()) {
|
||||
const auto& lifetime =
|
||||
simulation::ifp_source_lifetime_bank[p.current_work()][0];
|
||||
score = lifetime * p.wgt_last();
|
||||
}
|
||||
break;
|
||||
|
||||
case SCORE_IFP_BETA_NUM:
|
||||
if (settings::ifp_on) {
|
||||
if (p.type().is_neutron() && p.fission()) {
|
||||
if (is_beta_effective_or_both()) {
|
||||
const auto& delayed_groups =
|
||||
simulation::ifp_source_delayed_group_bank[p.current_work()];
|
||||
if (delayed_groups.size() == settings::ifp_n_generation) {
|
||||
if (delayed_groups[0] > 0) {
|
||||
score = p.wgt_last();
|
||||
if (tally.delayedgroup_filter_ != C_NONE) {
|
||||
auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_];
|
||||
const DelayedGroupFilter& filt {
|
||||
*dynamic_cast<DelayedGroupFilter*>(
|
||||
model::tally_filters[i_dg_filt].get())};
|
||||
score_fission_delayed_dg(i_tally, delayed_groups[0] - 1,
|
||||
score, score_index, p.filter_matches());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p.type().is_neutron() && p.fission()) {
|
||||
const auto& delayed_group =
|
||||
simulation::ifp_source_delayed_group_bank[p.current_work()][0];
|
||||
if (delayed_group > 0) {
|
||||
score = p.wgt_last();
|
||||
if (tally.delayedgroup_filter_ != C_NONE) {
|
||||
auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_];
|
||||
const DelayedGroupFilter& filt {*dynamic_cast<DelayedGroupFilter*>(
|
||||
model::tally_filters[i_dg_filt].get())};
|
||||
score_fission_delayed_dg(i_tally, delayed_group - 1, score,
|
||||
score_index, p.filter_matches());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SCORE_IFP_DENOM:
|
||||
if (settings::ifp_on) {
|
||||
if (p.type().is_neutron() && p.fission()) {
|
||||
int ifp_data_size;
|
||||
if (is_beta_effective_or_both()) {
|
||||
ifp_data_size = static_cast<int>(
|
||||
simulation::ifp_source_delayed_group_bank[p.current_work()]
|
||||
.size());
|
||||
} else {
|
||||
ifp_data_size = static_cast<int>(
|
||||
simulation::ifp_source_lifetime_bank[p.current_work()].size());
|
||||
}
|
||||
if (ifp_data_size == settings::ifp_n_generation) {
|
||||
score = p.wgt_last();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p.type().is_neutron() && p.fission())
|
||||
score = p.wgt_last();
|
||||
break;
|
||||
|
||||
case N_2N:
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
</geometry>
|
||||
<settings>
|
||||
<run_mode>eigenvalue</run_mode>
|
||||
<particles>1000</particles>
|
||||
<particles>10000</particles>
|
||||
<batches>20</batches>
|
||||
<inactive>5</inactive>
|
||||
<source type="independent" strength="1.0" particle="neutron">
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
k-combined:
|
||||
1.006559E+00 5.389391E-03
|
||||
1.011403E+00 2.852123E-03
|
||||
tally 1:
|
||||
9.109384E-08
|
||||
5.667165E-16
|
||||
6.322790E-08
|
||||
4.014613E-16
|
||||
tally 2:
|
||||
3.000000E-03
|
||||
9.000000E-06
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
2.100000E-02
|
||||
1.370000E-04
|
||||
2.800000E-02
|
||||
2.220000E-04
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
0.000000E+00
|
||||
1.700000E-03
|
||||
1.490000E-06
|
||||
9.100000E-03
|
||||
1.351000E-05
|
||||
1.630000E-02
|
||||
5.251000E-05
|
||||
2.090000E-02
|
||||
5.605000E-05
|
||||
1.060000E-02
|
||||
2.056000E-05
|
||||
9.000000E-04
|
||||
2.300000E-07
|
||||
tally 3:
|
||||
1.489000E+01
|
||||
1.480036E+01
|
||||
9.945300E+00
|
||||
9.892586E+00
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ def ifp_model():
|
|||
|
||||
# Settings
|
||||
settings = openmc.Settings()
|
||||
settings.particles = 1000
|
||||
settings.particles = 10000
|
||||
settings.batches = 20
|
||||
settings.inactive = 5
|
||||
settings.ifp_n_generation = 5
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
k-combined:
|
||||
1.006559E+00 5.389391E-03
|
||||
tally 1:
|
||||
9.109384E-08
|
||||
5.667165E-16
|
||||
5.200000E-02
|
||||
5.420000E-04
|
||||
1.489000E+01
|
||||
1.480036E+01
|
||||
6.064971E-08
|
||||
3.807785E-16
|
||||
3.300000E-02
|
||||
3.610000E-04
|
||||
9.876000E+00
|
||||
9.761494E+00
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ def geometry():
|
|||
({"ifp_n_generation": 0}, ValueError),
|
||||
({"ifp_n_generation": -1}, ValueError),
|
||||
({"run_mode": "fixed source"}, RuntimeError),
|
||||
({"inactive": 5, "ifp_n_generation": 6}, RuntimeError),
|
||||
({"inactive": 9}, RuntimeError)
|
||||
],
|
||||
)
|
||||
def test_exceptions(options, error, run_in_tmpdir, geometry):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue