Line data Source code
1 : /********************************************************************/ 2 : /* SOFTWARE COPYRIGHT NOTIFICATION */ 3 : /* Cardinal */ 4 : /* */ 5 : /* (c) 2021 UChicago Argonne, LLC */ 6 : /* ALL RIGHTS RESERVED */ 7 : /* */ 8 : /* Prepared by UChicago Argonne, LLC */ 9 : /* Under Contract No. DE-AC02-06CH11357 */ 10 : /* With the U. S. Department of Energy */ 11 : /* */ 12 : /* Prepared by Battelle Energy Alliance, LLC */ 13 : /* Under Contract No. DE-AC07-05ID14517 */ 14 : /* With the U. S. Department of Energy */ 15 : /* */ 16 : /* See LICENSE for full restrictions */ 17 : /********************************************************************/ 18 : 19 : #pragma once 20 : 21 : #include "MooseObject.h" 22 : #include "CardinalEnums.h" 23 : 24 : #include "openmc/tallies/tally.h" 25 : #include "openmc/tensor.h" 26 : 27 : /// Forward declarations. 28 : class OpenMCCellAverageProblem; 29 : class MooseMesh; 30 : class AuxiliarySystem; 31 : class FilterBase; 32 : 33 : typedef openmc::tensor::Tensor<double> OMCTensor; 34 : 35 : class TallyBase : public MooseObject 36 : { 37 : public: 38 : static InputParameters validParams(); 39 : 40 : TallyBase(const InputParameters & parameters); 41 : 42 : /** 43 : * A function which the derivied tally must override to create the OpenMC spatial filter 44 : * the object maps to. 45 : * @return a pair where the first entry is the filter index in the global filter array and the 46 : * second entry is the OpenMC filter 47 : */ 48 : virtual std::pair<unsigned int, openmc::Filter *> spatialFilter() = 0; 49 : 50 : /** 51 : * A function to initialize the tally object. Override with care. 52 : */ 53 : virtual void initializeTally(); 54 : 55 : /** 56 : * A function to reset the tally object. Override with care. 57 : */ 58 : virtual void resetTally(); 59 : 60 : /** 61 : * A function which stores the results of this tally into the created 62 : * auxvariables. This calls storeResultsInner. 63 : * @param[in] var_numbers variables which the tally will store results in 64 : * @param[in] local_score index into the tally's local array of scores which represents the 65 : * current score being stored 66 : * @param[in] output_type the output type 67 : * @return the sum of the tally over all bins. Only applicable for 'output_type = relaxed' 68 : */ 69 : Real storeResults(const std::vector<unsigned int> & var_numbers, 70 : unsigned int local_score, 71 : const std::string & output_type); 72 : 73 : /** 74 : * Add a score to this tally. 75 : * @param[in] score score to add 76 : */ 77 : void addScore(const std::string & score); 78 : 79 : /** 80 : * A function which sets the relaxation type and factor for a tally. 81 : * @param[in] relaxation_type the type of relaxation to use 82 : * @param[in] factor the relaxation factor to use (for constant relxation or no relaxation) 83 : */ 84 : virtual void setRelaxation(relaxation::RelaxationEnum relaxation_type, 85 : const Real & relaxation_factor); 86 : 87 : /** 88 : * A function which computes and stores the sum and mean of the tally across all bins for a 89 : * particular score. 90 : */ 91 : void computeSumAndMean(); 92 : 93 : /** 94 : * A function which gathers the sums and means from all tallies linked to this tally. 95 : */ 96 : virtual void gatherLinkedSum(); 97 : 98 : /** 99 : * A function which renormalizes this tally based on the gathered sum from linked tallies. 100 : */ 101 : virtual void renormalizeLinkedTallies(); 102 : 103 : /** 104 : * Relax the tally and normalize it according to some normalization factor 'norm'. This tends to 105 : * either be the sum of the over all bins OR a global tally over the entire problem. 106 : * 107 : * NOTE: This function relaxes the tally _distribution_, and not the actual magnitude of the sum. 108 : * That is, we relax the shape distribution and then multiply it by the power 109 : * (for k-eigenvalue) or source strength (for fixed source) of the current step before 110 : * applying it to MOOSE. If the magnitude of the power or source strength is constant in time, 111 : * there is zero error in this. But if the magnitude of the tally varies in time, we are basically 112 : * relaxing the distribution of the tally, but then multiplying it by the _current_ mean tally 113 : * magnitude. 114 : * 115 : * There will be very small errors in these approximations unless the power/source strength 116 : * change dramatically with iteration. But because relaxation is itself a numerical approximation, 117 : * this is still inconsequential at the end of the day as long as your problem has converged 118 : * the relaxed tally to the raw (unrelaxed) tally. 119 : */ 120 : void relaxAndNormalizeTally(); 121 : 122 : /** 123 : * Add a linked tally for normalization. 124 : * @param[in] tally the other tally to link for normalization 125 : */ 126 : void addLinkedTally(const TallyBase * other); 127 : 128 : /** 129 : * Get the local OpenMC tally that this object wraps. 130 : * @return the OpenMC tally object 131 : */ 132 : const openmc::Tally * getWrappedTally() const; 133 : 134 : /** 135 : * Get the global OpenMC tally that this object wraps. 136 : * @return the OpenMC tally object 137 : */ 138 : const openmc::Tally * getWrappedGlobalTally() const; 139 : 140 : /** 141 : * Get the ID of the tally this object wraps. 142 : */ 143 : int32_t getTallyID() const; 144 : 145 : /** 146 : * Get the global ID of the tally this object wraps. 147 : */ 148 : int32_t getGlobalTallyID() const; 149 : 150 : /** 151 : * Get the list of scores this tally uses. 152 : * @return list of scores this tally uses 153 : */ 154 : const std::vector<std::string> & getScores() const { return _tally_score; } 155 : 156 : /** 157 : * Get the index corresponding to a specific score. 158 : * @param[in] score the score 159 : * @return the index of the score, -1 indicates the score does not exist 160 : */ 161 : int scoreIndex(const std::string & score) const; 162 : 163 : /** 164 : * Gets the auxvariable names for use in creating and storing tally results. 165 : * This allows for the splitting of tally results into energy bins, angular bins, etc. 166 : * 167 : * @return vector of variable names to be associated with this tally 168 : */ 169 : const std::vector<std::string> & getAuxVarNames() const { return _tally_name; } 170 : 171 : /** 172 : * Gets the output names to append to the end of the '_tally_name' when adding tally auxvariables 173 : * for additional outputs. 174 : * @return additional tally outputs 175 : */ 176 : const std::vector<std::string> & getOutputs() const { return _output_name; } 177 : 178 : /** 179 : * Get the estimator used in this tally. 180 : * @return the tally estimator 181 : */ 182 : openmc::TallyEstimator getTallyEstimator() const { return _estimator; } 183 : 184 : /** 185 : * Get the mean for a score summed over all bins. 186 : * @param[in] local_score the index representing a tally score 187 : * @return mean for a score summed over all bins. 188 : */ 189 178152 : const Real & getMean(unsigned int local_score) const { return _local_mean_tally[local_score]; } 190 : 191 : /** 192 : * Get the sum for a score summed over all bins. 193 : * @param[in] local_score the index representing a tally score 194 : * @return sum for a score summed over all bins. 195 : */ 196 : const Real & getSum(unsigned int local_score) const { return _local_sum_tally[local_score]; } 197 : 198 : /** 199 : * Get a vector of variable names corresponding to the provided score. 200 : * @param[in] score the score that the user wishes to fetch variable names from 201 : * @return a vector of variables corresponding to the score 202 : */ 203 : std::vector<std::string> getScoreVars(const std::string & score) const; 204 : 205 : /** 206 : * Check to see if the given external filter bin is skipped during normalization. 207 : * @param[in] ext_bin the external filter bin 208 : * @return whether the bin is skipped during normalization or not 209 : */ 210 : bool extBinSkipped(unsigned int ext_bin) const { return _ext_bins_to_skip[ext_bin]; } 211 : 212 : /** 213 : * Check to see if this tally uses a trigger or not. 214 : * @return whether this tally uses a trigger or not 215 : */ 216 2508 : bool hasTrigger() const { return _tally_trigger != nullptr; } 217 : 218 : /** 219 : * Check to see if this tally adds additional output variables or not. 220 : * @return whether this tally adds additional output variables or not 221 : */ 222 10744 : bool hasOutputs() const { return _has_outputs; } 223 : 224 : /** 225 : * Check to see if this tally contains a specific score. 226 : * @param[in] score the score to check 227 : * @return whether this tally has 228 : */ 229 3982 : bool hasScore(const std::string & score) const 230 : { 231 3982 : return std::find(_tally_score.begin(), _tally_score.end(), score) != _tally_score.end(); 232 : } 233 : 234 : /** 235 : * Check to see if the user has requested special names for the tallies. 236 : * @return whether this tally names stored values something other than '_tally_score' 237 : */ 238 18 : bool renamesTallyVars() const { return _renames_tally_vars; } 239 : 240 : /** 241 : * Get the total number of external filter bins applied to this tally. 242 : * @return the total number of external filter bins. 243 : */ 244 2524 : unsigned int numExtFilterBins() const { return _num_ext_filter_bins; } 245 : 246 : /** 247 : * A function to get the blocks associated with this CellTally. 248 : * @return a set of blocks associated with this tally. 249 : */ 250 : const std::set<SubdomainID> & getBlocks() const { return _tally_blocks; } 251 : 252 : /** 253 : * Whether this tally requires a global tally or not. 254 : * @return if the tally adds a global tally in addition to a mapped local tally 255 : */ 256 6902 : virtual bool addingGlobalTally() const { return _needs_global_tally; } 257 : 258 : /** 259 : * Get the vector of tallies linked to this tally object for normalization 260 : * @return the vector of linked tallies 261 : */ 262 : const std::vector<const TallyBase *> & linkedTallies() const { return _linked_tallies; } 263 : 264 : protected: 265 : /** 266 : * A function which stores the results of this tally into the created 267 : * auxvariables. This must be implemented by the derived class. 268 : * @param[in] var_numbers variables which the tally will store results in 269 : * @param[in] local_score index into the tally's local array of scores which represents the 270 : * current score being stored 271 : * @param[in] tally_vals the tally values to store 272 : * @param[in] norm_by_src_rate whether or not tally_vals should be normalized by the source rate 273 : * @return the sum of the tally over all bins. 274 : */ 275 : virtual Real storeResultsInner(const std::vector<unsigned int> & var_numbers, 276 : unsigned int local_score, 277 : const std::vector<OMCTensor> & tally_vals, 278 : bool norm_by_src_rate = true) = 0; 279 : 280 : /** 281 : * Set an auxiliary elemental variable to a specified value 282 : * @param[in] var_num variable number 283 : * @param[in] elem_ids element IDs to set 284 : * @param[in] value value to set 285 : */ 286 : void fillElementalAuxVariable(const unsigned int & var_num, 287 : const std::vector<unsigned int> & elem_ids, 288 : const Real & value); 289 : 290 : /** 291 : * Applies triggers to a tally. This is often the local tally wrapped by this object. 292 : * @param[in] tally the tally to apply triggers to 293 : */ 294 : void applyTriggersToLocalTally(openmc::Tally * tally); 295 : 296 : /** 297 : * Factor by which to normalize a tally 298 : * @param[in] score index for the tally score 299 : * @return value to divide tally sum by for normalization 300 : */ 301 : Real tallyNormalization(unsigned int score) const; 302 : 303 : /** 304 : * Check the sum of the tallies against the global tally 305 : * @param[in] score tally score 306 : */ 307 : void checkTallySum(const unsigned int & score) const; 308 : 309 : /** 310 : * Check that the tally normalization gives a total tally sum of 1.0 (when normalized 311 : * against the total tally value). 312 : * @param[in] sum sum of the tally 313 : * @param[in] score tally score 314 : */ 315 : void checkNormalization(const Real & sum, unsigned int score) const; 316 : 317 : /// The OpenMCCellAverageProblem using the tally system. 318 : OpenMCCellAverageProblem & _openmc_problem; 319 : 320 : /// The MooseMesh. 321 : MooseMesh & _mesh; 322 : 323 : /// The aux system. 324 : AuxiliarySystem & _aux; 325 : 326 : /// The external filters added in the [Problem/Filters] block. 327 : std::vector<std::shared_ptr<FilterBase>> _ext_filters; 328 : 329 : /// The OpenMC estimator to use with this tally. 330 : openmc::TallyEstimator _estimator; 331 : 332 : /// OpenMC tally score(s) to use with this tally. 333 : std::vector<std::string> _tally_score; 334 : 335 : /// Auxiliary variable name(s) for this tally. 336 : std::vector<std::string> _tally_name; 337 : 338 : /// The OpenMC tally object this class wraps. 339 : openmc::Tally * _local_tally = nullptr; 340 : 341 : /// The index of the OpenMC tally this object wraps. 342 : unsigned int _local_tally_index; 343 : 344 : /** 345 : * The global OpenMC tally object this class wraps. Used for global normalization 346 : * and error-checking of the sum of local tally results over all bins. 347 : */ 348 : openmc::Tally * _global_tally = nullptr; 349 : 350 : /// The index of the global OpenMC tally this object wraps. 351 : unsigned int _global_tally_index; 352 : 353 : /// The index of the first filter added by this tally. 354 : unsigned int _filter_index; 355 : 356 : /// The number of non-spatial bins in this tally. 357 : unsigned int _num_ext_filter_bins = 1; 358 : 359 : /// Sum value of this tally across all bins. Indexed by score. 360 : std::vector<Real> _local_sum_tally; 361 : 362 : /** 363 : * Sum value of the global tally associated with this tally object. Each entry in 364 : * _global_sum_tally corresponds to a score in _tally_score. As an example, 365 : * _global_sum_tally[0] corresponds to the score located at _tally_score[0]. 366 : */ 367 : std::vector<Real> _global_sum_tally; 368 : 369 : /** 370 : * Mean value of this tally across all bins; only used for fixed source mode. 371 : * Each entry in _local_mean_tally corresponds to a score in _tally_score. As 372 : * an example, _local_mean_tally[0] corresponds to the score located at 373 : * _tally_score[0]. 374 : */ 375 : std::vector<Real> _local_mean_tally; 376 : 377 : /// Linked sum value across all bins. Indexed by score. 378 : std::vector<Real> _linked_local_sum_tally; 379 : 380 : /** 381 : * Type of trigger to apply to OpenMC tallies to indicate when 382 : * the simulation is complete. These can be used to on-the-fly adjust the number 383 : * of active batches in order to reach some desired criteria (which is specified 384 : * by this parameter). 385 : */ 386 : const MultiMooseEnum * _tally_trigger; 387 : 388 : /** 389 : * Thresholds to use for accepting this tally when using triggers. Indexed by 390 : * score. 391 : */ 392 : std::vector<Real> _tally_trigger_threshold; 393 : 394 : /** 395 : * Whether tally bins for certain scores should ignore bins with zeros when computing 396 : * trigger metrics. Indexed by the tally score. 397 : */ 398 : std::vector<bool> _trigger_ignore_zeros; 399 : 400 : /** 401 : * Current fixed point iteration tally result; for instance, when using constant 402 : * relaxation, the tally is updated as: 403 : * q(n+1) = (1-a) * q(n) + a * PHI(q(n), s) 404 : * where q(n+1) is _current_tally, a is the relaxation factor, q(n) 405 : * is _previous_tally, and PHI is the most-recently-computed tally result 406 : * (the _current_raw_tally). 407 : */ 408 : std::vector<OMCTensor> _current_tally; 409 : 410 : /// Previous fixed point iteration tally result (after relaxation) 411 : std::vector<OMCTensor> _previous_tally; 412 : 413 : /// Current "raw" tally output from Monte Carlo solution 414 : std::vector<OMCTensor> _current_raw_tally; 415 : 416 : /// Current "raw" tally relative error. 417 : std::vector<OMCTensor> _current_raw_tally_rel_error; 418 : 419 : /// Current "raw" tally standard deviation 420 : std::vector<OMCTensor> _current_raw_tally_std_dev; 421 : 422 : /** 423 : * How to normalize the OpenMC tally into units of W/volume. If 'true', 424 : * normalization is performed by dividing each local tally against a problem-global 425 : * tally. The advantage of this approach is that some non-zero tally regions of the 426 : * OpenMC domain can be excluded from multiphysics feedback (without us having to guess 427 : * what the power of the *included* part of the domain is). This can let us do 428 : * "zooming" type calculations, where perhaps we only want to send T/H feedback to 429 : * one bundle in a full core. 430 : * 431 : * If 'false', normalization is performed by dividing each local tally by the sum 432 : * of the local tally itself. The advantage of this approach becomes evident when 433 : * using mesh tallies. If a mesh tally does not perfectly align with an OpenMC cell - 434 : * for instance, a first-order sphere mesh will not perfectly match the volume of a 435 : * TRISO pebble - then not all of the power actually produced in the pebble is 436 : * tallies on the mesh approximation to that pebble. Therefore, if you set a core 437 : * power of 1 MW and you normalized based on a global tally, you'd always 438 : * miss some of that power when sending to MOOSE. So, in this case, it is better to 439 : * normalize against the local tally itself so that the correct power is preserved. 440 : */ 441 : const bool _normalize_by_global; 442 : 443 : /** 444 : * Whether to check the tallies against the global tally; 445 : * if set to true, and the tallies added for the 'tally_blocks' do not 446 : * sum to the global tally, an error is thrown. If you are 447 : * only performing multiphysics feedback for, say, a single assembly in a 448 : * full-core OpenMC model, you must set this check to false, because there 449 : * are known fission sources outside the domain of interest. 450 : * 451 : * If not specified, then this is set to 'true' if normalizing by a global 452 : * tally, and to 'false' if normalizing by the local tally (because when we choose 453 : * to normalize by the local tally, we're probably using mesh tallies). But you can 454 : * of course still set a value for this parameter to override the default. 455 : */ 456 : const bool _check_tally_sum; 457 : 458 : /** 459 : * Whether a global tally is required for the sake of normalization and/or checking 460 : * the tally sum 461 : */ 462 : const bool _needs_global_tally; 463 : 464 : /// Whether this tally stores results in variables names something other than '_tally_score'. 465 : const bool _renames_tally_vars; 466 : 467 : /// Whether this tally has additional outputs or not. 468 : const bool _has_outputs; 469 : 470 : /// Suffixes to apply to 'tally_name' in order to name the fields in the 'output'. 471 : std::vector<std::string> _output_name; 472 : 473 : /// Whether the problem uses adaptive mesh refinement or not. 474 : const bool _is_adaptive; 475 : 476 : /// External filter bins to skip while computing the tally sum and mean for normalization. 477 : std::vector<bool> _ext_bins_to_skip; 478 : 479 : /// Blocks for which to add tallies. 480 : std::set<SubdomainID> _tally_blocks; 481 : 482 : /// Other tallies linked for normalization. 483 : std::vector<const TallyBase *> _linked_tallies; 484 : 485 : /// The type of relaxation this tally should employ. 486 : relaxation::RelaxationEnum _relaxation_type; 487 : 488 : /// The relaxation factor this tally should use (for constant relaxation). 489 : Real _relaxation_factor; 490 : 491 : /// Tolerance for setting zero tally 492 : static constexpr Real ZERO_TALLY_THRESHOLD = 1e-12; 493 : };