Line data Source code
1 : // The libMesh Finite Element Library.
2 : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 :
4 : // This library is free software; you can redistribute it and/or
5 : // modify it under the terms of the GNU Lesser General Public
6 : // License as published by the Free Software Foundation; either
7 : // version 2.1 of the License, or (at your option) any later version.
8 :
9 : // This library is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : // Lesser General Public License for more details.
13 :
14 : // You should have received a copy of the GNU Lesser General Public
15 : // License along with this library; if not, write to the Free Software
16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 :
18 :
19 :
20 : #ifndef LIBMESH_WRAPPED_FUNCTION_H
21 : #define LIBMESH_WRAPPED_FUNCTION_H
22 :
23 : // Local Includes
24 : #include "libmesh/dense_vector.h"
25 : #include "libmesh/equation_systems.h"
26 : #include "libmesh/function_base.h"
27 : #include "libmesh/libmesh_common.h"
28 : #include "libmesh/point.h"
29 : #include "libmesh/system.h"
30 : #include "libmesh/fe_interface.h"
31 :
32 : // C++ includes
33 : #include <cstddef>
34 : #include <memory>
35 :
36 : namespace libMesh
37 : {
38 :
39 : /**
40 : * \brief Wrap a libMesh-style function pointer into a FunctionBase object.
41 : *
42 : * This class provides a wrapper with which to evaluate a
43 : * (libMesh-style) function pointer in a FunctionBase-compatible
44 : * interface. All overridden virtual functions are documented in
45 : * function_base.h.
46 : *
47 : * \author Roy Stogner
48 : * \date 2012
49 : * \note To wrap an ordinary function pointer use the AnalyticFunction class.
50 : */
51 : template <typename Output=Number>
52 : class WrappedFunction : public FunctionBase<Output>
53 : {
54 : public:
55 :
56 : /**
57 : * Constructor to wrap scalar-valued function pointers.
58 : */
59 805540 : WrappedFunction (const System & sys,
60 : Output fptr(const Point & p,
61 : const Parameters & parameters,
62 : const std::string & sys_name,
63 : const std::string & unknown_name) = nullptr,
64 : const Parameters * parameters = nullptr,
65 : unsigned int varnum=0)
66 781914 : : _sys(sys),
67 781914 : _fptr(fptr),
68 781914 : _parameters(parameters),
69 811110 : _varnum(varnum)
70 : {
71 437944 : this->_initialized = true;
72 613387 : if (!parameters)
73 0 : _parameters = &sys.get_equation_systems().parameters;
74 18056 : }
75 :
76 : /**
77 : * The move/copy ctor and destructor are defaulted for this class.
78 : */
79 : WrappedFunction (WrappedFunction &&) = default;
80 : WrappedFunction (const WrappedFunction &) = default;
81 1786801 : virtual ~WrappedFunction () = default;
82 :
83 : /**
84 : * This class contains a const reference so it can't be assigned.
85 : */
86 : WrappedFunction & operator= (const WrappedFunction &) = delete;
87 : WrappedFunction & operator= (WrappedFunction &&) = delete;
88 :
89 : virtual std::unique_ptr<FunctionBase<Output>> clone () const override;
90 :
91 : virtual Output operator() (const Point & p,
92 : const Real time = 0.) override;
93 :
94 : virtual void operator() (const Point & p,
95 : const Real time,
96 : DenseVector<Output> & output) override;
97 :
98 : virtual Output component (unsigned int i,
99 : const Point & p,
100 : Real time=0.) override;
101 :
102 : protected:
103 :
104 : const System & _sys;
105 :
106 : Output (*_fptr)(const Point & p,
107 : const Parameters & parameters,
108 : const std::string & sys_name,
109 : const std::string & unknown_name);
110 :
111 : const Parameters * _parameters;
112 :
113 : unsigned int _varnum;
114 : };
115 :
116 :
117 : // ------------------------------------------------------------
118 : // WrappedFunction inline methods
119 :
120 :
121 : template <typename Output>
122 : inline
123 0 : Output WrappedFunction<Output>::operator() (const Point & p,
124 : const Real /*time*/)
125 : {
126 0 : libmesh_assert(_fptr);
127 0 : libmesh_assert(_parameters);
128 0 : return _fptr(p,
129 0 : *_parameters,
130 0 : _sys.name(),
131 0 : _sys.variable_name(_varnum));
132 : }
133 :
134 :
135 : template <typename Output>
136 : inline
137 : std::unique_ptr<FunctionBase<Output>>
138 659146 : WrappedFunction<Output>::clone () const
139 : {
140 : return std::make_unique<WrappedFunction<Output>>
141 659146 : (_sys, _fptr, _parameters, _varnum);
142 : }
143 :
144 :
145 : template <typename Output>
146 : inline
147 0 : void WrappedFunction<Output>::operator() (const Point & p,
148 : const Real /*time*/,
149 : DenseVector<Output> & output)
150 : {
151 0 : libmesh_assert(_fptr);
152 0 : libmesh_assert(_parameters);
153 :
154 : // We fill each entry of output with a single scalar component of
155 : // the data in our System
156 0 : libmesh_assert_equal_to (output.size(), _sys.n_components());
157 :
158 : // Loop over variables, then over each component in
159 : // vector-valued variables, evaluating each.
160 0 : const unsigned int n_vars = _sys.n_vars();
161 0 : for (unsigned int v = 0; v != n_vars; ++v)
162 : {
163 : const auto n_components =
164 0 : _sys.variable(v).n_components(_sys.get_mesh());
165 0 : if (n_components == 1)
166 0 : output(_sys.variable_scalar_number(v,0)) =
167 0 : _fptr(p, *_parameters, _sys.name(), _sys.variable_name(v));
168 : else
169 : {
170 : // Right now our only non-scalar variable type is the
171 : // SCALAR variables. The irony is priceless.
172 0 : libmesh_assert_equal_to (_sys.variable(v).type().family, SCALAR);
173 :
174 : // We pass the point (j,0,0) to an old-style fptr function
175 : // pointer to distinguish the different scalars within the
176 : // SCALAR variable.
177 0 : for (unsigned int j=0; j != n_components; ++j)
178 0 : output(_sys.variable_scalar_number(v,j)) =
179 0 : _fptr(Point(j,0,0), *_parameters,
180 0 : _sys.name(), _sys.variable_name(v));
181 : }
182 : }
183 0 : }
184 :
185 :
186 : template <typename Output>
187 : inline
188 14809902 : Output WrappedFunction<Output>::component (unsigned int i,
189 : const Point & p,
190 : Real /*time*/)
191 : {
192 1235435 : libmesh_assert(_fptr);
193 1235435 : libmesh_assert(_parameters);
194 :
195 : // Loop over variables, then over each component in
196 : // FEFamily SCALAR variables.
197 1235435 : unsigned int vc = 0;
198 14809902 : const unsigned int n_vars = _sys.n_vars();
199 14833134 : for (unsigned int v = 0; v != n_vars; ++v)
200 : {
201 14833134 : const auto & var_fe_type = _sys.variable_type(v);
202 14833134 : const auto n_components = _sys.variable(v).n_components(_sys.get_mesh());
203 14833134 : if (i >= vc + n_components)
204 : {
205 2112 : vc += n_components;
206 21120 : continue;
207 : }
208 :
209 14809902 : if (n_components > 1 && var_fe_type.family != SCALAR)
210 0 : libmesh_error_msg(
211 : "WrappedFunction::component cannot currently evaluate vector finite element families");
212 :
213 14809902 : if (n_components == 1)
214 16045337 : return _fptr(p, *_parameters, _sys.name(), _sys.variable_name(v));
215 : else
216 : {
217 0 : libmesh_assert_equal_to (_sys.variable(i).type().family, SCALAR);
218 :
219 : // We pass the point (j,0,0) to an old-style fptr function
220 : // pointer to distinguish the different scalars within the
221 : // SCALAR variable.
222 0 : for (unsigned int j=0; j != n_components; ++j)
223 0 : if (i == vc + j)
224 0 : return _fptr(Point(j,0,0), *_parameters,
225 0 : _sys.name(), _sys.variable_name(v));
226 : }
227 : }
228 :
229 0 : libmesh_error_msg("Component index " << i << " not found in system " << _sys.name());
230 : return Output();
231 : }
232 :
233 :
234 :
235 : } // namespace libMesh
236 :
237 : #endif // LIBMESH_WRAPPED_FUNCTION_H
|