$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_FEM_FUNCTION_H 00019 #define LIBMESH_COMPOSITE_FEM_FUNCTION_H 00020 00021 // libMesh includes 00022 #include "libmesh/dense_vector.h" 00023 #include "libmesh/fem_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 CompositeFEMFunction : public FEMFunctionBase<Output> 00037 { 00038 public: 00039 explicit 00040 CompositeFEMFunction () {} 00041 00042 ~CompositeFEMFunction () 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 FEMFunctionBase<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 FEMContext& c, 00081 const Point& p, 00082 const Real time = 0) 00083 { 00084 return this->component(c,0,p,time); 00085 } 00086 00087 virtual void operator() (const FEMContext& c, 00088 const Point& p, 00089 const Real time, 00090 DenseVector<Output>& output) 00091 { 00092 libmesh_assert_greater_equal (output.size(), 00093 reverse_index_map.size()); 00094 00095 // Necessary in case we have output components not covered by 00096 // any subfunctions 00097 output.zero(); 00098 00099 DenseVector<Output> temp; 00100 for (unsigned int i=0; i != subfunctions.size(); ++i) 00101 { 00102 temp.resize(index_maps[i].size()); 00103 (*subfunctions[i])(c, p, time, temp); 00104 for (unsigned int j=0; j != temp.size(); ++j) 00105 output(index_maps[i][j]) = temp(j); 00106 } 00107 } 00108 00113 virtual Output component (const FEMContext& c, 00114 unsigned int i, 00115 const Point& p, 00116 Real time) 00117 { 00118 if (i >= reverse_index_map.size() || 00119 reverse_index_map[i].first == libMesh::invalid_uint) 00120 return 0; 00121 00122 libmesh_assert_less(reverse_index_map[i].first, 00123 subfunctions.size()); 00124 libmesh_assert_not_equal_to(reverse_index_map[i].second, 00125 libMesh::invalid_uint); 00126 return subfunctions[reverse_index_map[i].first]-> 00127 component(c, reverse_index_map[i].second, p, time); 00128 } 00129 00130 virtual UniquePtr<FEMFunctionBase<Output> > clone() const { 00131 CompositeFEMFunction* returnval = new CompositeFEMFunction(); 00132 for (unsigned int i=0; i != subfunctions.size(); ++i) 00133 returnval->attach_subfunction(*subfunctions[i], index_maps[i]); 00134 return UniquePtr<FEMFunctionBase<Output> > (returnval); 00135 } 00136 00137 unsigned int n_subfunctions () const { 00138 return subfunctions.size(); 00139 } 00140 00141 unsigned int n_components () const { 00142 return reverse_index_map.size(); 00143 } 00144 00145 private: 00146 // list of functions which fill in our values 00147 std::vector<FEMFunctionBase<Output> *> subfunctions; 00148 00149 // for each function, list of which global indices it fills in 00150 std::vector<std::vector<unsigned int> > index_maps; 00151 00152 // for each global index, which local index of which function is it? 00153 std::vector<std::pair<unsigned int, unsigned int> > reverse_index_map; 00154 }; 00155 00156 00157 } // namespace libMesh 00158 00159 #endif // LIBMESH_COMPOSITE_FEM_FUNCTION_H