libMesh
composite_function.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 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_COMPOSITE_FUNCTION_H
19 #define LIBMESH_COMPOSITE_FUNCTION_H
20 
21 // libMesh includes
22 #include "libmesh/dense_vector.h"
23 #include "libmesh/function_base.h"
24 #include "libmesh/int_range.h"
25 #include "libmesh/libmesh.h"
26 #include "libmesh/point.h"
27 
28 // C++ includes
29 #include <algorithm>
30 #include <utility>
31 #include <vector>
32 
33 namespace libMesh
34 {
35 
48 template <typename Output=Number>
49 class CompositeFunction : public FunctionBase<Output>
50 {
51 public:
52  explicit
53  CompositeFunction () = default;
54 
58  CompositeFunction (CompositeFunction &&) = default;
60 
65  CompositeFunction (const CompositeFunction &) = delete;
67 
71  virtual ~CompositeFunction () = default;
72 
83  const std::vector<unsigned int> & index_map)
84  {
85  const unsigned int subfunction_index =
86  cast_int<unsigned int>(subfunctions.size());
87  libmesh_assert_equal_to(subfunctions.size(), index_maps.size());
88 
89  subfunctions.push_back(f.clone());
90  index_maps.push_back(index_map);
91 
92  unsigned int max_index =
93  *std::max_element(index_map.begin(), index_map.end());
94 
95  if (max_index >= reverse_index_map.size())
96  reverse_index_map.resize
97  (max_index+1, std::make_pair(libMesh::invalid_uint,
99 
100  for (auto j : index_range(index_map))
101  {
102  libmesh_assert_less(index_map[j], reverse_index_map.size());
103  libmesh_assert_equal_to(reverse_index_map[index_map[j]].first,
105  libmesh_assert_equal_to(reverse_index_map[index_map[j]].second,
107  reverse_index_map[index_map[j]] =
108  std::make_pair(subfunction_index, j);
109  }
110 
111  // Now check for time dependence
112  // We only check the function we just added instead of researching all subfunctions
113  // If this is the first subfunction, then that determines the time-dependence.
114  if (subfunctions.size() == 1)
116 
117  // Otherwise, we have more than 1 function already.
118  // If _is_time_dependent is true, then one of the previous
119  // subfunctions is time-dependent and thus this CompositeFunction
120  // time-dependent. If _is_time_dependent is false, then the subfunction
121  // just added determines the time-dependence.
122  else if (!this->_is_time_dependent)
124  }
125 
126  virtual Output operator() (const Point & p,
127  const Real time = 0) override
128  {
129  return this->component(0,p,time);
130  }
131 
132  virtual void operator() (const Point & p,
133  const Real time,
134  DenseVector<Output> & output) override
135  {
136  libmesh_assert_greater_equal (output.size(),
137  reverse_index_map.size());
138 
139  // Necessary in case we have output components not covered by
140  // any subfunctions
141  output.zero();
142 
143  DenseVector<Output> temp;
144  for (auto i : index_range(subfunctions))
145  {
146  temp.resize(cast_int<unsigned int>(index_maps[i].size()));
147  (*subfunctions[i])(p, time, temp);
148  for (auto j : index_range(temp))
149  output(index_maps[i][j]) = temp(j);
150  }
151  }
152 
153  virtual Output component (unsigned int i,
154  const Point & p,
155  Real time) override
156  {
157  if (i >= reverse_index_map.size() ||
159  return 0;
160 
161  libmesh_assert_less(reverse_index_map[i].first,
162  subfunctions.size());
163  libmesh_assert_not_equal_to(reverse_index_map[i].second,
165  return subfunctions[reverse_index_map[i].first]->
166  component(reverse_index_map[i].second,p,time);
167  }
168 
169  virtual std::unique_ptr<FunctionBase<Output>> clone() const override
170  {
171  CompositeFunction * returnval = new CompositeFunction();
172  for (auto i : index_range(subfunctions))
173  returnval->attach_subfunction(*subfunctions[i], index_maps[i]);
174  return std::unique_ptr<FunctionBase<Output>> (returnval);
175  }
176 
177  unsigned int n_subfunctions () const
178  {
179  return subfunctions.size();
180  }
181 
182  unsigned int n_components () const
183  {
184  return reverse_index_map.size();
185  }
186 
187 private:
188  // list of functions which fill in our values
189  std::vector<std::unique_ptr<FunctionBase<Output>>> subfunctions;
190 
191  // for each function, list of which global indices it fills in
192  std::vector<std::vector<unsigned int>> index_maps;
193 
194  // for each global index, which local index of which function is it?
195  std::vector<std::pair<unsigned int, unsigned int>> reverse_index_map;
196 };
197 
198 
199 } // namespace libMesh
200 
201 #endif // LIBMESH_COMPOSITE_FUNCTION_H
libMesh::FunctionBase
Base class for functors that can be evaluated at a point and (optionally) time.
Definition: dirichlet_boundaries.h:44
libMesh::invalid_uint
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value.
Definition: libmesh.h:249
libMesh::CompositeFunction
A function that returns a vector whose components are defined by multiple functions.
Definition: composite_function.h:49
libMesh::FunctionBase::is_time_dependent
bool is_time_dependent() const
Definition: function_base.h:219
libMesh::FunctionBase::clone
virtual std::unique_ptr< FunctionBase< Output > > clone() const =0
libMesh::index_range
IntRange< std::size_t > index_range(const std::vector< T > &vec)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:106
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::DenseVector::zero
virtual void zero() override
Set every element in the vector to 0.
Definition: dense_vector.h:379
libMesh::FunctionBase::_is_time_dependent
bool _is_time_dependent
Cache whether or not this function is actually time-dependent.
Definition: function_base.h:184
libMesh::CompositeFunction::CompositeFunction
CompositeFunction()=default
libMesh::CompositeFunction::reverse_index_map
std::vector< std::pair< unsigned int, unsigned int > > reverse_index_map
Definition: composite_function.h:195
libMesh::CompositeFunction::clone
virtual std::unique_ptr< FunctionBase< Output > > clone() const override
Definition: composite_function.h:169
libMesh::CompositeFunction::operator=
CompositeFunction & operator=(CompositeFunction &&)=default
libMesh::CompositeFunction::subfunctions
std::vector< std::unique_ptr< FunctionBase< Output > > > subfunctions
Definition: composite_function.h:189
libMesh::CompositeFunction::~CompositeFunction
virtual ~CompositeFunction()=default
The subfunctions vector is automatically cleaned up.
libMesh::CompositeFunction::component
virtual Output component(unsigned int i, const Point &p, Real time) override
Definition: composite_function.h:153
libMesh::Point
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38
libMesh::CompositeFunction::index_maps
std::vector< std::vector< unsigned int > > index_maps
Definition: composite_function.h:192
libMesh::DenseVector::size
virtual unsigned int size() const override
Definition: dense_vector.h:92
libMesh::CompositeFunction::n_subfunctions
unsigned int n_subfunctions() const
Definition: composite_function.h:177
libMesh::DenseVector::resize
void resize(const unsigned int n)
Resize the vector.
Definition: dense_vector.h:355
libMesh::CompositeFunction::attach_subfunction
void attach_subfunction(const FunctionBase< Output > &f, const std::vector< unsigned int > &index_map)
Attach a new subfunction, along with a map from the indices of the attached subfunction to the indice...
Definition: composite_function.h:82
libMesh::CompositeFunction::n_components
unsigned int n_components() const
Definition: composite_function.h:182
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::DenseVector< Output >
libMesh::CompositeFunction::operator()
virtual Output operator()(const Point &p, const Real time=0) override
Definition: composite_function.h:126