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