libMesh
composite_function.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2017 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/libmesh.h"
25 #include "libmesh/point.h"
26 
27 // C++ includes
28 #include <algorithm>
29 #include <utility>
30 #include <vector>
31 
32 namespace libMesh
33 {
34 
43 template <typename Output=Number>
44 class CompositeFunction : public FunctionBase<Output>
45 {
46 public:
47  explicit
49 
51  {
52  for (std::size_t i=0; i != subfunctions.size(); ++i)
53  delete subfunctions[i];
54  }
55 
62  const std::vector<unsigned int> & index_map)
63  {
64  const unsigned int subfunction_index = subfunctions.size();
65  libmesh_assert_equal_to(subfunctions.size(), index_maps.size());
66 
67  subfunctions.push_back(f.clone().release());
68  index_maps.push_back(index_map);
69 
70  unsigned int max_index =
71  *std::max_element(index_map.begin(), index_map.end());
72 
73  if (max_index >= reverse_index_map.size())
74  reverse_index_map.resize
75  (max_index+1, std::make_pair(libMesh::invalid_uint,
77 
78  for (std::size_t j=0; j != index_map.size(); ++j)
79  {
80  libmesh_assert_less(index_map[j], reverse_index_map.size());
81  libmesh_assert_equal_to(reverse_index_map[index_map[j]].first,
83  libmesh_assert_equal_to(reverse_index_map[index_map[j]].second,
85  reverse_index_map[index_map[j]] =
86  std::make_pair(subfunction_index, j);
87  }
88 
89  // Now check for time dependence
90  // We only check the function we just added instead of researching all subfunctions
91  // If this is the first subfunction, then that determines the time-dependence.
92  if (subfunctions.size() == 1)
94 
95  // Otherwise, we have more than 1 function already.
96  // If _is_time_dependent is true, then one of the previous
97  // subfunctions is time-dependent and thus this CompositeFunction
98  // time-dependent. If _is_time_dependent is false, then the subfunction
99  // just added determines the time-dependence.
100  else if (!this->_is_time_dependent)
102  }
103 
104  virtual Output operator() (const Point & p,
105  const Real time = 0) libmesh_override
106  {
107  return this->component(0,p,time);
108  }
109 
110  virtual void operator() (const Point & p,
111  const Real time,
112  DenseVector<Output> & output) libmesh_override
113  {
114  libmesh_assert_greater_equal (output.size(),
115  reverse_index_map.size());
116 
117  // Necessary in case we have output components not covered by
118  // any subfunctions
119  output.zero();
120 
121  DenseVector<Output> temp;
122  for (std::size_t i=0; i != subfunctions.size(); ++i)
123  {
124  temp.resize(index_maps[i].size());
125  (*subfunctions[i])(p, time, temp);
126  for (std::size_t j=0; j != temp.size(); ++j)
127  output(index_maps[i][j]) = temp(j);
128  }
129  }
130 
131  virtual Output component (unsigned int i,
132  const Point & p,
133  Real time) libmesh_override
134  {
135  if (i >= reverse_index_map.size() ||
137  return 0;
138 
139  libmesh_assert_less(reverse_index_map[i].first,
140  subfunctions.size());
141  libmesh_assert_not_equal_to(reverse_index_map[i].second,
143  return subfunctions[reverse_index_map[i].first]->
144  component(reverse_index_map[i].second,p,time);
145  }
146 
147  virtual UniquePtr<FunctionBase<Output>> clone() const libmesh_override
148  {
149  CompositeFunction * returnval = new CompositeFunction();
150  for (std::size_t i=0; i != subfunctions.size(); ++i)
151  returnval->attach_subfunction(*subfunctions[i], index_maps[i]);
152  return UniquePtr<FunctionBase<Output>> (returnval);
153  }
154 
155  unsigned int n_subfunctions () const
156  {
157  return subfunctions.size();
158  }
159 
160  unsigned int n_components () const
161  {
162  return reverse_index_map.size();
163  }
164 
165 private:
166  // list of functions which fill in our values
167  std::vector<FunctionBase<Output> *> subfunctions;
168 
169  // for each function, list of which global indices it fills in
170  std::vector<std::vector<unsigned int>> index_maps;
171 
172  // for each global index, which local index of which function is it?
173  std::vector<std::pair<unsigned int, unsigned int>> reverse_index_map;
174 };
175 
176 
177 } // namespace libMesh
178 
179 #endif // LIBMESH_COMPOSITE_FUNCTION_H
unsigned int n_subfunctions() const
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 that subfunction to the indices of the...
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value.
Definition: libmesh.h:184
virtual Output operator()(const Point &p, const Real time=0) libmesh_override
void resize(const unsigned int n)
Resize the vector.
Definition: dense_vector.h:350
The libMesh namespace provides an interface to certain functionality in the library.
virtual unsigned int size() const libmesh_override
Definition: dense_vector.h:87
unsigned int n_components() const
bool is_time_dependent() const
std::vector< FunctionBase< Output > * > subfunctions
std::unique_ptr< T > UniquePtr
Definition: auto_ptr.h:46
Function which is a function of another function.
bool _is_time_dependent
Cache whether or not this function is actually time-dependent.
virtual Output component(unsigned int i, const Point &p, Real time) libmesh_override
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< std::pair< unsigned int, unsigned int > > reverse_index_map
virtual UniquePtr< FunctionBase< Output > > clone() const libmesh_override
std::vector< std::vector< unsigned int > > index_maps
virtual UniquePtr< FunctionBase< Output > > clone() const =0
Defines a dense vector for use in Finite Element-type computations.
This is the base class for functor-like classes.
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38