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 : #include "libmesh/variable.h"
32 :
33 : // C++ includes
34 : #include <cstddef>
35 : #include <memory>
36 :
37 : namespace libMesh
38 : {
39 :
40 : /**
41 : * \brief Wrap a libMesh-style function pointer into a FunctionBase object.
42 : *
43 : * This class provides a wrapper with which to evaluate a
44 : * (libMesh-style) function pointer in a FunctionBase-compatible
45 : * interface. All overridden virtual functions are documented in
46 : * function_base.h.
47 : *
48 : * \author Roy Stogner
49 : * \date 2012
50 : * \note To wrap an ordinary function pointer use the AnalyticFunction class.
51 : */
52 : template <typename Output=Number>
53 : class WrappedFunction : public FunctionBase<Output>
54 : {
55 : public:
56 :
57 : /**
58 : * Constructor to wrap scalar-valued function pointers.
59 : */
60 805540 : WrappedFunction (const System & sys,
61 : Output fptr(const Point & p,
62 : const Parameters & parameters,
63 : const std::string & sys_name,
64 : const std::string & unknown_name) = nullptr,
65 : const Parameters * parameters = nullptr,
66 : unsigned int varnum=0)
67 781914 : : _sys(sys),
68 781914 : _fptr(fptr),
69 781914 : _parameters(parameters),
70 811110 : _varnum(varnum)
71 : {
72 437944 : this->_initialized = true;
73 613387 : if (!parameters)
74 0 : _parameters = &sys.get_equation_systems().parameters;
75 18056 : }
76 :
77 : /**
78 : * The move/copy ctor and destructor are defaulted for this class.
79 : */
80 : WrappedFunction (WrappedFunction &&) = default;
81 : WrappedFunction (const WrappedFunction &) = default;
82 1786801 : virtual ~WrappedFunction () = default;
83 :
84 : /**
85 : * This class contains a const reference so it can't be assigned.
86 : */
87 : WrappedFunction & operator= (const WrappedFunction &) = delete;
88 : WrappedFunction & operator= (WrappedFunction &&) = delete;
89 :
90 : virtual std::unique_ptr<FunctionBase<Output>> clone () const override;
91 :
92 : virtual Output operator() (const Point & p,
93 : const Real time = 0.) override;
94 :
95 : virtual void operator() (const Point & p,
96 : const Real time,
97 : DenseVector<Output> & output) override;
98 :
99 : virtual Output component (unsigned int i,
100 : const Point & p,
101 : Real time=0.) override;
102 :
103 : protected:
104 :
105 : const System & _sys;
106 :
107 : Output (*_fptr)(const Point & p,
108 : const Parameters & parameters,
109 : const std::string & sys_name,
110 : const std::string & unknown_name);
111 :
112 : const Parameters * _parameters;
113 :
114 : unsigned int _varnum;
115 : };
116 :
117 :
118 : // ------------------------------------------------------------
119 : // WrappedFunction inline methods
120 :
121 :
122 : template <typename Output>
123 : inline
124 0 : Output WrappedFunction<Output>::operator() (const Point & p,
125 : const Real /*time*/)
126 : {
127 0 : libmesh_assert(_fptr);
128 0 : libmesh_assert(_parameters);
129 0 : return _fptr(p,
130 0 : *_parameters,
131 0 : _sys.name(),
132 0 : _sys.variable_name(_varnum));
133 : }
134 :
135 :
136 : template <typename Output>
137 : inline
138 : std::unique_ptr<FunctionBase<Output>>
139 659146 : WrappedFunction<Output>::clone () const
140 : {
141 : return std::make_unique<WrappedFunction<Output>>
142 659146 : (_sys, _fptr, _parameters, _varnum);
143 : }
144 :
145 :
146 : template <typename Output>
147 : inline
148 0 : void WrappedFunction<Output>::operator() (const Point & p,
149 : const Real /*time*/,
150 : DenseVector<Output> & output)
151 : {
152 0 : libmesh_assert(_fptr);
153 0 : libmesh_assert(_parameters);
154 :
155 : // We fill each entry of output with a single scalar component of
156 : // the data in our System
157 0 : libmesh_assert_equal_to (output.size(), _sys.n_components());
158 :
159 : // Loop over variables, then over each component in
160 : // vector-valued variables, evaluating each.
161 0 : const unsigned int n_vars = _sys.n_vars();
162 0 : for (unsigned int v = 0; v != n_vars; ++v)
163 : {
164 : const auto n_components =
165 0 : _sys.variable(v).n_components(_sys.get_mesh());
166 0 : if (n_components == 1)
167 0 : output(_sys.variable_scalar_number(v,0)) =
168 0 : _fptr(p, *_parameters, _sys.name(), _sys.variable_name(v));
169 : else
170 : {
171 : // Right now our only non-scalar variable type is the
172 : // SCALAR variables. The irony is priceless.
173 0 : libmesh_assert_equal_to (_sys.variable(v).type().family, SCALAR);
174 :
175 : // We pass the point (j,0,0) to an old-style fptr function
176 : // pointer to distinguish the different scalars within the
177 : // SCALAR variable.
178 0 : for (unsigned int j=0; j != n_components; ++j)
179 0 : output(_sys.variable_scalar_number(v,j)) =
180 0 : _fptr(Point(j,0,0), *_parameters,
181 0 : _sys.name(), _sys.variable_name(v));
182 : }
183 : }
184 0 : }
185 :
186 :
187 : template <typename Output>
188 : inline
189 14809902 : Output WrappedFunction<Output>::component (unsigned int i,
190 : const Point & p,
191 : Real /*time*/)
192 : {
193 1235435 : libmesh_assert(_fptr);
194 1235435 : libmesh_assert(_parameters);
195 :
196 : // Loop over variables, then over each component in
197 : // FEFamily SCALAR variables.
198 1235435 : unsigned int vc = 0;
199 14809902 : const unsigned int n_vars = _sys.n_vars();
200 14833134 : for (unsigned int v = 0; v != n_vars; ++v)
201 : {
202 14833134 : const auto & var_fe_type = _sys.variable_type(v);
203 14833134 : const auto n_components = _sys.variable(v).n_components(_sys.get_mesh());
204 14833134 : if (i >= vc + n_components)
205 : {
206 2112 : vc += n_components;
207 21120 : continue;
208 : }
209 :
210 14809902 : if (n_components > 1 && var_fe_type.family != SCALAR)
211 0 : libmesh_error_msg(
212 : "WrappedFunction::component cannot currently evaluate vector finite element families");
213 :
214 14809902 : if (n_components == 1)
215 14809902 : return _fptr(p, *_parameters, _sys.name(), _sys.variable_name(v));
216 : else
217 : {
218 0 : libmesh_assert_equal_to (_sys.variable(i).type().family, SCALAR);
219 :
220 : // We pass the point (j,0,0) to an old-style fptr function
221 : // pointer to distinguish the different scalars within the
222 : // SCALAR variable.
223 0 : for (unsigned int j=0; j != n_components; ++j)
224 0 : if (i == vc + j)
225 0 : return _fptr(Point(j,0,0), *_parameters,
226 0 : _sys.name(), _sys.variable_name(v));
227 : }
228 : }
229 :
230 0 : libmesh_error_msg("Component index " << i << " not found in system " << _sys.name());
231 : return Output();
232 : }
233 :
234 :
235 :
236 : } // namespace libMesh
237 :
238 : #endif // LIBMESH_WRAPPED_FUNCTION_H
|