$extrastylesheet
composite_fem_function.h
Go to the documentation of this file.
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