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