composite_fem_function.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 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_FEM_FUNCTION_H
19 #define LIBMESH_COMPOSITE_FEM_FUNCTION_H
20 
21 // libMesh includes
22 #include "libmesh/dense_vector.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 
42 template <typename Output=Number>
43 class CompositeFEMFunction : public FEMFunctionBase<Output>
44 {
45 public:
46  explicit
47  CompositeFEMFunction () = default;
48 
54 
59  CompositeFEMFunction (const CompositeFEMFunction &) = delete;
61 
65  virtual ~CompositeFEMFunction () = default;
66 
73  const std::vector<unsigned int> & index_map)
74  {
75  const unsigned int subfunction_index =
76  cast_int<unsigned int>(subfunctions.size());
77  libmesh_assert_equal_to(subfunctions.size(), index_maps.size());
78 
79  subfunctions.push_back(f.clone());
80  index_maps.push_back(index_map);
81 
82  unsigned int max_index =
83  *std::max_element(index_map.begin(), index_map.end());
84 
85  if (max_index >= reverse_index_map.size())
86  reverse_index_map.resize
87  (max_index+1, std::make_pair(libMesh::invalid_uint,
89 
90  for (std::size_t j=0; j != index_map.size(); ++j)
91  {
92  libmesh_assert_less(index_map[j], reverse_index_map.size());
93  libmesh_assert_equal_to(reverse_index_map[index_map[j]].first,
95  libmesh_assert_equal_to(reverse_index_map[index_map[j]].second,
97  reverse_index_map[index_map[j]] =
98  std::make_pair(subfunction_index, j);
99  }
100  }
101 
102  virtual Output operator() (const FEMContext & c,
103  const Point & p,
104  const Real time = 0) override
105  {
106  return this->component(c,0,p,time);
107  }
108 
109  virtual void operator() (const FEMContext & c,
110  const Point & p,
111  const Real time,
112  DenseVector<Output> & output) 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(cast_int<unsigned int>(index_maps[i].size()));
125  (*subfunctions[i])(c, p, time, temp);
126  for (unsigned int j=0; j != temp.size(); ++j)
127  output(index_maps[i][j]) = temp(j);
128  }
129  }
130 
131  virtual Output component (const FEMContext & c,
132  unsigned int i,
133  const Point & p,
134  Real time) override
135  {
136  if (i >= reverse_index_map.size() ||
138  return 0;
139 
140  libmesh_assert_less(reverse_index_map[i].first,
141  subfunctions.size());
142  libmesh_assert_not_equal_to(reverse_index_map[i].second,
144  return subfunctions[reverse_index_map[i].first]->
145  component(c, reverse_index_map[i].second, p, time);
146  }
147 
148  virtual std::unique_ptr<FEMFunctionBase<Output>> clone() const override
149  {
150  CompositeFEMFunction * returnval = new CompositeFEMFunction();
151  for (std::size_t i=0; i != subfunctions.size(); ++i)
152  returnval->attach_subfunction(*subfunctions[i], index_maps[i]);
153  return std::unique_ptr<FEMFunctionBase<Output>> (returnval);
154  }
155 
156  unsigned int n_subfunctions () const
157  {
158  return subfunctions.size();
159  }
160 
161  unsigned int n_components () const
162  {
163  return reverse_index_map.size();
164  }
165 
166 private:
167  // list of functions which fill in our values
168  std::vector<std::unique_ptr<FEMFunctionBase<Output>>> subfunctions;
169 
170  // for each function, list of which global indices it fills in
171  std::vector<std::vector<unsigned int>> index_maps;
172 
173  // for each global index, which local index of which function is it?
174  std::vector<std::pair<unsigned int, unsigned int>> reverse_index_map;
175 };
176 
177 
178 } // namespace libMesh
179 
180 #endif // LIBMESH_COMPOSITE_FEM_FUNCTION_H
virtual unsigned int size() const override
Definition: dense_vector.h:92
const unsigned int invalid_uint
Definition: libmesh.h:245
std::vector< std::pair< unsigned int, unsigned int > > reverse_index_map
void resize(const unsigned int n)
Definition: dense_vector.h:355
void attach_subfunction(const FEMFunctionBase< Output > &f, const std::vector< unsigned int > &index_map)
virtual std::unique_ptr< FEMFunctionBase< Output > > clone() const override
virtual Output component(const FEMContext &c, unsigned int i, const Point &p, Real time) override
CompositeFEMFunction & operator=(CompositeFEMFunction &&)=default
std::vector< std::vector< unsigned int > > index_maps
FEMFunction which is a function of another function.
std::vector< std::unique_ptr< FEMFunctionBase< Output > > > subfunctions
virtual Output operator()(const FEMContext &c, const Point &p, const Real time=0) override
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual ~CompositeFEMFunction()=default
virtual std::unique_ptr< FEMFunctionBase< Output > > clone() const =0
A geometric point in (x,y,z) space.
Definition: point.h:38
virtual void zero() override
Definition: dense_vector.h:379