libMesh
wrapped_function.h
Go to the documentation of this file.
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 
51 template <typename Output=Number>
52 class WrappedFunction : public FunctionBase<Output>
53 {
54 public:
55 
59  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  : _sys(sys),
67  _fptr(fptr),
68  _parameters(parameters),
69  _varnum(varnum)
70  {
71  this->_initialized = true;
72  if (!parameters)
74  }
75 
79  WrappedFunction (WrappedFunction &&) = default;
80  WrappedFunction (const WrappedFunction &) = default;
81  virtual ~WrappedFunction () = default;
82 
86  WrappedFunction & operator= (const 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 
112 
113  unsigned int _varnum;
114 };
115 
116 
117 // ------------------------------------------------------------
118 // WrappedFunction inline methods
119 
120 
121 template <typename Output>
122 inline
124  const Real /*time*/)
125 {
126  libmesh_assert(_fptr);
127  libmesh_assert(_parameters);
128  return _fptr(p,
129  *_parameters,
130  _sys.name(),
131  _sys.variable_name(_varnum));
132 }
133 
134 
135 template <typename Output>
136 inline
137 std::unique_ptr<FunctionBase<Output>>
139 {
140  return std::make_unique<WrappedFunction<Output>>
141  (_sys, _fptr, _parameters, _varnum);
142 }
143 
144 
145 template <typename Output>
146 inline
148  const Real /*time*/,
149  DenseVector<Output> & output)
150 {
151  libmesh_assert(_fptr);
152  libmesh_assert(_parameters);
153 
154  // We fill each entry of output with a single scalar component of
155  // the data in our System
156  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  const unsigned int n_vars = _sys.n_vars();
161  for (unsigned int v = 0; v != n_vars; ++v)
162  {
163  const auto n_components =
164  _sys.variable(v).n_components(_sys.get_mesh());
165  if (n_components == 1)
166  output(_sys.variable_scalar_number(v,0)) =
167  _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  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  for (unsigned int j=0; j != n_components; ++j)
178  output(_sys.variable_scalar_number(v,j)) =
179  _fptr(Point(j,0,0), *_parameters,
180  _sys.name(), _sys.variable_name(v));
181  }
182  }
183 }
184 
185 
186 template <typename Output>
187 inline
188 Output WrappedFunction<Output>::component (unsigned int i,
189  const Point & p,
190  Real /*time*/)
191 {
192  libmesh_assert(_fptr);
193  libmesh_assert(_parameters);
194 
195  // Loop over variables, then over each component in
196  // FEFamily SCALAR variables.
197  unsigned int vc = 0;
198  const unsigned int n_vars = _sys.n_vars();
199  for (unsigned int v = 0; v != n_vars; ++v)
200  {
201  const auto & var_fe_type = _sys.variable_type(v);
202  const auto n_components = _sys.variable(v).n_components(_sys.get_mesh());
203  if (i >= vc + n_components)
204  {
205  vc += n_components;
206  continue;
207  }
208 
209  if (n_components > 1 && var_fe_type.family != SCALAR)
210  libmesh_error_msg(
211  "WrappedFunction::component cannot currently evaluate vector finite element families");
212 
213  if (n_components == 1)
214  return _fptr(p, *_parameters, _sys.name(), _sys.variable_name(v));
215  else
216  {
217  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  for (unsigned int j=0; j != n_components; ++j)
223  if (i == vc + j)
224  return _fptr(Point(j,0,0), *_parameters,
225  _sys.name(), _sys.variable_name(v));
226  }
227  }
228 
229  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
Wrap a libMesh-style function pointer into a FunctionBase object.
virtual Output component(unsigned int i, const Point &p, Real time=0.) override
This class provides the ability to map between arbitrary, user-defined strings and several data types...
Definition: parameters.h:67
virtual Output operator()(const Point &p, const Real time=0.) override
Output(* _fptr)(const Point &p, const Parameters &parameters, const std::string &sys_name, const std::string &unknown_name)
const EquationSystems & get_equation_systems() const
Definition: system.h:721
bool _initialized
When init() was called so that everything is ready for calls to operator() (...), then this bool is t...
The libMesh namespace provides an interface to certain functionality in the library.
Number fptr(const Point &p, const Parameters &, const std::string &libmesh_dbg_var(sys_name), const std::string &unknown_name)
Definition: projection.C:80
unsigned int n_vars
Manages consistently variables, degrees of freedom, and coefficient vectors.
Definition: system.h:96
virtual std::unique_ptr< FunctionBase< Output > > clone() const override
libmesh_assert(ctx)
WrappedFunction & operator=(const WrappedFunction &)=delete
This class contains a const reference so it can&#39;t be assigned.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual ~WrappedFunction()=default
const Parameters * _parameters
Parameters parameters
Data structure holding arbitrary parameters.
WrappedFunction(const System &sys, Output fptr(const Point &p, const Parameters &parameters, const std::string &sys_name, const std::string &unknown_name)=nullptr, const Parameters *parameters=nullptr, unsigned int varnum=0)
Constructor to wrap scalar-valued function pointers.
virtual unsigned int size() const override final
Definition: dense_vector.h:104
Base class for functors that can be evaluated at a point and (optionally) time.
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39