https://mooseframework.inl.gov
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  params.addClassDescription(
29  "A base class for automatic computation of view factors between sidesets.");
30  return params;
31 }
32 
34  : SideUserObject(parameters),
35  _n_sides(boundaryIDs().size()),
36  _areas(_n_sides),
37  _view_factor_tol(getParam<Real>("view_factor_tol")),
38  _normalize_view_factor(getParam<bool>("normalize_view_factor")),
39  _print_view_factor_info(getParam<bool>("print_view_factor_info"))
40 {
41  // sizing the view factor array
42  _view_factors.resize(_n_sides);
43  for (auto & v : _view_factors)
44  v.resize(_n_sides);
45 
46  // set up the map from the side id to the local index & side name to local index
47  std::vector<BoundaryName> boundary_names = getParam<std::vector<BoundaryName>>("boundary");
48  for (unsigned int j = 0; j < boundary_names.size(); ++j)
49  _side_name_index[boundary_names[j]] = j;
50 }
51 
52 unsigned int
54 {
55  auto it = _side_name_index.find(name);
56  if (it == _side_name_index.end())
57  mooseError("Boundary ", name, " does not exist.");
58  return it->second;
59 }
60 
61 Real
63 {
64  auto from_name = _mesh.getBoundaryName(from_id);
65  auto to_name = _mesh.getBoundaryName(to_id);
66 
67  return getViewFactor(from_name, to_name);
68 }
69 
70 Real
71 ViewFactorBase::getViewFactor(BoundaryName from_name, BoundaryName to_name) const
72 {
73  auto from = _side_name_index.find(from_name);
74  auto to = _side_name_index.find(to_name);
75  if (from == _side_name_index.end())
76  mooseError("Boundary id ",
77  _mesh.getBoundaryID(from_name),
78  " with name ",
79  from_name,
80  " not listed in boundary parameter.");
81 
82  if (to == _side_name_index.end())
83  mooseError("Boundary id ",
84  _mesh.getBoundaryID(to_name),
85  " with name ",
86  to_name,
87  " not listed in boundary parameter.");
88 
89  return _view_factors[from->second][to->second];
90 }
91 
92 void
94 {
95  // do some communication before finalizing view_factors
96  for (unsigned int i = 0; i < _n_sides; ++i)
98 
101 }
102 
103 void
105 {
106  const auto & pps = static_cast<const ViewFactorBase &>(y);
107  for (unsigned int i = 0; i < _n_sides; ++i)
108  {
109  for (unsigned int j = 0; j < _n_sides; ++j)
110  _view_factors[i][j] += pps._view_factors[i][j];
111  }
113 }
114 
115 Real
116 ViewFactorBase::devReciprocity(unsigned int i, unsigned int j) const
117 {
118  return _view_factors[i][j] - _areas[j] / _areas[i] * _view_factors[j][i];
119 }
120 
121 Real
123 {
124  Real v = 0;
125  for (unsigned int i = 0; i < _n_sides; ++i)
126  for (unsigned int j = i + 1; j < _n_sides; ++j)
127  {
128  Real s = std::abs(devReciprocity(i, j));
129  if (s > v)
130  v = s;
131  }
132  return v;
133 }
134 
135 Real
136 ViewFactorBase::viewFactorRowSum(unsigned int i) const
137 {
138  Real s = 0;
139  for (unsigned int to = 0; to < _n_sides; ++to)
140  s += _view_factors[i][to];
141  return s;
142 }
143 
144 Real
146 {
147  Real v = 0;
148  for (unsigned int i = 0; i < _n_sides; ++i)
149  {
150  Real s = std::abs(1 - viewFactorRowSum(i));
151  if (s > v)
152  v = s;
153  }
154  return v;
155 }
156 
157 void
159 {
160  // collect statistics
161  Real max_sum_deviation = maxDevRowSum();
162  Real max_reciprocity_deviation = maxDevReciprocity();
163  Real max_correction = std::numeric_limits<Real>::lowest();
164  Real min_correction = std::numeric_limits<Real>::max();
165 
167  _console << "\nSum of all view factors from side i to all other faces before normalization.\n"
168  << std::endl;
169 
170  // check view factors
172  for (unsigned int from = 0; from < _n_sides; ++from)
173  _console << "View factors from sideset " << boundaryNames()[from] << " sum to "
174  << viewFactorRowSum(from) << std::endl;
175 
176  if (max_sum_deviation > _view_factor_tol)
177  mooseError("Maximum deviation of view factor row sum is ",
178  max_sum_deviation,
179  " exceeding the set tolerance of ",
181 
182  // normalize view factors
184  {
186  _console << "\nNormalizing view factors.\n" << std::endl;
187 
188  // allocate space
189  DenseVector<Real> rhs(_n_sides);
190  DenseVector<Real> lmults(_n_sides);
192 
193  // equations for the Lagrange multiplier
194  for (unsigned int i = 0; i < _n_sides; ++i)
195  {
196  // set the right hand side
197  rhs(i) = 1 - viewFactorRowSum(i);
198 
199  // contribution from the delta_ii element
200  matrix(i, i) = -0.5;
201 
202  // contributions from the upper diagonal
203  for (unsigned int j = i + 1; j < _n_sides; ++j)
204  {
205  Real ar = _areas[i] / _areas[j];
206  Real f = 2 * (1 + ar * ar);
207  matrix(i, i) += -1 / f;
208  matrix(i, j) += -1 / f * ar;
209  rhs(i) += ar * ar / (1 + ar * ar) * devReciprocity(i, j);
210  }
211 
212  // contributions from the lower diagonal
213  for (unsigned int j = 0; j < i; ++j)
214  {
215  Real ar = _areas[j] / _areas[i];
216  Real f = 2 * (1 + ar * ar);
217  matrix(i, i) += -1 / f * ar * ar;
218  matrix(i, j) += -1 / f * ar;
219  rhs(i) -= ar * devReciprocity(j, i) * (1 - ar * ar / (1 + ar * ar));
220  }
221  }
222 
223  // solve the linear system
224  matrix.lu_solve(rhs, lmults);
225 
226  // perform corrections but store view factors to temporary array
227  // because we cannot modify _view_factors as it's used in this calc
228  std::vector<std::vector<Real>> vf_temp = _view_factors;
229  for (unsigned int i = 0; i < _n_sides; ++i)
230  for (unsigned int j = 0; j < _n_sides; ++j)
231  {
232  Real correction;
233  if (i == j)
234  correction = -0.5 * lmults(i);
235  else
236  {
237  Real ar = _areas[i] / _areas[j];
238  Real f = 2 * (1 + ar * ar);
239  correction = -(lmults(i) + lmults(j) * ar + 2 * ar * ar * devReciprocity(i, j)) / f;
240  }
241 
242  // update the temporary view factor
243  vf_temp[i][j] += correction;
244 
245  if (correction < min_correction)
246  min_correction = correction;
247  if (correction > max_correction)
248  max_correction = correction;
249  }
250  _view_factors = vf_temp;
251  }
252 
254  {
255  _console << "\nFinal view factors.\n" << std::endl;
256  for (unsigned int from = 0; from < _n_sides; ++from)
257  {
258  std::string from_name;
259  for (auto pair : _side_name_index)
260  if (pair.second == from)
261  from_name = pair.first;
262  auto from_id = _mesh.getBoundaryID(from_name);
263 
264  for (unsigned int to = 0; to < _n_sides; ++to)
265  {
266  std::string to_name;
267  for (auto pair : _side_name_index)
268  if (pair.second == to)
269  to_name = pair.first;
270  auto to_id = _mesh.getBoundaryID(to_name);
271  _console << from_name << " (" << from_id << ") -> " << to_name << " (" << to_id
272  << ") = " << _view_factors[from][to] << std::endl;
273  }
274  }
275  }
276 
277  // check sum of view factors and maximum deviation on reciprocity
278  Real max_sum_deviation_after_normalization = maxDevRowSum();
279  Real max_reciprocity_deviation_after_normalization = maxDevReciprocity();
280 
281  // print summary
282  _console << std::endl;
283  _console << COLOR_CYAN << "Summary of the view factor computation"
284  << "\n"
285  << COLOR_DEFAULT << std::endl;
287  _console << "Normalization is performed." << std::endl;
288  else
289  _console << "Normalization is skipped." << std::endl;
290  _console << std::setw(60) << std::left << "Number of patches: " << _n_sides << std::endl;
291  _console << std::setw(60) << std::left
292  << "Max deviation sum = 1 before normalization: " << max_sum_deviation << std::endl;
293  _console << std::setw(60) << std::left
294  << "Max deviation from reciprocity before normalization: " << max_reciprocity_deviation
295  << std::endl;
297  {
298  _console << std::setw(60) << std::left << "Maximum correction: " << max_correction << std::endl;
299  _console << std::setw(60) << std::left << "Minimum correction: " << min_correction << std::endl;
300  _console << std::setw(60) << "Max deviation sum = 1 after normalization: "
301  << max_sum_deviation_after_normalization << std::endl;
302  _console << std::setw(60) << std::left << "Max deviation from reciprocity after normalization: "
303  << max_reciprocity_deviation_after_normalization << std::endl;
304  _console << std::endl;
305  }
306 }
307 
308 unsigned int
309 ViewFactorBase::indexHelper(unsigned int i, unsigned int j) const
310 {
311  mooseAssert(i <= j, "indexHelper requires i <= j");
312  if (i == j)
313  return _n_sides + i;
314  unsigned int pos = 2 * _n_sides;
315  for (unsigned int l = 0; l < _n_sides; ++l)
316  for (unsigned int m = l + 1; m < _n_sides; ++m)
317  {
318  if (l == i && m == j)
319  return pos;
320  else
321  ++pos;
322  }
323  mooseError("Should never get here");
324  return 0;
325 }
virtual void finalizeViewFactor()=0
a purely virtural function called in finalize, must be overriden by derived class ...
static InputParameters validParams()
unsigned int indexHelper(unsigned int i, unsigned int j) const
helper for finding index of correction for i,j-th entry
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
std::vector< Real > _areas
area of the sides i
virtual void finalize() override final
std::unordered_map< std::string, unsigned int > _side_name_index
boundary name to index map
const Real _view_factor_tol
view factor tolerance
ViewFactorBase(const InputParameters &parameters)
unsigned int _n_sides
number of boundaries of this side uo
const std::string & getBoundaryName(BoundaryID boundary_id)
const bool _print_view_factor_info
const std::vector< double > y
const bool _normalize_view_factor
whether to normalize view factors so vf[from][:] sums to one
Real devReciprocity(unsigned int i, unsigned int j) const
this function computes the deviation from reciprocity defined as Fij - Aj/Ai * Fji ...
Real getViewFactor(BoundaryID from_id, BoundaryID to_id) const
public interface for obtaining view factors
virtual const std::string & name() const
A base class for automatic computation of view factors between sidesets.
Real maxDevRowSum() const
maximum deviation of any view factor row sum from 1
void gatherSum(T &value)
std::vector< std::vector< Real > > _view_factors
the view factor from side i to side j
Real f(Real x)
Test function for Brents method.
boundary_id_type BoundaryID
const std::string name
Definition: Setup.h:20
unsigned int getSideNameIndex(std::string name) const
helper function to get the index from the boundary name
Real viewFactorRowSum(unsigned int i) const
sum of a row in the view factor matrix
virtual void threadJoinViewFactor(const UserObject &y)=0
a purely virtual function called in finalize, must be overriden by derived class
static InputParameters validParams()
void checkAndNormalizeViewFactor()
this function checks & normalizes view factors to sum to one, this is not always
void lu_solve(const DenseVector< Real > &b, DenseVector< Real > &x)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string v
Definition: NS.h:84
MooseMesh & _mesh
virtual void threadJoin(const UserObject &y) override final
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
const ConsoleStream _console
const std::vector< BoundaryName > & boundaryNames() const
Real maxDevReciprocity() const
this function computes the maximum absolute value of the deviation from reciprocity ...
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const