$extrastylesheet
00001 //-------------// The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 #ifndef LIBMESH_COMPOSITE_FUNCTION_H 00019 #define LIBMESH_COMPOSITE_FUNCTION_H 00020 00021 // libMesh includes 00022 #include "libmesh/dense_vector.h" 00023 #include "libmesh/function_base.h" 00024 #include "libmesh/libmesh.h" 00025 #include "libmesh/point.h" 00026 00027 // C++ includes 00028 #include <algorithm> 00029 #include <utility> 00030 #include <vector> 00031 00032 namespace libMesh 00033 { 00034 00035 template <typename Output=Number> 00036 class CompositeFunction : public FunctionBase<Output> 00037 { 00038 public: 00039 explicit 00040 CompositeFunction () {} 00041 00042 ~CompositeFunction () 00043 { 00044 for (unsigned int i=0; i != subfunctions.size(); ++i) 00045 delete subfunctions[i]; 00046 } 00047 00048 // Attach a new subfunction, along with a map from the indices of 00049 // that subfunction to the indices of the global function. 00050 // (*this)(index_map[i]) will return f(i). 00051 void attach_subfunction (const FunctionBase<Output>& f, 00052 const std::vector<unsigned int>& index_map) 00053 { 00054 const unsigned int subfunction_index = subfunctions.size(); 00055 libmesh_assert_equal_to(subfunctions.size(), index_maps.size()); 00056 00057 subfunctions.push_back(f.clone().release()); 00058 index_maps.push_back(index_map); 00059 00060 unsigned int max_index = 00061 *std::max_element(index_map.begin(), index_map.end()); 00062 00063 if (max_index >= reverse_index_map.size()) 00064 reverse_index_map.resize 00065 (max_index+1, std::make_pair(libMesh::invalid_uint, 00066 libMesh::invalid_uint)); 00067 00068 for (unsigned int j=0; j != index_map.size(); ++j) 00069 { 00070 libmesh_assert_less(index_map[j], reverse_index_map.size()); 00071 libmesh_assert_equal_to(reverse_index_map[index_map[j]].first, 00072 libMesh::invalid_uint); 00073 libmesh_assert_equal_to(reverse_index_map[index_map[j]].second, 00074 libMesh::invalid_uint); 00075 reverse_index_map[index_map[j]] = 00076 std::make_pair(subfunction_index, j); 00077 } 00078 } 00079 00080 virtual Output operator() (const Point& p, 00081 const Real time = 0) 00082 { 00083 return this->component(0,p,time); 00084 } 00085 00086 virtual void operator() (const Point& p, 00087 const Real time, 00088 DenseVector<Output>& output) 00089 { 00090 libmesh_assert_greater_equal (output.size(), 00091 reverse_index_map.size()); 00092 00093 // Necessary in case we have output components not covered by 00094 // any subfunctions 00095 output.zero(); 00096 00097 DenseVector<Output> temp; 00098 for (unsigned int i=0; i != subfunctions.size(); ++i) 00099 { 00100 temp.resize(index_maps[i].size()); 00101 (*subfunctions[i])(p, time, temp); 00102 for (unsigned int j=0; j != temp.size(); ++j) 00103 output(index_maps[i][j]) = temp(j); 00104 } 00105 } 00106 00111 virtual Output component (unsigned int i, 00112 const Point& p, 00113 Real time) 00114 { 00115 if (i >= reverse_index_map.size() || 00116 reverse_index_map[i].first == libMesh::invalid_uint) 00117 return 0; 00118 00119 libmesh_assert_less(reverse_index_map[i].first, 00120 subfunctions.size()); 00121 libmesh_assert_not_equal_to(reverse_index_map[i].second, 00122 libMesh::invalid_uint); 00123 return subfunctions[reverse_index_map[i].first]-> 00124 component(reverse_index_map[i].second,p,time); 00125 } 00126 00127 virtual UniquePtr<FunctionBase<Output> > clone() const { 00128 CompositeFunction* returnval = new CompositeFunction(); 00129 for (unsigned int i=0; i != subfunctions.size(); ++i) 00130 returnval->attach_subfunction(*subfunctions[i], index_maps[i]); 00131 return UniquePtr<FunctionBase<Output> > (returnval); 00132 } 00133 00134 unsigned int n_subfunctions () const { 00135 return subfunctions.size(); 00136 } 00137 00138 unsigned int n_components () const { 00139 return reverse_index_map.size(); 00140 } 00141 00142 private: 00143 // list of functions which fill in our values 00144 std::vector<FunctionBase<Output> *> subfunctions; 00145 00146 // for each function, list of which global indices it fills in 00147 std::vector<std::vector<unsigned int> > index_maps; 00148 00149 // for each global index, which local index of which function is it? 00150 std::vector<std::pair<unsigned int, unsigned int> > reverse_index_map; 00151 }; 00152 00153 00154 } // namespace libMesh 00155 00156 #endif // LIBMESH_COMPOSITE_FUNCTION_H