$extrastylesheet
wrapped_function.h
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 
00020 #ifndef LIBMESH_WRAPPED_FUNCTION_H
00021 #define LIBMESH_WRAPPED_FUNCTION_H
00022 
00023 // Local Includes
00024 #include "libmesh/dense_vector.h"
00025 #include "libmesh/equation_systems.h"
00026 #include "libmesh/function_base.h"
00027 #include "libmesh/libmesh_common.h"
00028 #include "libmesh/point.h"
00029 #include "libmesh/system.h"
00030 
00031 // C++ includes
00032 #include <cstddef>
00033 
00034 namespace libMesh
00035 {
00036 
00037 
00041 // ------------------------------------------------------------
00042 // WrappedFunction class definition
00043 template <typename Output=Number>
00044 class WrappedFunction : public FunctionBase<Output>
00045 {
00046 public:
00047 
00051   WrappedFunction (const System &sys,
00052                    Output fptr(const Point& p,
00053                                const Parameters& parameters,
00054                                const std::string& sys_name,
00055                                const std::string& unknown_name) = NULL,
00056                    const Parameters* parameters = NULL,
00057                    unsigned int varnum=0)
00058     : _sys(sys),
00059       _fptr(fptr),
00060       _parameters(parameters),
00061       _varnum(varnum)
00062   {
00063     this->_initialized = true;
00064     if (!parameters)
00065       _parameters = &sys.get_equation_systems().parameters;
00066   }
00067 
00068   virtual UniquePtr<FunctionBase<Output> > clone () const;
00069 
00074   virtual Output operator() (const Point& p,
00075                              const Real time = 0.);
00076 
00082   virtual void operator() (const Point& p,
00083                            const Real time,
00084                            DenseVector<Output>& output);
00085 
00090   virtual Output component (unsigned int i,
00091                             const Point& p,
00092                             Real time=0.);
00093 
00094 protected:
00095 
00096   const System& _sys;
00097 
00098   Output (*_fptr)(const Point& p,
00099                   const Parameters& parameters,
00100                   const std::string& sys_name,
00101                   const std::string& unknown_name);
00102 
00103   const Parameters* _parameters;
00104 
00105   unsigned int _varnum;
00106 };
00107 
00108 
00109 // ------------------------------------------------------------
00110 // WrappedFunction inline methods
00111 
00112 
00113 template <typename Output>
00114 inline
00115 Output WrappedFunction<Output>::operator() (const Point& p,
00116                                             const Real /*time*/)
00117 {
00118   libmesh_assert(_fptr);
00119   libmesh_assert(_parameters);
00120   return _fptr(p,
00121                *_parameters,
00122                _sys.name(),
00123                _sys.variable_name(_varnum));
00124 }
00125 
00126 
00127 template <typename Output>
00128 inline
00129 UniquePtr<FunctionBase<Output> >
00130 WrappedFunction<Output>::clone () const
00131 {
00132   return UniquePtr<FunctionBase<Output> >
00133     (new WrappedFunction<Output>
00134      (_sys, _fptr, _parameters, _varnum));
00135 }
00136 
00137 
00143 template <typename Output>
00144 inline
00145 void WrappedFunction<Output>::operator() (const Point& p,
00146                                           const Real /*time*/,
00147                                           DenseVector<Output>& output)
00148 {
00149   libmesh_assert(_fptr);
00150   libmesh_assert(_parameters);
00151 
00152   // We fill each entry of output with a single scalar component of
00153   // the data in our System
00154   libmesh_assert_equal_to (output.size(), _sys.n_components());
00155 
00156   // Loop over variables, then over each component in
00157   // vector-valued variables, evaluating each.
00158   const unsigned int n_vars = _sys.n_vars();
00159   for (unsigned int v = 0; v != n_vars; ++v)
00160     {
00161       const unsigned int n_components =
00162         _sys.variable(v).n_components();
00163       if (n_components == 1)
00164         output(_sys.variable_scalar_number(v,0)) =
00165           _fptr(p, *_parameters, _sys.name(), _sys.variable_name(v));
00166       else
00167         {
00168           // Right now our only non-scalar variable type is the
00169           // SCALAR variables.  The irony is priceless.
00170           libmesh_assert_equal_to (_sys.variable(v).type().family, SCALAR);
00171 
00172           // We pass the point (j,0,0) to an old-style fptr function
00173           // pointer to distinguish the different scalars within the
00174           // SCALAR variable.
00175           for (unsigned int j=0; j != n_components; ++j)
00176             output(_sys.variable_scalar_number(v,j)) =
00177               _fptr(Point(j,0,0), *_parameters,
00178                     _sys.name(), _sys.variable_name(v));
00179         }
00180     }
00181 }
00182 
00183 
00188 template <typename Output>
00189 inline
00190 Output WrappedFunction<Output>::component (unsigned int i,
00191                                            const Point& p,
00192                                            Real /*time*/)
00193 {
00194   libmesh_assert(_fptr);
00195   libmesh_assert(_parameters);
00196 
00197   // Loop over variables, then over each component in
00198   // vector-valued variables.
00199   const unsigned int n_vars = _sys.n_vars();
00200   for (unsigned int v = 0; v != n_vars; ++v)
00201     {
00202       const unsigned int n_components =
00203         _sys.variable(v).n_components();
00204       if (n_components == 1 &&
00205           i == _sys.variable_scalar_number(v,0))
00206         return _fptr(p, *_parameters, _sys.name(), _sys.variable_name(v));
00207       else if (i >= _sys.variable_scalar_number(v,0) &&
00208                i <= _sys.variable_scalar_number(v,n_components-1))
00209         {
00210           // Right now our only non-scalar variable type is the
00211           // SCALAR variables.  The irony is priceless.
00212           libmesh_assert_equal_to (_sys.variable(i).type().family, SCALAR);
00213 
00214           // We pass the point (j,0,0) to an old-style fptr function
00215           // pointer to distinguish the different scalars within the
00216           // SCALAR variable.
00217           for (unsigned int j=0; j != n_components; ++j)
00218             if (i == _sys.variable_scalar_number(v,j))
00219               return _fptr(Point(j,0,0), *_parameters,
00220                            _sys.name(), _sys.variable_name(v));
00221         }
00222     }
00223 
00224   libmesh_error_msg("Component index " << i << " not found in system " << _sys.name());
00225   return Output();
00226 }
00227 
00228 
00229 
00230 } // namespace libMesh
00231 
00232 #endif // LIBMESH_WRAPPED_FUNCTION_H