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()
const std::string & getBoundaryName(BoundaryID boundary_id) const
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 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
A base class for automatic computation of view factors between sidesets.
const std::string & name() const
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