Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #include "HistogramVectorPostprocessor.h" 11 : 12 : #include <algorithm> 13 : 14 : registerMooseObject("MooseApp", HistogramVectorPostprocessor); 15 : 16 : InputParameters 17 14297 : HistogramVectorPostprocessor::validParams() 18 : { 19 14297 : InputParameters params = GeneralVectorPostprocessor::validParams(); 20 14297 : params.addClassDescription("Compute a histogram for each column of a VectorPostprocessor"); 21 : 22 14297 : params.addRequiredParam<VectorPostprocessorName>( 23 : "vpp", "The VectorPostprocessor to compute histogram of"); 24 : 25 14297 : params.addRequiredParam<unsigned int>("num_bins", "The number of bins for the histograms"); 26 : 27 14297 : return params; 28 0 : } 29 : 30 16 : HistogramVectorPostprocessor::HistogramVectorPostprocessor(const InputParameters & parameters) 31 : : GeneralVectorPostprocessor(parameters), 32 16 : _vpp_name(getParam<VectorPostprocessorName>("vpp")), 33 32 : _num_bins(getParam<unsigned int>("num_bins")) 34 : { 35 16 : } 36 : 37 : void 38 16 : HistogramVectorPostprocessor::initialSetup() 39 : { 40 16 : const VectorPostprocessor & vpp = getUserObjectByName<VectorPostprocessor>(_vpp_name); 41 28 : for (const auto & vec_name : vpp.getVectorNames()) 42 24 : _histogram_data[vec_name] = {&declareVector(vec_name + "_lower"), 43 24 : &declareVector(vec_name + "_upper"), 44 12 : &declareVector(vec_name)}; 45 16 : if (_histogram_data.empty()) 46 4 : paramError("vpp", "The specified VectorPostprocessor does not have any declared vectors"); 47 12 : } 48 : 49 : void 50 11 : HistogramVectorPostprocessor::initialize() 51 : { 52 : // no need to reset, execute() writes in place 53 11 : } 54 : 55 : void 56 11 : HistogramVectorPostprocessor::execute() 57 : { 58 11 : if (processor_id() == 0) // Only compute on processor 0 59 : { 60 8 : const VectorPostprocessor & vpp = getUserObjectByName<VectorPostprocessor>(_vpp_name); 61 16 : for (const auto & vec_name : vpp.getVectorNames()) 62 : { 63 8 : const auto & values = _fe_problem.getVectorPostprocessorValueByName(_vpp_name, vec_name); 64 : 65 : mooseAssert(_histogram_data.count(vec_name), "Error retrieving VPP vector"); 66 8 : auto & histo_data = _histogram_data.at(vec_name); 67 8 : computeHistogram(values, histo_data); 68 : } 69 : } 70 11 : } 71 : 72 : void 73 11 : HistogramVectorPostprocessor::finalize() 74 : { 75 11 : } 76 : 77 : void 78 8 : HistogramVectorPostprocessor::computeHistogram(const std::vector<Real> & values, 79 : HistoData & histo_data) 80 : { 81 8 : if (values.empty()) 82 0 : mooseError("Cannot compute histogram without data!"); 83 : 84 : // Grab the vectors to fill 85 8 : auto & lower_vector = *histo_data._lower; 86 8 : auto & upper_vector = *histo_data._upper; 87 8 : auto & histogram = *histo_data._histogram; 88 : 89 : // Resize everything 90 : // Note: no need to zero anything out 91 : // that will automatically be done if the bin should be zero by the algorithm below 92 8 : lower_vector.resize(_num_bins); 93 8 : upper_vector.resize(_num_bins); 94 8 : histogram.resize(_num_bins); 95 : 96 : // Create a sorted copy of the values 97 8 : std::vector<Real> sorted_values(values.size()); 98 8 : std::partial_sort_copy(values.begin(), values.end(), sorted_values.begin(), sorted_values.end()); 99 : 100 : // Get the min and max values 101 8 : auto min = sorted_values.front(); 102 8 : auto max = sorted_values.back(); 103 : 104 : // The bin stride/length 105 8 : auto bin_stride = (max - min) / static_cast<Real>(_num_bins); 106 : 107 8 : auto current_value_iter = sorted_values.begin(); 108 8 : auto sorted_values_end = sorted_values.end(); 109 : 110 : // Fill the bins 111 40 : for (unsigned int bin = 0; bin < _num_bins; bin++) 112 : { 113 : // Compute bin edges 114 : // These are computed individually on purpose so that the exact same values will match the 115 : // previous and next bins 116 32 : auto lower = (bin * bin_stride) + min; 117 32 : auto upper = ((bin + 1) * bin_stride) + min; 118 : 119 32 : lower_vector[bin] = lower; 120 32 : upper_vector[bin] = upper; 121 : 122 : // Find the number of values that fall in this bin 123 32 : unsigned long int num_values = 0; 124 120 : while (current_value_iter != sorted_values_end && *current_value_iter <= upper) 125 : { 126 88 : num_values++; 127 88 : current_value_iter++; 128 : } 129 : 130 32 : histogram[bin] = static_cast<Real>(num_values); 131 : } 132 8 : }