https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ViewFactorBase.C
Go to the documentation of this file.
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 "ViewFactorBase.h"
11#include "libmesh/quadrature.h"
12
13#include <limits>
14
17{
19 params.addParam<Real>("view_factor_tol",
20 std::numeric_limits<Real>::max(),
21 "Tolerance for checking view factors. Default is to allow everything.");
22 params.addParam<bool>(
23 "print_view_factor_info", false, "Flag to print information about computed view factors.");
24 params.addParam<bool>("normalize_view_factor",
25 true,
26 "Determines if view factors are normalized to sum to one (consistent with "
27 "their definition).");
28
29 MooseEnum normalization_method("lagrange_multiplier inverse_row_sum", "lagrange_multiplier");
30 normalization_method.addDocumentation("lagrange_multiplier", "Uses Lagrange multiplier method");
31 normalization_method.addDocumentation("inverse_row_sum",
32 "Divides each view factor by its row sum");
33 params.addParam<MooseEnum>("normalization_method",
34 normalization_method,
35 "Normalization method to use if 'normalize_view_factor' is 'true'.");
36
38 "A base class for automatic computation of view factors between sidesets.");
39 return params;
40}
41
43 : SideUserObject(parameters),
44 _n_sides(boundaryIDs().size()),
45 _areas(_n_sides),
46 _view_factor_tol(getParam<Real>("view_factor_tol")),
47 _normalize_view_factor(getParam<bool>("normalize_view_factor")),
48 _normalization_method(
49 getParam<MooseEnum>("normalization_method").getEnum<NormalizationMethod>()),
50 _print_view_factor_info(getParam<bool>("print_view_factor_info"))
51{
52 // sizing the view factor array
53 _view_factors.resize(_n_sides);
54 for (auto & v : _view_factors)
55 v.resize(_n_sides);
56
57 // set up the map from the side id to the local index & side name to local index
58 std::vector<BoundaryName> boundary_names = getParam<std::vector<BoundaryName>>("boundary");
59 for (unsigned int j = 0; j < boundary_names.size(); ++j)
60 _side_name_index[boundary_names[j]] = j;
61}
62
63unsigned int
65{
66 auto it = _side_name_index.find(name);
67 if (it == _side_name_index.end())
68 mooseError("Boundary ", name, " does not exist.");
69 return it->second;
70}
71
72Real
74{
75 auto from_name = _mesh.getBoundaryName(from_id);
76 auto to_name = _mesh.getBoundaryName(to_id);
77
78 return getViewFactor(from_name, to_name);
79}
80
81Real
82ViewFactorBase::getViewFactor(BoundaryName from_name, BoundaryName to_name) const
83{
84 auto from = _side_name_index.find(from_name);
85 auto to = _side_name_index.find(to_name);
86 if (from == _side_name_index.end())
87 mooseError("Boundary id ",
88 _mesh.getBoundaryID(from_name),
89 " with name ",
90 from_name,
91 " not listed in boundary parameter.");
92
93 if (to == _side_name_index.end())
94 mooseError("Boundary id ",
95 _mesh.getBoundaryID(to_name),
96 " with name ",
97 to_name,
98 " not listed in boundary parameter.");
99
100 return _view_factors[from->second][to->second];
101}
102
103void
105{
106 std::fill(_areas.begin(), _areas.end(), 0);
107}
108
109void
111{
112 // compute areas
113 auto current_boundary_name = _mesh.getBoundaryName(_current_boundary_id);
114 auto it = _side_name_index.find(current_boundary_name);
115 if (it == _side_name_index.end())
116 mooseError("Current boundary name: ",
117 current_boundary_name,
118 " with id ",
120 " not in boundary parameter.");
121
122 _areas[it->second] += _current_side_volume;
123}
124
125void
133
134void
136{
137 const auto & pps = static_cast<const ViewFactorBase &>(y);
138 for (unsigned int i = 0; i < _n_sides; ++i)
139 _areas[i] += pps._areas[i];
140
142}
143
144Real
145ViewFactorBase::devReciprocity(unsigned int i, unsigned int j) const
146{
147 return _view_factors[i][j] - _areas[j] / _areas[i] * _view_factors[j][i];
148}
149
150Real
152{
153 Real v = 0;
154 for (unsigned int i = 0; i < _n_sides; ++i)
155 for (unsigned int j = i + 1; j < _n_sides; ++j)
156 {
157 Real s = std::abs(devReciprocity(i, j));
158 if (s > v)
159 v = s;
160 }
161 return v;
162}
163
164Real
166{
167 Real s = 0;
168 for (unsigned int to = 0; to < _n_sides; ++to)
169 s += _view_factors[i][to];
170 return s;
171}
172
173Real
175{
176 Real v = 0;
177 for (unsigned int i = 0; i < _n_sides; ++i)
178 {
179 Real s = std::abs(1 - viewFactorRowSum(i));
180 if (s > v)
181 v = s;
182 }
183 return v;
184}
185
186void
188{
189 // collect statistics
190 Real max_sum_deviation = maxDevRowSum();
191 Real max_reciprocity_deviation = maxDevReciprocity();
192 Real max_correction = std::numeric_limits<Real>::lowest();
193 Real min_correction = std::numeric_limits<Real>::max();
194
196 _console << "\nSum of all view factors from side i to all other faces before normalization.\n"
197 << std::endl;
198
199 // check view factors
201 for (unsigned int from = 0; from < _n_sides; ++from)
202 _console << "View factors from sideset " << boundaryNames()[from] << " sum to "
203 << viewFactorRowSum(from) << std::endl;
204
205 if (max_sum_deviation > _view_factor_tol)
206 mooseError("Maximum deviation of view factor row sum is ",
207 max_sum_deviation,
208 " exceeding the set tolerance of ",
210
211 // normalize view factors
213 {
215 _console << "\nNormalizing view factors.\n" << std::endl;
216
217 const auto view_factors_original = _view_factors;
218
219 switch (_normalization_method)
220 {
223 break;
226 break;
227 default:
228 mooseError("Invalid normalization method.");
229 }
230
231 // compute max and min correction for reporting
232 for (const auto i : make_range(_n_sides))
233 for (const auto j : make_range(_n_sides))
234 {
235 const Real correction = _view_factors[i][j] - view_factors_original[i][j];
236 min_correction = std::min(correction, min_correction);
237 max_correction = std::max(correction, max_correction);
238 }
239 }
240
242 {
243 _console << "\nFinal view factors.\n" << std::endl;
244 for (unsigned int from = 0; from < _n_sides; ++from)
245 {
246 std::string from_name;
247 for (auto pair : _side_name_index)
248 if (pair.second == from)
249 from_name = pair.first;
250 auto from_id = _mesh.getBoundaryID(from_name);
251
252 for (unsigned int to = 0; to < _n_sides; ++to)
253 {
254 std::string to_name;
255 for (auto pair : _side_name_index)
256 if (pair.second == to)
257 to_name = pair.first;
258 auto to_id = _mesh.getBoundaryID(to_name);
259 _console << from_name << " (" << from_id << ") -> " << to_name << " (" << to_id
260 << ") = " << _view_factors[from][to] << std::endl;
261 }
262 }
263 }
264
265 // check sum of view factors and maximum deviation on reciprocity
266 Real max_sum_deviation_after_normalization = maxDevRowSum();
267 Real max_reciprocity_deviation_after_normalization = maxDevReciprocity();
268
269 // print summary
270 _console << std::endl;
271 _console << COLOR_CYAN << "Summary of the view factor computation"
272 << "\n"
273 << COLOR_DEFAULT << std::endl;
275 _console << "Normalization is performed." << std::endl;
276 else
277 _console << "Normalization is skipped." << std::endl;
278 _console << std::setw(60) << std::left << "Number of patches: " << _n_sides << std::endl;
279 _console << std::setw(60) << std::left
280 << "Max deviation sum = 1 before normalization: " << max_sum_deviation << std::endl;
281 _console << std::setw(60) << std::left
282 << "Max deviation from reciprocity before normalization: " << max_reciprocity_deviation
283 << std::endl;
285 {
286 _console << std::setw(60) << std::left << "Maximum correction: " << max_correction << std::endl;
287 _console << std::setw(60) << std::left << "Minimum correction: " << min_correction << std::endl;
288 _console << std::setw(60) << "Max deviation sum = 1 after normalization: "
289 << max_sum_deviation_after_normalization << std::endl;
290 _console << std::setw(60) << std::left << "Max deviation from reciprocity after normalization: "
291 << max_reciprocity_deviation_after_normalization << std::endl;
292 _console << std::endl;
293 }
294}
295
296void
298{
299 // allocate space
300 DenseVector<Real> rhs(_n_sides);
301 DenseVector<Real> lmults(_n_sides);
302 DenseMatrix<Real> matrix(_n_sides, _n_sides);
303
304 // equations for the Lagrange multiplier
305 for (unsigned int i = 0; i < _n_sides; ++i)
306 {
307 // set the right hand side
308 rhs(i) = 1 - viewFactorRowSum(i);
309
310 // contribution from the delta_ii element
311 matrix(i, i) = -0.5;
312
313 // contributions from the upper diagonal
314 for (unsigned int j = i + 1; j < _n_sides; ++j)
315 {
316 Real ar = _areas[i] / _areas[j];
317 Real f = 2 * (1 + ar * ar);
318 matrix(i, i) += -1 / f;
319 matrix(i, j) += -1 / f * ar;
320 rhs(i) += ar * ar / (1 + ar * ar) * devReciprocity(i, j);
321 }
322
323 // contributions from the lower diagonal
324 for (unsigned int j = 0; j < i; ++j)
325 {
326 Real ar = _areas[j] / _areas[i];
327 Real f = 2 * (1 + ar * ar);
328 matrix(i, i) += -1 / f * ar * ar;
329 matrix(i, j) += -1 / f * ar;
330 rhs(i) -= ar * devReciprocity(j, i) * (1 - ar * ar / (1 + ar * ar));
331 }
332 }
333
334 // solve the linear system
335 matrix.lu_solve(rhs, lmults);
336
337 // perform corrections but store view factors to temporary array
338 // because we cannot modify _view_factors as it's used in this calc
339 std::vector<std::vector<Real>> vf_temp = _view_factors;
340 for (unsigned int i = 0; i < _n_sides; ++i)
341 for (unsigned int j = 0; j < _n_sides; ++j)
342 {
343 Real correction;
344 if (i == j)
345 correction = -0.5 * lmults(i);
346 else
347 {
348 Real ar = _areas[i] / _areas[j];
349 Real f = 2 * (1 + ar * ar);
350 correction = -(lmults(i) + lmults(j) * ar + 2 * ar * ar * devReciprocity(i, j)) / f;
351 }
352
353 // update the temporary view factor
354 vf_temp[i][j] += correction;
355 }
356 _view_factors = vf_temp;
357}
358
359void
361{
362 for (unsigned int i = 0; i < _n_sides; ++i)
363 {
364 const Real row_sum = viewFactorRowSum(i);
365 for (auto & v : _view_factors[i])
366 v /= row_sum;
367 }
368}
369
370unsigned int
371ViewFactorBase::indexHelper(unsigned int i, unsigned int j) const
372{
373 mooseAssert(i <= j, "indexHelper requires i <= j");
374 if (i == j)
375 return _n_sides + i;
376 unsigned int pos = 2 * _n_sides;
377 for (unsigned int l = 0; l < _n_sides; ++l)
378 for (unsigned int m = l + 1; m < _n_sides; ++m)
379 {
380 if (l == i && m == j)
381 return pos;
382 else
383 ++pos;
384 }
385 mooseError("Should never get here");
386 return 0;
387}
boundary_id_type BoundaryID
Real f(Real x)
Test function for Brents method.
const std::vector< double > y
const double v
const std::string name
Definition Setup.h:21
const std::vector< BoundaryName > & boundaryNames() const
const ConsoleStream _console
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
const std::string & name() const
void mooseError(Args &&... args) const
const std::string & getBoundaryName(const BoundaryID boundary_id) const
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
const Real & _current_side_volume
static InputParameters validParams()
MooseMesh & _mesh
const BoundaryID & _current_boundary_id
void gatherSum(T &value)
A base class for automatic computation of view factors between sidesets.
virtual void execute() override
const bool _normalize_view_factor
whether to normalize view factors so vf[from][:] sums to one
virtual void finalizeViewFactor()=0
a purely virtural function called in finalize, must be overriden by derived class
const Real _view_factor_tol
view factor tolerance
void normalizeUsingLagrangeMultiplier()
normalizes view factors by Lagrange multiplier method
void normalizeUsingInverseRowSum()
normalizes view factors by inverse row sum
unsigned int indexHelper(unsigned int i, unsigned int j) const
helper for finding index of correction for i,j-th entry
unsigned int getSideNameIndex(std::string name) const
helper function to get the index from the boundary name
virtual void threadJoin(const UserObject &y) override final
std::vector< std::vector< Real > > _view_factors
the view factor from side i to side j
std::unordered_map< std::string, unsigned int > _side_name_index
boundary name to index map
Real maxDevRowSum() const
maximum deviation of any view factor row sum from 1
virtual void initialize() override
virtual void threadJoinViewFactor(const UserObject &y)=0
a purely virtual function called in finalize, must be overriden by derived class
virtual void finalize() override final
unsigned int _n_sides
number of boundaries of this side uo
NormalizationMethod
How to normalize view factors.
Real devReciprocity(unsigned int i, unsigned int j) const
this function computes the deviation from reciprocity defined as Fij - Aj/Ai * Fji
const NormalizationMethod _normalization_method
How to normalize view factors.
std::vector< Real > _areas
area of the sides i
Real getViewFactor(BoundaryID from_id, BoundaryID to_id) const
public interface for obtaining view factors
Real maxDevReciprocity() const
this function computes the maximum absolute value of the deviation from reciprocity
const bool _print_view_factor_info
void checkAndNormalizeViewFactor()
this function checks & normalizes view factors to sum to one, this is not always
ViewFactorBase(const InputParameters &parameters)
static InputParameters validParams()
Real viewFactorRowSum(unsigned int i) const
sum of a row in the view factor matrix