https://mooseframework.inl.gov
PolygonalMeshGenerationUtils.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 
11 
12 Real
13 PolygonalMeshGenerationUtils::dummyTRI6VolCalculator(const std::pair<Real, Real> & azi_pair)
14 {
15  // The algorithm is copied from libMesh's face_tri6.C
16  // Original license is LGPL so it can be used here.
17  const Real & azi_1 = azi_pair.first;
18  const Real & azi_2 = azi_pair.second;
19 
20  Point x0 = Point(0.0, 0.0, 0.0), x1 = Point(1.0, 0.0, 0.0),
21  x2 = Point(std::cos(azi_1 + azi_2), std::sin(azi_1 + azi_2), 0.0),
22  x3 = Point(0.5, 0.0, 0.0), x4 = Point(std::cos(azi_1), std::sin(azi_1), 0.0),
23  x5 = Point(std::cos(azi_1 + azi_2) / 2.0, std::sin(azi_1 + azi_2) / 2.0, 0.0);
24 
25  // Construct constant data vectors.
26  // \vec{x}_{\xi} = \vec{a1}*xi + \vec{b1}*eta + \vec{c1}
27  // \vec{x}_{\eta} = \vec{a2}*xi + \vec{b2}*eta + \vec{c2}
28  Point a1 = 4 * x0 + 4 * x1 - 8 * x3, b1 = 4 * x0 - 4 * x3 + 4 * x4 - 4 * x5,
29  c1 = -3 * x0 - 1 * x1 + 4 * x3, b2 = 4 * x0 + 4 * x2 - 8 * x5,
30  c2 = -3 * x0 - 1 * x2 + 4 * x5;
31 
32  // 7-point rule, exact for quintics.
33  const unsigned int N = 7;
34 
35  // Parameters of the quadrature rule
36  const static Real w1 = Real(31) / 480 + Real(std::sqrt(15.0L) / 2400),
37  w2 = Real(31) / 480 - Real(std::sqrt(15.0L) / 2400),
38  q1 = Real(2) / 7 + Real(std::sqrt(15.0L) / 21),
39  q2 = Real(2) / 7 - Real(std::sqrt(15.0L) / 21);
40 
41  const static Real xi[N] = {Real(1) / 3, q1, q1, 1 - 2 * q1, q2, q2, 1 - 2 * q2};
42  const static Real eta[N] = {Real(1) / 3, q1, 1 - 2 * q1, q1, q2, 1 - 2 * q2, q2};
43  const static Real wts[N] = {Real(9) / 80, w1, w1, w1, w2, w2, w2};
44 
45  // Approximate the area with quadrature
46  Real vol = 0.;
47  for (unsigned int q = 0; q < N; ++q)
48  vol += wts[q] * cross_norm(xi[q] * a1 + eta[q] * b1 + c1, xi[q] * b1 + eta[q] * b2 + c2);
49 
50  return vol;
51 }
52 
53 Real
54 PolygonalMeshGenerationUtils::radiusCorrectionFactor(const std::vector<Real> & azimuthal_list,
55  const bool full_circle,
56  const unsigned int order,
57  const bool is_first_value_vertex)
58 {
59  Real tmp_acc = 0.0;
60  Real tmp_acc_azi = 0.0;
61  if (order == 1)
62  {
63  // A vector to collect the azimuthal intervals of all EDGE2 side elements
64  std::vector<Real> azi_interval_list;
65  for (unsigned int i = 1; i < azimuthal_list.size(); i++)
66  azi_interval_list.push_back((azimuthal_list[i] - azimuthal_list[i - 1]) / 180.0 * M_PI);
67  if (full_circle)
68  azi_interval_list.push_back((azimuthal_list.front() + 360.0 - azimuthal_list.back()) / 180.0 *
69  M_PI);
70  // summation of triangles S = 0.5 * r * r * Sigma_i [sin (azi_i)]
71  // Circle area S_c = pi * r_0 * r_0
72  // r = sqrt{2 * pi / Sigma_i [sin (azi_i)]} * r_0
73  for (const auto i : index_range(azi_interval_list))
74  {
75  tmp_acc += std::sin(azi_interval_list[i]);
76  tmp_acc_azi += azi_interval_list[i];
77  }
78  }
79  else // order == 2
80  {
81  // A vector to collect the pairs of azimuthal intervals of all EDGE3 side elements
82  // The midpoint divides the interval into two parts, which are stored as first and second of
83  // each pair; the sum of the two parts is the full interval of the EDGE3 element
84  std::vector<std::pair<Real, Real>> azi_interval_list;
85  for (unsigned int i = is_first_value_vertex ? 2 : 3; i < azimuthal_list.size(); i += 2)
86  azi_interval_list.push_back(
87  std::make_pair((azimuthal_list[i - 1] - azimuthal_list[i - 2]) / 180.0 * M_PI,
88  (azimuthal_list[i] - azimuthal_list[i - 1]) / 180.0 * M_PI));
89  // If it is not a full circle, the first value should always belong to a vertex
90  if (full_circle)
91  {
92  if (is_first_value_vertex)
93  azi_interval_list.push_back(std::make_pair(
94  (azimuthal_list.back() - azimuthal_list[azimuthal_list.size() - 2]) / 180.0 * M_PI,
95  (azimuthal_list.front() + 360.0 - azimuthal_list.back()) / 180.0 * M_PI));
96  else
97  azi_interval_list.push_back(
98  std::make_pair((azimuthal_list.front() + 360.0 - azimuthal_list.back()) / 180.0 * M_PI,
99  (azimuthal_list[1] - azimuthal_list.front()) / 180.0 * M_PI));
100  }
101  // Use the libMesh TRI6 element volume algorithm
102  for (const auto i : index_range(azi_interval_list))
103  {
104  tmp_acc += 2.0 * dummyTRI6VolCalculator(azi_interval_list[i]);
105  tmp_acc_azi += azi_interval_list[i].first + azi_interval_list[i].second;
106  }
107  }
108  return std::sqrt(tmp_acc_azi / tmp_acc);
109 }
Real dummyTRI6VolCalculator(const std::pair< Real, Real > &azi_pair)
Based on a pair of azimuthal angles, calculates the volume of a TRI6 element with one vertex at the o...
T cross_norm(const TypeVector< T > &b, const TypeVector< T > &c)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
int N
Real radiusCorrectionFactor(const std::vector< Real > &azimuthal_list, const bool full_circle=true, const unsigned int order=1, const bool is_first_value_vertex=true)
Makes radial correction to preserve ring area.
auto index_range(const T &sizable)