https://mooseframework.inl.gov
ControlDrumMaterial.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 "ControlDrumMaterial.h"
11 
13 
16 {
18 
19  params.addRequiredParam<std::vector<Point>>("rotation_centers", "The centers of the rotation");
20 
21  params.addRequiredParam<std::vector<MooseFunctorName>>("rotation_angle_functors",
22  "The rotation angle as functor values");
23  params.addParam<std::vector<Real>>(
24  "rotation_angle_offsets", "Offsets of rotation angles corresponding to rotation centers");
25 
26  MooseEnum dir("x y z -x -y -z", "z");
27  params.addParam<MooseEnum>("rotation_axis", dir, "The rotation axis");
28 
29  params.addRequiredParam<std::vector<Real>>(
30  "segment_angles",
31  "The covering angles in degree of all segments that sum to 360.\n"
32  "Order by starting segment in a counter-clock-wise direction with respect to the rotation "
33  "axis.\n"
34  "All rotation centers share the same segment angles.");
35 
36  params.addRequiredParam<std::vector<std::vector<MaterialPropertyName>>>(
37  "segment_material_properties",
38  "Material properties for all the rotation segments corresponding to drum material "
39  "properties");
40  params.addRequiredParam<std::vector<MaterialPropertyName>>(
41  "drum_material_properties", "Material property names for the drums");
42 
43  params.addClassDescription("Evaluate a material property based on the material properties of all "
44  "segments of a rotating drum.");
45  return params;
46 }
47 
49  : Material(parameters),
50  _rotation_centers(parameters.get<std::vector<Point>>("rotation_centers")),
51  _rotation_axis(parameters.get<MooseEnum>("rotation_axis")),
52  _plus(_rotation_axis == "x" || _rotation_axis == "y" || _rotation_axis == "z"),
53  _rotation_offsets(isParamValid("rotation_angle_offsets")
54  ? parameters.get<std::vector<Real>>("rotation_angle_offsets")
55  : std::vector<Real>(_rotation_centers.size(), 0.0)),
56  _segment_angles(parameters.get<std::vector<Real>>("segment_angles")),
57  _n_segments(_segment_angles.size())
58 {
59  if (_rotation_axis == "x" || _rotation_axis == "-x")
60  _dir = 0;
61  else if (_rotation_axis == "y" || _rotation_axis == "-y")
62  _dir = 1;
63  else
64  _dir = 2;
65 
66  if ((_dir == 0 || _dir == 1) && _mesh.spatialDimension() < 3)
68  "rotation_axis", _rotation_axis, " requires mesh spatial dimention to be three.");
69 
70  const auto funcs = parameters.get<std::vector<MooseFunctorName>>("rotation_angle_functors");
71  for (const auto & func_name : funcs)
72  {
73  _rotation_functors.push_back(&getFunctor<Real>(func_name));
74  // fixme: we should check whether the functor is constant in space, but
75  // that requires resolving MOOSE Issue #32787.
76  }
77 
78  if (_rotation_centers.size() != _rotation_functors.size())
79  {
80  if (_rotation_functors.size() == 1)
81  {
82  // all rotation centers share the same function
84  }
85  else
86  parameters.paramError("rotation_angle_function",
87  "Number of rotation angle functions must agree with "
88  "the size of 'rotation_centers' or be equal to one in case of all "
89  "rotation centers sharing "
90  "the same function");
91  }
92  if (_rotation_offsets.size() != _rotation_centers.size())
93  parameters.paramError("rotation_angle_offsets",
94  "Size must be equal to the size of 'rotation_centers' ");
95 
96  if (_n_segments < 2)
97  parameters.paramError("segment_angles", "At least 2 segments are required.");
98 
99  Real angle = 0;
100  for (const auto & v : _segment_angles)
101  angle += v;
102  if (angle != 360)
103  parameters.paramError("segment_angles", "Must sum to 360 degree.");
104 
105  for (const auto & c : _rotation_centers)
106  if (c(_dir) != 0)
107  parameters.paramError("rotation_centers",
108  "Must have zero coordinate in the rotation direction");
109 
110  const auto drum_props = getParam<std::vector<MaterialPropertyName>>("drum_material_properties");
111  for (const auto & prop_name : drum_props)
112  _drum_properties.push_back(&declareProperty<Real>(prop_name));
113 
114  const auto all_prop_names =
115  getParam<std::vector<std::vector<MaterialPropertyName>>>("segment_material_properties");
116  if (all_prop_names.size() != drum_props.size())
117  paramError(
118  "segment_material_properties",
119  "Leading size of the 2D array must be equal to the size of 'drum_material_properties'");
120  for (const auto & prop_names : all_prop_names)
121  {
122  if (prop_names.size() != _n_segments)
123  paramError("segment_material_properties",
124  "Number of segment materal properties of one drum material property must be equal "
125  "to the number of segments (",
126  _n_segments,
127  ")");
128  std::vector<const MaterialProperty<Real> *> props;
129  for (const auto & prop_name : prop_names)
130  props.push_back(&getMaterialPropertyByName<Real>(prop_name));
131  _segment_properties.push_back(props);
132  }
133 }
134 
135 void
137 {
138  // get the id of the rotation center the current element is rotating around
139  unsigned int rotation_id = 0;
140  Real min_dist = std::numeric_limits<Real>::max();
141  auto p = _current_elem->vertex_average();
142  p(_dir) = 0;
143  for (const auto i : index_range(_rotation_centers))
144  {
145  auto c = _rotation_centers[i];
146  Real dist = (p - c).norm();
147  if (dist < min_dist)
148  {
149  rotation_id = i;
150  min_dist = dist;
151  }
152  }
153 
154  // functor does not depend on state and element, but we pass them to meet the interface
155  const auto state = determineState();
156  const auto elem_arg = makeElemArg(_current_elem);
157  Real rotation_angle =
158  (*_rotation_functors[rotation_id])(elem_arg, state) + _rotation_offsets[rotation_id];
159 
160  // get the angle of the current quadrature point
161  Point v = _q_point[_qp] - _rotation_centers[rotation_id];
162  v(_dir) = 0;
163  const Real vnorm = v.norm();
164  if (vnorm != 0.0)
165  v /= vnorm;
166 
167  // (-180, 180]
168  Real ang = std::acos(v((_dir + 1) % 3)) * (180 / M_PI);
169  if (v((_dir + 2) % 3) < 0)
170  ang = -ang;
171 
172  // make sure returned angle is within [rotation_angle, rotation_angle+360)
173  while (ang < rotation_angle)
174  ang += 360;
175  while (ang - 360 >= rotation_angle)
176  ang -= 360;
177 
178  // rotation wrt current rotation_angle [0, 360)
179  if (_plus)
180  ang -= rotation_angle;
181  else
182  {
183  // flip the angle
184  if (ang == rotation_angle)
185  ang = 0;
186  else
187  ang = rotation_angle + 360 - ang;
188  }
189 
190  // find the segment where the qp is located
191  unsigned int seg_id = 0;
192  Real upper_angle = _segment_angles[0];
193  while (ang > upper_angle)
194  {
195  ++seg_id;
196  mooseAssert(seg_id < _n_segments, "Internal error: segement id");
197  upper_angle += _segment_angles[seg_id];
198  }
199 
200  // assign material properties
201  // Note: we do not attempt adjust the value considering the weight with the location
202  // of the segment interface.
203  for (const auto i : index_range(_drum_properties))
204  (*_drum_properties[i])[_qp] = (*_segment_properties[i][seg_id])[_qp];
205 }
const MooseArray< Point > & _q_point
const MooseEnum _rotation_axis
x/y/z/-x/-y/-z
virtual unsigned int spatialDimension() const
ControlDrumMaterial(const InputParameters &parameters)
const bool _plus
Whether the rotation axis points to the positive direction, i.e. equal to x, y or z...
void paramError(const std::string &param, Args... args) const
const std::vector< Real > _rotation_offsets
Rotation offsets of all drums.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
unsigned int _dir
Rotation direction (x/y/z - 0/1/2)
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
const InputParameters & parameters() const
Moose::StateArg determineState() const
const double v
const std::vector< Real > _segment_angles
Segment angles (all rotation centers share the same segment angles)
const unsigned int _n_segments
Number of rod segments.
void addRequiredParam(const std::string &name, const std::string &doc_string)
static InputParameters validParams()
const std::vector< Point > _rotation_centers
Rotation center.
Moose::ElemArg makeElemArg(const Elem *elem, bool correct_skewnewss=false) const
unsigned int _qp
void paramError(const std::string &param, Args... args) const
virtual void computeQpProperties() override
MooseMesh & _mesh
static InputParameters validParams()
std::vector< const Moose::Functor< Real > * > _rotation_functors
Rotation angle functors of all drums.
registerMooseObject("ReactorApp", ControlDrumMaterial)
std::vector< std::vector< const MaterialProperty< Real > * > > _segment_properties
Material properties of all segments.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
auto norm(const T &a)
const Real p
void addClassDescription(const std::string &doc_string)
This material evaluate a material property on elements on a rotating control drum from material prope...
auto index_range(const T &sizable)
const Elem & get(const ElemType type_in)
const Elem *const & _current_elem
std::vector< MaterialProperty< Real > * > _drum_properties
The properties this material evaluates.