https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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())
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 (",
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
135void
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}
registerMooseObject("ReactorApp", ControlDrumMaterial)
const Real p
const double v
This material evaluate a material property on elements on a rotating control drum from material prope...
const std::vector< Point > _rotation_centers
Rotation center.
const std::vector< Real > _segment_angles
Segment angles (all rotation centers share the same segment angles)
static InputParameters validParams()
ControlDrumMaterial(const InputParameters &parameters)
const std::vector< Real > _rotation_offsets
Rotation offsets of all drums.
const MooseEnum _rotation_axis
x/y/z/-x/-y/-z
std::vector< const Moose::Functor< Real > * > _rotation_functors
Rotation angle functors of all drums.
unsigned int _dir
Rotation direction (x/y/z - 0/1/2)
std::vector< MaterialProperty< Real > * > _drum_properties
The properties this material evaluates.
const bool _plus
Whether the rotation axis points to the positive direction, i.e. equal to x, y or z.
virtual void computeQpProperties() override
const unsigned int _n_segments
Number of rod segments.
std::vector< std::vector< const MaterialProperty< Real > * > > _segment_properties
Material properties of all segments.
Moose::ElemArg makeElemArg(const Elem *elem, bool correct_skewnewss=false) const
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
void paramError(const std::string &param, Args... args) const
void addClassDescription(const std::string &doc_string)
unsigned int _qp
MooseMesh & _mesh
static InputParameters validParams()
const Elem *const & _current_elem
const MooseArray< Point > & _q_point
const InputParameters & parameters() const
void paramError(const std::string &param, Args... args) const
virtual unsigned int spatialDimension() const
Moose::StateArg determineState() const