www.mooseframework.org
FunctionSeries.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 <numeric> // Provides accumulate()
11 
12 #include "FunctionalBasisInterface.h" // Provides _domain_options
13 #include "FunctionSeries.h"
14 #include "Cartesian.h"
15 #include "CylindricalDuo.h"
16 
17 registerMooseObject("FunctionalExpansionToolsApp", FunctionSeries);
18 
19 template <>
20 InputParameters
22 {
23  InputParameters params = validParams<MutableCoefficientsFunctionInterface>();
24 
25  params.addClassDescription("This function uses a convolution of functional series (functional "
26  "expansion or FX) to create a 1D, 2D, or 3D function");
27 
28  // The available composite series types.
29  // Cartesian: 1D, 2D, or 3D, depending on which of x, y, and z are present
30  // CylindricalDuo: planar disc expansion and axial expansion
31  MooseEnum series_types("Cartesian CylindricalDuo");
32  MooseEnum single_series_types_1D("Legendre");
33  MooseEnum single_series_types_2D("Zernike");
34 
35  params.addRequiredParam<MooseEnum>(
36  "series_type", series_types, "The type of function series to construct.");
37 
38  /*
39  * This needs to use `unsigned int` instead of `std::size_t` because otherwise MOOSE errors at
40  * runtime
41  */
42  params.addRequiredParam<std::vector<unsigned int>>("orders",
43  "The order of each series. These must be "
44  "defined as \"x y z\" for Cartesian, and \"z "
45  "disc\" for CylindricalDuo.");
46 
47  params.addParam<std::vector<Real>>("physical_bounds",
48  "The physical bounds of the function series. These must be "
49  "defined as \"x_min x_max y_min y_max z_min z_max\" for "
50  "Cartesian, and \"axial_min axial_max disc_center1 "
51  "disc_center2 radius\" for CylindricalDuo");
52 
53  params.addParam<MooseEnum>("x", single_series_types_1D, "The series to use for the x-direction.");
54  params.addParam<MooseEnum>("y", single_series_types_1D, "The series to use for the y-direction.");
55  params.addParam<MooseEnum>("z", single_series_types_1D, "The series to use for the z-direction.");
56 
57  params.addParam<MooseEnum>("disc",
59  "The series to use for the disc. Its direction is determined by "
60  "orthogonality to the declared direction of the axis.");
61 
62  std::string normalization_types = "orthonormal sqrt_mu standard";
63  MooseEnum expansion_type(normalization_types, "standard");
64  MooseEnum generation_type(normalization_types, "orthonormal");
65  params.addParam<MooseEnum>("expansion_type",
67  "The normalization used for expansion of the basis functions");
68  params.addParam<MooseEnum>(
69  "generation_type",
71  "The normalization used for generation of the basis function coefficients");
72  return params;
73 }
74 
75 FunctionSeries::FunctionSeries(const InputParameters & parameters)
76  : MutableCoefficientsFunctionInterface(this, parameters),
77  _orders(convertOrders(getParam<std::vector<unsigned int>>("orders"))),
78  _physical_bounds(getParam<std::vector<Real>>("physical_bounds")),
79  _series_type_name(getParam<MooseEnum>("series_type")),
80  _x(getParam<MooseEnum>("x")),
81  _y(getParam<MooseEnum>("y")),
82  _z(getParam<MooseEnum>("z")),
83  _disc(getParam<MooseEnum>("disc")),
84  _expansion_type(getParam<MooseEnum>("expansion_type")),
85  _generation_type(getParam<MooseEnum>("generation_type"))
86 {
87  std::vector<MooseEnum> domains;
88  std::vector<MooseEnum> types;
89 
90  if (_series_type_name == "Cartesian")
91  {
92  /*
93  * For Cartesian series, at least one of 'x', 'y', and 'z' must be specified.
94  *
95  * The individual series are always stored in x, y, z order (independent of the order in which
96  * they appear in the input file). Hence, the 'orders' and 'physical_bounds' vectors must always
97  * be specified in x, y, z order.
98  */
99  if (isParamValid("x"))
100  {
101  domains.push_back(FunctionalBasisInterface::_domain_options = "x");
102  types.push_back(_x);
103  }
104  if (isParamValid("y"))
105  {
106  domains.push_back(FunctionalBasisInterface::_domain_options = "y");
107  types.push_back(_y);
108  }
109  if (isParamValid("z"))
110  {
111  domains.push_back(FunctionalBasisInterface::_domain_options = "z");
112  types.push_back(_z);
113  }
114  if (types.size() == 0)
115  mooseError("Must specify one of 'x', 'y', or 'z' for 'Cartesian' series!");
116  _series_type = libmesh_make_unique<Cartesian>(
117  domains, _orders, types, name(), _expansion_type, _generation_type);
118  }
119  else if (_series_type_name == "CylindricalDuo")
120  {
121  /*
122  * CylindricalDuo represents a disc-axial expansion, where the disc is described by a single
123  * series, such as Zernike (as opposed to a series individually representing r and a second
124  * series independently representing theta. For CylindricalDuo series, the series are always
125  * stored in the axial, planar order, independent of which order the series appear in the input
126  * file. Therefore, the _orders and _physical_bounds vectors must always appear in axial, planar
127  * order. The first entry in _domains is interpreted as the axial direction, and the following
128  * two as the planar.
129  */
130  if (isParamValid("x"))
131  {
135  types.push_back(_x);
136  }
137  if (isParamValid("y"))
138  {
142  types.push_back(_y);
143  }
144  if (isParamValid("z"))
145  {
149  types.push_back(_z);
150  }
151 
152  if (types.size() == 0)
153  mooseError("Must specify one of 'x', 'y', or 'z' for 'CylindricalDuo' series!");
154 
155  if (types.size() > 1)
156  mooseError("Cannot specify more than one of 'x', 'y', or 'z' for 'CylindricalDuo' series!");
157 
158  types.push_back(_disc);
159  _series_type = libmesh_make_unique<CylindricalDuo>(
160  domains, _orders, types, name(), _expansion_type, _generation_type);
161  }
162  else
163  mooseError("Unknown functional series type \"", _series_type_name, "\"");
164 
165  // Set the physical bounds of each of the single series if defined
166  if (isParamValid("physical_bounds"))
167  _series_type->setPhysicalBounds(_physical_bounds);
168 
169  // Resize the coefficient array as needed
170  enforceSize(false), resize(getNumberOfTerms(), 0.0), enforceSize(true);
172 }
173 
175 FunctionSeries::checkAndConvertFunction(const Function & function,
176  const std::string & typeName,
177  const std::string & objectName)
178 {
179  const FunctionSeries * test = dynamic_cast<const FunctionSeries *>(&function);
180  if (!test)
181  ::mooseError("In ",
182  typeName,
183  "-type object \"",
184  objectName,
185  "\": the named Function \"",
186  function.name(),
187  "\" must be a FunctionSeries-type object.");
188 
189  return *const_cast<FunctionSeries *>(test);
190 }
191 
192 Real
194 {
195  return _series_type->getStandardizedFunctionVolume();
196 }
197 
198 std::size_t
200 {
201  return _series_type->getNumberOfTerms();
202 }
203 
204 const std::vector<size_t> &
206 {
207  return _orders;
208 }
209 
210 /*
211  * getAllGeneration() is defined in the FunctionalBasisInterface, which calls the pure virtual
212  * evaluateGeneration() method of the CompositeSeriesBasisInterface class, which then calls the
213  * getAllGeneration() method of each of the single series.
214  */
215 const std::vector<Real> &
217 {
218  return _series_type->getAllGeneration();
219 }
220 
221 /*
222  * getAllExpansion() is defined in the FunctionalBasisInterface, which calls the pure virtual
223  * evaluateExpansion() method of the CompositeSeriesBasisInterface class, which then calls the
224  * getAllExpansion() method of each of the single series.
225  */
226 const std::vector<Real> &
228 {
229  return _series_type->getAllExpansion();
230 }
231 
232 /*
233  * isInPhysicalBounds() is a pure virtual method of the FunctionalBasisInterface that is defined in
234  * the CompositeSeriesBasisInterface class because it is agnostic to the underlying types of the
235  * single series.
236  */
237 bool
238 FunctionSeries::isInPhysicalBounds(const Point & point) const
239 {
240  return _series_type->isInPhysicalBounds(point);
241 }
242 
243 void
244 FunctionSeries::setLocation(const Point & point)
245 {
246  _series_type->setLocation(point);
247 }
248 
249 Real
250 FunctionSeries::evaluateValue(Real, const Point & point)
251 {
252  // Check that the point is within the physical bounds of the series
253  if (!isInPhysicalBounds(point))
254  return 0.0;
255 
256  // Set the location at which to evaluate the series
257  setLocation(point);
258 
259  return expand();
260 }
261 
262 Real
264 {
265  return expand(_coefficients);
266 }
267 
268 Real
269 FunctionSeries::expand(const std::vector<Real> & coefficients)
270 {
271  // Evaluate all of the terms in the series
272  const std::vector<Real> & terms = getExpansion();
273 
274  return std::inner_product(terms.begin(), terms.end(), coefficients.begin(), 0.0);
275 }
276 
277 std::ostream &
278 operator<<(std::ostream & stream, const FunctionSeries & me)
279 {
280  stream << "\n\n"
281  << "FunctionSeries: " << me.name() << "\n"
282  << " Terms: " << me.getNumberOfTerms() << "\n";
283  me._series_type->formatCoefficients(stream, me._coefficients);
284  stream << "\n\n";
285 
286  return stream;
287 }
288 
289 std::vector<std::size_t>
290 FunctionSeries::convertOrders(const std::vector<unsigned int> & orders)
291 {
292  return std::vector<std::size_t>(orders.begin(), orders.end());
293 }
FunctionSeries::_disc
const MooseEnum & _disc
Stores the name of the single function series to use for a unit disc.
Definition: FunctionSeries.h:114
MutableCoefficientsInterface::setCharacteristics
void setCharacteristics(const std::vector< std::size_t > &new_characteristics)
Sets the characteristics array.
Definition: MutableCoefficientsInterface.C:149
FunctionalBasisInterface::_domain_options
static MooseEnum _domain_options
An enumeration of the domains available to each functional series.
Definition: FunctionalBasisInterface.h:115
Cartesian.h
MutableCoefficientsInterface::resize
void resize(std::size_t size, Real fill=0.0, bool fill_out_to_size=true)
Resize the array, using the value for fill if the new size is larger.
Definition: MutableCoefficientsInterface.C:131
FunctionSeries::expand
Real expand()
Expand the function series at the current location and with the current coefficients.
Definition: FunctionSeries.C:263
FunctionSeries::evaluateValue
virtual Real evaluateValue(Real t, const Point &p) override
Used in derived classes, equivalent to Function::value()
Definition: FunctionSeries.C:250
single_series_types_1D
MooseEnum single_series_types_1D
MutableCoefficientsFunctionInterface
Interface for a type of functions using coefficients that may be changed before or after a solve.
Definition: MutableCoefficientsFunctionInterface.h:25
FunctionSeries::getNumberOfTerms
std::size_t getNumberOfTerms() const
Returns the number of terms (coefficients) in the underlying function series.
Definition: FunctionSeries.C:199
FunctionSeries::_orders
const std::vector< std::size_t > _orders
The vector holding the orders of each single series.
Definition: FunctionSeries.h:92
FunctionSeries::_series_type
std::unique_ptr< CompositeSeriesBasisInterface > _series_type
Stores a pointer to the functional series object.
Definition: FunctionSeries.h:98
expansion_type
MooseEnum expansion_type
MutableCoefficientsInterface::_coefficients
std::vector< Real > & _coefficients
The coefficient array.
Definition: MutableCoefficientsInterface.h:113
FunctionSeries::isInPhysicalBounds
bool isInPhysicalBounds(const Point &point) const
Returns true if the provided point is within the set physical boundaries.
Definition: FunctionSeries.C:238
FunctionSeries
This class uses implementations of CompositeSeriesBasisInterface to generate a function based on conv...
Definition: FunctionSeries.h:25
FunctionSeries::FunctionSeries
FunctionSeries(const InputParameters &parameters)
Definition: FunctionSeries.C:75
single_series_types_2D
MooseEnum single_series_types_2D
FunctionSeries::_z
const MooseEnum & _z
Stores the name of the single function series to use in the z direction.
Definition: FunctionSeries.h:112
CylindricalDuo.h
FunctionalBasisInterface.h
registerMooseObject
registerMooseObject("FunctionalExpansionToolsApp", FunctionSeries)
generation_type
MooseEnum generation_type
FunctionSeries::_expansion_type
const MooseEnum & _expansion_type
The normalization type for expansion.
Definition: FunctionSeries.h:116
FunctionSeries::getExpansion
const std::vector< Real > & getExpansion()
Returns a vector of the expansion-evaluated functional series at the current location.
Definition: FunctionSeries.C:227
FunctionSeries::getGeneration
const std::vector< Real > & getGeneration()
Returns a vector of the generation-evaluated functional series at the current location.
Definition: FunctionSeries.C:216
FunctionSeries::convertOrders
static std::vector< std::size_t > convertOrders(const std::vector< unsigned int > &orders)
Static function to convert an array of unsigned int to std::size_t.
Definition: FunctionSeries.C:290
validParams< FunctionSeries >
InputParameters validParams< FunctionSeries >()
Definition: FunctionSeries.C:21
name
const std::string name
Definition: Setup.h:21
MutableCoefficientsInterface::enforceSize
void enforceSize(bool enforce)
Toggle whether the size of the coefficient array can be changed.
Definition: MutableCoefficientsInterface.C:111
validParams< MutableCoefficientsFunctionInterface >
InputParameters validParams< MutableCoefficientsFunctionInterface >()
Definition: MutableCoefficientsFunctionInterface.C:14
FunctionSeries::getOrders
const std::vector< std::size_t > & getOrders() const
Returns a vector of the functional orders in the underlying functional series.
Definition: FunctionSeries.C:205
FunctionSeries::_physical_bounds
const std::vector< Real > _physical_bounds
The physical bounds of the function series.
Definition: FunctionSeries.h:95
FunctionSeries::_x
const MooseEnum & _x
Stores the name of the single function series to use in the x direction.
Definition: FunctionSeries.h:108
FunctionSeries::getStandardizedFunctionVolume
Real getStandardizedFunctionVolume() const
Returns the volume of evaluation in the functional series standardized space.
Definition: FunctionSeries.C:193
FunctionSeries::_generation_type
const MooseEnum & _generation_type
The normalization type for generation.
Definition: FunctionSeries.h:118
operator<<
std::ostream & operator<<(std::ostream &stream, const FunctionSeries &me)
Definition: FunctionSeries.C:278
FunctionSeries::checkAndConvertFunction
static FunctionSeries & checkAndConvertFunction(const Function &function, const std::string &typeName, const std::string &objectName)
Static function to cast a Function to SeriesFunction.
Definition: FunctionSeries.C:175
FunctionSeries::_y
const MooseEnum & _y
Stores the name of the single function series to use in the y direction.
Definition: FunctionSeries.h:110
FunctionSeries::setLocation
void setLocation(const Point &point)
Set the current evaluation location.
Definition: FunctionSeries.C:244
FunctionSeries::_series_type_name
const MooseEnum & _series_type_name
Stores the name of the current functional series type.
Definition: FunctionSeries.h:101
FunctionSeries.h