libMesh
fdm_gradient.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 #ifndef LIBMESH_FDM_GRADIENT_H
19 #define LIBMESH_FDM_GRADIENT_H
20 
21 // libMesh includes
22 #include "libmesh/fem_function_base.h"
23 #include "libmesh/libmesh_common.h"
24 #include "libmesh/tensor_tools.h"
25 
26 namespace libMesh
27 {
28 
29 template <typename GradType>
30 class FDMGradient : public FEMFunctionBase<GradType>
31 {
32 public:
34 
36  Real eps) :
37  _val_func(value_func.clone()), _eps(eps)
38  {}
39 
40  virtual void init_context (const FEMContext & c) override
41  { _val_func->init_context(c); }
42 
43  virtual std::unique_ptr<FEMFunctionBase<GradType>> clone () const override
44  { return std::make_unique<FDMGradient<GradType>>(*_val_func, _eps); }
45 
46  virtual GradType operator() (const FEMContext & c,
47  const Point & p,
48  const Real time = 0.) override
49  {
50  GradType g;
51 
52  auto & val = *_val_func;
53 
54  Real one_over_dim = Real(0.5) / _eps;
55 
56  g(0) = (val(c, p+Point(_eps), time) -
57  val(c, p+Point(-_eps), time)) * one_over_dim;
58 #if LIBMESH_DIM > 1
59  g(1) = (val(c, p+Point(0,_eps), time) -
60  val(c, p+Point(0,-_eps), time)) * one_over_dim;
61 #endif
62 #if LIBMESH_DIM > 2
63  g(2) = (val(c, p+Point(0,0,_eps), time) -
64  val(c, p+Point(0,0,-_eps), time)) * one_over_dim;
65 #endif
66 
67  return g;
68  }
69 
70  virtual void operator() (const FEMContext & c,
71  const Point & p,
72  const Real time,
73  DenseVector<GradType> & output) override
74  {
75  auto sz = output.size();
77 
78  auto & val = *_val_func;
79 
80  val(c, p+Point(_eps), time, v);
81  for (auto i : make_range(sz))
82  output(i)(0) = v(i);
83 
84  val(c, p+Point(-_eps), time, v);
85  for (auto i : make_range(sz))
86  {
87  output(i)(0) -= v(i);
88  output(i)(0) /= 2;
89  }
90 
91 #if LIBMESH_DIM > 1
92  val(c, p+Point(0,_eps), time, v);
93  for (auto i : make_range(sz))
94  output(i)(1) = v(i);
95 
96  val(c, p+Point(0,-_eps), time, v);
97  for (auto i : make_range(sz))
98  {
99  output(i)(1) -= v(i);
100  output(i)(1) /= 2;
101  }
102 #endif
103 #if LIBMESH_DIM > 2
104  val(c, p+Point(0,0,_eps), time, v);
105  for (auto i : make_range(sz))
106  output(i)(2) = v(i);
107 
108  val(c, p+Point(0,0,-_eps), time, v);
109  for (auto i : make_range(sz))
110  {
111  output(i)(2) -= v(i);
112  output(i)(2) /= 2;
113  }
114 #endif
115  }
116 
117 
118  virtual GradType component (const FEMContext & c,
119  unsigned int i,
120  const Point & p,
121  Real time) override
122  {
123  GradType g;
124 
125  auto & val = *_val_func;
126 
127  Real one_over_dim = Real(0.5) / _eps;
128 
129  g(0) = (val.component(c, i, p+Point(_eps), time) -
130  val.component(c, i, p+Point(-_eps), time)) * one_over_dim;
131 #if LIBMESH_DIM > 1
132  g(1) = (val.component(c, i, p+Point(0,_eps), time) -
133  val.component(c, i, p+Point(0,-_eps), time)) * one_over_dim;
134 #endif
135 #if LIBMESH_DIM > 2
136  g(2) = (val.component(c, i, p+Point(0,0,_eps), time) -
137  val.component(c, i, p+Point(0,0,-_eps), time)) * one_over_dim;
138 #endif
139 
140  return g;
141  }
142 
143 private:
144 
145  std::unique_ptr<FEMFunctionBase<ValType>> _val_func;
146 
148 };
149 
150 
151 } // namespace libMesh
152 
153 #endif // LIBMESH_FDM_GRADIENT_H
virtual void init_context(const FEMContext &c) override
Prepares a context object for use.
Definition: fdm_gradient.h:40
std::unique_ptr< FEMFunctionBase< ValType > > _val_func
Definition: fdm_gradient.h:145
The libMesh namespace provides an interface to certain functionality in the library.
This class provides all data required for a physics package (e.g.
Definition: fem_context.h:62
FDMGradient(FEMFunctionBase< ValType > &value_func, Real eps)
Definition: fdm_gradient.h:35
virtual GradType component(const FEMContext &c, unsigned int i, const Point &p, Real time) override
Definition: fdm_gradient.h:118
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
TensorTools::DecrementRank< GradType >::type ValType
Definition: fdm_gradient.h:33
virtual GradType operator()(const FEMContext &c, const Point &p, const Real time=0.) override
Definition: fdm_gradient.h:46
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:140
virtual unsigned int size() const override final
Definition: dense_vector.h:104
Defines a dense vector for use in Finite Element-type computations.
Definition: dof_map.h:74
virtual std::unique_ptr< FEMFunctionBase< GradType > > clone() const override
Definition: fdm_gradient.h:43
FEMFunctionBase is a base class from which users can derive in order to define "function-like" object...
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39