https://mooseframework.inl.gov
Loading...
Searching...
No Matches
CompositeSeriesBasisInterface.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
11#include "Legendre.h"
12
13#include <memory>
14
15/*
16 * Default constructor creates a functional basis with one term. In order for the _series member to
17 * be initialized, we initialized it with a Legendre series.
18 */
20 : FunctionalBasisInterface(1), _who_is_using_me(who_is_using_me)
21{
22 _series.push_back(std::make_unique<Legendre>());
23}
24
25/*
26 * The non-default constructor is where we actually loop over the series_types and initialize
27 * pointers to those members. Because we won't know the number of terms until the end of the body
28 * of the constructor, we need to call the default FunctionalBasisInterface constructor.
29 */
31 const std::vector<std::size_t> & orders,
32 std::vector<MooseEnum> series_types,
33 const std::string & who_is_using_me)
34 : FunctionalBasisInterface(), _series_types(series_types), _who_is_using_me(who_is_using_me)
35{
36 if (orders.size() != _series_types.size())
38 " calling CSBI::CSBI(...): Incorrect number of 'orders' specified for "
39 "'FunctionSeries'! Check that 'orders' is the correct length and no invalid "
40 "enumerations are specified for the series.");
41}
42
43void
45{
46 /*
47 * Evaluate the generation versions of each of the single series, and collect the results before
48 * passing them to evaluateSeries, where they will be multiplied together correctly and stored in
49 * the composite series basis evaluation.
50 */
51 std::vector<std::vector<Real>> single_series_basis_evaluation;
52 for (auto & series : _series)
53 single_series_basis_evaluation.push_back(series->getAllGeneration());
54
55 evaluateSeries(single_series_basis_evaluation);
56}
57
58void
60 const std::vector<std::vector<Real>> & single_series_basis_evaluations)
61{
62 /*
63 * Appropriate number of loops based on 1-D, 2-D, or 3-D to multiply the basis evaluations of the
64 * single series together to form the basis evaluation of the entire composite series.
65 */
66 Real f1, f2, f3;
67 std::size_t term = 0;
68
69 if (single_series_basis_evaluations.size() == 1)
70 for (std::size_t i = 0; i < _series[0]->getNumberOfTerms(); ++i, ++term)
71 save(term, single_series_basis_evaluations[0][i]);
72
73 if (single_series_basis_evaluations.size() == 2)
74 for (std::size_t i = 0; i < _series[0]->getNumberOfTerms(); ++i)
75 {
76 f1 = single_series_basis_evaluations[0][i];
77 for (std::size_t j = 0; j < _series[1]->getNumberOfTerms(); ++j, ++term)
78 {
79 f2 = single_series_basis_evaluations[1][j];
80 save(term, f1 * f2);
81 }
82 }
83
84 if (single_series_basis_evaluations.size() == 3)
85 for (std::size_t i = 0; i < _series[0]->getNumberOfTerms(); ++i)
86 {
87 f1 = single_series_basis_evaluations[0][i];
88 for (std::size_t j = 0; j < _series[1]->getNumberOfTerms(); ++j)
89 {
90 f2 = single_series_basis_evaluations[1][j];
91 for (std::size_t k = 0; k < _series[2]->getNumberOfTerms(); ++k, ++term)
92 {
93 f3 = single_series_basis_evaluations[2][k];
94 save(term, f1 * f2 * f3);
95 }
96 }
97 }
98}
99
100void
102{
103 /*
104 * Evaluate the expansion versions of each of the single series, and collect the results before
105 * passing them to evaluateSeries, where they will be multiplied together correctly and stored in
106 * the composite series basis evaluation.
107 */
108 std::vector<std::vector<Real>> single_series_basis_evaluation;
109 for (auto & series : _series)
110 single_series_basis_evaluation.push_back(series->getAllExpansion());
111
112 evaluateSeries(single_series_basis_evaluation);
113}
114
115const std::vector<Real> &
117{
118 static const std::vector<Real> function_limits = combineStandardizedFunctionLimits();
119
120 return function_limits;
121}
122
123Real
125{
126 Real function_volume = 1.0;
127
128 for (auto & series : _series)
129 function_volume *= series->getStandardizedFunctionVolume();
130
131 return function_volume;
132}
133
134std::vector<Real>
136{
137 std::vector<Real> function_limits;
138
139 for (auto & series : _series)
140 {
141 std::vector<Real> local_limits = series->getStandardizedFunctionLimits();
142 for (auto & limit : local_limits)
143 function_limits.push_back(limit);
144 }
145
146 return function_limits;
147}
148
149void
151 const std::vector<Real> & coefficients) const
152{
153 // clang-format off
154 std::ostringstream formatted, domains, orders;
155 std::size_t term = 0;
156
157 stream << "---------------- Coefficients ----------------\n"
158 << " == Subindices ==\n";
159
160 if (_series_types.size() == 1)
161 {
162 orders << " Orders: " << std::setw(3) << _series[0]->getOrder(0) << "\n";
163 domains << " == Index == " << std::setw(3) << _series[0]->_domains[0]
164 << " === Value ===\n"
165 << "----------------------------------------------\n";
166
167 for (std::size_t i = 0; i < _series[0]->getNumberOfTerms(); ++i, ++term)
168 formatted << " " << std::setw(4) << term
169 << " " << std::setw(3) << i
170 << " " << std::setw(12) << coefficients[term] << "\n";
171 }
172 else if (_series_types.size() == 2)
173 {
174 orders << " Orders: " << std::setw(3) << _series[0]->getOrder(0)
175 << " " << std::setw(3) << _series[1]->getOrder(0) << "\n";
176 domains << " == Index == " << std::setw(3) << _series[0]->_domains[0]
177 << " " << std::setw(3) << _series[1]->_domains[0]
178 << " === Value ===\n"
179 << "----------------------------------------------\n";
180
181 for (std::size_t i = 0; i < _series[0]->getNumberOfTerms(); ++i)
182 {
183 for (std::size_t j = 0; j < _series[1]->getNumberOfTerms(); ++j, ++term)
184 formatted << " " << std::setw(4) << term
185 << " " << std::setw(3) << i
186 << " " << std::setw(3) << j
187 << " " << std::setw(12) << coefficients[term] << "\n";
188 }
189 }
190 else if (_series_types.size() == 3)
191 {
192 orders << " Orders: " << std::setw(3) << _series[0]->getOrder(0)
193 << " " << std::setw(3) << _series[1]->getOrder(0)
194 << " " << std::setw(3) << _series[2]->getOrder(0) << "\n";
195 domains << " == Index == " << std::setw(3) << _series[0]->_domains[0]
196 << " " << std::setw(3) << _series[1]->_domains[0]
197 << " " << std::setw(3) << _series[2]->_domains[0]
198 << " === Value ===\n"
199 << "----------------------------------------------\n";
200
201 for (std::size_t i = 0; i < _series[0]->getNumberOfTerms(); ++i)
202 {
203 for (std::size_t j = 0; j < _series[1]->getNumberOfTerms(); ++j)
204 {
205 for (std::size_t k = 0; k < _series[2]->getNumberOfTerms(); ++k, ++term)
206 formatted << " " << std::setw(4) << term
207 << " " << std::setw(3) << i
208 << " " << std::setw(3) << j
209 << " " << std::setw(3) << k
210 << " " << std::setw(12) << coefficients[term] << "\n";
211 }
212 }
213 }
214 // clang-format on
215
216 stream << orders.str() << domains.str() << formatted.str() << std::flush;
217}
218
219bool
221{
222 /*
223 * If any one of the single series have an invalid cache, then we need to re-evaluate the entire
224 * composite series because the terms are multiplied.
225 */
226 for (auto & series : _series)
227 if (series->isCacheInvalid())
228 return true;
229
230 return false;
231}
232
233bool
235{
236 /*
237 * A point is in the physical bounds of the composite series if it is in the physical bounds of
238 * each of the single series
239 */
240 for (auto & series : _series)
241 if (!series->isInPhysicalBounds(point))
242 return false;
243
244 return true;
245}
246
247void
249{
250 unsigned int number_of_terms = 1;
251
252 // Accumulate the number of terms for each series
253 for (auto & series : _series)
254 number_of_terms *= series->getNumberOfTerms();
255
256 _number_of_terms = number_of_terms;
257
258 /*
259 * The length of the _basis_evaluation depends on the number of terms, so we need to clear the
260 * entries because the number of terms in the composite series may have changed.
261 */
263}
264
265void
266CompositeSeriesBasisInterface::setOrder(const std::vector<std::size_t> & orders)
267{
268 // One order must be specified for each single series
269 if (orders.size() != _series.size())
271 " calling CSBI::setOrder(): Mismatch between the orders provided and the number of "
272 "series in the functional basis!");
273
274 // Update the orders of each of the single series
275 for (std::size_t i = 0; i < _series.size(); ++i)
276 _series[i]->setOrder({orders[i]});
277
278 /*
279 * After changing the order of each single series, we need to recompute the number of terms by
280 * looping over those single series. This also clears the basis evaluation of the composite
281 * series.
282 */
284}
285
286void
288{
289 // Return if this point is the same as the last at which the composite series was evaluated
290 if (point.absolute_fuzzy_equals(_previous_point))
291 return;
292
293 // Set the location of each of the single series
294 for (auto & series : _series)
295 series->setLocation(point);
296
297 // Store the previous point
298 _previous_point = point;
299}
300
void mooseError(Args &&... args)
virtual void setOrder(const std::vector< std::size_t > &orders) final
Set the order of the series.
void evaluateSeries(const std::vector< std::vector< Real > > &single_series_basis_evaluations)
Evaluates the values of _basis_evaluation for either evaluateGeneration() or evaluateExpansion()
virtual void evaluateExpansion() final
Evaluate the expansion form of the functional basis.
std::vector< std::unique_ptr< SingleSeriesBasisInterface > > _series
A pointer to the single series type (one for each entry in _domains)
virtual void setLocation(const Point &p) final
Set the location that will be used by the series to compute values.
virtual Real getStandardizedFunctionVolume() const final
Returns the volume within the standardized function local_limits.
virtual void evaluateGeneration() final
Evaluate the generation form of the functional basis.
Point _previous_point
The previous point at which the series was evaluated.
virtual const std::vector< Real > & getStandardizedFunctionLimits() const final
Returns a vector of the lower and upper bounds of the standard functional space.
virtual void formatCoefficients(std::ostream &stream, const std::vector< Real > &coefficients) const
Appends a tabulated form of the coefficients to the stream.
std::vector< MooseEnum > _series_types
The series types in this composite series.
virtual bool isInPhysicalBounds(const Point &point) const final
Determines if the point provided is in within the physical bounds.
virtual void clearBasisEvaluation(const unsigned int &number_of_terms)
Set all entries of the basis evaluation to zero.
void setNumberOfTerms()
Initialize the number of terms in the composite series by looping over the single series.
CompositeSeriesBasisInterface(const std::string &who_is_using_me)
const std::string & _who_is_using_me
The name of the MooseObject that is using this class.
std::vector< Real > combineStandardizedFunctionLimits() const
Get the function limits by looping over each of the single series.
virtual bool isCacheInvalid() const final
Whether the cached values correspond to the current point.
This class provides the basis for any custom functional basis, and is the parent class of both Single...
unsigned int _number_of_terms
The number of terms in the series.
void save(std::size_t index, Real value)
Helper function to store a value in #_series.