https://mooseframework.inl.gov
CSGNPolygonUnit.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 "CSGNPolygonUnit.h"
11 #include "CSGPlane.h"
12 #include "CSGBase.h" // complete type required to call methods on _internal_base
13 
14 namespace CSG
15 {
16 
17 CSGNPolygonUnit::CSGNPolygonUnit(const std::string & name, int n_sides, Real apothem)
18  : CSGSurfaceEngUnit(name), _n_sides(n_sides), _apothem(apothem)
19 {
20  if (_n_sides < 3)
21  mooseError("N-sided polygon engineering unit " + name + " must have 3 or more sides.");
22  if (_apothem <= 0.0)
23  mooseError("N-sided polygon engineering unit " + name + " apothem must be positive.");
24 }
25 
26 Real
28 {
29  // Condition for interior (negative value) vs exterior (positive value) for the polygon is:
30  // for point (x, y), if the following is true for all values of k, then the point is "interior".
31  // If any one value is positive, then the point is outside the polygon. Therefore, we calculate
32  // the maximum value. If that max value remains negative, then getHalfspaceFromPoint will
33  // correctly determine the point to be interior.
34  //
35  // x*cos(2*pi*k/N) + y*sin(2*pi*k/N) <= apothem, for all k = 0..N-1
36 
37  Real max_val =
38  -std::numeric_limits<Real>::max(); // initialize to extremely large negative (to be updated)
39  for (int k = 0; k < _n_sides; ++k)
40  {
41  auto val =
42  (p(0) * std::cos(2.0 * M_PI * k / _n_sides) + p(1) * std::sin(2.0 * M_PI * k / _n_sides)) -
43  _apothem;
44  if (val > max_val)
45  max_val = val;
46  }
47  return max_val;
48 }
49 
50 std::unordered_map<std::string, AttributeVariant>
52 {
53  return {{"num_sides", _n_sides}, {"apothem", _apothem}};
54 }
55 
56 void
58 {
59  // Polygon orientation assumes an infinite prism oriented with the z-axis.
60  // The right-most face is parallel to the y-axis and is centered at the origin.
61  // Equation for the kth face, where the 0th face is the right-most and A is the apothem, follows
62  // this equation:
63  // x*cos(2*pi*k/N) + y*sin(2*pi*k/N) + z*0 = A
64  // Coefficients for the plane ax + by + cz = d:
65  // a = cos(2*pi*k/N)
66  // b = sin(2*pi*k/N)
67  // c = 0.0
68  // d = A (apothem)
69  //
70  // Surface naming scheme: [UnitName]_expanded_surf_[k]
71 
72  Real a, b; // to be calculated based on side
73  Real c = 0.0;
74  Real d = _apothem;
75 
76  // Initialize region to be added to:
77  Point p(0, 0, 0); // origin used for determining half-space
78 
79  // base name for surfaces
80  std::string base_name = getName() + "_expanded_surf_";
81 
82  for (int k = 0; k < _n_sides; ++k)
83  {
84  auto sname = base_name + std::to_string(k);
85  a = std::cos(2.0 * M_PI * k / _n_sides);
86  b = std::sin(2.0 * M_PI * k / _n_sides);
87  std::unique_ptr<CSG::CSGPlane> s_ptr = std::make_unique<CSG::CSGPlane>(sname, a, b, c, d);
88  auto & surf = _internal_base->addSurface(std::move(s_ptr));
89 
90  // determine the half-space that contains the origin for this surface
91  auto hp_type = surf.getHalfspaceFromPoint(p);
92  // half-space region for this surface only (to be intersected below)
93  auto hp = (hp_type == CSGSurface::Halfspace::POSITIVE) ? +surf : -surf;
94 
95  // start the region with first half-space, otherwise intersect with existing region
97  _expanded_region = hp;
98  else
99  _expanded_region &= hp; // intersect with existing region
100  }
101 }
102 
103 } // namespace CSG
std::string name(const ElemQuality q)
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sin(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tan
CSGNPolygonUnit(const std::string &name, int n_sides, Real apothem)
Construct a new CSGNPolygonUnit.
Real evaluateSurfaceEquationAtPoint(const Point &p) const override
Evaluate the polygon&#39;s surface equation at the given point.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
std::unique_ptr< CSGBase > _internal_base
CSGBase populated by expandUnit(); joined into the parent CSGBase by expandEngUnit() ...
Definition: CSGEngUnit.h:130
auto max(const L &left, const R &right)
CSGRegion _expanded_region
Stores the result of expandUnit(); EMPTY until then.
const std::string & getName() const override
Satisfy CSGEngUnit::getName() – resolved via CSGSurface::getName()
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template cos(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(cos
RegionType getRegionType() const
Get the region type.
Definition: CSGRegion.h:123
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const int _n_sides
Number of sides of the regular polygon.
const Real _apothem
Distance from the polygon center to the midpoint of each side.
std::unordered_map< std::string, AttributeVariant > getAttributes() const override
Return the polygon attributes for this object.
CSGSurfaceEngUnit is an abstract base class for "engineering units" that can be used as surfaces in c...
void expandUnit() override
Create N CSGPlane surfaces in _internal_base, one per polygon side.