LCOV - code coverage report
Current view: top level - ugbase/lib_disc/function_spaces - integrate.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 839 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 1938 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2011-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Andreas Vogel
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #ifndef __H__UG__LIB_DISC__FUNCTION_SPACES__INTEGRATE__
      34              : #define __H__UG__LIB_DISC__FUNCTION_SPACES__INTEGRATE__
      35              : 
      36              : #include <cmath>
      37              : 
      38              : #include <boost/function.hpp>
      39              : 
      40              : #include "common/common.h"
      41              : 
      42              : #include "lib_grid/tools/subset_group.h"
      43              : 
      44              : #include "lib_disc/common/function_group.h"
      45              : #include "lib_disc/common/groups_util.h"
      46              : #include "lib_disc/domain_util.h"  // for CollectCornerCoordinates
      47              : #include "lib_disc/quadrature/quadrature_provider.h"
      48              : #include "lib_disc/local_finite_element/local_finite_element_provider.h"
      49              : #include "lib_disc/spatial_disc/disc_util/fv1_geom.h"
      50              : #include "lib_disc/spatial_disc/user_data/user_data.h"
      51              : #include "lib_disc/spatial_disc/user_data/const_user_data.h"
      52              : #include "lib_disc/reference_element/reference_mapping_provider.h"
      53              : 
      54              : #ifdef UG_FOR_LUA
      55              : #include "bindings/lua/lua_user_data.h"
      56              : #endif
      57              : 
      58              : namespace ug{
      59              : 
      60              : 
      61              : ////////////////////////////////////////////////////////////////////////////////
      62              : // Object encapsulating (scalar) GridFunction related data
      63              : ////////////////////////////////////////////////////////////////////////////////
      64              : template <typename TGridFunction>
      65              : class ScalarGridFunctionData
      66              : {
      67              : public:
      68              :         typedef typename TGridFunction::domain_type domain_type;
      69              : 
      70            0 :         ScalarGridFunctionData(TGridFunction& gridFct, size_t cmp)
      71            0 :         : m_gridFct(gridFct), m_fct(cmp),
      72            0 :          m_id(m_gridFct.local_finite_element_id(m_fct))
      73              :         {}
      74              : 
      75              :         TGridFunction& grid_function()
      76            0 :         {return  m_gridFct;}
      77              : 
      78              :         const TGridFunction& grid_function() const
      79              :         {return  m_gridFct;}
      80              : 
      81              :         size_t fct()
      82            0 :         {return m_fct;}
      83              : 
      84              :         const LFEID &id() const
      85            0 :         {return m_id;}
      86              : 
      87              :         //! returns true, iff scalar function is defined in subset si
      88              :         bool is_def_in_subset(int si) const
      89            0 :         { return m_gridFct.is_def_in_subset(m_fct, si); }
      90              : 
      91              :         ///     returns domain (forward)
      92            0 :         SmartPtr<domain_type> domain() {return m_gridFct.domain();}
      93              : 
      94              :         ///     returns const domain (forward)
      95              :         ConstSmartPtr<domain_type> domain() const {return m_gridFct.domain();}
      96              : 
      97              :         template <typename TElem>
      98              :         size_t dof_indices(TElem* elem, std::vector<DoFIndex>& ind, bool bHang = false, bool bClear = true) const
      99            0 :         {return m_gridFct.dof_indices(elem, m_fct, ind, bHang, bClear);}
     100              : 
     101              : private:
     102              :         /// grid function
     103              :                 TGridFunction& m_gridFct;
     104              : 
     105              :         ///     component of function
     106              :                 size_t m_fct;
     107              : 
     108              :         ///     local finite element id
     109              :                 LFEID m_id;
     110              : };
     111              : 
     112              : ////////////////////////////////////////////////////////////////////////////////
     113              : // Integrand Interface
     114              : ////////////////////////////////////////////////////////////////////////////////
     115              : 
     116              : 
     117              : /// Abstract integrand interface
     118              : /*! An integrand is a short-living (temporary) object that is generated/used in various integration functions.*/
     119              : template <typename TData, int TWorldDim>
     120              : class IIntegrand
     121              : {
     122              :         public:
     123              :         ///     world dimension
     124              :                 static const int worldDim = TWorldDim;
     125              : 
     126              :         ///     data type
     127              :                 typedef TData data_type;
     128              : 
     129              :         ///     returns the values of the integrand for a bunch of ips
     130              :         /**
     131              :          *
     132              :          * @param vValue[out]           the value of the integrand at the ips
     133              :          * @param vGlobIP[in]           global integration point positions
     134              :          * @param pElem[in]             the element to integrate
     135              :          * @param vCornerCoords[in]     corner coordinates of the element
     136              :          * @param vLocIP[in]            local integration point positions
     137              :          * @param vJT[in]                       jacobian transposed at integration point
     138              :          * @param numIP[in]                     number of integration points
     139              :          */
     140              :         /// \{
     141              :                 virtual void values(TData vValue[],
     142              :                                     const MathVector<worldDim> vGlobIP[],
     143              :                                     GridObject* pElem,
     144              :                                 const MathVector<worldDim> vCornerCoords[],
     145              :                                     const MathVector<1> vLocIP[],
     146              :                                     const MathMatrix<1, worldDim> vJT[],
     147              :                                     const size_t numIP) = 0;
     148              :                 virtual void values(TData vValue[],
     149              :                                     const MathVector<worldDim> vGlobIP[],
     150              :                                     GridObject* pElem,
     151              :                                 const MathVector<worldDim> vCornerCoords[],
     152              :                                     const MathVector<2> vLocIP[],
     153              :                                     const MathMatrix<2, worldDim> vJT[],
     154              :                                     const size_t numIP) = 0;
     155              :                 virtual void values(TData vValue[],
     156              :                                     const MathVector<worldDim> vGlobIP[],
     157              :                                     GridObject* pElem,
     158              :                                 const MathVector<worldDim> vCornerCoords[],
     159              :                                     const MathVector<3> vLocIP[],
     160              :                                     const MathMatrix<3, worldDim> vJT[],
     161              :                                     const size_t numIP) = 0;
     162              :         /// \}
     163              : 
     164              :                 virtual ~IIntegrand() {}
     165              : 
     166              : 
     167              :         ///     sets the subset
     168            0 :                 virtual void set_subset(int si) {m_si = si;}
     169              : 
     170              :         ///     returns the subset
     171            0 :                 inline int subset() const {return m_si;}
     172              :         
     173              :                 protected:
     174              :         ///     subset
     175              :                 int m_si;
     176              : };
     177              : 
     178              : /// Abstract integrand interface (using CRTP)
     179              : template <typename TData, int TWorldDim, typename TImpl>
     180            0 : class StdIntegrand : public IIntegrand<TData, TWorldDim>
     181              : {
     182              :         public:
     183              :         ///     world dimension
     184              :                 static const int worldDim = TWorldDim;
     185              : 
     186              :         ///     data type
     187              :                 typedef TData data_type;
     188              : 
     189              :         /// \copydoc IIntegrand::values
     190              :         /// \{
     191            0 :                 virtual void values(TData vValue[],
     192              :                                     const MathVector<worldDim> vGlobIP[],
     193              :                                     GridObject* pElem,
     194              :                                 const MathVector<worldDim> vCornerCoords[],
     195              :                                     const MathVector<1> vLocIP[],
     196              :                                     const MathMatrix<1, worldDim> vJT[],
     197              :                                     const size_t numIP)
     198              :                 {
     199            0 :                         getImpl().template evaluate<1>(vValue,vGlobIP,pElem,vCornerCoords,vLocIP,vJT,numIP);
     200            0 :                 }
     201            0 :                 virtual void values(TData vValue[],
     202              :                                     const MathVector<worldDim> vGlobIP[],
     203              :                                     GridObject* pElem,
     204              :                                 const MathVector<worldDim> vCornerCoords[],
     205              :                                     const MathVector<2> vLocIP[],
     206              :                                     const MathMatrix<2, worldDim> vJT[],
     207              :                                     const size_t numIP)
     208              :                 {
     209            0 :                         getImpl().template evaluate<2>(vValue,vGlobIP,pElem,vCornerCoords,vLocIP,vJT,numIP);
     210            0 :                 }
     211            0 :                 virtual void values(TData vValue[],
     212              :                                     const MathVector<worldDim> vGlobIP[],
     213              :                                     GridObject* pElem,
     214              :                                 const MathVector<worldDim> vCornerCoords[],
     215              :                                     const MathVector<3> vLocIP[],
     216              :                                     const MathMatrix<3, worldDim> vJT[],
     217              :                                     const size_t numIP)
     218              :                 {
     219            0 :                         getImpl().template evaluate<3>(vValue,vGlobIP,pElem,vCornerCoords,vLocIP,vJT,numIP);
     220            0 :                 }
     221              :         /// \}
     222              :                 
     223              :         protected:
     224              :         ///     access to implementation
     225              :                 TImpl& getImpl() {return static_cast<TImpl&>(*this);}
     226              : 
     227              :         ///     const access to implementation
     228              :                 const TImpl& getImpl() const {return static_cast<const TImpl&>(*this);}
     229              : };
     230              : 
     231              : ////////////////////////////////////////////////////////////////////////////////
     232              : ////////////////////////////////////////////////////////////////////////////////
     233              : // Generic Volume Integration Routine
     234              : ////////////////////////////////////////////////////////////////////////////////
     235              : ////////////////////////////////////////////////////////////////////////////////
     236              : 
     237              : /// integrates on the whole domain
     238              : /**
     239              :  * This function integrates an arbitrary integrand over the whole domain.
     240              :  * Note:
     241              :  *  - only grid elements of the same dimension as the world dimension of the
     242              :  *    domain are integrated. Thus, no manifolds.
     243              :  *  - The implementation is using virtual functions. Thus, there is a small
     244              :  *    performance drawback compared to hard coding everything, but we gain
     245              :  *    flexibility. In addition all virtual calls compute for the whole set of
     246              :  *    integration points to avoid many virtual calls, i.e. only one virtual
     247              :  *    call for all integration points is needed.
     248              :  *
     249              :  * \param[in]           iterBegin       iterator to first geometric object to integrate
     250              :  * \param[in]           iterBegin       iterator to last geometric object to integrate
     251              :  * \param[in]           integrand       Integrand
     252              :  * \param[in]           quadOrder       order of quadrature rule
     253              :  * \param[in]           quadType
     254              :  * \param[in]           paaElemContribs (optional). If != NULL, the method will store
     255              :  *                                                                      the contribution of each element in the
     256              :  *                                                                      associated attachment entry.
     257              :  * \returns                     value of the integral
     258              :  */
     259              : template <int WorldDim, int dim, typename TConstIterator>
     260            0 : number Integrate(TConstIterator iterBegin,
     261              :                  TConstIterator iterEnd,
     262              :                  typename domain_traits<WorldDim>::position_accessor_type& aaPos,
     263              :                  IIntegrand<number, WorldDim>& integrand,
     264              :                  int quadOrder, std::string quadType,
     265              :                  Grid::AttachmentAccessor<
     266              :                         typename domain_traits<dim>::grid_base_object, ANumber>
     267              :                         *paaElemContribs = NULL
     268              :                  )
     269              : {
     270              :         PROFILE_FUNC();
     271              : 
     272              : //      reset the result
     273              :         number integral = 0.0;
     274              : 
     275              : //      note: this iterator is for the base elements, e.g. Face and not
     276              : //                      for the special type, e.g. Triangle, Quadrilateral
     277              :         TConstIterator iter = iterBegin;
     278              : 
     279              : //      this is the base element type (e.g. Face). This is the type when the
     280              : //      iterators above are dereferenciated.
     281              :         typedef typename domain_traits<dim>::grid_base_object grid_base_object;
     282              : 
     283              : //      get quad type
     284            0 :         if(quadType.empty()) quadType = "best";
     285            0 :         QuadType type = GetQuadratureType(quadType);
     286              : 
     287              : //      accessing without dereferencing a pointer first is simpler...
     288              :         Grid::AttachmentAccessor<grid_base_object, ANumber> aaElemContribs;
     289            0 :         if(paaElemContribs)
     290            0 :                 aaElemContribs = *paaElemContribs;
     291              : 
     292              : //      We'll reuse containers to avoid reallocations
     293              :         std::vector<MathVector<WorldDim> > vCorner;
     294              :         std::vector<MathVector<WorldDim> > vGlobIP;
     295              :         std::vector<MathMatrix<dim, WorldDim> > vJT;
     296              :         std::vector<number> vValue;
     297              : 
     298              : //      iterate over all elements
     299            0 :         for(; iter != iterEnd; ++iter)
     300              :         {
     301              :         //      get element
     302              :                 grid_base_object* pElem = *iter;
     303              : 
     304              :         //      get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
     305            0 :                 ReferenceObjectID roid = (ReferenceObjectID) pElem->reference_object_id();
     306              : 
     307              :         //      get quadrature Rule for reference object id and order
     308              :                 try{
     309              :                 const QuadratureRule<dim>& rQuadRule
     310            0 :                                         = QuadratureRuleProvider<dim>::get(roid, quadOrder, type);
     311              : 
     312              :         //      get reference element mapping by reference object id
     313              :                 DimReferenceMapping<dim, WorldDim>& mapping
     314            0 :                                                         = ReferenceMappingProvider::get<dim, WorldDim>(roid);
     315              : 
     316              :         //      number of integration points
     317              :                 const size_t numIP = rQuadRule.size();
     318              : 
     319              :         //      get all corner coordinates
     320              :                 CollectCornerCoordinates(vCorner, *pElem, aaPos, true);
     321              : 
     322              :         //      update the reference mapping for the corners
     323            0 :                 mapping.update(&vCorner[0]);
     324              : 
     325              :         //      compute global integration points
     326            0 :                 vGlobIP.resize(numIP);
     327            0 :                 mapping.local_to_global(&(vGlobIP[0]), rQuadRule.points(), numIP);
     328              : 
     329              :         //      compute transformation matrices
     330            0 :                 vJT.resize(numIP);
     331            0 :                 mapping.jacobian_transposed(&(vJT[0]), rQuadRule.points(), numIP);
     332              : 
     333              :         //      compute integrand values at integration points
     334            0 :                 vValue.resize(numIP);
     335              :                 try
     336              :                 {
     337            0 :                         integrand.values(&(vValue[0]), &(vGlobIP[0]),
     338              :                                          pElem, &vCorner[0], rQuadRule.points(),
     339              :                                                          &(vJT[0]),
     340              :                                                          numIP);
     341              :                 }
     342            0 :                 UG_CATCH_THROW("Unable to compute values of integrand at integration point.");
     343              : 
     344              :         //      reset contribution of this element
     345              :                 number intValElem = 0;
     346              : 
     347              :         //      loop integration points
     348            0 :                 for(size_t ip = 0; ip < numIP; ++ip)
     349              :                 {
     350              :                 //      get quadrature weight
     351              :                         const number weightIP = rQuadRule.weight(ip);
     352              : 
     353              :                 //      get determinate of mapping
     354            0 :                         const number det = SqrtGramDeterminant(vJT[ip]);
     355              : 
     356              :                 //      add contribution of integration point
     357            0 :                         intValElem += vValue[ip] * weightIP * det;
     358              :                 }
     359              : 
     360              :         //      add to global sum
     361            0 :                 integral += intValElem;
     362            0 :                 if(aaElemContribs.valid())
     363            0 :                         aaElemContribs[pElem] = intValElem;
     364              : 
     365            0 :                 }UG_CATCH_THROW("SumValuesOnElems failed.");
     366              :         } // end elem
     367              : 
     368              : //      return the summed integral contributions of all elements
     369            0 :         return integral;
     370            0 : }
     371              : 
     372              : template <typename TGridFunction, int dim>
     373            0 : number IntegrateSubset(IIntegrand<number, TGridFunction::dim> &spIntegrand,
     374              :                        TGridFunction& spGridFct,
     375              :                        int si, int quadOrder, std::string quadType)
     376              : {
     377              : //      integrate elements of subset
     378              :         typedef typename TGridFunction::template dim_traits<dim>::grid_base_object grid_base_object;
     379              :         typedef typename TGridFunction::template dim_traits<dim>::const_iterator const_iterator;
     380              : 
     381            0 :         spIntegrand.set_subset(si);
     382              :         
     383              :         return Integrate<TGridFunction::dim,dim,const_iterator>
     384            0 :                                         (spGridFct.template begin<grid_base_object>(si),
     385              :                          spGridFct.template end<grid_base_object>(si),
     386            0 :                                          spGridFct.domain()->position_accessor(),
     387              :                          spIntegrand,
     388            0 :                          quadOrder, quadType);
     389              : }
     390              : 
     391              : 
     392              : template <typename TGridFunction>
     393            0 : number IntegrateSubsets(IIntegrand<number, TGridFunction::dim> &spIntegrand,
     394              :                         TGridFunction& spGridFct,
     395              :                         const char* subsets, int quadOrder,
     396              :                         std::string quadType = std::string())
     397              : {
     398              : //      world dimensions
     399              :         static const int dim = TGridFunction::dim;
     400              : 
     401              : //      read subsets
     402            0 :         SubsetGroup ssGrp(spGridFct.domain()->subset_handler());
     403            0 :         if(subsets != NULL)
     404              :         {
     405            0 :                 ssGrp.add(TokenizeString(subsets));
     406            0 :                 UG_COND_THROW(!SameDimensionsInAllSubsets(ssGrp), "IntegrateSubsets: Subsets '"<<subsets<<"' do not have same dimension."
     407              :                                  "Cannot integrate on subsets of different dimensions.");
     408            0 :                 UG_LOG("IntegrateSubsets for subsets="<<subsets<<"\n");
     409              :         }
     410              :         else
     411              :         {
     412              :         //      add all subsets and remove lower dim subsets afterwards
     413            0 :                 ssGrp.add_all();
     414            0 :                 RemoveLowerDimSubsets(ssGrp);
     415              :         }
     416              : 
     417              : //      reset value
     418              :         number value = 0;
     419              : 
     420              : //      loop subsets
     421            0 :         for(size_t i = 0; i < ssGrp.size(); ++i)
     422              :         {
     423              :         //      get subset index
     424              :                 const int si = ssGrp[i];
     425              : 
     426              :         //      check dimension
     427            0 :         UG_COND_THROW(ssGrp.dim(i) > dim, "IntegrateSubsets: Dimension of subset is "<<ssGrp.dim(i)<<", but "
     428              :                               " world dimension is "<<dim<<". Cannot integrate this.");
     429              : 
     430              :         //      integrate elements of subset
     431              :                 try{
     432            0 :                 switch(ssGrp.dim(i))
     433              :                 {
     434              :                         case DIM_SUBSET_EMPTY_GRID: break;
     435            0 :                         case 1: value += IntegrateSubset<TGridFunction, 1>(spIntegrand, spGridFct, si, quadOrder, quadType); break;
     436            0 :                         case 2: value += IntegrateSubset<TGridFunction, 2>(spIntegrand, spGridFct, si, quadOrder, quadType); break;
     437            0 :                         case 3: value += IntegrateSubset<TGridFunction, 3>(spIntegrand, spGridFct, si, quadOrder, quadType); break;
     438            0 :                         default: UG_THROW("IntegrateSubsets: Dimension "<<ssGrp.dim(i)<<" not supported. "
     439              :                                           " World dimension is "<<dim<<".");
     440              :                 }
     441              :                 }
     442            0 :                 UG_CATCH_THROW("IntegrateSubsets: Integration failed on subset "<<si);
     443              :         }
     444              : 
     445              : #ifdef UG_PARALLEL
     446              :         // sum over processes
     447              :         if(pcl::NumProcs() > 1)
     448              :         {
     449              :                 pcl::ProcessCommunicator com;
     450              :                 number local = value;
     451              :                 com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
     452              :         }
     453              : #endif
     454              : 
     455              : //      return the result
     456            0 :         return value;
     457              : }
     458              : 
     459              : 
     460              : ////////////////////////////////////////////////////////////////////////////////
     461              : // UserData Integrand
     462              : ////////////////////////////////////////////////////////////////////////////////
     463              : 
     464              : //! For arbitrary UserData \f$\rho\f$, this class defines the integrand \f$\rho(u)\f$.
     465              : template <typename TData, typename TGridFunction>
     466            0 : class UserDataIntegrand
     467              :         : public StdIntegrand<TData, TGridFunction::dim, UserDataIntegrand<TData, TGridFunction> >
     468              : {
     469              :         public:
     470              :         //      world dimension of grid function
     471              :                 static const int worldDim = TGridFunction::dim;
     472              : 
     473              :         //      data type
     474              :                 typedef TData data_type;
     475              : 
     476              :         private:
     477              :         //  data to integrate
     478              :                 SmartPtr<UserData<TData, worldDim> > m_spData;
     479              : 
     480              :         //      grid function
     481              :                 TGridFunction* m_spGridFct;
     482              : 
     483              :         //      time
     484              :                 number m_time;
     485              : 
     486              :         public:
     487              :         /// constructor
     488            0 :                 UserDataIntegrand(SmartPtr<UserData<TData, worldDim> > spData,
     489              :                                       TGridFunction* spGridFct,
     490              :                                       number time)
     491            0 :                 : m_spData(spData), m_spGridFct(spGridFct), m_time(time)
     492              :                 {
     493            0 :                         m_spData->set_function_pattern(spGridFct->function_pattern());
     494            0 :                 };
     495              : 
     496              :         /// constructor
     497              :                 UserDataIntegrand(SmartPtr<UserData<TData, worldDim> > spData,
     498              :                                                           number time)
     499              :                 : m_spData(spData), m_spGridFct(NULL), m_time(time)
     500              :                 {
     501              :                         UG_COND_THROW(m_spData->requires_grid_fct(),
     502              :                                                 "UserDataIntegrand: Missing GridFunction, but data requires grid function.");
     503              :                 };
     504              : 
     505              :         /// \copydoc IIntegrand::values
     506              :                 template <int elemDim>
     507            0 :                 void evaluate(TData vValue[],
     508              :                               const MathVector<worldDim> vGlobIP[],
     509              :                               GridObject* pElem,
     510              :                               const MathVector<worldDim> vCornerCoords[],
     511              :                               const MathVector<elemDim> vLocIP[],
     512              :                               const MathMatrix<elemDim, worldDim> vJT[],
     513              :                               const size_t numIP)
     514              :                 {
     515              :                 //      get local solution if needed
     516            0 :                         if(m_spData->requires_grid_fct())
     517              :                         {
     518              :                         //      create storage
     519              :                                 LocalIndices ind;
     520              :                                 LocalVector u;
     521              : 
     522              :                         //      get global indices
     523            0 :                                 m_spGridFct->indices(pElem, ind);
     524              : 
     525              :                         //      adapt local algebra
     526            0 :                                 u.resize(ind);
     527              : 
     528              :                         //      read local values of u
     529            0 :                                 GetLocalVector(u, *m_spGridFct);
     530              : 
     531              :                         //      compute data
     532              :                                 try{
     533            0 :                                         (*m_spData)(vValue, vGlobIP, m_time, this->m_si, pElem,
     534              :                                                                 vCornerCoords, vLocIP, numIP, &u, &vJT[0]);
     535              :                                 }
     536            0 :                                 UG_CATCH_THROW("UserDataIntegrand: Cannot evaluate data.");
     537              :                         }
     538              :                         else
     539              :                         {
     540              :                         //      compute data
     541              :                                 try{
     542            0 :                                         (*m_spData)(vValue, vGlobIP, m_time, this->m_si, numIP);
     543              :                                 }
     544            0 :                                 UG_CATCH_THROW("UserDataIntegrand: Cannot evaluate data.");
     545              :                         }
     546              : 
     547            0 :                 }
     548              : };
     549              : 
     550              : 
     551              : 
     552              : 
     553              : //! For arbitrary UserData \f$f\f$ (of type TData), this class defines the integrand \f$f^2(u)\f$.
     554              : template <typename TData, typename TGridFunction>
     555            0 : class UserDataIntegrandSq
     556              :         : public StdIntegrand<number, TGridFunction::dim, UserDataIntegrandSq<TData, TGridFunction> >
     557              : {
     558              :         public:
     559              :         //      world dimension of grid function
     560              :                 static const int worldDim = TGridFunction::dim;
     561              : 
     562              :         //      data type
     563              :                 typedef TData data_type;
     564              : 
     565              :         private:
     566              :         //  data to integrate
     567              :                 SmartPtr<UserData<TData, worldDim> > m_spData;
     568              : 
     569              :         //      grid function
     570              :                 const TGridFunction* m_pGridFct;
     571              : 
     572              :         //      time
     573              :                 number m_time;
     574              : 
     575              :         public:
     576              :         /// constructor
     577            0 :                 UserDataIntegrandSq(SmartPtr<UserData<TData, worldDim> > spData,
     578              :                                       const TGridFunction* pGridFct,
     579              :                                       number time)
     580            0 :                 : m_spData(spData), m_pGridFct(pGridFct), m_time(time)
     581              :                 {
     582            0 :                         m_spData->set_function_pattern(pGridFct->function_pattern());
     583            0 :                 };
     584              : 
     585              :         /// constructor
     586              :                 UserDataIntegrandSq(SmartPtr<UserData<TData, worldDim> > spData,
     587              :                                                           number time)
     588              :                 : m_spData(spData), m_pGridFct(NULL), m_time(time)
     589              :                 {
     590              :                         if(m_spData->requires_grid_fct())
     591              :                                 UG_THROW("UserDataIntegrand: Missing GridFunction, but "
     592              :                                                 " data requires grid function.")
     593              :                 };
     594              : 
     595              :                 
     596              :         /// \copydoc IIntegrand::values
     597              :                 template <int elemDim>
     598            0 :                 void evaluate(number vValue[],
     599              :                               const MathVector<worldDim> vGlobIP[],
     600              :                               GridObject* pElem,
     601              :                               const MathVector<worldDim> vCornerCoords[],
     602              :                               const MathVector<elemDim> vLocIP[],
     603              :                               const MathMatrix<elemDim, worldDim> vJT[],
     604              :                               const size_t numIP)
     605              :                 {
     606              : 
     607            0 :                         std::vector<TData> tmpValues(numIP);
     608              : 
     609              :                 //      get local solution if needed
     610            0 :                         if(m_spData->requires_grid_fct())
     611              :                         {
     612              :                                 UG_ASSERT(m_pGridFct!=NULL, "Error: Requires valid pointer!")
     613              :                         //      create storage
     614              :                                 LocalIndices ind;
     615              :                                 LocalVector u;
     616              : 
     617              :                         //      get global indices
     618            0 :                                 m_pGridFct->indices(pElem, ind);
     619              : 
     620              :                         //      adapt local algebra
     621            0 :                                 u.resize(ind);
     622              : 
     623              :                         //      read local values of u
     624            0 :                                 GetLocalVector(u, *m_pGridFct);
     625              : 
     626              :                         //      compute data
     627              :                                 try{
     628            0 :                                         (*m_spData)(&tmpValues.front(), vGlobIP, m_time, this->m_si, pElem,
     629              :                                                                 vCornerCoords, vLocIP, numIP, &u, &vJT[0]);
     630              :                                 }
     631            0 :                                 UG_CATCH_THROW("UserDataIntegrand: Cannot evaluate data.");
     632              :                         }
     633              :                         else
     634              :                         {
     635              :                         //      compute data
     636              :                                 try{
     637            0 :                                         (*m_spData)(&tmpValues.front(), vGlobIP, m_time, this->m_si, numIP);
     638              :                                 }
     639            0 :                                 UG_CATCH_THROW("UserDataIntegrand: Cannot evaluate data.");
     640              :                         }
     641              : 
     642            0 :                         for (size_t i=0; i<numIP; ++i)
     643              :                         {
     644            0 :                                 vValue[i]=inner_prod(tmpValues[i], tmpValues[i]);
     645              :                         }
     646              : 
     647            0 :                 }
     648              :         protected:
     649              : 
     650              :                 number inner_prod(const number &d1, const number &d2)
     651              :                 {return d1*d2;}
     652              : 
     653              :                 number inner_prod(const MathVector<worldDim> &d1, const MathVector<worldDim> &d2)
     654              :                 {return VecDot(d1, d2);}
     655              : 
     656              :                 template<typename T>
     657              :                 number inner_prod(const T &d1, const T &d2)
     658              :                 { UG_ASSERT(0, "NOT IMPLEMENTED"); return 0.0;}
     659              : };
     660              : 
     661              : 
     662              : 
     663              : 
     664              : //! For arbitrary UserData \f$f\f$ and grid functions \f$u_1\f$ and \f$u_2\f$, this class (should) define the integrand \f$ (f(u_1)- f(u_2))^2 \f$.
     665              : template <typename TData, typename TGridFunction>
     666              : class UserDataDistIntegrandSq
     667              :                 : public StdIntegrand<number, TGridFunction::dim, UserDataDistIntegrandSq<TData, TGridFunction> >
     668              : {
     669              :         public:
     670              :         ///     world dimension of grid function
     671              :                 static const int worldDim = TGridFunction::dim;
     672              :                 // typedef typename L2Integrand<TGridFunction>::weight_type weight_type;
     673              : 
     674              :         protected:
     675              :                 ScalarGridFunctionData<TGridFunction> m_fineData;
     676              :                 const int m_fineTopLevel;
     677              : 
     678              :                 ScalarGridFunctionData<TGridFunction> m_coarseData;
     679              :                 const int m_coarseTopLevel;
     680              : 
     681              :         ///     multigrid
     682              :                 SmartPtr<MultiGrid> m_spMG;
     683              : 
     684              : 
     685              : 
     686              :                 SmartPtr<UserData<TData, worldDim> > m_spData;
     687              :                 // ConstSmartPtr<weight_type> m_spWeight;
     688              : 
     689              :                 double m_time;
     690              :         public:
     691              : 
     692              :                 /// constructor (1st is fine grid function)
     693              :                 UserDataDistIntegrandSq(SmartPtr<UserData<TData, worldDim> > spData, TGridFunction& fineGridFct, size_t fineCmp,
     694              :                                         TGridFunction& coarseGridFct, size_t coarseCmp)
     695              :                 : m_fineData(fineGridFct, fineCmp), m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
     696              :                   m_coarseData(coarseGridFct, coarseCmp), m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
     697              :                   m_spMG(m_fineData.domain()->grid()), m_spData(spData), m_time(0.0) /*, m_spWeight(make_sp(new ConstUserNumber<TGridFunction::dim>(1.0)))*/
     698              :                 {
     699              :                         if(m_fineTopLevel < m_coarseTopLevel)
     700              :                                 UG_THROW("UserDataDistIntegrandSq: fine and top level inverted.");
     701              : 
     702              :                         if(m_fineData.domain().get() != m_coarseData.domain().get())
     703              :                                 UG_THROW("UserDataDistIntegrandSq: grid functions defined on different domains.");
     704              :                 };
     705              : 
     706              :                 virtual ~UserDataDistIntegrandSq() {}
     707              : 
     708              :                 ///     sets subset
     709              :                 virtual void set_subset(int si)
     710              :                 {
     711              :                         if(!m_fineData.is_def_in_subset(si))
     712              :                                 UG_THROW("UserDataDistIntegrandSq: Grid function component"
     713              :                                                 <<m_fineData.fct()<<" not defined on subset "<<si);
     714              :                         if(!m_coarseData.is_def_in_subset(si))
     715              :                                 UG_THROW("UserDataDistIntegrandSq: Grid function component"
     716              :                                                 <<m_coarseData.fct()<<" not defined on subset "<<si);
     717              :                         IIntegrand<number, worldDim>::set_subset(si);
     718              :                 }
     719              : 
     720              :         /// \copydoc IIntegrand::values
     721              :                 template <int elemDim>
     722              :                 void evaluate(number vValue[],
     723              :                               const MathVector<worldDim> vGlobIP[],
     724              :                               GridObject* pFineElem,
     725              :                               const MathVector<worldDim> vCornerCoords[],
     726              :                               const MathVector<elemDim> vFineLocIP[],
     727              :                               const MathMatrix<elemDim, worldDim> vJT[],
     728              :                               const size_t numIP)
     729              :                 {
     730              : 
     731              : 
     732              :                 // must return 0.0, if m_spData is independent of grid functions
     733              :                         if(!m_spData->requires_grid_fct()) {
     734              :                                 for (size_t i=0; i<numIP; ++i) { vValue[i]=0.0; }
     735              :                                 return;
     736              :                         }
     737              : 
     738              :                 //      get coarse element
     739              :                         GridObject* pCoarseElem = pFineElem;
     740              :                         if(m_coarseTopLevel < m_fineTopLevel){
     741              :                                 int parentLevel = m_spMG->get_level(pCoarseElem);
     742              :                                 while(parentLevel > m_coarseTopLevel){
     743              :                                         pCoarseElem = m_spMG->get_parent(pCoarseElem);
     744              :                                         parentLevel = m_spMG->get_level(pCoarseElem);
     745              :                                 }
     746              :                         }
     747              : 
     748              :                 //      get corner coordinates
     749              :                         typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object TElem;
     750              :                         std::vector<MathVector<worldDim> > vCornerCoarse;
     751              :                         CollectCornerCoordinates(vCornerCoarse, *static_cast<TElem*>(pCoarseElem), *m_coarseData.domain());
     752              : 
     753              :                 //      get Reference Mapping
     754              :                         const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
     755              :                         DimReferenceMapping<elemDim, worldDim>& map
     756              :                                 = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
     757              : 
     758              :                         std::vector<MathVector<elemDim> > vCoarseLocIP;
     759              :                         vCoarseLocIP.resize(numIP);
     760              :                         for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
     761              :                         map.global_to_local(&vCoarseLocIP[0], vGlobIP, numIP);
     762              : 
     763              :                 // element weights
     764              :                 /*      typedef typename weight_type::data_type ipdata_type;
     765              :                         std::vector<ipdata_type> fineElemWeights(numIP, 1.0);
     766              :                         UG_ASSERT(m_spWeight.valid(), "L2DistIntegrand::evaluate requires valid weights! ");
     767              :                         (*m_spWeight)(&fineElemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);*/
     768              : 
     769              : 
     770              :                 //      get trial space
     771              :                 /*      const LocalShapeFunctionSet<elemDim>& rFineLSFS =
     772              :                                         LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
     773              :                         const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
     774              :                                         LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());*/
     775              : 
     776              :                 //      get multiindices of element
     777              :                         /*std::vector<DoFIndex> vFineMI, vCoarseMI;
     778              :                         m_fineData.dof_indices(pFineElem, vFineMI);
     779              :                         m_coarseData.dof_indices(pCoarseElem, vCoarseMI);*/
     780              : 
     781              :                         TData fineValues[numIP];
     782              :                         TData coarseValues[numIP];
     783              : 
     784              : 
     785              : 
     786              :                 //      compute coarse data
     787              :                         try{
     788              :                                 LocalVector uCoarse;
     789              :                                 LocalIndices indCoarse;
     790              : 
     791              :                                 m_coarseData.grid_function().indices(pCoarseElem, indCoarse);
     792              :                                 uCoarse.resize(indCoarse);
     793              :                                 GetLocalVector(uCoarse, m_coarseData.grid_function());
     794              : 
     795              :                                 (*m_spData)(coarseValues, vGlobIP, m_time, this->m_si, pCoarseElem,
     796              :                                                 &vCornerCoarse[0], &vCoarseLocIP[0], numIP, &uCoarse, &vJT[0]);
     797              :                         } UG_CATCH_THROW("UserDataDistIntegrandSq: Cannot evaluate coarse data.");
     798              : 
     799              : 
     800              :                 //      compute fine data
     801              :                         try{
     802              :                                 LocalVector uFine;
     803              :                                 LocalIndices indFine;
     804              : 
     805              :                                 m_fineData.grid_function().indices(pFineElem, indFine);
     806              :                                 uFine.resize(indFine);
     807              :                                 GetLocalVector(uFine, m_fineData.grid_function());
     808              : 
     809              :                                 (*m_spData)(fineValues, vGlobIP, m_time, this->m_si, pFineElem,
     810              :                                                 vCornerCoords, vFineLocIP, numIP, &uFine, &vJT[0]);
     811              :                         } UG_CATCH_THROW("UserDataDistIntegrandSq: Cannot evaluate fine data.");
     812              : 
     813              :                 //      loop all integration points
     814              :                         for(size_t ip = 0; ip < numIP; ++ip)
     815              :                         {
     816              :                                 vValue[ip] = inner_dist2(fineValues[ip], coarseValues[ip]);
     817              :                         }
     818              : 
     819              :                 }
     820              : 
     821              : 
     822              :         protected:
     823              : 
     824              :                         number inner_prod(const number &d1, const number &d2)
     825              :                         {return d1*d2;}
     826              : 
     827              :                         number inner_prod(const MathVector<worldDim> &d1, const MathVector<worldDim> &d2)
     828              :                         {return VecDot(d1, d2);}
     829              : 
     830              :                         template<typename T>
     831              :                         number inner_prod(const T &d1, const T &d2)
     832              :                         { UG_ASSERT(0, "NOT IMPLEMENTED"); return 0.0;}
     833              : 
     834              : 
     835              : 
     836              :                         number inner_dist2(const number &v1, const number &v2)
     837              :                         { return (v1-v2)*(v1-v2); }
     838              : 
     839              :                         number inner_dist2(const MathVector<worldDim> &v1, const MathVector<worldDim> &v2)
     840              :                         { return VecDistanceSq(v1, v2); }
     841              : 
     842              :                         template<typename T>
     843              :                         number inner_dist2(const T &d1, const T &d2)
     844              :                         { UG_ASSERT(0, "NOT IMPLEMENTED"); return 0.0;}
     845              : 
     846              : };
     847              : 
     848              : 
     849              : ////////////////////////////////////////////////////////////////////////////////
     850              : ////////////////////////////////////////////////////////////////////////////////
     851              : // Volume Integrand implementations
     852              : ////////////////////////////////////////////////////////////////////////////////
     853              : ////////////////////////////////////////////////////////////////////////////////
     854              : 
     855              : template <typename TGridFunction>
     856            0 : number Integral(SmartPtr<UserData<number, TGridFunction::dim> > spData,
     857              :                 TGridFunction& spGridFct,
     858              :                 const char* subsets, number time,
     859              :                 int quadOrder, std::string quadType)
     860              : {
     861            0 :         UserDataIntegrand<number, TGridFunction> spIntegrand(spData, &spGridFct, time);
     862            0 :         return IntegrateSubsets(spIntegrand, spGridFct, subsets, quadOrder, quadType);
     863              : }
     864              : 
     865              : template <typename TGridFunction>
     866            0 : number Integral(SmartPtr<UserData<number, TGridFunction::dim> > spData, SmartPtr<TGridFunction> spGridFct,
     867              :                 const char* subsets, number time, int quadOrder, std::string quadType)
     868            0 : { return Integral(spData, *spGridFct, subsets, time, quadOrder, quadType); }
     869              : 
     870              : template <typename TGridFunction>
     871            0 : number Integral(SmartPtr<UserData<number, TGridFunction::dim> > spData, SmartPtr<TGridFunction> spGridFct,const char* subsets,number time, int order)
     872            0 : {return Integral(spData, spGridFct, subsets, time, order, "best");}
     873              : 
     874              : template <typename TGridFunction>
     875            0 : number Integral(SmartPtr<UserData<number, TGridFunction::dim> > spData, SmartPtr<TGridFunction> spGridFct,const char* subsets,number time)
     876            0 : {return Integral(spData, spGridFct, subsets, time, 1, "best");}
     877              : 
     878              : template <typename TGridFunction>
     879            0 : number Integral(SmartPtr<UserData<number, TGridFunction::dim> > spData, SmartPtr<TGridFunction> spGridFct,number time)
     880            0 : {return Integral(spData, spGridFct, NULL, time, 1, "best");}
     881              : 
     882              : template <typename TGridFunction>
     883            0 : number Integral(SmartPtr<UserData<number, TGridFunction::dim> > spData, SmartPtr<TGridFunction> spGridFct,const char* subsets)
     884            0 : {return Integral(spData, spGridFct, subsets, 0.0, 1, "best");}
     885              : 
     886              : template <typename TGridFunction>
     887            0 : number Integral(SmartPtr<UserData<number, TGridFunction::dim> > spData, SmartPtr<TGridFunction> spGridFct)
     888            0 : {return Integral(spData, spGridFct, NULL, 0.0, 1, "best");}
     889              : 
     890              : ///////////////
     891              : // const data
     892              : ///////////////
     893              : 
     894              : template <typename TGridFunction>
     895            0 : number Integral(number val, SmartPtr<TGridFunction> spGridFct,
     896              :                 const char* subsets,
     897              :                 number time, int quadOrder)
     898              : {
     899              :         static const int dim = TGridFunction::dim;
     900            0 :         SmartPtr<UserData<number, dim> > sp =
     901            0 :                         make_sp(new ConstUserNumber<dim>(val));
     902            0 :         return Integral(sp, spGridFct, subsets, time, quadOrder);
     903              : }
     904              : 
     905              : template <typename TGridFunction>
     906            0 : number Integral(number val, SmartPtr<TGridFunction> spGridFct,const char* subsets,number time)
     907            0 : {return Integral(val, spGridFct, subsets, time, 1);}
     908              : 
     909              : template <typename TGridFunction>
     910            0 : number Integral(number val, SmartPtr<TGridFunction> spGridFct,number time)
     911            0 : {return Integral(val, spGridFct, NULL, time, 1);}
     912              : 
     913              : template <typename TGridFunction>
     914            0 : number Integral(number val, SmartPtr<TGridFunction> spGridFct,const char* subsets)
     915            0 : {return Integral(val, spGridFct, subsets, 0.0, 1);}
     916              : 
     917              : template <typename TGridFunction>
     918            0 : number Integral(number val, SmartPtr<TGridFunction> spGridFct)
     919            0 : {return Integral(val, spGridFct, NULL, 0.0, 1);}
     920              : 
     921              : ///////////////
     922              : // lua data
     923              : ///////////////
     924              : 
     925              : #ifdef UG_FOR_LUA
     926              : template <typename TGridFunction>
     927            0 : number Integral(const char* luaFct,
     928              :                 SmartPtr<TGridFunction> spGridFct,
     929              :                 const char* subsets, number time,
     930              :                 int quadOrder, std::string quadType)
     931              : {
     932              :         static const int dim = TGridFunction::dim;
     933            0 :         SmartPtr<UserData<number, dim> > sp =
     934              :                         LuaUserDataFactory<number, dim>::create(luaFct);
     935            0 :         return Integral(sp, *spGridFct, subsets, time, quadOrder, quadType);
     936              : }
     937              : 
     938              : template <typename TGridFunction>
     939            0 : number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct,const char* subsets,number time, int quadOrder)
     940            0 : {return Integral(luaFct, spGridFct, subsets, time, quadOrder, "best");}
     941              : 
     942              : template <typename TGridFunction>
     943            0 : number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct,const char* subsets,number time)
     944            0 : {return Integral(luaFct, spGridFct, subsets, time, 1, "best");}
     945              : 
     946              : template <typename TGridFunction>
     947            0 : number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct,number time)
     948            0 : {return Integral(luaFct, spGridFct, NULL, time, 1, "best");}
     949              : 
     950              : template <typename TGridFunction>
     951            0 : number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct,const char* subsets)
     952            0 : {return Integral(luaFct, spGridFct, subsets, 0.0, 1, "best");}
     953              : 
     954              : template <typename TGridFunction>
     955            0 : number Integral(const char* luaFct, SmartPtr<TGridFunction> spGridFct)
     956            0 : {return Integral(luaFct, spGridFct, NULL, 0.0, 1, "best");}
     957              : 
     958              : #endif
     959              : 
     960              : 
     961              : 
     962              : template <typename TGridFunction>
     963              : class MaximumDistIntegrand
     964              :         : public StdIntegrand<number, TGridFunction::dim, MaximumDistIntegrand<TGridFunction> >
     965              : {
     966              :         public:
     967              :         ///     world dimension of grid function
     968              :                 static const int worldDim = TGridFunction::dim;
     969              : 
     970              :         protected:
     971              :                 ScalarGridFunctionData<TGridFunction> m_scalarData;
     972              : 
     973              :                 double m_max, m_min;
     974              : 
     975              :         public:
     976              :         /// constructor
     977            0 :                 MaximumDistIntegrand(TGridFunction& gridFct, size_t cmp)
     978              : 
     979              :                 : m_scalarData(gridFct, cmp),
     980            0 :                         m_max(-std::numeric_limits<float>::infinity()),
     981            0 :                         m_min(std::numeric_limits<float>::infinity())
     982              :                 {};
     983              : 
     984            0 :                 virtual ~MaximumDistIntegrand() {};
     985              : 
     986              :         ///     sets subset
     987            0 :                 virtual void set_subset(int si)
     988              :                 {
     989            0 :                         UG_COND_THROW(!m_scalarData.is_def_in_subset(si), "L2ErrorIntegrand: Grid function component" <<
     990              :                                                         m_scalarData.fct()<<" not defined on subset "<<si);
     991              :                         IIntegrand<number, worldDim>::set_subset(si);
     992            0 :                 }
     993              : 
     994              :                 void reset()
     995              :                 {
     996              :                         m_min = std::numeric_limits<double>::infinity();
     997              :                         m_max = -std::numeric_limits<double>::infinity();
     998              :                 }
     999              : 
    1000            0 :                 double min() { return m_min; }
    1001              :                 double max() { return m_max; }
    1002              : 
    1003              :         /// \copydoc IIntegrand::values
    1004              :                 template <int elemDim>
    1005            0 :                 void evaluate(number vValue[],
    1006              :                               const MathVector<worldDim> vGlobIP[],
    1007              :                               GridObject* pElem,
    1008              :                               const MathVector<worldDim> vCornerCoords[],
    1009              :                               const MathVector<elemDim> vLocIP[],
    1010              :                               const MathMatrix<elemDim, worldDim> vJT[],
    1011              :                               const size_t numIP)
    1012              :                 {
    1013              :                 //      get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
    1014            0 :                         const ReferenceObjectID roid = pElem->reference_object_id();
    1015              : 
    1016              :                         try{
    1017              :                                 //      get trial space
    1018              :                                 const LocalShapeFunctionSet<elemDim>& rTrialSpace =
    1019              :                                                         LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
    1020              : 
    1021              :                                 //      number of dofs on element
    1022            0 :                                 const size_t num_sh = rTrialSpace.num_sh();
    1023              : 
    1024              :                                 //      get multiindices of element
    1025              :                                 std::vector<DoFIndex> ind;  //    aux. index array
    1026              :                                 m_scalarData.dof_indices(pElem, ind);
    1027              : 
    1028              :                                 //      check multi indices
    1029            0 :                                 UG_COND_THROW(ind.size() != num_sh, "L2ErrorIntegrand::evaluate: Wrong number of multi indices.");
    1030              : 
    1031              :                                 //      evaluate function in corners.
    1032            0 :                                 for(size_t sh = 0; sh < num_sh; ++sh)
    1033              :                                 {
    1034              :                                         //      get value at shape point (e.g. corner for P1 fct)
    1035            0 :                                         const number val = DoFRef(m_scalarData.grid_function(), ind[sh]);
    1036              : 
    1037            0 :                                         m_max = std::max(m_max, val);
    1038            0 :                                         m_min = std::min(m_min, val);
    1039              :                                 }
    1040              : 
    1041              : 
    1042            0 :                         } UG_CATCH_THROW("L2ErrorIntegrand::evaluate: trial space missing.");
    1043            0 :                 }
    1044              : };
    1045              : 
    1046              : 
    1047              : template <typename TGridFunction>
    1048            0 : number GetMinimum(TGridFunction &gridFct, const char* cmp, const char* subsets)
    1049              : {
    1050              :         //      get function id of name & check that function exists
    1051              :         const size_t fct = gridFct.fct_id_by_name(cmp);
    1052            0 :         UG_COND_THROW(fct >= gridFct.num_fct(),
    1053              :                                 "L2Error: Function space does not contain a function with name " << cmp << ".");
    1054              : 
    1055              :         // Find minimum.
    1056              :         MaximumDistIntegrand<TGridFunction> spIntegrand(gridFct, fct);
    1057            0 :         IntegrateSubsets(spIntegrand, gridFct, subsets, 2);
    1058            0 :         return spIntegrand.min();
    1059              : }
    1060              : 
    1061              : template <typename TGridFunction>
    1062            0 : number Minimum(SmartPtr<TGridFunction> spGridFct, const char* cmp, const char* subsets)
    1063            0 : { return GetMinimum(*spGridFct, cmp, subsets); }
    1064              : 
    1065              : 
    1066              : ////////////////////////////////////////////////////////////////////////////////
    1067              : // L2 Error Integrand
    1068              : ////////////////////////////////////////////////////////////////////////////////
    1069              : 
    1070              : template <typename TGridFunction>
    1071              : class L2ErrorIntegrand
    1072              :         : public StdIntegrand<number, TGridFunction::dim, L2ErrorIntegrand<TGridFunction> >
    1073              : {
    1074              :         public:
    1075              :         ///     world dimension of grid function
    1076              :                 static const int worldDim = TGridFunction::dim;
    1077              : 
    1078              :         private:
    1079              :                 ScalarGridFunctionData<TGridFunction> m_scalarData;
    1080              : 
    1081              :         ///  exact solution
    1082              :                 SmartPtr<UserData<number, worldDim> > m_spExactSolution;
    1083              : 
    1084              :         ///     time
    1085              :                 number m_time;
    1086              : 
    1087              :         public:
    1088              :         /// constructor
    1089            0 :                 L2ErrorIntegrand(SmartPtr<UserData<number, worldDim> > spExactSol,
    1090              :                                  TGridFunction& gridFct, size_t cmp,
    1091              :                                  number time)
    1092              :                 : m_scalarData(gridFct, cmp),
    1093            0 :                   m_spExactSolution(spExactSol), m_time(time)
    1094              :                 {};
    1095              : 
    1096            0 :                 virtual ~L2ErrorIntegrand() {};
    1097              : 
    1098              :         ///     sets subset
    1099            0 :                 virtual void set_subset(int si)
    1100              :                 {
    1101            0 :                         if(!m_scalarData.is_def_in_subset(si))
    1102            0 :                                 UG_THROW("L2ErrorIntegrand: Grid function component"
    1103              :                                                 <<m_scalarData.fct()<<" not defined on subset "<<si);
    1104              :                         IIntegrand<number, worldDim>::set_subset(si);
    1105            0 :                 }
    1106              : 
    1107              :         /// \copydoc IIntegrand::values
    1108              :                 template <int elemDim>
    1109            0 :                 void evaluate(number vValue[],
    1110              :                               const MathVector<worldDim> vGlobIP[],
    1111              :                               GridObject* pElem,
    1112              :                               const MathVector<worldDim> vCornerCoords[],
    1113              :                               const MathVector<elemDim> vLocIP[],
    1114              :                               const MathMatrix<elemDim, worldDim> vJT[],
    1115              :                               const size_t numIP)
    1116              :                 {
    1117              :                 //      get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
    1118            0 :                         const ReferenceObjectID roid = pElem->reference_object_id();
    1119              : 
    1120              :                         try{
    1121              :                 //      get trial space
    1122              :                         const LocalShapeFunctionSet<elemDim>& rTrialSpace =
    1123              :                                                         LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
    1124              : 
    1125              :                 //      number of dofs on element
    1126            0 :                         const size_t num_sh = rTrialSpace.num_sh();
    1127              : 
    1128              :                 //      get multiindices of element
    1129              :                         std::vector<DoFIndex> ind;  //    aux. index array
    1130              :                         m_scalarData.dof_indices(pElem, ind);
    1131              : 
    1132              :                 //      check multi indices
    1133            0 :                         if(ind.size() != num_sh)
    1134            0 :                                 UG_THROW("L2ErrorIntegrand::evaluate: Wrong number of"
    1135              :                                                 " multi indices.");
    1136              : 
    1137              :                 //      loop all integration points
    1138            0 :                         for(size_t ip = 0; ip < numIP; ++ip)
    1139              :                         {
    1140              :                         //      compute exact solution at integration point
    1141              :                                 number exactSolIP;
    1142            0 :                                 (*m_spExactSolution)(exactSolIP, vGlobIP[ip], m_time, this->subset());
    1143              : 
    1144              :                         //      compute approximated solution at integration point
    1145              :                                 number approxSolIP = 0.0;
    1146            0 :                                 for(size_t sh = 0; sh < num_sh; ++sh)
    1147              :                                 {
    1148              :                                 //      get value at shape point (e.g. corner for P1 fct)
    1149            0 :                                         const number valSH = DoFRef(m_scalarData.grid_function(), ind[sh]);
    1150              : 
    1151              :                                 //      add shape fct at ip * value at shape
    1152            0 :                                         approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
    1153              :                                 }
    1154              : 
    1155              :                         //      get squared of difference
    1156            0 :                                 vValue[ip] = (exactSolIP - approxSolIP);
    1157            0 :                                 vValue[ip] *= vValue[ip];
    1158              :                         }
    1159              : 
    1160              :                         }
    1161            0 :                         UG_CATCH_THROW("L2ErrorIntegrand::evaluate: trial space missing.");
    1162            0 :                 }
    1163              : };
    1164              : 
    1165              : 
    1166              : 
    1167              : ////////////////////////////////////////////////////////////////////////////////
    1168              : // L2 Error Integrand
    1169              : ////////////////////////////////////////////////////////////////////////////////
    1170              : 
    1171              : /// computes the l2 error function on the whole domain or on some subsets
    1172              : /**
    1173              :  * This function computes the L2-difference between a given analytic function
    1174              :  * and a grid function.
    1175              :  *
    1176              :  * \param[in]           ExactSol        analytic function
    1177              :  * \param[in]           spGridFct       grid function
    1178              :  * \param[in]           cmp                     symbolic name of component function
    1179              :  * \param[in]           time            time point
    1180              :  * \param[in]           quadOrder       order of quadrature rule
    1181              :  * \param[in]           subsets         subsets, where to compute
    1182              :  * \returns                     number          l2-norm of difference
    1183              :  */
    1184              : template <typename TGridFunction>
    1185            0 : number L2Error(SmartPtr<UserData<number, TGridFunction::dim> > spExactSol,
    1186              :                TGridFunction& gridFct, const char* cmp,
    1187              :                number time, int quadOrder, const char* subsets)
    1188              : {
    1189              : //      get function id of name
    1190              :         const size_t fct = gridFct.fct_id_by_name(cmp);
    1191              : 
    1192              : //      check that function exists
    1193            0 :         UG_COND_THROW(fct >= gridFct.num_fct(),
    1194              :                                 "L2Error: Function space does not contain a function with name " << cmp << ".");
    1195              : 
    1196            0 :         L2ErrorIntegrand<TGridFunction> spIntegrand(spExactSol, gridFct, fct, time);
    1197            0 :         return sqrt(IntegrateSubsets(spIntegrand, gridFct, subsets, quadOrder));
    1198              : }
    1199              : 
    1200              : template <typename TGridFunction>
    1201            0 : number L2Error(SmartPtr<UserData<number, TGridFunction::dim> > spExactSol,
    1202              :                SmartPtr<TGridFunction> spGridFct, const char* cmp,
    1203              :                number time, int quadOrder, const char* subsets)
    1204            0 : { return L2Error(spExactSol, *spGridFct, cmp, time, quadOrder, subsets); }
    1205              : 
    1206              : template <typename TGridFunction>
    1207            0 : number L2Error(SmartPtr<UserData<number, TGridFunction::dim> > spExactSol,
    1208              :                SmartPtr<TGridFunction> spGridFct, const char* cmp,
    1209              :                number time, int quadOrder)
    1210            0 : { return L2Error(spExactSol, *spGridFct, cmp, time, quadOrder, NULL); }
    1211              : 
    1212              : 
    1213              : 
    1214              : 
    1215              : #ifdef UG_FOR_LUA
    1216              : template <typename TGridFunction>
    1217            0 : number L2Error(const char* ExactSol,
    1218              :                SmartPtr<TGridFunction> spGridFct, const char* cmp,
    1219              :                number time, int quadOrder, const char* subsets)
    1220              : {
    1221            0 :         SmartPtr<UserData<number, TGridFunction::dim> > spExactSol
    1222            0 :          = make_sp(new LuaUserData<number, TGridFunction::domain_type::dim>(ExactSol));
    1223            0 :         return L2Error(spExactSol, spGridFct, cmp, time, quadOrder, subsets);
    1224              : }
    1225              : 
    1226              : template <typename TGridFunction>
    1227            0 : number L2Error(const char* ExactSol,
    1228              :                SmartPtr<TGridFunction> spGridFct, const char* cmp,
    1229              :                number time, int quadOrder)
    1230              : {
    1231            0 :         return L2Error(ExactSol, spGridFct, cmp, time, quadOrder, NULL);
    1232              : }
    1233              : #endif //UG_FOR_LUA
    1234              : 
    1235              : 
    1236              : 
    1237              : #ifdef UG_DEBUG
    1238              : // True, if max norm is less than SMALL.
    1239              : template <int worldDim, int elemDim>
    1240              : void CheckGeneralizedInverse(const MathMatrix<elemDim, worldDim> &JT, const MathMatrix<worldDim, elemDim> &JTInv)
    1241              : {
    1242              :         if (worldDim==elemDim) return;
    1243              : 
    1244              :         MathMatrix<worldDim, elemDim> myTmp;
    1245              :         GeneralizedInverse(myTmp, JT); //old algorithms with Inverse, but Inverse is only defined for NxN Matrix
    1246              :         MatSubtract(myTmp, JTInv, myTmp);
    1247              : 
    1248              :         UG_ASSERT(MatMaxNorm(myTmp)<SMALL,
    1249              :                 "The inverse matrix is not identity to the map jacobian transposed inverse.");
    1250              : 
    1251              : }
    1252              : #endif
    1253              : 
    1254              : 
    1255              : ////////////////////////////////////////////////////////////////////////////////
    1256              : // H1 Error Integrand
    1257              : ////////////////////////////////////////////////////////////////////////////////
    1258              : 
    1259              : template <typename TGridFunction>
    1260            0 : class H1ErrorIntegrand
    1261              :         : public StdIntegrand<number, TGridFunction::dim, H1ErrorIntegrand<TGridFunction> >
    1262              : {
    1263              :         public:
    1264              :         ///     world dimension of grid function
    1265              :                 static const int worldDim = TGridFunction::dim;
    1266              : 
    1267              :         private:
    1268              :         /// grid function
    1269              :                 ScalarGridFunctionData<TGridFunction> m_scalarData;
    1270              : 
    1271              :         ///     exact solution
    1272              :                 SmartPtr<UserData<number, worldDim> > m_spExactSolution;
    1273              : 
    1274              :         ///     exact gradient
    1275              :                 SmartPtr<UserData<MathVector<worldDim>, worldDim> > m_spExactGrad;
    1276              : 
    1277              :         ///     time
    1278              :                 number m_time;
    1279              : 
    1280              :         public:
    1281              :         /// constructor
    1282            0 :                 H1ErrorIntegrand(SmartPtr<UserData<number, worldDim> > spExactSol,
    1283              :                                  SmartPtr<UserData<MathVector<worldDim>, worldDim> > spExactGrad,
    1284              :                                  TGridFunction& gridFct, size_t cmp,
    1285              :                                  number time)
    1286              :                 : m_scalarData (gridFct, cmp),
    1287              :                   m_spExactSolution(spExactSol),
    1288              :                   m_spExactGrad(spExactGrad),
    1289            0 :                   m_time(time)
    1290            0 :                 {}
    1291              : 
    1292              :         ///     sets subset
    1293            0 :                 virtual void set_subset(int si)
    1294              :                 {
    1295            0 :                         if(!m_scalarData.is_def_in_subset(si))
    1296            0 :                                 UG_THROW("H1Error: Grid function component"
    1297              :                                                 <<m_scalarData.fct()<<" not defined on subset "<<si);
    1298              :                         IIntegrand<number, worldDim>::set_subset(si);
    1299            0 :                 }
    1300              : 
    1301              :         /// \copydoc IIntegrand::values
    1302              :                 template <int elemDim>
    1303            0 :                 void evaluate(number vValue[],
    1304              :                               const MathVector<worldDim> vGlobIP[],
    1305              :                               GridObject* pElem,
    1306              :                               const MathVector<worldDim> vCornerCoords[],
    1307              :                               const MathVector<elemDim> vLocIP[],
    1308              :                               const MathMatrix<elemDim, worldDim> vJT[],
    1309              :                               const size_t numIP)
    1310              :                 {
    1311              :                 //      get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
    1312            0 :                         const ReferenceObjectID roid = pElem->reference_object_id();
    1313              : 
    1314              :                         DimReferenceMapping<elemDim, worldDim>& map
    1315              :                                 = ReferenceMappingProvider::get<elemDim, worldDim>(roid, vCornerCoords);
    1316              : 
    1317              :                         try{
    1318              :                 //      get trial space
    1319              :                         const LocalShapeFunctionSet<elemDim>& rTrialSpace =
    1320              :                                                         LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
    1321              : 
    1322              :                 //      number of dofs on element
    1323            0 :                         const size_t num_sh = rTrialSpace.num_sh();
    1324              : 
    1325              :                 //      get multiindices of element
    1326              :                         std::vector<DoFIndex> ind;  //    aux. index array
    1327              :                         m_scalarData.dof_indices(pElem, ind);
    1328              : 
    1329              :                 //      check multi indices
    1330            0 :                         if(ind.size() != num_sh)
    1331            0 :                                 UG_THROW("H1ErrorIntegrand::evaluate: Wrong number of"
    1332              :                                                 " multi indices.");
    1333              : 
    1334              :                 //      loop all integration points
    1335            0 :                         std::vector<MathVector<elemDim> > vLocGradient(num_sh);
    1336            0 :                         for(size_t ip = 0; ip < numIP; ++ip)
    1337              :                         {
    1338              :                         //      compute exact solution at integration point
    1339              :                                 number exactSolIP;
    1340            0 :                                 (*m_spExactSolution)(exactSolIP, vGlobIP[ip], m_time, this->subset());
    1341              : 
    1342              :                         //      compute exact gradient at integration point
    1343              :                                 MathVector<worldDim> exactGradIP;
    1344            0 :                                 (*m_spExactGrad)(exactGradIP, vGlobIP[ip], m_time, this->subset());
    1345              : 
    1346              :                         //      compute shape gradients at ip
    1347            0 :                                 rTrialSpace.grads(&vLocGradient[0], vLocIP[ip]);
    1348              : 
    1349              :                         //      compute approximated solution at integration point
    1350              :                                 number approxSolIP = 0.0;
    1351              :                                 MathVector<elemDim> locTmp; VecSet(locTmp, 0.0);
    1352            0 :                                 for(size_t sh = 0; sh < num_sh; ++sh)
    1353              :                                 {
    1354              :                                 //      get value at shape point (e.g. corner for P1 fct)
    1355            0 :                                         const number valSH = DoFRef(m_scalarData.grid_function(), ind[sh]);
    1356              : 
    1357              :                                 //      add shape fct at ip * value at shape
    1358            0 :                                         approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
    1359              : 
    1360              :                                 //      add gradient at ip
    1361              :                                         VecScaleAppend(locTmp, valSH, vLocGradient[sh]);
    1362              :                                 }
    1363              : 
    1364              :                         //      compute global gradient
    1365              :                                 MathVector<worldDim> approxGradIP;
    1366              :                                 MathMatrix<worldDim, elemDim> JTInv;
    1367            0 :                                 map.jacobian_transposed_inverse(JTInv, vLocIP[ip]); //Inverse(JTInv, vJT[ip]);
    1368              :                                 
    1369              : #ifdef UG_DEBUG
    1370              :                                 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], JTInv);
    1371              : #endif //UG_DEBUG
    1372              : 
    1373              :                                 MatVecMult(approxGradIP, JTInv, locTmp);
    1374              : 
    1375              :                         //      get squared of difference
    1376            0 :                                 vValue[ip] = (exactSolIP - approxSolIP) * (exactSolIP - approxSolIP);
    1377            0 :                                 vValue[ip] += VecDistanceSq(approxGradIP, exactGradIP);
    1378              :                         }
    1379              : 
    1380            0 :                         }
    1381            0 :                         UG_CATCH_THROW("H1ErrorIntegrand::evaluate: trial space missing.");
    1382            0 :                 }
    1383              : };
    1384              : 
    1385              : /// compute H1 error of a function on the whole domain or on some subsets
    1386              : /**
    1387              :  * This function computes the H1-difference between a given analytic function
    1388              :  * and a grid function.
    1389              :  *
    1390              :  * \param[in]           spExactSol      analytic function
    1391              :  * \param[in]           spExactGrad     analytic gradient
    1392              :  * \param[in]           spGridFct       grid function
    1393              :  * \param[in]           cmp                     symbolic name of component function
    1394              :  * \param[in]           time            time point
    1395              :  * \param[in]           quadOrder       order of quadrature rule
    1396              :  * \param[in]           subsets         subsets, where to compute
    1397              :  * \returns                     number          l2-norm of difference
    1398              :  */
    1399              : template <typename TGridFunction>
    1400            0 : number H1Error(SmartPtr<UserData<number, TGridFunction::dim> > spExactSol,
    1401              :                SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spExactGrad,
    1402              :                            SmartPtr<TGridFunction> spGridFct, const char* cmp,
    1403              :                            number time, int quadOrder, const char* subsets)
    1404              : {
    1405              : //      get function id of name
    1406              :         const size_t fct = spGridFct->fct_id_by_name(cmp);
    1407              : 
    1408              : //      check that function exists
    1409            0 :         if(fct >= spGridFct->num_fct())
    1410            0 :                 UG_THROW("H1Error: Function space does not contain"
    1411              :                                 " a function with name " << cmp << ".");
    1412              : 
    1413            0 :         H1ErrorIntegrand<TGridFunction> spIntegrand(spExactSol, spExactGrad, *spGridFct, fct, time);
    1414            0 :         return sqrt(IntegrateSubsets(spIntegrand, *spGridFct, subsets, quadOrder));
    1415              : }
    1416              : 
    1417              : template <typename TGridFunction>
    1418            0 : number H1Error(SmartPtr<UserData<number, TGridFunction::dim> > spExactSol,
    1419              :                SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spExactGrad,
    1420              :                            SmartPtr<TGridFunction> spGridFct, const char* cmp,
    1421              :                            number time, int quadOrder)
    1422              : {
    1423            0 :         return H1Error(spExactSol, spExactGrad, spGridFct, cmp, time, quadOrder, NULL);
    1424              : }
    1425              : 
    1426              : #ifdef UG_FOR_LUA
    1427              : template <typename TGridFunction>
    1428            0 : number H1Error(const char* ExactSol, const char* ExactGrad,
    1429              :                            SmartPtr<TGridFunction> spGridFct, const char* cmp,
    1430              :                            number time, int quadOrder, const char* subsets)
    1431              : {
    1432              :         static const int dim = TGridFunction::domain_type::dim;
    1433            0 :         SmartPtr<UserData<number, dim> > spExactSol
    1434            0 :          = make_sp(new LuaUserData<number, dim>(ExactSol));
    1435            0 :         SmartPtr<UserData<MathVector<dim>, dim> > spExactGrad
    1436            0 :          = make_sp(new LuaUserData<MathVector<dim>, dim>(ExactGrad));
    1437            0 :         return H1Error(spExactSol, spExactGrad, spGridFct, cmp, time, quadOrder, subsets);
    1438              : }
    1439              : 
    1440              : template <typename TGridFunction>
    1441            0 : number H1Error(const char* ExactSol, const char* ExactGrad,
    1442              :                            SmartPtr<TGridFunction> spGridFct, const char* cmp,
    1443              :                            number time, int quadOrder)
    1444              : {
    1445            0 :         return H1Error(ExactSol, ExactGrad, spGridFct, cmp, time, quadOrder, NULL);
    1446              : }
    1447              : #endif
    1448              : 
    1449              : 
    1450              : 
    1451              : /// computes an (abstract) distance between two functions
    1452              : /**
    1453              :  * This function computes the (abstract) TDiffError-difference between two grid functions that
    1454              :  * may be defined on different grids. The element loop is performed over the
    1455              :  * finer level.
    1456              :  *
    1457              :  * \param[in]           spGridFct1      grid function 1
    1458              :  * \param[in]           cmp1            symbolic name of component function
    1459              :  * \param[in]           spGridFct2      grid function 2
    1460              :  * \param[in]           cmp2            symbolic name of component function
    1461              :  * \param[in]           quadOrder       order of quadrature rule
    1462              :  * \param[in]           subsets         subsets, where to compute
    1463              :  * \returns                     number          H1-norm of difference
    1464              :  */
    1465              : template <typename TDistIntegrand, typename TGridFunction>
    1466            0 : number GridFunctionDistance2(TGridFunction& spGridFct1, const char* cmp1,
    1467              :                                                         TGridFunction& spGridFct2, const char* cmp2,
    1468              :                                                         int quadOrder, const char* subsets)
    1469              : {
    1470              : //      get function id of name
    1471              :         const size_t fct1 = spGridFct1.fct_id_by_name(cmp1);
    1472              :         const size_t fct2 = spGridFct2.fct_id_by_name(cmp2);
    1473              : 
    1474              : //      check that function exists
    1475            0 :         if(fct1 >= spGridFct1.num_fct())
    1476            0 :                 UG_THROW("GridFunctionDistance: Function space does not contain"
    1477              :                                 " a function with name " << cmp1 << ".");
    1478            0 :         if(fct2 >= spGridFct2.num_fct())
    1479            0 :                 UG_THROW("GridFunctionDistance: Function space does not contain"
    1480              :                                 " a function with name " << cmp2 << ".");
    1481              : 
    1482              : //      get top level of grid functions
    1483            0 :         const int level1 = spGridFct1.dof_distribution()->grid_level().level();
    1484            0 :         const int level2 = spGridFct2.dof_distribution()->grid_level().level();
    1485              : 
    1486            0 :         if(level1 > level2){
    1487              :                 // level check
    1488            0 :                 TDistIntegrand spIntegrand(spGridFct1, fct1, spGridFct2, fct2);
    1489            0 :                 return IntegrateSubsets(spIntegrand, spGridFct1, subsets, quadOrder);
    1490              :         }else{
    1491            0 :                 TDistIntegrand spIntegrand(spGridFct2, fct2, spGridFct1, fct1);
    1492            0 :                 return IntegrateSubsets(spIntegrand, spGridFct2, subsets, quadOrder);
    1493              :         }
    1494              : 
    1495              : }
    1496              : 
    1497              : //! Computes (weighted) distance
    1498              : template <typename TDistIntegrand, typename TGridFunction>
    1499            0 : number GridFunctionDistance2(TGridFunction& spGridFct1, const char* cmp1,
    1500              :                TGridFunction& spGridFct2, const char* cmp2,
    1501              :                int quadOrder, const char* subsets, ConstSmartPtr<typename TDistIntegrand::weight_type> spWeights)
    1502              : {
    1503              : //      get function id of name
    1504              :         const size_t fct1 = spGridFct1.fct_id_by_name(cmp1);
    1505              :         const size_t fct2 = spGridFct2.fct_id_by_name(cmp2);
    1506              : 
    1507              : //      check that function exists
    1508            0 :         if(fct1 >= spGridFct1.num_fct())
    1509            0 :                 UG_THROW("GridFunctionDistance: Function space does not contain"
    1510              :                                 " a function with name " << cmp1 << ".");
    1511            0 :         if(fct2 >= spGridFct2.num_fct())
    1512            0 :                 UG_THROW("GridFunctionDistance: Function space does not contain"
    1513              :                                 " a function with name " << cmp2 << ".");
    1514              : 
    1515              : //      get top level of gridfunctions
    1516            0 :         const int level1 = spGridFct1.dof_distribution()->grid_level().level();
    1517            0 :         const int level2 = spGridFct2.dof_distribution()->grid_level().level();
    1518              : 
    1519              :         // w/ weights
    1520            0 :         if(level1 > level2){
    1521            0 :                 TDistIntegrand spIntegrand(spGridFct1, fct1, spGridFct2, fct2, spWeights);
    1522            0 :                 return IntegrateSubsets(spIntegrand, spGridFct1, subsets, quadOrder);
    1523              :         }else{
    1524            0 :                 TDistIntegrand spIntegrand(spGridFct2, fct2, spGridFct1, fct1, spWeights);
    1525            0 :                 return IntegrateSubsets(spIntegrand, spGridFct2, subsets, quadOrder);
    1526              :         }
    1527              : }
    1528              : 
    1529              : 
    1530              : //! Computes (weighted) distance with shift for averages
    1531              : template <typename TDistIntegrand, typename TGridFunction>
    1532            0 : number GridFunctionDistance2(TGridFunction& spGridFct1, const char* cmp1,
    1533              :                TGridFunction& spGridFct2, const char* cmp2,
    1534              :                int quadOrder, const char* subsets,
    1535              :                            ConstSmartPtr<typename TDistIntegrand::weight_type> spWeights,
    1536              :                            number distAvg12)
    1537              : {
    1538              : //      get function id of name
    1539              :         const size_t fct1 = spGridFct1.fct_id_by_name(cmp1);
    1540              :         const size_t fct2 = spGridFct2.fct_id_by_name(cmp2);
    1541              : 
    1542              : //      check that function exists
    1543            0 :         if(fct1 >= spGridFct1.num_fct())
    1544            0 :                 UG_THROW("GridFunctionDistance: Function space does not contain"
    1545              :                                 " a function with name " << cmp1 << ".");
    1546            0 :         if(fct2 >= spGridFct2.num_fct())
    1547            0 :                 UG_THROW("GridFunctionDistance: Function space does not contain"
    1548              :                                 " a function with name " << cmp2 << ".");
    1549              : 
    1550              : //      get top level of gridfunctions
    1551            0 :         const int level1 = spGridFct1.dof_distribution()->grid_level().level();
    1552            0 :         const int level2 = spGridFct2.dof_distribution()->grid_level().level();
    1553              : 
    1554              :         // w/ weights
    1555            0 :         if(level1 > level2){
    1556            0 :                 TDistIntegrand spIntegrand(spGridFct1, fct1, spGridFct2, fct2, spWeights, distAvg12);
    1557            0 :                 return IntegrateSubsets(spIntegrand, spGridFct1, subsets, quadOrder);
    1558              :         }else{
    1559            0 :                 TDistIntegrand spIntegrand(spGridFct2, fct2, spGridFct1, fct1, spWeights, -distAvg12);
    1560            0 :                 return IntegrateSubsets(spIntegrand, spGridFct2, subsets, quadOrder);
    1561              :         }
    1562              : }
    1563              : 
    1564              : 
    1565              : 
    1566              : ////////////////////////////////////////////////////////////////////////////////
    1567              : // L2 Integrand
    1568              : ////////////////////////////////////////////////////////////////////////////////
    1569              : 
    1570              : /// Grid function as L2 integrand
    1571              : template <typename TGridFunction>
    1572              : class L2Integrand
    1573              :         : public StdIntegrand<number, TGridFunction::dim, L2Integrand<TGridFunction> >
    1574              : {
    1575              :         public:
    1576              :         //      world dimension of grid function
    1577              :                 static const int worldDim = TGridFunction::dim;
    1578              :                 typedef UserData<number, worldDim> weight_type;
    1579              : 
    1580              :         protected:
    1581              :         // grid function data
    1582              :                 ScalarGridFunctionData<TGridFunction> m_scalarData;
    1583              : 
    1584              :         /// scalar weight (optional, default is 1.0)
    1585              :                 ConstSmartPtr<weight_type> m_spWeight;
    1586              : 
    1587              :         public:
    1588              :         /// CTOR
    1589            0 :                 L2Integrand(TGridFunction& spGridFct, size_t cmp)
    1590            0 :                 : m_scalarData(spGridFct, cmp), m_spWeight(make_sp(new ConstUserNumber<worldDim>(1.0)))
    1591            0 :                 {};
    1592              : 
    1593            0 :                 L2Integrand(TGridFunction& spGridFct, size_t cmp, ConstSmartPtr<weight_type> spWeight)
    1594            0 :                 : m_scalarData(spGridFct, cmp), m_spWeight(spWeight)
    1595              :                 {};
    1596              : 
    1597              :         /// DTOR
    1598            0 :                 virtual ~L2Integrand() {};
    1599              : 
    1600              :         ///     sets subset
    1601            0 :                 virtual void set_subset(int si)
    1602              :                 {
    1603            0 :                         if(!m_scalarData.is_def_in_subset(si))
    1604            0 :                                 UG_THROW("L2ErrorIntegrand: Grid function component" <<m_scalarData.fct() <<" not defined on subset "<<si);
    1605              :                         IIntegrand<number, worldDim>::set_subset(si);
    1606            0 :                 }
    1607              : 
    1608              :         /// \copydoc IIntegrand::values
    1609              :                 template <int elemDim>
    1610            0 :                 void evaluate(number vValue[],
    1611              :                               const MathVector<worldDim> vGlobIP[],
    1612              :                               GridObject* pElem,
    1613              :                               const MathVector<worldDim> vCornerCoords[],
    1614              :                               const MathVector<elemDim> vLocIP[],
    1615              :                               const MathMatrix<elemDim, worldDim> vJT[],
    1616              :                               const size_t numIP)
    1617              :                 {
    1618              :                 //      get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
    1619            0 :                         ReferenceObjectID roid = (ReferenceObjectID) pElem->reference_object_id();
    1620              : 
    1621              :                 // element weights
    1622              :                         typedef typename weight_type::data_type ipdata_type;
    1623            0 :                         std::vector<ipdata_type> locElemWeights(numIP, 1.0);
    1624              :                         UG_ASSERT(m_spWeight.valid(), "L2Integrand::evaluate requires valid weights!");
    1625            0 :                         (*m_spWeight)(&locElemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
    1626              : 
    1627              :                         try{
    1628              :                 //      get trial space
    1629              :                         const LocalShapeFunctionSet<elemDim>& rTrialSpace =
    1630              :                                                         LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
    1631              : 
    1632              :                 //      number of dofs on element
    1633            0 :                         const size_t num_sh = rTrialSpace.num_sh();
    1634              : 
    1635              :                 //      get multiindices of element
    1636              :                         std::vector<DoFIndex> ind;  //    aux. index array
    1637              :                         m_scalarData.dof_indices(pElem, ind);
    1638              : 
    1639              :                 //      check multi indices
    1640            0 :                         if(ind.size() != num_sh)
    1641            0 :                                 UG_THROW("L2Integrand::evaluate: Wrong number of multi indices.");
    1642              : 
    1643              :                 //      loop all integration points
    1644            0 :                         for(size_t ip = 0; ip < numIP; ++ip)
    1645              :                         {
    1646              : 
    1647              :                         //      compute approximated solution at integration point
    1648              :                                 number approxSolIP = 0.0;
    1649            0 :                                 for(size_t sh = 0; sh < num_sh; ++sh)
    1650              :                                 {
    1651              :                                         //      get value at shape point (e.g. corner for P1 fct)
    1652              :                                         //      and add shape fct at ip * value at shape
    1653            0 :                                         const number valSH = DoFRef(m_scalarData.grid_function(), ind[sh]);
    1654            0 :                                         approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
    1655              :                                 }
    1656              : 
    1657              :                                 //      get square
    1658            0 :                                 vValue[ip] = locElemWeights[ip]*approxSolIP*approxSolIP;
    1659              : 
    1660              :                         }
    1661              : 
    1662              :                         }
    1663            0 :                         UG_CATCH_THROW("L2FuncIntegrand::values: trial space missing.");
    1664            0 :                 }
    1665              : };
    1666              : 
    1667              : /**
    1668              :  * This function computes the square of the L2-norm of a grid function.
    1669              :  *
    1670              :  * \param[in]           spGridFct       grid function
    1671              :  * \param[in]           cmp                     symbolic name of function
    1672              :  * \param[in]           quadOrder       order of quadrature rule
    1673              :  * \param[in]           subsets         subsets, where to interpolate
    1674              :  *                                                              (NULL indicates that all full-dimensional subsets
    1675              :  *                                                              shall be considered)
    1676              :  * \returns                     number          l2-norm
    1677              :  */
    1678              : 
    1679              : template <typename TGridFunction>
    1680            0 : number L2Norm2(TGridFunction& u, const char* cmp,
    1681              :               int quadOrder, const char* subsets,
    1682              :                           ConstSmartPtr<typename L2Integrand<TGridFunction>::weight_type> spWeight)
    1683              : {
    1684              : //      get function id of name
    1685              :         const size_t fct = u.fct_id_by_name(cmp);
    1686              : 
    1687              : //      check that function exists
    1688            0 :         UG_COND_THROW(fct >= u.num_fct(), "L2Norm: Function space does not contain"
    1689              :                                 " a function with name " << cmp << ".");
    1690              : 
    1691            0 :         L2Integrand<TGridFunction> integrandL2(u, fct, spWeight);
    1692            0 :         return IntegrateSubsets(integrandL2, u, subsets, quadOrder);
    1693              : }
    1694              : 
    1695              : template <typename TGridFunction>
    1696            0 : number L2Norm2(TGridFunction& u, const char* cmp,
    1697              :               int quadOrder, const char* subsets)
    1698              : {
    1699              : //      get function id of name
    1700              :         const size_t fct = u.fct_id_by_name(cmp);
    1701              : 
    1702              : //      check that function exists
    1703            0 :         UG_COND_THROW(fct >= u.num_fct(), "L2Norm: Function space does not contain"
    1704              :                                 " a function with name " << cmp << ".");
    1705              : 
    1706            0 :         L2Integrand<TGridFunction> integrandL2(u, fct);
    1707            0 :         return IntegrateSubsets(integrandL2, u, subsets, quadOrder);
    1708              : }
    1709              : 
    1710              : template <typename TGridFunction>
    1711              : number L2Norm(TGridFunction& u, const char* cmp,
    1712              :               int quadOrder, const char* subsets)
    1713              : {
    1714            0 :         return sqrt(L2Norm2(u, cmp, quadOrder, subsets));
    1715              : }
    1716              : /**
    1717              :  * This function computes the L2-norm of a grid function on all full-dim subsets.
    1718              :  *
    1719              :  * \param[in]           spGridFct       grid function
    1720              :  * \param[in]           cmp                     symbolic name of function
    1721              :  * \param[in]           quadOrder       order of quadrature rule
    1722              :  * \returns                     number          l2-norm
    1723              :  */
    1724              : template <typename TGridFunction>
    1725              : number L2Norm(TGridFunction& gridFct, const char* cmp, int quadOrder)
    1726              : { return L2Norm(gridFct, cmp, quadOrder, NULL); }
    1727              : 
    1728              : template <typename TGridFunction>
    1729            0 : number L2Norm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder, const char* subsets)
    1730            0 : { return L2Norm(*spGridFct, cmp, quadOrder, subsets); }
    1731              : 
    1732              : template <typename TGridFunction>
    1733            0 : number L2Norm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder)
    1734            0 : { return L2Norm(spGridFct, cmp, quadOrder, NULL); }
    1735              : 
    1736              : 
    1737              : /// Integrand for the distance of two grid functions - evaluated in the (weighted) H1-semi norm
    1738              : template <typename TGridFunction>
    1739              : class L2DistIntegrand
    1740              :                 : public StdIntegrand<number, TGridFunction::dim, L2DistIntegrand<TGridFunction> >
    1741              : {
    1742              :         public:
    1743              :         ///     world dimension of grid function
    1744              :                 static const int worldDim = TGridFunction::dim;
    1745              :                 typedef typename L2Integrand<TGridFunction>::weight_type weight_type;
    1746              : 
    1747              :         protected:
    1748              :                 ScalarGridFunctionData<TGridFunction> m_fineData;
    1749              :                 const int m_fineTopLevel;
    1750              : 
    1751              :                 ScalarGridFunctionData<TGridFunction> m_coarseData;
    1752              :                 const int m_coarseTopLevel;
    1753              : 
    1754              :         ///     multigrid
    1755              :                 SmartPtr<MultiGrid> m_spMG;
    1756              : 
    1757              :                 ConstSmartPtr<weight_type> m_spWeight;
    1758              : 
    1759              :         /// shift
    1760              :                 double m_deltaFineCoarse;
    1761              : 
    1762              :         public:
    1763              : 
    1764              :                 /// constructor (1st is fine grid function)
    1765            0 :                 L2DistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
    1766              :                                         TGridFunction& coarseGridFct, size_t coarseCmp)
    1767            0 :                 : m_fineData(fineGridFct, fineCmp), m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
    1768            0 :                   m_coarseData(coarseGridFct, coarseCmp), m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
    1769            0 :                   m_spMG(m_fineData.domain()->grid()), m_spWeight(make_sp(new ConstUserNumber<TGridFunction::dim>(1.0))),
    1770            0 :                   m_deltaFineCoarse(0.0)
    1771              :                 {
    1772            0 :                         UG_COND_THROW(m_fineTopLevel < m_coarseTopLevel,
    1773              :                                 "L2DiffIntegrand: fine and top level inverted.");
    1774            0 :                         UG_COND_THROW(m_fineData.domain().get() != m_coarseData.domain().get(),
    1775              :                                 "L2DiffIntegrand: grid functions defined on different domains.");
    1776            0 :                 };
    1777              : 
    1778              :                 /// constructor (1st is fine grid function)
    1779              :                 L2DistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
    1780              :                                         TGridFunction& coarseGridFct, size_t coarseCmp, ConstSmartPtr<weight_type> spWeight)
    1781              :                 : m_fineData(fineGridFct, fineCmp), m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
    1782              :                   m_coarseData(coarseGridFct, coarseCmp), m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
    1783              :                   m_spMG(m_fineData.domain()->grid()), m_spWeight(spWeight),
    1784              :                   m_deltaFineCoarse(0.0)
    1785              :                 {
    1786              :                         UG_COND_THROW(m_fineTopLevel < m_coarseTopLevel,
    1787              :                                         "L2DiffIntegrand: fine and top level inverted.");
    1788              :                         UG_COND_THROW(m_fineData.domain().get() != m_coarseData.domain().get(),
    1789              :                                         "L2DiffIntegrand: grid functions defined on different domains.");
    1790              :                 };
    1791              : 
    1792              :                 /// constructor (1st is fine grid function)
    1793            0 :                 L2DistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
    1794              :                                 TGridFunction& coarseGridFct, size_t coarseCmp, ConstSmartPtr<weight_type> spWeight, number dist12)
    1795            0 :                 : m_fineData(fineGridFct, fineCmp), m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
    1796            0 :                   m_coarseData(coarseGridFct, coarseCmp), m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
    1797            0 :                   m_spMG(m_fineData.domain()->grid()), m_spWeight(spWeight),
    1798            0 :                   m_deltaFineCoarse(dist12)
    1799              :                 {
    1800            0 :                         UG_COND_THROW(m_fineTopLevel < m_coarseTopLevel,
    1801              :                                         "L2DiffIntegrand: fine and top level inverted.");
    1802            0 :                         UG_COND_THROW(m_fineData.domain().get() != m_coarseData.domain().get(),
    1803              :                                         "L2DiffIntegrand: grid functions defined on different domains.");
    1804            0 :                 };
    1805              : 
    1806              : 
    1807            0 :                 virtual ~L2DistIntegrand() {}
    1808              : 
    1809              :                 ///     sets subset
    1810            0 :                 virtual void set_subset(int si)
    1811              :                 {
    1812            0 :                         UG_COND_THROW(!m_fineData.is_def_in_subset(si),
    1813              :                                 "L2DiffIntegrand: Grid function component" <<m_fineData.fct()<<" not defined on subset "<<si);
    1814            0 :                         UG_COND_THROW(!m_coarseData.is_def_in_subset(si),
    1815              :                                 "L2DiffIntegrand: Grid function component" <<m_coarseData.fct()<<" not defined on subset "<<si);
    1816              :                         IIntegrand<number, worldDim>::set_subset(si);
    1817            0 :                 }
    1818              : 
    1819              :         /// \copydoc IIntegrand::values
    1820              :                 template <int elemDim>
    1821            0 :                 void evaluate(number vValue[],
    1822              :                               const MathVector<worldDim> vFineGlobIP[],
    1823              :                               GridObject* pFineElem,
    1824              :                               const MathVector<worldDim> vCornerCoords[],
    1825              :                               const MathVector<elemDim> vFineLocIP[],
    1826              :                               const MathMatrix<elemDim, worldDim> vJT[],
    1827              :                               const size_t numIP)
    1828              :                 {
    1829              :                         typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object Element;
    1830              : 
    1831              :                         //      get coarse element
    1832              :                         GridObject* pCoarseElem = pFineElem;
    1833            0 :                         if(m_coarseTopLevel < m_fineTopLevel){
    1834              :                                 int parentLevel = m_spMG->get_level(pCoarseElem);
    1835            0 :                                 while(parentLevel > m_coarseTopLevel){
    1836            0 :                                         pCoarseElem = m_spMG->get_parent(pCoarseElem);
    1837              :                                         parentLevel = m_spMG->get_level(pCoarseElem);
    1838              :                                 }
    1839              :                         }
    1840              : 
    1841              :                 //      get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
    1842            0 :                         const ReferenceObjectID fineROID = pFineElem->reference_object_id();
    1843            0 :                         const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
    1844              : 
    1845              :                 //      get corner coordinates
    1846              :                         std::vector<MathVector<worldDim> > vCornerCoarse;
    1847            0 :                         CollectCornerCoordinates(vCornerCoarse, *static_cast<Element*>(pCoarseElem), *m_coarseData.domain());
    1848              : 
    1849              :                 //      get Reference Mapping
    1850              :                         DimReferenceMapping<elemDim, worldDim>& map
    1851              :                                 = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
    1852              : 
    1853              :                         std::vector<MathVector<elemDim> > vCoarseLocIP;
    1854            0 :                         vCoarseLocIP.resize(numIP);
    1855            0 :                         for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
    1856            0 :                         map.global_to_local(&vCoarseLocIP[0], vFineGlobIP, numIP);
    1857              : 
    1858              :                 // element weights
    1859              :                         typedef typename weight_type::data_type ipdata_type;
    1860            0 :                         std::vector<ipdata_type> fineElemWeights(numIP, 1.0);
    1861              :                         UG_ASSERT(m_spWeight.valid(), "L2DistIntegrand::evaluate requires valid weights! ");
    1862            0 :                         (*m_spWeight)(&fineElemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
    1863              : 
    1864              :                 try{
    1865              :                 //      get trial space
    1866              :                         const LocalShapeFunctionSet<elemDim>& rFineLSFS =
    1867              :                                         LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
    1868              :                         const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
    1869              :                                         LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());
    1870              : 
    1871              :                 //      get multiindices of element
    1872              :                         std::vector<DoFIndex> vFineMI, vCoarseMI;
    1873              :                         m_fineData.dof_indices(pFineElem, vFineMI);
    1874              :                         m_coarseData.dof_indices(pCoarseElem, vCoarseMI);
    1875              : 
    1876              :                 //      loop all integration points
    1877            0 :                         for(size_t ip = 0; ip < numIP; ++ip)
    1878              :                         {
    1879              :                         //      compute approximated solution at integration point
    1880              :                                 number fineSolIP = 0.0;
    1881            0 :                                 for(size_t sh = 0; sh < vFineMI.size(); ++sh)
    1882              :                                 {
    1883              :                                 //      get value at shape point (e.g. corner for P1 fct)
    1884            0 :                                         const number val = DoFRef(m_fineData.grid_function(), vFineMI[sh]);
    1885              : 
    1886              :                                 //      add shape fct at ip * value at shape
    1887            0 :                                         fineSolIP += val * rFineLSFS.shape(sh, vFineLocIP[ip]);
    1888              :                                 }
    1889              :                                 number coarseSolIP = 0.0;
    1890            0 :                                 for(size_t sh = 0; sh < vCoarseMI.size(); ++sh)
    1891              :                                 {
    1892              :                                 //      get value at shape point (e.g. corner for P1 fct)
    1893            0 :                                         const number val = DoFRef(m_coarseData.grid_function(), vCoarseMI[sh]);
    1894              : 
    1895              :                                 //      add shape fct at ip * value at shape
    1896            0 :                                         coarseSolIP += val * rCoarseLSFS.shape(sh, vCoarseLocIP[ip]);
    1897              :                                 }
    1898              : 
    1899              :                         //      get squared of difference
    1900            0 :                                 vValue[ip] = fineElemWeights[ip]*(fineSolIP - coarseSolIP -m_deltaFineCoarse)*(fineSolIP-coarseSolIP-m_deltaFineCoarse);
    1901              :                         }
    1902              : 
    1903              :                         }
    1904            0 :                         UG_CATCH_THROW("L2DistIntegrand::evaluate: trial space missing.");
    1905            0 :                 }
    1906              : };
    1907              : 
    1908              : 
    1909              : /// computes the squared l2 distance between two functions
    1910              : template <typename TGridFunction>
    1911            0 : number L2Distance2(TGridFunction& spGridFct1, const char* cmp1,
    1912              :                TGridFunction& spGridFct2, const char* cmp2,
    1913              :                int quadOrder, const char* subsets,
    1914              :                            ConstSmartPtr<typename L2Integrand<TGridFunction>::weight_type> spWeight, number avgDist12=0.0)
    1915              : {
    1916              :         return GridFunctionDistance2<L2DistIntegrand<TGridFunction>, TGridFunction>
    1917            0 :                 (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, spWeight, avgDist12);
    1918              : }
    1919              : 
    1920              : 
    1921              : /// computes the squared l2 distance between two functions
    1922              : template <typename TGridFunction>
    1923              : number L2Distance2(TGridFunction& spGridFct1, const char* cmp1,
    1924              :                TGridFunction& spGridFct2, const char* cmp2,
    1925              :                int quadOrder, const char* subsets)
    1926              : {
    1927              :         return GridFunctionDistance2<L2DistIntegrand<TGridFunction>, TGridFunction>
    1928            0 :                 (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets);
    1929              : }
    1930              : 
    1931              : /// computes the l2 distance between two functions
    1932              : template <typename TGridFunction>
    1933              : number L2Distance(TGridFunction& spGridFct1, const char* cmp1,
    1934              :                TGridFunction& spGridFct2, const char* cmp2,
    1935              :                int quadOrder, const char* subsets)
    1936              : {
    1937            0 :         return sqrt(L2Distance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets));
    1938              : }
    1939              : 
    1940              : 
    1941              : template <typename TGridFunction>
    1942            0 : number L2Error(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
    1943              :                SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
    1944              :                int quadOrder)
    1945              : {
    1946            0 :         return L2Distance(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, NULL);
    1947              : }
    1948              : 
    1949              : template <typename TGridFunction>
    1950            0 : number L2Error(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
    1951              :                SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
    1952              :                int quadOrder, const char* subsets)
    1953              : {
    1954            0 :         return L2Distance(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, subsets);
    1955              : }
    1956              : 
    1957              : ////////////////////////////////////////////////////////////////////////////////
    1958              : // H1 semi-norm Integrand
    1959              : ////////////////////////////////////////////////////////////////////////////////
    1960              : 
    1961              : 
    1962              : 
    1963              : //! Norm of a grid function, evaluated in (weighted) H1-semi norm
    1964              : template <typename TGridFunction>
    1965              : class H1SemiIntegrand
    1966              :         : public StdIntegrand<number, TGridFunction::dim, H1SemiIntegrand<TGridFunction> >
    1967              : {
    1968              :         public:
    1969              :         ///     world dimension of grid function
    1970              :                 static const int worldDim = TGridFunction::dim;
    1971              :                 typedef UserData<MathMatrix<worldDim, worldDim>, worldDim> weight_type;
    1972              : 
    1973              :         protected:
    1974              :         /// grid function data
    1975              :                 ScalarGridFunctionData<TGridFunction> m_scalarData;
    1976              : 
    1977              :         /// scalar weight (optional)
    1978              :                 ConstSmartPtr<weight_type> m_spWeight;
    1979              : 
    1980              :         public:
    1981              :         /// constructor
    1982            0 :                 H1SemiIntegrand(TGridFunction& gridFct, size_t cmp)
    1983            0 :                 : m_scalarData(gridFct, cmp), m_spWeight(make_sp(new ConstUserMatrix<worldDim>(1.0))) {}
    1984              : 
    1985              :         /// constructor
    1986            0 :                 H1SemiIntegrand(TGridFunction& gridFct, size_t cmp, ConstSmartPtr<weight_type> spWeight)
    1987            0 :                 : m_scalarData(gridFct, cmp), m_spWeight(spWeight) {}
    1988              : 
    1989              :         /// DTOR
    1990            0 :                 virtual ~H1SemiIntegrand() {};
    1991              : 
    1992              :         ///     sets subset
    1993            0 :                 virtual void set_subset(int si)
    1994              :                 {
    1995              : 
    1996            0 :                         UG_COND_THROW(!m_scalarData.is_def_in_subset(si), "H1Error: Grid function component"
    1997              :                                                 <<m_scalarData.fct()<<" not defined on subset "<<si);
    1998              :                         IIntegrand<number, worldDim>::set_subset(si);
    1999            0 :                 }
    2000              : 
    2001              :         /// \copydoc IIntegrand::values
    2002              :                 template <int elemDim>
    2003            0 :                 void evaluate(number vValue[],
    2004              :                               const MathVector<worldDim> vGlobIP[],
    2005              :                               GridObject* pElem,
    2006              :                               const MathVector<worldDim> vCornerCoords[],
    2007              :                               const MathVector<elemDim> vLocIP[],
    2008              :                               const MathMatrix<elemDim, worldDim> vJT[],
    2009              :                               const size_t numIP)
    2010              :                 {
    2011              :                 //      get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
    2012            0 :                         const ReferenceObjectID roid = pElem->reference_object_id();
    2013              :                         const TGridFunction &gridFct= m_scalarData.grid_function();
    2014              : 
    2015              :                         DimReferenceMapping<elemDim, worldDim>& map
    2016              :                                 = ReferenceMappingProvider::get<elemDim, worldDim>(roid, vCornerCoords);
    2017              : 
    2018              :                         typedef typename weight_type::data_type ipdata_type;
    2019              : 
    2020            0 :                         std::vector<ipdata_type> elemWeights(numIP, MathMatrix<worldDim, worldDim>());
    2021              :                         UG_ASSERT(m_spWeight.valid(), "H1SemiIntegrand::evaluate requires valid weights!");
    2022              : 
    2023              : 
    2024            0 :                         if(m_spWeight->requires_grid_fct())
    2025              :                         {
    2026              :                                 //      get local solution if needed
    2027              :                                 LocalIndices ind;
    2028              :                                 LocalVector uloc;
    2029              :                                 gridFct.indices(pElem, ind);    //      get global indices
    2030            0 :                                 uloc.resize(ind);                               //      adapt local algebra
    2031            0 :                                 GetLocalVector(uloc, gridFct);  //      read local values of u
    2032              : 
    2033              :                                 //      compute data
    2034              :                                 try{
    2035            0 :                                         (*m_spWeight)(&elemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), pElem,
    2036              :                                                         vCornerCoords, vLocIP, numIP, &uloc, NULL);
    2037            0 :                                 } UG_CATCH_THROW("H1SemiIntegrand: Cannot evaluate weight data.");
    2038              :                         }
    2039              :                         else
    2040              :                         {
    2041              :                                 //      compute data
    2042              :                                 try{
    2043            0 :                                         (*m_spWeight)(&elemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
    2044            0 :                                 } UG_CATCH_THROW("H1SemiIntegrand: Cannot evaluate weight data.");
    2045              :                         }
    2046              : 
    2047              : 
    2048              :                         try{
    2049              : 
    2050              : 
    2051              : 
    2052              : 
    2053              :                 //      get trial space
    2054              :                         const LocalShapeFunctionSet<elemDim>& rTrialSpace =
    2055              :                                                         LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
    2056              : 
    2057              :                 //      number of dofs on element
    2058            0 :                         const size_t num_sh = rTrialSpace.num_sh();
    2059              : 
    2060              :                 //      get multiindices of element
    2061              :                         std::vector<DoFIndex> ind;  //    aux. index array
    2062              :                         gridFct.dof_indices(pElem, m_scalarData.fct(), ind);
    2063              : 
    2064              :                 //      check multi indices
    2065            0 :                         UG_COND_THROW(ind.size() != num_sh, "H1SemiNormFuncIntegrand::evaluate: Wrong number of multi-)indices.");
    2066              : 
    2067              :                 //      loop all integration points
    2068            0 :                         std::vector<MathVector<elemDim> > vLocGradient(num_sh);
    2069            0 :                         for(size_t ip = 0; ip < numIP; ++ip)
    2070              :                         {
    2071              :                         //      compute shape gradients at ip
    2072            0 :                                 rTrialSpace.grads(&vLocGradient[0], vLocIP[ip]);
    2073              : 
    2074              :                         //      compute approximated solution at integration point
    2075              :                                 number approxSolIP = 0.0;
    2076              :                                 MathVector<elemDim> tmpVec(0.0);
    2077            0 :                                 for(size_t sh = 0; sh < num_sh; ++sh)
    2078              :                                 {
    2079              :                                 //      get value at shape point (e.g. corner for P1 fct)
    2080            0 :                                         const number valSH = DoFRef(gridFct, ind[sh]);
    2081              : 
    2082              :                                 //      add shape fct at ip * value at shape
    2083            0 :                                         approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
    2084              : 
    2085              :                                 //      add gradient at ip
    2086              :                                         VecScaleAppend(tmpVec, valSH, vLocGradient[sh]);
    2087              :                                 }
    2088              : 
    2089              :                         //      compute gradient
    2090              :                                 MathVector<worldDim> approxGradIP;
    2091              :                                 MathMatrix<worldDim, elemDim> JTInv;
    2092            0 :                                 map.jacobian_transposed_inverse(JTInv, vLocIP[ip]);//Inverse(JTInv, vJT[ip]);
    2093              : 
    2094              : #ifdef UG_DEBUG
    2095              :                                 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], JTInv);
    2096              : #endif //UG_DEBUG
    2097              : 
    2098              :                                 MatVecMult(approxGradIP, JTInv, tmpVec);
    2099              : 
    2100              :                         //      get norm squared
    2101              :                                 MathVector<worldDim> approxDGradIP;
    2102              :                                 MatVecMult(approxDGradIP, elemWeights[ip], approxGradIP);
    2103            0 :                                 vValue[ip] = VecDot(approxDGradIP, approxGradIP);
    2104              :                         }
    2105              : 
    2106            0 :                         }
    2107            0 :                         UG_CATCH_THROW("H1SemiIntegrand::evaluate: trial space missing.");
    2108            0 :                 }
    2109              : };
    2110              : 
    2111              : 
    2112              : /// compute H1 semi-norm of a function on the whole domain (or on selected subsets)
    2113              : /**
    2114              :  * This function computes the H1 semi-norm of a grid function
    2115              :  *
    2116              :  * \param[in]           spGridFct       grid function
    2117              :  * \param[in]           cmp                     symbolic name of component function
    2118              :  * \param[in]           time            time point
    2119              :  * \param[in]           quadOrder       order of quadrature rule
    2120              :  * \param[in]           subsets         subsets, where to compute (OPTIONAL)
    2121              :  * \param[in]           weights         element-wise weights (OPTIONAL)
    2122              :  * \returns                     number          l2-norm
    2123              :  */
    2124              : template <typename TGridFunction>
    2125            0 : number H1SemiNorm2(TGridFunction& gridFct, const char* cmp, int quadOrder, const char* subsets=NULL,
    2126              :                                 ConstSmartPtr<typename H1SemiIntegrand<TGridFunction>::weight_type> weights = SPNULL)
    2127              : {
    2128              : //      get function id of name
    2129              :         const size_t fct = gridFct.fct_id_by_name(cmp);
    2130              : 
    2131              : //      check that function exists
    2132            0 :         UG_COND_THROW(fct >= gridFct.num_fct(), "H1SemiNorm: Function space does not contain"
    2133              :                                 " a function with name " << cmp << ".");
    2134            0 :         if  (weights.invalid()) {
    2135            0 :                 H1SemiIntegrand<TGridFunction> integrand(gridFct, fct);
    2136            0 :                 return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
    2137              :         } else {
    2138            0 :                 H1SemiIntegrand<TGridFunction> integrand(gridFct, fct, weights);
    2139            0 :                 return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
    2140              :         }
    2141              : }
    2142              : 
    2143              : /// Computes the H1SemiNorm
    2144              : template <typename TGridFunction>
    2145            0 : number H1SemiNorm(TGridFunction& gridFct, const char* cmp, int quadOrder, const char* subsets=NULL,
    2146              :                                 ConstSmartPtr<typename H1SemiIntegrand<TGridFunction>::weight_type> weights = SPNULL)
    2147              : {
    2148            0 :         return (sqrt(H1SemiNorm2(gridFct, cmp, quadOrder, subsets, weights)));
    2149              : }
    2150              : 
    2151              : // Delegating to H1SemiNorm
    2152              : template <typename TGridFunction>
    2153            0 : number H1SemiNorm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder, const char* subsets)
    2154            0 : { return H1SemiNorm(*spGridFct, cmp, quadOrder, subsets); }
    2155              : 
    2156              : template <typename TGridFunction>
    2157              : number H1SemiNorm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder,
    2158              :                 const char* subsets, ConstSmartPtr<typename H1SemiIntegrand<TGridFunction>::weight_type> weights = SPNULL)
    2159              : { return H1SemiNorm(*spGridFct, cmp, quadOrder, subsets, weights); }
    2160              : 
    2161              : template <typename TGridFunction>
    2162            0 : number H1SemiNorm( SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder)
    2163            0 : { return H1SemiNorm(*spGridFct, cmp, quadOrder, NULL); }
    2164              : 
    2165              : template <typename TGridFunction>
    2166              : number H1SemiNorm( SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder,
    2167              :                 ConstSmartPtr<typename H1SemiIntegrand<TGridFunction>::weight_type> weights)
    2168              : { return H1SemiNorm(*spGridFct, cmp, quadOrder, NULL, weights); }
    2169              : 
    2170              : /// Integrand for the distance of two grid functions - evaluated in the (weighted) H1-semi norm
    2171              : template <typename TGridFunction>
    2172              : class H1SemiDistIntegrand : public StdIntegrand<number, TGridFunction::dim, H1SemiDistIntegrand<TGridFunction> >
    2173              : {
    2174              :         public:
    2175              :         ///     world dimension of grid function
    2176              :                 static const int worldDim = TGridFunction::dim;
    2177              :                 typedef typename H1SemiIntegrand<TGridFunction>::weight_type weight_type;
    2178              : 
    2179              :         private:
    2180              :                 ScalarGridFunctionData<TGridFunction> m_fineData;
    2181              :                 const int m_fineTopLevel;
    2182              : 
    2183              :                 ScalarGridFunctionData<TGridFunction> m_coarseData;
    2184              :                 const int m_coarseTopLevel;
    2185              : 
    2186              :         ///     multigrid
    2187              :                 SmartPtr<MultiGrid> m_spMG;
    2188              : 
    2189              :         /// scalar weight (optional)
    2190              :                 ConstSmartPtr<weight_type> m_spWeight;
    2191              : 
    2192              :         public:
    2193              :                 /// constructor
    2194              :                 H1SemiDistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
    2195              :                                                         TGridFunction& coarseGridFct, size_t coarseCmp)
    2196              :                 : m_fineData(fineGridFct, fineCmp),
    2197              :                   m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
    2198              :                   m_coarseData(coarseGridFct, coarseCmp),
    2199              :                   m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
    2200              :                   m_spMG(fineGridFct.domain()->grid()),
    2201              :                   m_spWeight(new ConstUserNumber<TGridFunction::dim>(1.0))
    2202              :                 {
    2203              :                         if(m_fineTopLevel < m_coarseTopLevel)
    2204              :                                 UG_THROW("H1SemiDiffIntegrand: fine and top level inverted.");
    2205              : 
    2206              :                         if(m_fineData.domain().get() != m_coarseData.domain().get())
    2207              :                                 UG_THROW("H1SemiDiffIntegrand: grid functions defined on different domains.");
    2208              :                 };
    2209              : 
    2210              :                 /// constructor
    2211            0 :                 H1SemiDistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
    2212              :                                                         TGridFunction& coarseGridFct, size_t coarseCmp,
    2213              :                                                         ConstSmartPtr<weight_type> spWeight)
    2214              :                 : m_fineData(fineGridFct, fineCmp),
    2215            0 :                   m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
    2216              :                   m_coarseData(coarseGridFct, coarseCmp),
    2217            0 :                   m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
    2218            0 :                   m_spMG(fineGridFct.domain()->grid()),
    2219            0 :                   m_spWeight(spWeight)
    2220              :                 {
    2221            0 :                         UG_COND_THROW(m_fineTopLevel < m_coarseTopLevel, "H1SemiDiffIntegrand: fine and top level inverted.");
    2222            0 :                         UG_COND_THROW(m_fineData.domain().get() != m_coarseData.domain().get(), "H1SemiDiffIntegrand: grid functions defined on different domains.");
    2223            0 :                 }
    2224            0 :                 virtual ~H1SemiDistIntegrand(){}
    2225              : 
    2226              :         ///     sets subset
    2227            0 :                 virtual void set_subset(int si)
    2228              :                 {
    2229              : 
    2230            0 :                         UG_COND_THROW(!m_fineData.is_def_in_subset(si), "H1SemiDiffIntegrand: Grid function component"
    2231              :                                                  <<m_fineData.fct()<<" not defined on subset "<<si);
    2232            0 :                         UG_COND_THROW(!m_coarseData.is_def_in_subset(si), "H1SemiDiffIntegrand: Grid function component"
    2233              :                                                 <<m_coarseData.fct()<<" not defined on subset "<<si);
    2234              :                         IIntegrand<number, worldDim>::set_subset(si);
    2235            0 :                 }
    2236              : 
    2237              :         /// \copydoc IIntegrand::values
    2238              :                 template <int elemDim>
    2239            0 :                 void evaluate(number vValue[],
    2240              :                               const MathVector<worldDim> vFineGlobIP[],
    2241              :                               GridObject* pFineElem,
    2242              :                               const MathVector<worldDim> vCornerCoords[],
    2243              :                               const MathVector<elemDim> vFineLocIP[],
    2244              :                               const MathMatrix<elemDim, worldDim> vJT[],
    2245              :                               const size_t numIP)
    2246              :                 {
    2247              :                         typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object Element;
    2248              : 
    2249              :                         const TGridFunction &fineGridFct  = m_fineData.grid_function();
    2250              :                         const TGridFunction &coarseGridFct  = m_coarseData.grid_function();
    2251              : 
    2252              :                         //      get coarse element
    2253              :                         GridObject* pCoarseElem = pFineElem;
    2254            0 :                         if(m_coarseTopLevel < m_fineTopLevel){
    2255              :                                 int parentLevel = m_spMG->get_level(pCoarseElem);
    2256            0 :                                 while(parentLevel > m_coarseTopLevel){
    2257            0 :                                         pCoarseElem = m_spMG->get_parent(pCoarseElem);
    2258              :                                         parentLevel = m_spMG->get_level(pCoarseElem);
    2259              :                                 }
    2260              :                         }
    2261              : 
    2262              :                 //      get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
    2263            0 :                         const ReferenceObjectID fineROID = pFineElem->reference_object_id();
    2264            0 :                         const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
    2265              : 
    2266              :                 //      get corner coordinates
    2267              :                         std::vector<MathVector<worldDim> > vCornerCoarse;
    2268            0 :                         CollectCornerCoordinates(vCornerCoarse, *static_cast<Element*>(pCoarseElem), *m_coarseData.domain());
    2269              : 
    2270              :                 //      get reference Mapping
    2271              :                         DimReferenceMapping<elemDim, worldDim>& map
    2272              :                                 = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
    2273              :                         DimReferenceMapping<elemDim, worldDim>& mapF
    2274              :                                 = ReferenceMappingProvider::get<elemDim, worldDim>(fineROID, vCornerCoords);
    2275              : 
    2276              :                         std::vector<MathVector<elemDim> > vCoarseLocIP;
    2277            0 :                         vCoarseLocIP.resize(numIP);
    2278            0 :                         for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
    2279            0 :                         map.global_to_local(&vCoarseLocIP[0], vFineGlobIP, numIP);
    2280              : 
    2281              : 
    2282              :                         // determine weights
    2283            0 :                         std::vector<typename weight_type::data_type> elemWeights(numIP, MathMatrix<worldDim, worldDim>());
    2284              :                         UG_ASSERT(m_spWeight.valid(), "H1SemiDistIntegrand::evaluate requires valid weights!");
    2285              : 
    2286              :                         //      get local solution (if required)
    2287            0 :                         if(m_spWeight->requires_grid_fct())
    2288              :                         {
    2289              : 
    2290              :                                 LocalIndices ind;
    2291              :                                 LocalVector u;
    2292              :                                 fineGridFct.indices(pFineElem, ind);    //      get global indices
    2293            0 :                                 u.resize(ind);                                                  //      adapt local algebra
    2294            0 :                                 GetLocalVector(u, fineGridFct);                 //      read local values of u
    2295              : 
    2296              :                                 //      compute data
    2297              :                                 try{
    2298            0 :                                         (*m_spWeight)(&elemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), pFineElem,
    2299              :                                                         vCornerCoords, vFineLocIP, numIP, &u, NULL);
    2300            0 :                                 } UG_CATCH_THROW("H1SemiDistIntegrand: Cannot evaluate data.");
    2301              :                         }
    2302              :                         else
    2303              :                         {
    2304              :                                 //      compute data
    2305              :                                 try{
    2306            0 :                                         (*m_spWeight)(&elemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
    2307            0 :                                 } UG_CATCH_THROW("H1SemiDistIntegrand: Cannot evaluate data.");
    2308              :                         }
    2309              : 
    2310              :                         try{
    2311              : 
    2312              : 
    2313              :                 //      get trial space
    2314              :                         const LocalShapeFunctionSet<elemDim>& rFineLSFS =
    2315              :                                         LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
    2316              :                         const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
    2317              :                                         LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());
    2318              : 
    2319              :                 //      get multiindices of element
    2320              :                         std::vector<DoFIndex> vFineMI, vCoarseMI;
    2321              :                         m_fineData.dof_indices(pFineElem, vFineMI);
    2322              :                         m_coarseData.dof_indices(pCoarseElem, vCoarseMI);
    2323              : 
    2324            0 :                         std::vector<MathVector<elemDim> > vFineLocGradient(vFineMI.size());
    2325            0 :                         std::vector<MathVector<elemDim> > vCoarseLocGradient(vCoarseMI.size());
    2326              : 
    2327              :                 //      loop all integration points
    2328            0 :                         for(size_t ip = 0; ip < numIP; ++ip)
    2329              :                         {
    2330              :                         //      compute shape gradients at ip
    2331            0 :                                 rFineLSFS.grads(&vFineLocGradient[0], vFineLocIP[ip]);
    2332            0 :                                 rCoarseLSFS.grads(&vCoarseLocGradient[0], vCoarseLocIP[ip]);
    2333              : 
    2334              :                         //      compute approximated solutions at integration point
    2335              :                                 number fineSolIP = 0.0;
    2336              :                                 MathVector<elemDim> fineLocTmp(0.0);
    2337            0 :                                 for(size_t sh = 0; sh < vFineMI.size(); ++sh)
    2338              :                                 {
    2339            0 :                                         const number val = DoFRef(fineGridFct, vFineMI[sh]);
    2340            0 :                                         fineSolIP += val * rFineLSFS.shape(sh, vFineLocIP[ip]);
    2341              :                                         VecScaleAppend(fineLocTmp, val, vFineLocGradient[sh]);
    2342              :                                 }
    2343              : 
    2344              :                                 number coarseSolIP = 0.0;
    2345              :                                 MathVector<elemDim> coarseLocTmp(0.0);
    2346            0 :                                 for(size_t sh = 0; sh < vCoarseMI.size(); ++sh)
    2347              :                                 {
    2348            0 :                                         const number val = DoFRef(coarseGridFct, vCoarseMI[sh]);
    2349            0 :                                         coarseSolIP += val * rCoarseLSFS.shape(sh, vCoarseLocIP[ip]);
    2350              :                                         VecScaleAppend(coarseLocTmp, val, vCoarseLocGradient[sh]);
    2351              :                                 }
    2352              : 
    2353              :                         //      compute global gradient
    2354              :                                 MathVector<worldDim> fineGradIP;
    2355              :                                 MathMatrix<worldDim, elemDim> fineJTInv;
    2356            0 :                                 mapF.jacobian_transposed_inverse(fineJTInv, vFineLocIP[ip]);//Inverse(fineJTInv, vJT[ip]);
    2357              : 
    2358              : #ifdef UG_DEBUG
    2359              :                                 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], fineJTInv);
    2360              : #endif //UG_DEBUG
    2361              : 
    2362              :                                 MatVecMult(fineGradIP, fineJTInv, fineLocTmp);
    2363              : 
    2364              :                         //      compute global gradient
    2365              :                                 MathVector<worldDim> coarseGradIP;
    2366              :                                 MathMatrix<worldDim, elemDim> coarseJTInv;
    2367            0 :                                 map.jacobian_transposed_inverse(coarseJTInv, vCoarseLocIP[ip]);
    2368              :                                 MatVecMult(coarseGradIP, coarseJTInv, coarseLocTmp);
    2369              : 
    2370              :                         //      get squared of difference
    2371              :                                 /*vValue[ip] = (coarseSolIP - fineSolIP);
    2372              :                                 vValue[ip] *= vValue[ip]; */
    2373            0 :                                 vValue[ip] = VecDistanceSq(coarseGradIP, fineGradIP, elemWeights[ip]);
    2374              :                         }
    2375              : 
    2376            0 :                         }
    2377            0 :                         UG_CATCH_THROW("H1SemiDiffIntegrand::evaluate: trial space missing.");
    2378            0 :                 }
    2379              : };
    2380              : 
    2381              : 
    2382              : //! Distance in H1 semi norm (with subset selection)
    2383              : template <typename TGridFunction>
    2384              : number H1SemiError2(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
    2385              :                SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
    2386              :                int quadOrder, const char* subsets)
    2387              : {
    2388              :         return GridFunctionDistance2<H1SemiDistIntegrand<TGridFunction>, TGridFunction>
    2389              :                 (*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, subsets);
    2390              : }
    2391              : 
    2392              : //! Distance in H1 semi norm (with subset selection)
    2393              : template <typename TGridFunction>
    2394              : number H1SemiError(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
    2395              :                SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
    2396              :                int quadOrder, const char* subsets)
    2397              : {
    2398              :         return sqrt(H1SemiError2(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, subsets));
    2399              : }
    2400              : 
    2401              : //! Distance in H1 semi norm (all subsets)
    2402              : template <typename TGridFunction>
    2403              : number H1SemiError(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
    2404              :                SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
    2405              :                int quadOrder)
    2406              : {
    2407              :         return H1SemiError(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, NULL);
    2408              : }
    2409              : 
    2410              : //! Squared distance in H1 semi norm (with select subsets & weights)
    2411              : template <typename TGridFunction>
    2412            0 : number H1SemiDistance2(TGridFunction& spGridFct1, const char* cmp1,
    2413              :                 TGridFunction& spGridFct2, const char* cmp2,
    2414              :         int quadOrder, const char* subsets,
    2415              :                 ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type> weights)
    2416              : {
    2417              :         return GridFunctionDistance2<H1SemiDistIntegrand<TGridFunction>, TGridFunction>
    2418            0 :                 (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, weights);
    2419              : }
    2420              : 
    2421              : //! Distance in H1 semi norm (with select subsets & weights)
    2422              : template <typename TGridFunction>
    2423              : number H1SemiDistance(TGridFunction& spGridFct1, const char* cmp1,
    2424              :                 TGridFunction& spGridFct2, const char* cmp2,
    2425              :         int quadOrder, const char* subsets,
    2426              :                 ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type> weights)
    2427              : { return sqrt(H1SemiDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, weights)); }
    2428              : 
    2429              : //! Squared distance in H1 semi norm (all subsets, with weights)
    2430              : template <typename TGridFunction>
    2431            0 : number H1SemiDistance2(TGridFunction& spGridFct1, const char* cmp1,
    2432              :                                           TGridFunction& spGridFct2, const char* cmp2,
    2433              :                int quadOrder, ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type > weights)
    2434            0 : { return H1SemiDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, NULL, weights); }
    2435              : 
    2436              : //! Distance in H1 semi norm (all subsets, with weights)
    2437              : template <typename TGridFunction>
    2438              : number H1SemiDistance(TGridFunction& spGridFct1, const char* cmp1,
    2439              :                                           TGridFunction& spGridFct2, const char* cmp2,
    2440              :                int quadOrder, ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type > weights)
    2441              : { return sqrt(H1SemiDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, NULL, weights)); }
    2442              : 
    2443              : 
    2444              : 
    2445              : 
    2446              : ////////////////////////////////////////////////////////////////////////////////
    2447              : // H1 semi-norm Integrand
    2448              : ////////////////////////////////////////////////////////////////////////////////
    2449              : 
    2450              : //! Norm of a grid function, evaluated in (weighted) H1-semi norm
    2451              : template <typename TGridFunction>
    2452              : class H1EnergyIntegrand
    2453              :         : public StdIntegrand<number, TGridFunction::dim, H1EnergyIntegrand<TGridFunction> >
    2454              : {
    2455              :         public:
    2456              :         ///     world dimension of grid function
    2457              :                 static const int worldDim = TGridFunction::dim;
    2458              :                 typedef UserData<MathMatrix<worldDim, worldDim>, worldDim> weight_type;
    2459              : 
    2460              :         protected:
    2461              :         /// grid function data
    2462              :                 ScalarGridFunctionData<TGridFunction> m_scalarData;
    2463              : 
    2464              :         /// scalar weight (optional)
    2465              :                 ConstSmartPtr<weight_type> m_spWeight;
    2466              : 
    2467              :         public:
    2468              :         /// constructor
    2469            0 :                 H1EnergyIntegrand(TGridFunction& gridFct, size_t cmp)
    2470            0 :                 : m_scalarData(gridFct, cmp), m_spWeight(make_sp(new ConstUserMatrix<worldDim>(1.0))) {}
    2471              : 
    2472              :         /// constructor
    2473            0 :                 H1EnergyIntegrand(TGridFunction& gridFct, size_t cmp, ConstSmartPtr<weight_type> spWeight)
    2474            0 :                 : m_scalarData(gridFct, cmp), m_spWeight(spWeight) {}
    2475              : 
    2476              :         /// DTOR
    2477            0 :                 virtual ~H1EnergyIntegrand() {};
    2478              : 
    2479              :         ///     sets subset
    2480            0 :                 virtual void set_subset(int si)
    2481              :                 {
    2482              : 
    2483            0 :                         UG_COND_THROW(!m_scalarData.is_def_in_subset(si), "H1EnergyIntegrand: Grid function component"
    2484              :                                                 <<m_scalarData.fct()<<" not defined on subset "<<si);
    2485              :                         IIntegrand<number, worldDim>::set_subset(si);
    2486            0 :                 }
    2487              : 
    2488              :         /// \copydoc IIntegrand::values
    2489              :                 template <int elemDim>
    2490            0 :                 void evaluate(number vValue[],
    2491              :                               const MathVector<worldDim> vGlobIP[],
    2492              :                               GridObject* pElem,
    2493              :                               const MathVector<worldDim> vCornerCoords[],
    2494              :                               const MathVector<elemDim> vLocIP[],
    2495              :                               const MathMatrix<elemDim, worldDim> vJT[],
    2496              :                               const size_t numIP)
    2497              :                 {
    2498              :                 //      get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
    2499            0 :                         const ReferenceObjectID roid = pElem->reference_object_id();
    2500              :                         const TGridFunction &gridFct= m_scalarData.grid_function();
    2501              : 
    2502              :                         DimReferenceMapping<elemDim, worldDim>& map
    2503              :                                 = ReferenceMappingProvider::get<elemDim, worldDim>(roid, vCornerCoords);
    2504              : 
    2505              :                         typedef typename weight_type::data_type ipdata_type;
    2506              : 
    2507            0 :                         std::vector<ipdata_type> elemWeights(numIP, MathMatrix<worldDim, worldDim>());
    2508              :                         UG_ASSERT(m_spWeight.valid(), "H1EnergyIntegrand::evaluate requires valid weights!");
    2509              : 
    2510              : 
    2511            0 :                         if(m_spWeight->requires_grid_fct())
    2512              :                         {
    2513              :                                 //      get local solution if needed
    2514              :                                 LocalIndices ind;
    2515              :                                 LocalVector uloc;
    2516              :                                 gridFct.indices(pElem, ind);    //      get global indices
    2517            0 :                                 uloc.resize(ind);                               //      adapt local algebra
    2518            0 :                                 GetLocalVector(uloc, gridFct);  //      read local values of u
    2519              : 
    2520              :                                 //      compute data
    2521              :                                 try{
    2522            0 :                                         (*m_spWeight)(&elemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), pElem,
    2523              :                                                         vCornerCoords, vLocIP, numIP, &uloc, NULL);
    2524            0 :                                 } UG_CATCH_THROW("H1EnergyIntegrand: Cannot evaluate weight data.");
    2525              :                         }
    2526              :                         else
    2527              :                         {
    2528              :                                 //      compute data
    2529              :                                 try{
    2530            0 :                                         (*m_spWeight)(&elemWeights[0], vGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
    2531            0 :                                 } UG_CATCH_THROW("H1EnergyIntegrand: Cannot evaluate weight data.");
    2532              :                         }
    2533              : 
    2534              : 
    2535              :                         try{
    2536              : 
    2537              : 
    2538              : 
    2539              : 
    2540              :                 //      get trial space
    2541              :                         const LocalShapeFunctionSet<elemDim>& rTrialSpace =
    2542              :                                                         LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
    2543              : 
    2544              :                 //      number of dofs on element
    2545            0 :                         const size_t num_sh = rTrialSpace.num_sh();
    2546              : 
    2547              :                 //      get multiindices of element
    2548              :                         std::vector<DoFIndex> ind;  //    aux. index array
    2549              :                         gridFct.dof_indices(pElem, m_scalarData.fct(), ind);
    2550              : 
    2551              :                 //      check multi indices
    2552            0 :                         UG_COND_THROW(ind.size() != num_sh, "H1EnergyIntegrand::evaluate: Wrong number of multi-)indices.");
    2553              : 
    2554              :                 //      loop all integration points
    2555            0 :                         std::vector<MathVector<elemDim> > vLocGradient(num_sh);
    2556            0 :                         for(size_t ip = 0; ip < numIP; ++ip)
    2557              :                         {
    2558              :                         //      compute shape gradients at ip
    2559            0 :                                 rTrialSpace.grads(&vLocGradient[0], vLocIP[ip]);
    2560              : 
    2561              :                         //      compute approximated solution at integration point
    2562              :                                 number approxSolIP = 0.0;
    2563              :                                 MathVector<elemDim> tmpVec(0.0);
    2564            0 :                                 for(size_t sh = 0; sh < num_sh; ++sh)
    2565              :                                 {
    2566              :                                 //      get value at shape point (e.g. corner for P1 fct)
    2567            0 :                                         const number valSH = DoFRef(gridFct, ind[sh]);
    2568              : 
    2569              :                                 //      add shape fct at ip * value at shape
    2570            0 :                                         approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
    2571              : 
    2572              :                                 //      add gradient at ip
    2573              :                                         VecScaleAppend(tmpVec, valSH, vLocGradient[sh]);
    2574              :                                 }
    2575              : 
    2576              :                         //      compute gradient
    2577              :                                 MathVector<worldDim> approxGradIP;
    2578              :                                 MathMatrix<worldDim, elemDim> JTInv;
    2579            0 :                                 map.jacobian_transposed_inverse(JTInv, vLocIP[ip]);//Inverse(JTInv, vJT[ip]);
    2580              : 
    2581              : #ifdef UG_DEBUG
    2582              :                                 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], JTInv);
    2583              : #endif //UG_DEBUG
    2584              : 
    2585              : 
    2586              :                                 MatVecMult(approxGradIP, JTInv, tmpVec);
    2587              : 
    2588              :                         //      get norm squared
    2589              :                                 MathVector<worldDim> approxDGradIP;
    2590              :                                 MatVecMult(approxDGradIP, elemWeights[ip], approxGradIP);
    2591            0 :                                 vValue[ip] = VecTwoNormSq(approxDGradIP);
    2592              :                         }
    2593              : 
    2594            0 :                         }
    2595            0 :                         UG_CATCH_THROW("H1EnergyIntegrand::evaluate: trial space missing.");
    2596            0 :                 }
    2597              : };
    2598              : 
    2599              : 
    2600              : /// compute energy -norm of a function on the whole domain (or on selected subsets)
    2601              : /**
    2602              :  * This function computes the integral over  \f$ \| q  \|^2 \f$ where the velocity is given by \f$ q:= \kappa \nabla u \f$ of a grid function u.
    2603              :  *
    2604              :  * \param[in]           spGridFct       grid function
    2605              :  * \param[in]           cmp                     symbolic name of component function
    2606              :  * \param[in]           time            time point
    2607              :  * \param[in]           quadOrder       order of quadrature rule
    2608              :  * \param[in]           subsets         subsets, where to compute (OPTIONAL)
    2609              :  * \param[in]           weights         element-wise matrix-valued weights kappa (OPTIONAL)
    2610              :  * \returns                     number          l2-norm
    2611              :  */
    2612              : template <typename TGridFunction>
    2613            0 : number H1EnergyNorm2(TGridFunction& gridFct, const char* cmp, int quadOrder, const char* subsets=NULL,
    2614              :                                 ConstSmartPtr<typename H1SemiIntegrand<TGridFunction>::weight_type> weights = SPNULL)
    2615              : {
    2616              : //      get function id of name
    2617              :         const size_t fct = gridFct.fct_id_by_name(cmp);
    2618              : 
    2619              : //      check that function exists
    2620            0 :         UG_COND_THROW(fct >= gridFct.num_fct(), "H1SemiNorm: Function space does not contain"
    2621              :                                 " a function with name " << cmp << ".");
    2622            0 :         if  (weights.invalid()) {
    2623            0 :                 H1EnergyIntegrand<TGridFunction> integrand(gridFct, fct);
    2624            0 :                 return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
    2625              :         } else {
    2626            0 :                 H1EnergyIntegrand<TGridFunction> integrand(gridFct, fct, weights);
    2627            0 :                 return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
    2628              :         }
    2629              : }
    2630              : template <typename TGridFunction>
    2631              : number H1EnergyNorm(TGridFunction& gridFct, const char* cmp, int quadOrder, const char* subsets=NULL,
    2632              :                                 ConstSmartPtr<typename H1SemiIntegrand<TGridFunction>::weight_type> weights = SPNULL)
    2633              : {
    2634              :         return (sqrt(H1EnergyNorm2(gridFct, cmp, quadOrder, subsets, weights)));
    2635              : }
    2636              : 
    2637              : template <typename TGridFunction>
    2638              : number H1EnergyNorm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder,
    2639              :                 const char* subsets, ConstSmartPtr<typename H1SemiIntegrand<TGridFunction>::weight_type> weights = SPNULL)
    2640              : { return H1EnergyNorm(*spGridFct, cmp, quadOrder, subsets, weights); }
    2641              : 
    2642              : template <typename TGridFunction>
    2643              : number H1EnergyNorm( SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder)
    2644              : { return H1EnergyNorm(spGridFct, cmp, quadOrder, NULL); }
    2645              : 
    2646              : template <typename TGridFunction>
    2647              : number H1EnergyNorm( SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder,
    2648              :                 ConstSmartPtr<typename H1SemiIntegrand<TGridFunction>::weight_type> weights)
    2649              : { return H1EnergyNorm(spGridFct, cmp, quadOrder, NULL, weights); }
    2650              : 
    2651              : 
    2652              : 
    2653              : 
    2654              : /// Integrand for the distance of two grid functions - evaluated in the norm \f$ |D \nabla u|^2 \f$
    2655              : template <typename TGridFunction>
    2656              : class H1EnergyDistIntegrand
    2657              :                 : public StdIntegrand<number, TGridFunction::dim, H1EnergyDistIntegrand<TGridFunction> >
    2658              : {
    2659              :         public:
    2660              :         ///     world dimension of grid function
    2661              :                 static const int worldDim = TGridFunction::dim;
    2662              :                 typedef typename H1SemiIntegrand<TGridFunction>::weight_type weight_type;
    2663              : 
    2664              :         private:
    2665              :                 ScalarGridFunctionData<TGridFunction> m_fineData;
    2666              :                 const int m_fineTopLevel;
    2667              : 
    2668              :                 ScalarGridFunctionData<TGridFunction> m_coarseData;
    2669              :                 const int m_coarseTopLevel;
    2670              : 
    2671              :         ///     multigrid
    2672              :                 SmartPtr<MultiGrid> m_spMG;
    2673              : 
    2674              :         /// scalar weight (optional)
    2675              :                 ConstSmartPtr<weight_type> m_spWeight;
    2676              : 
    2677              :         public:
    2678              :                 /// constructor
    2679              :                 H1EnergyDistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
    2680              :                                                         TGridFunction& coarseGridFct, size_t coarseCmp)
    2681              :                 : m_fineData(fineGridFct, fineCmp),
    2682              :                   m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
    2683              :                   m_coarseData(coarseGridFct, coarseCmp),
    2684              :                   m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
    2685              :                   m_spMG(fineGridFct.domain()->grid()),
    2686              :                   m_spWeight(new ConstUserNumber<TGridFunction::dim>(1.0))
    2687              :                 {
    2688              :                         if(m_fineTopLevel < m_coarseTopLevel)
    2689              :                                 UG_THROW("H1EnergyDistIntegrand: fine and top level inverted.");
    2690              : 
    2691              :                         if(m_fineData.domain().get() != m_coarseData.domain().get())
    2692              :                                 UG_THROW("H1EnergyDistIntegrand: grid functions defined on different domains.");
    2693              :                 };
    2694              : 
    2695              :                 /// constructor
    2696            0 :                 H1EnergyDistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
    2697              :                                                         TGridFunction& coarseGridFct, size_t coarseCmp,
    2698              :                                                         ConstSmartPtr<weight_type> spWeight)
    2699              :                 : m_fineData(fineGridFct, fineCmp),
    2700            0 :                   m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
    2701              :                   m_coarseData(coarseGridFct, coarseCmp),
    2702            0 :                   m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
    2703            0 :                   m_spMG(fineGridFct.domain()->grid()),
    2704            0 :                   m_spWeight(spWeight)
    2705              :                 {
    2706            0 :                         if(m_fineTopLevel < m_coarseTopLevel)
    2707            0 :                                 UG_THROW("H1EnergyDistIntegrand: fine and top level inverted.");
    2708              : 
    2709            0 :                         if(m_fineData.domain().get() != m_coarseData.domain().get())
    2710            0 :                                 UG_THROW("H1EnergyDistIntegrand: grid functions defined on different domains.");
    2711            0 :                 }
    2712            0 :                 virtual ~H1EnergyDistIntegrand(){}
    2713              : 
    2714              :         ///     sets subset
    2715            0 :                 virtual void set_subset(int si)
    2716              :                 {
    2717            0 :                         if(!m_fineData.is_def_in_subset(si))
    2718            0 :                                 UG_THROW("H1EnergyDistIntegrand: Grid function component"
    2719              :                                                 <<m_fineData.fct()<<" not defined on subset "<<si);
    2720            0 :                         if(!m_coarseData.is_def_in_subset(si))
    2721            0 :                                 UG_THROW("H1EnergyDistIntegrand: Grid function component"
    2722              :                                                 <<m_coarseData.fct()<<" not defined on subset "<<si);
    2723              :                         IIntegrand<number, worldDim>::set_subset(si);
    2724            0 :                 }
    2725              : 
    2726              :         /// \copydoc IIntegrand::values
    2727              :                 template <int elemDim>
    2728            0 :                 void evaluate(number vValue[],
    2729              :                               const MathVector<worldDim> vFineGlobIP[],
    2730              :                               GridObject* pFineElem,
    2731              :                               const MathVector<worldDim> vCornerCoords[],
    2732              :                               const MathVector<elemDim> vFineLocIP[],
    2733              :                               const MathMatrix<elemDim, worldDim> vJT[],
    2734              :                               const size_t numIP)
    2735              :                 {
    2736              :                         typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object Element;
    2737              : 
    2738              :                         const TGridFunction &fineGridFct  = m_fineData.grid_function();
    2739              :                         const TGridFunction &coarseGridFct  = m_coarseData.grid_function();
    2740              : 
    2741              :                         //      get coarse element
    2742              :                         GridObject* pCoarseElem = pFineElem;
    2743            0 :                         if(m_coarseTopLevel < m_fineTopLevel){
    2744              :                                 int parentLevel = m_spMG->get_level(pCoarseElem);
    2745            0 :                                 while(parentLevel > m_coarseTopLevel){
    2746            0 :                                         pCoarseElem = m_spMG->get_parent(pCoarseElem);
    2747              :                                         parentLevel = m_spMG->get_level(pCoarseElem);
    2748              :                                 }
    2749              :                         }
    2750              : 
    2751              :                 //      get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
    2752            0 :                         const ReferenceObjectID fineROID = pFineElem->reference_object_id();
    2753            0 :                         const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
    2754              : 
    2755              :                 //      get corner coordinates
    2756              :                         std::vector<MathVector<worldDim> > vCornerCoarse;
    2757            0 :                         CollectCornerCoordinates(vCornerCoarse, *static_cast<Element*>(pCoarseElem), *m_coarseData.domain());
    2758              : 
    2759              :                 //      get reference Mapping
    2760              :                         DimReferenceMapping<elemDim, worldDim>& map
    2761              :                                 = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
    2762              :                         DimReferenceMapping<elemDim, worldDim>& mapF
    2763              :                                 = ReferenceMappingProvider::get<elemDim, worldDim>(fineROID, vCornerCoords);
    2764              : 
    2765              :                         std::vector<MathVector<elemDim> > vCoarseLocIP;
    2766            0 :                         vCoarseLocIP.resize(numIP);
    2767            0 :                         for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
    2768            0 :                         map.global_to_local(&vCoarseLocIP[0], vFineGlobIP, numIP);
    2769              : 
    2770              : 
    2771              :                         // determine weights
    2772            0 :                         std::vector<typename weight_type::data_type> elemWeights(numIP, MathMatrix<worldDim, worldDim>());
    2773              :                         UG_ASSERT(m_spWeight.valid(), "H1SemiDistIntegrand::evaluate requires valid weights!");
    2774              : 
    2775              :                         //      get local solution if needed
    2776            0 :                         if(m_spWeight->requires_grid_fct())
    2777              :                         {
    2778              : 
    2779              :                                 LocalIndices ind;
    2780              :                                 LocalVector u;
    2781              :                                 fineGridFct.indices(pFineElem, ind);    //      get global indices
    2782            0 :                                 u.resize(ind);                                                  //      adapt local algebra
    2783            0 :                                 GetLocalVector(u, fineGridFct);                 //      read local values of u
    2784              : 
    2785              :                                 //      compute data
    2786              :                                 try{
    2787            0 :                                         (*m_spWeight)(&elemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), pFineElem,
    2788              :                                                         vCornerCoords, vFineLocIP, numIP, &u, NULL);
    2789            0 :                                 } UG_CATCH_THROW("H1SemiDistIntegrand: Cannot evaluate data.");
    2790              :                         }
    2791              :                         else
    2792              :                         {
    2793              :                                 //      compute data
    2794              :                                 try{
    2795            0 :                                         (*m_spWeight)(&elemWeights[0], vFineGlobIP, 0.0, IIntegrand<number, worldDim>::subset(), numIP);
    2796            0 :                                 } UG_CATCH_THROW("H1SemiDistIntegrand: Cannot evaluate data.");
    2797              :                         }
    2798              : 
    2799              :                         try{
    2800              : 
    2801              : 
    2802              :                 //      get trial space
    2803              :                         const LocalShapeFunctionSet<elemDim>& rFineLSFS =
    2804              :                                         LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
    2805              :                         const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
    2806              :                                         LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());
    2807              : 
    2808              :                 //      get multiindices of element
    2809              :                         std::vector<DoFIndex> vFineMI, vCoarseMI;
    2810              :                         m_fineData.dof_indices(pFineElem, vFineMI);
    2811              :                         m_coarseData.dof_indices(pCoarseElem, vCoarseMI);
    2812              : 
    2813            0 :                         std::vector<MathVector<elemDim> > vFineLocGradient(vFineMI.size());
    2814            0 :                         std::vector<MathVector<elemDim> > vCoarseLocGradient(vCoarseMI.size());
    2815              : 
    2816              :                 //      loop all integration points
    2817            0 :                         for(size_t ip = 0; ip < numIP; ++ip)
    2818              :                         {
    2819              :                         //      compute shape gradients at ip
    2820            0 :                                 rFineLSFS.grads(&vFineLocGradient[0], vFineLocIP[ip]);
    2821            0 :                                 rCoarseLSFS.grads(&vCoarseLocGradient[0], vCoarseLocIP[ip]);
    2822              : 
    2823              :                         //      compute approximated solutions at integration point
    2824              :                                 number fineSolIP = 0.0;
    2825              :                                 MathVector<elemDim> fineLocTmp(0.0);
    2826            0 :                                 for(size_t sh = 0; sh < vFineMI.size(); ++sh)
    2827              :                                 {
    2828            0 :                                         const number val = DoFRef(fineGridFct, vFineMI[sh]);
    2829            0 :                                         fineSolIP += val * rFineLSFS.shape(sh, vFineLocIP[ip]);
    2830              :                                         VecScaleAppend(fineLocTmp, val, vFineLocGradient[sh]);
    2831              :                                 }
    2832              : 
    2833              :                                 number coarseSolIP = 0.0;
    2834              :                                 MathVector<elemDim> coarseLocTmp(0.0);
    2835            0 :                                 for(size_t sh = 0; sh < vCoarseMI.size(); ++sh)
    2836              :                                 {
    2837            0 :                                         const number val = DoFRef(coarseGridFct, vCoarseMI[sh]);
    2838            0 :                                         coarseSolIP += val * rCoarseLSFS.shape(sh, vCoarseLocIP[ip]);
    2839              :                                         VecScaleAppend(coarseLocTmp, val, vCoarseLocGradient[sh]);
    2840              :                                 }
    2841              : 
    2842              :                         //      compute global D*gradient
    2843              :                                 MathVector<worldDim> fineGradIP;
    2844              :                                 MathMatrix<worldDim, elemDim> fineJTInv;
    2845            0 :                                 mapF.jacobian_transposed_inverse(fineJTInv, vFineLocIP[ip]);//Inverse(fineJTInv, vJT[ip]);
    2846              : 
    2847              : #ifdef UG_DEBUG
    2848              :                                 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], fineJTInv);
    2849              : #endif //UG_DEBUG
    2850              : 
    2851              : 
    2852              :                                 MatVecMult(fineGradIP, fineJTInv, fineLocTmp);
    2853              :                                 MathVector<worldDim> fineWorldLocTmp(0.0);
    2854              :                                 MatVecMult(fineWorldLocTmp, elemWeights[ip], fineGradIP);
    2855              : 
    2856              :                         //      compute global D*gradient
    2857              :                                 MathVector<worldDim> coarseGradIP;
    2858              :                                 MathMatrix<worldDim, elemDim> coarseJTInv;
    2859            0 :                                 map.jacobian_transposed_inverse(coarseJTInv, vCoarseLocIP[ip]);
    2860              :                                 MatVecMult(coarseGradIP, coarseJTInv, coarseLocTmp);
    2861              :                                 MathVector<worldDim> coarseWorldLocTmp(0.0);
    2862              :                                 MatVecMult(coarseWorldLocTmp, elemWeights[ip], coarseGradIP);
    2863              : 
    2864              :                         //      get squared difference
    2865            0 :                                 vValue[ip] = VecDistanceSq(fineWorldLocTmp, coarseWorldLocTmp);
    2866              :                                 //vValue[ip] = VecDistanceSq(fineGradIP, coarseGradIP, elemWeights[ip]);
    2867              :                         }
    2868              : 
    2869            0 :                         }
    2870            0 :                         UG_CATCH_THROW("H1EnergyDiffIntegrand::evaluate: trial space missing.");
    2871            0 :                 }
    2872              : };
    2873              : 
    2874              : 
    2875              : //! Squared distance in H1 semi norm (with select subsets & weights)
    2876              : template <typename TGridFunction>
    2877            0 : number H1EnergyDistance2(TGridFunction& spGridFct1, const char* cmp1,
    2878              :                 TGridFunction& spGridFct2, const char* cmp2,
    2879              :         int quadOrder, const char* subsets,
    2880              :                 ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type> weights)
    2881              : {
    2882              :         return GridFunctionDistance2<H1EnergyDistIntegrand<TGridFunction>, TGridFunction>
    2883            0 :                 (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, weights);
    2884              : }
    2885              : 
    2886              : //! Distance in H1 semi norm (with select subsets & weights)
    2887              : template <typename TGridFunction>
    2888              : number H1EnergyDistance(TGridFunction& spGridFct1, const char* cmp1,
    2889              :                 TGridFunction& spGridFct2, const char* cmp2,
    2890              :         int quadOrder, const char* subsets,
    2891              :                 ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type> weights)
    2892              : { return sqrt(H1EnergyDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets, weights)); }
    2893              : 
    2894              : //! Squared distance in H1 semi norm (all subsets, with weights)
    2895              : template <typename TGridFunction>
    2896              : number H1EnergyDistance2(TGridFunction& spGridFct1, const char* cmp1,
    2897              :                                           TGridFunction& spGridFct2, const char* cmp2,
    2898              :                int quadOrder, ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type > weights)
    2899              : { return H1EnergyDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, NULL, weights); }
    2900              : 
    2901              : //! Distance in H1 semi norm (all subsets, with weights)
    2902              : template <typename TGridFunction>
    2903              : number H1EnergyDistance(TGridFunction& spGridFct1, const char* cmp1,
    2904              :                                           TGridFunction& spGridFct2, const char* cmp2,
    2905              :                int quadOrder, ConstSmartPtr<typename H1SemiDistIntegrand<TGridFunction>::weight_type > weights)
    2906              : { return sqrt(H1EnergyDistance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, NULL, weights)); }
    2907              : 
    2908              : 
    2909              : 
    2910              : 
    2911              : ////////////////////////////////////////////////////////////////////////////////
    2912              : // H1 norm integrand
    2913              : ////////////////////////////////////////////////////////////////////////////////
    2914              : template <typename TGridFunction>
    2915              : class H1NormIntegrand
    2916              :         : public StdIntegrand<number, TGridFunction::dim, H1NormIntegrand<TGridFunction> >
    2917              : {
    2918              :         public:
    2919              :         ///     world dimension of grid function
    2920              :                 static const int worldDim = TGridFunction::dim;
    2921              : 
    2922              :         private:
    2923              :                 ScalarGridFunctionData<TGridFunction> m_scalarData;
    2924              : 
    2925              :         public:
    2926              :         /// CTOR
    2927            0 :                 H1NormIntegrand(TGridFunction& gridFct, size_t cmp)
    2928            0 :                 : m_scalarData(gridFct, cmp) {}
    2929              : 
    2930              :         /// DTOR
    2931            0 :                 virtual ~H1NormIntegrand() {}
    2932              : 
    2933              :         ///     sets subset
    2934            0 :                 virtual void set_subset(int si)
    2935              :                 {
    2936            0 :                         if(!m_scalarData.is_def_in_subset(si))
    2937            0 :                                 UG_THROW("H1Norm: Grid function component"
    2938              :                                                 <<m_scalarData.fct()<<" not defined on subset "<<si);
    2939              :                         IIntegrand<number, worldDim>::set_subset(si);
    2940            0 :                 }
    2941              : 
    2942              :         /// \copydoc IIntegrand::values
    2943              :                 template <int elemDim>
    2944            0 :                 void evaluate(number vValue[],
    2945              :                               const MathVector<worldDim> vGlobIP[],
    2946              :                               GridObject* pElem,
    2947              :                               const MathVector<worldDim> vCornerCoords[],
    2948              :                               const MathVector<elemDim> vLocIP[],
    2949              :                               const MathMatrix<elemDim, worldDim> vJT[],
    2950              :                               const size_t numIP)
    2951              :                 {
    2952              :                 //      get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
    2953            0 :                         const ReferenceObjectID roid = pElem->reference_object_id();
    2954              : 
    2955              :                         DimReferenceMapping<elemDim, worldDim>& map
    2956              :                                 = ReferenceMappingProvider::get<elemDim, worldDim>(roid, vCornerCoords);
    2957              : 
    2958              :                         try{
    2959              :                 //      get trial space
    2960              :                         const LocalShapeFunctionSet<elemDim>& rTrialSpace =
    2961              :                                                         LocalFiniteElementProvider::get<elemDim>(roid, m_scalarData.id());
    2962              : 
    2963              :                 //      number of dofs on element
    2964            0 :                         const size_t num_sh = rTrialSpace.num_sh();
    2965              : 
    2966              :                 //      get multiindices of element
    2967              :                         std::vector<DoFIndex> ind;  //    aux. index array
    2968              :                         m_scalarData.dof_indices(pElem, ind);
    2969              : 
    2970              :                 //      check multi indices
    2971            0 :                         if(ind.size() != num_sh)
    2972            0 :                                 UG_THROW("H1ErrorIntegrand::evaluate: Wrong number of"
    2973              :                                                 " multi indices.");
    2974              : 
    2975              :                 //      loop all integration points
    2976            0 :                         std::vector<MathVector<elemDim> > vLocGradient(num_sh);
    2977            0 :                         for(size_t ip = 0; ip < numIP; ++ip)
    2978              :                         {
    2979              : 
    2980              :                         //      compute shape gradients at ip
    2981            0 :                                 rTrialSpace.grads(&vLocGradient[0], vLocIP[ip]);
    2982              : 
    2983              :                         //      compute approximated solution at integration point
    2984              :                                 number approxSolIP = 0.0;
    2985              :                                 MathVector<elemDim> locTmp; VecSet(locTmp, 0.0);
    2986            0 :                                 for(size_t sh = 0; sh < num_sh; ++sh)
    2987              :                                 {
    2988              :                                 //      get value at shape point (e.g. corner for P1 fct)
    2989            0 :                                         const number valSH = DoFRef(m_scalarData.grid_function(), ind[sh]);
    2990              : 
    2991              :                                 //      add shape fct at ip * value at shape
    2992            0 :                                         approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
    2993              : 
    2994              :                                 //      add gradient at ip
    2995              :                                         VecScaleAppend(locTmp, valSH, vLocGradient[sh]);
    2996              :                                 }
    2997              : 
    2998              :                         //      compute global gradient
    2999              :                                 MathVector<worldDim> approxGradIP;
    3000              :                                 MathMatrix<worldDim, elemDim> JTInv;
    3001            0 :                                 map.jacobian_transposed_inverse(JTInv, vLocIP[ip]);//RightInverse(JTInv, vJT[ip]);
    3002              : 
    3003              : #ifdef UG_DEBUG
    3004              :                                 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], JTInv);
    3005              : #endif //UG_DEBUG
    3006              : 
    3007              :                                 MatVecMult(approxGradIP, JTInv, locTmp);
    3008              : 
    3009              :                         //      get squared of difference
    3010            0 :                                 vValue[ip] = approxSolIP * approxSolIP;
    3011            0 :                                 vValue[ip] += VecDot(approxGradIP, approxGradIP);
    3012              :                         }
    3013              : 
    3014            0 :                         }
    3015            0 :                         UG_CATCH_THROW("H1SemiNormFuncIntegrand::evaluate: trial space missing.");
    3016            0 :                 }
    3017              : };
    3018              : 
    3019              : 
    3020              : 
    3021              : 
    3022              : template <typename TGridFunction>
    3023            0 : number H1Norm2(TGridFunction& u, const char* cmp,
    3024              :                            int quadOrder, const char* subsets=NULL)
    3025              : {
    3026              : //      get function id of name
    3027              :         const size_t fct = u.fct_id_by_name(cmp);
    3028              : 
    3029              : //      check that function exists
    3030            0 :         if(fct >= u.num_fct())
    3031            0 :                 UG_THROW("H1Norm: Function space does not contain"
    3032              :                                 " a function with name " << cmp << ".");
    3033              : 
    3034              :         H1NormIntegrand<TGridFunction> spIntegrand(u, fct);
    3035            0 :         return IntegrateSubsets(spIntegrand, u, subsets, quadOrder);
    3036              : }
    3037              : 
    3038              : 
    3039              : template <typename TGridFunction>
    3040              : number H1Norm(TGridFunction& u, const char* cmp,
    3041              :                            int quadOrder, const char* subsets=NULL)
    3042              : {
    3043            0 :         return sqrt(H1Norm2(u, cmp, quadOrder,subsets));
    3044              : }
    3045              : 
    3046              : template <typename TGridFunction>
    3047            0 : number H1Norm(SmartPtr<TGridFunction> spGridFct, const char* cmp,
    3048              :                            int quadOrder, const char* subsets)
    3049              : {
    3050            0 :         return H1Norm(*spGridFct, cmp, quadOrder, subsets);
    3051              : }
    3052              : 
    3053              : template <typename TGridFunction>
    3054            0 : number H1Norm(SmartPtr<TGridFunction> spGridFct, const char* cmp, int quadOrder)
    3055              : {
    3056            0 :         return H1Norm(*spGridFct, cmp, quadOrder, NULL);
    3057              : }
    3058              : 
    3059              : 
    3060              : 
    3061              : /// Integrand for the distance of two grid functions - evaluated in the H1 norm
    3062              : template <typename TGridFunction>
    3063              : class H1DistIntegrand
    3064              :         : public StdIntegrand<number, TGridFunction::dim, H1DistIntegrand<TGridFunction> >
    3065              : {
    3066              :         public:
    3067              :         ///     world dimension of grid function
    3068              :                 static const int worldDim = TGridFunction::dim;
    3069              : 
    3070              :         private:
    3071              :                 ScalarGridFunctionData<TGridFunction> m_fineData;
    3072              :                 const int m_fineTopLevel;
    3073              : 
    3074              :                 ScalarGridFunctionData<TGridFunction> m_coarseData;
    3075              :                 const int m_coarseTopLevel;
    3076              : 
    3077              :         ///     multigrid
    3078              :                 SmartPtr<MultiGrid> m_spMG;
    3079              : 
    3080              :         public:
    3081              :         /// constructor (1 is fine grid function)
    3082            0 :                 H1DistIntegrand(TGridFunction& fineGridFct, size_t fineCmp,
    3083              :                                 TGridFunction& coarseGridFct, size_t coarseCmp)
    3084              :                 : m_fineData(fineGridFct, fineCmp),
    3085            0 :                   m_fineTopLevel(fineGridFct.dof_distribution()->grid_level().level()),
    3086              :                   m_coarseData(coarseGridFct, coarseCmp),
    3087            0 :                   m_coarseTopLevel(coarseGridFct.dof_distribution()->grid_level().level()),
    3088            0 :                   m_spMG(fineGridFct.domain()->grid())
    3089              :                 {
    3090            0 :                         if(m_fineTopLevel < m_coarseTopLevel)
    3091            0 :                                 UG_THROW("H1DiffIntegrand: fine and top level inverted.");
    3092              : 
    3093            0 :                         if(fineGridFct.domain().get() !=
    3094            0 :                                         coarseGridFct.domain().get())
    3095            0 :                                 UG_THROW("H1DiffIntegrand: grid functions defined on different domains.");
    3096            0 :                 };
    3097              : 
    3098              :         /// DTOR
    3099            0 :                 virtual ~H1DistIntegrand() {};
    3100              : 
    3101              :         ///     sets subset
    3102            0 :                 virtual void set_subset(int si)
    3103              :                 {
    3104            0 :                         if(!m_fineData.is_def_in_subset(si))
    3105            0 :                                 UG_THROW("H1DiffIntegrand: Grid function component"
    3106              :                                                 <<m_fineData.fct()<<" not defined on subset "<<si);
    3107            0 :                         if(!m_coarseData.is_def_in_subset(si))
    3108            0 :                                 UG_THROW("H1DiffIntegrand: Grid function component"
    3109              :                                                 <<m_coarseData.fct()<<" not defined on subset "<<si);
    3110              :                         IIntegrand<number, worldDim>::set_subset(si);
    3111            0 :                 }
    3112              : 
    3113              :         /// \copydoc IIntegrand::values
    3114              :                 template <int elemDim>
    3115            0 :                 void evaluate(number vValue[],
    3116              :                               const MathVector<worldDim> vFineGlobIP[],
    3117              :                               GridObject* pFineElem,
    3118              :                               const MathVector<worldDim> vCornerCoords[],
    3119              :                               const MathVector<elemDim> vFineLocIP[],
    3120              :                               const MathMatrix<elemDim, worldDim> vJT[],
    3121              :                               const size_t numIP)
    3122              :                 {
    3123              :                         typedef typename TGridFunction::template dim_traits<elemDim>::grid_base_object Element;
    3124              : 
    3125              :                         //      get coarse element
    3126              :                         GridObject* pCoarseElem = pFineElem;
    3127            0 :                         if(m_coarseTopLevel < m_fineTopLevel){
    3128              :                                 int parentLevel = m_spMG->get_level(pCoarseElem);
    3129            0 :                                 while(parentLevel > m_coarseTopLevel){
    3130            0 :                                         pCoarseElem = m_spMG->get_parent(pCoarseElem);
    3131              :                                         parentLevel = m_spMG->get_level(pCoarseElem);
    3132              :                                 }
    3133              :                         }
    3134              : 
    3135              :                 //      get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
    3136            0 :                         const ReferenceObjectID fineROID = pFineElem->reference_object_id();
    3137            0 :                         const ReferenceObjectID coarseROID = pCoarseElem->reference_object_id();
    3138              : 
    3139              :                 //      get corner coordinates
    3140              :                         std::vector<MathVector<worldDim> > vCornerCoarse;
    3141            0 :                         CollectCornerCoordinates(vCornerCoarse, *static_cast<Element*>(pCoarseElem), *m_coarseData.domain());
    3142              : 
    3143              :                 //      get Reference Mapping
    3144              :                         DimReferenceMapping<elemDim, worldDim>& map
    3145              :                                 = ReferenceMappingProvider::get<elemDim, worldDim>(coarseROID, vCornerCoarse);
    3146              :                         DimReferenceMapping<elemDim, worldDim>& mapF
    3147              :                                 = ReferenceMappingProvider::get<elemDim, worldDim>(fineROID, vCornerCoords);
    3148              : 
    3149              :                         std::vector<MathVector<elemDim> > vCoarseLocIP;
    3150            0 :                         vCoarseLocIP.resize(numIP);
    3151            0 :                         for(size_t ip = 0; ip < vCoarseLocIP.size(); ++ip) VecSet(vCoarseLocIP[ip], 0.0);
    3152            0 :                         map.global_to_local(&vCoarseLocIP[0], vFineGlobIP, numIP);
    3153              : 
    3154              :                         try{
    3155              :                 //      get trial space
    3156              :                         const LocalShapeFunctionSet<elemDim>& rFineLSFS =
    3157              :                                         LocalFiniteElementProvider::get<elemDim>(fineROID, m_fineData.id());
    3158              :                         const LocalShapeFunctionSet<elemDim>& rCoarseLSFS =
    3159              :                                         LocalFiniteElementProvider::get<elemDim>(coarseROID, m_coarseData.id());
    3160              : 
    3161              :                 //      get multiindices of element
    3162              :                         std::vector<DoFIndex> vFineMI, vCoarseMI;
    3163              :                         m_fineData.dof_indices(pFineElem, vFineMI);
    3164              :                         m_coarseData.dof_indices(pCoarseElem, vCoarseMI);
    3165              : 
    3166            0 :                         std::vector<MathVector<elemDim> > vFineLocGradient(vFineMI.size());
    3167            0 :                         std::vector<MathVector<elemDim> > vCoarseLocGradient(vCoarseMI.size());
    3168              : 
    3169              :                 //      loop all integration points
    3170            0 :                         for(size_t ip = 0; ip < numIP; ++ip)
    3171              :                         {
    3172              :                         //      compute shape gradients at ip
    3173            0 :                                 rFineLSFS.grads(&vFineLocGradient[0], vFineLocIP[ip]);
    3174            0 :                                 rCoarseLSFS.grads(&vCoarseLocGradient[0], vCoarseLocIP[ip]);
    3175              : 
    3176              :                         //      compute approximated solution at integration point
    3177              :                                 number fineSolIP = 0.0;
    3178              :                                 MathVector<elemDim> fineLocTmp; VecSet(fineLocTmp, 0.0);
    3179            0 :                                 for(size_t sh = 0; sh < vFineMI.size(); ++sh)
    3180              :                                 {
    3181            0 :                                         const number val = DoFRef(m_fineData.grid_function(), vFineMI[sh]);
    3182            0 :                                         fineSolIP += val * rFineLSFS.shape(sh, vFineLocIP[ip]);
    3183              :                                         VecScaleAppend(fineLocTmp, val, vFineLocGradient[sh]);
    3184              :                                 }
    3185              :                                 number coarseSolIP = 0.0;
    3186              :                                 MathVector<elemDim> coarseLocTmp; VecSet(coarseLocTmp, 0.0);
    3187            0 :                                 for(size_t sh = 0; sh < vCoarseMI.size(); ++sh)
    3188              :                                 {
    3189            0 :                                         const number val = DoFRef(m_coarseData.grid_function(), vCoarseMI[sh]);
    3190            0 :                                         coarseSolIP += val * rCoarseLSFS.shape(sh, vCoarseLocIP[ip]);
    3191              :                                         VecScaleAppend(coarseLocTmp, val, vCoarseLocGradient[sh]);
    3192              :                                 }
    3193              : 
    3194              :                         //      compute global gradient
    3195              :                                 MathVector<worldDim> fineGradIP;
    3196              :                                 MathMatrix<worldDim, elemDim> fineJTInv;
    3197            0 :                                 mapF.jacobian_transposed_inverse(fineJTInv, vFineLocIP[ip]);//RightInverse(fineJTInv, vJT[ip]);
    3198              : 
    3199              : #ifdef UG_DEBUG
    3200              :                                 CheckGeneralizedInverse<worldDim,elemDim>(vJT[ip], fineJTInv);
    3201              : #endif //UG_DEBUG
    3202              : 
    3203              : 
    3204              :                                 MatVecMult(fineGradIP, fineJTInv, fineLocTmp);
    3205              : 
    3206              :                         //      compute global gradient
    3207              :                                 MathVector<worldDim> coarseGradIP;
    3208              :                                 MathMatrix<worldDim, elemDim> coarseJTInv;
    3209            0 :                                 map.jacobian_transposed_inverse(coarseJTInv, vCoarseLocIP[ip]);
    3210              :                                 MatVecMult(coarseGradIP, coarseJTInv, coarseLocTmp);
    3211              : 
    3212              :                         //      get squared of difference
    3213            0 :                                 vValue[ip] = (coarseSolIP - fineSolIP);
    3214            0 :                                 vValue[ip] *= vValue[ip];
    3215            0 :                                 vValue[ip] += VecDistanceSq(coarseGradIP, fineGradIP);
    3216              :                         }
    3217              : 
    3218            0 :                         }
    3219            0 :                         UG_CATCH_THROW("H1DiffIntegrand::evaluate: trial space missing.");
    3220            0 :                 }
    3221              : };
    3222              : 
    3223              : 
    3224              : 
    3225              : template <typename TGridFunction>
    3226              : number H1Distance2(TGridFunction& spGridFct1, const char* cmp1,
    3227              :                TGridFunction& spGridFct2, const char* cmp2,
    3228              :                int quadOrder, const char* subsets=NULL)
    3229              : {
    3230              :         return GridFunctionDistance2<H1DistIntegrand<TGridFunction>, TGridFunction>
    3231            0 :                 (spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets);
    3232              : }
    3233              : 
    3234              : 
    3235              : template <typename TGridFunction>
    3236              : number H1Distance(TGridFunction& spGridFct1, const char* cmp1,
    3237              :                TGridFunction& spGridFct2, const char* cmp2,
    3238              :                int quadOrder, const char* subsets=NULL)
    3239              : {
    3240            0 :         return sqrt(H1Distance2(spGridFct1, cmp1, spGridFct2, cmp2, quadOrder, subsets));
    3241              : }
    3242              : /// for lua shell
    3243              : template <typename TGridFunction>
    3244            0 : number H1Error(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
    3245              :                SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
    3246              :                int quadOrder, const char* subsets)
    3247              : {
    3248            0 :         return H1Distance(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, subsets);
    3249              : }
    3250              : 
    3251              : /// for lua shell
    3252              : template <typename TGridFunction>
    3253            0 : number H1Error(SmartPtr<TGridFunction> spGridFct1, const char* cmp1,
    3254              :                SmartPtr<TGridFunction> spGridFct2, const char* cmp2,
    3255              :                int quadOrder)
    3256              : {
    3257            0 :         return H1Distance(*spGridFct1, cmp1, *spGridFct2, cmp2, quadOrder, NULL);
    3258              : }
    3259              : 
    3260              : 
    3261              : ////////////////////////////////////////////////////////////////////////////////
    3262              : // Standard Integrand
    3263              : ////////////////////////////////////////////////////////////////////////////////
    3264              : 
    3265              : template <typename TGridFunction>
    3266              : class StdFuncIntegrand
    3267              :         : public StdIntegrand<number, TGridFunction::dim, StdFuncIntegrand<TGridFunction> >
    3268              : {
    3269              :         public:
    3270              :         //      world dimension of grid function
    3271              :                 static const int worldDim = TGridFunction::dim;
    3272              : 
    3273              :         private:
    3274              :         // grid function
    3275              :                 TGridFunction* m_pGridFct;
    3276              : 
    3277              :         //      component of function
    3278              :                 const size_t m_fct;
    3279              : 
    3280              :         public:
    3281              :         /// constructor
    3282            0 :                 StdFuncIntegrand(TGridFunction* pGridFct, size_t cmp)
    3283            0 :                 : m_pGridFct(pGridFct), m_fct(cmp)
    3284              :                 {};
    3285              : 
    3286            0 :                 virtual ~StdFuncIntegrand(){}
    3287              : 
    3288              :         ///     sets subset
    3289            0 :                 virtual void set_subset(int si)
    3290              :                 {
    3291            0 :                         if(!m_pGridFct->is_def_in_subset(m_fct, si))
    3292            0 :                                 UG_THROW("L2ErrorIntegrand: Grid function component"
    3293              :                                                 <<m_fct<<" not defined on subset "<<si);
    3294              :                         IIntegrand<number, worldDim>::set_subset(si);
    3295            0 :                 }
    3296              : 
    3297              :         /// \copydoc IIntegrand::values
    3298              :                 template <int elemDim>
    3299            0 :                 void evaluate(number vValue[],
    3300              :                               const MathVector<worldDim> vGlobIP[],
    3301              :                               GridObject* pElem,
    3302              :                               const MathVector<worldDim> vCornerCoords[],
    3303              :                               const MathVector<elemDim> vLocIP[],
    3304              :                               const MathMatrix<elemDim, worldDim> vJT[],
    3305              :                               const size_t numIP)
    3306              :                 {
    3307              :                 //      get reference object id (i.e. Triangle, Quadrilateral, Tetrahedron, ...)
    3308            0 :                         ReferenceObjectID roid = (ReferenceObjectID) pElem->reference_object_id();
    3309              : 
    3310            0 :                         const LFEID m_id = m_pGridFct->local_finite_element_id(m_fct);
    3311              : 
    3312              :                         try{
    3313              :                 //      get trial space
    3314              :                         const LocalShapeFunctionSet<elemDim>& rTrialSpace =
    3315              :                                                         LocalFiniteElementProvider::get<elemDim>(roid, m_id);
    3316              : 
    3317              :                 //      number of dofs on element
    3318            0 :                         const size_t num_sh = rTrialSpace.num_sh();
    3319              : 
    3320              :                 //      get multiindices of element
    3321              : 
    3322              :                         std::vector<DoFIndex> ind;  //    aux. index array
    3323            0 :                         m_pGridFct->dof_indices(pElem, m_fct, ind);
    3324              : 
    3325              :                 //      check multi indices
    3326            0 :                         UG_COND_THROW(ind.size() != num_sh,
    3327              :                                                 "StdFuncIntegrand::evaluate: Wrong number of multi indices.");
    3328              : 
    3329              :                 //      loop all integration points
    3330            0 :                         for(size_t ip = 0; ip < numIP; ++ip)
    3331              :                         {
    3332              : 
    3333              :                         //      compute approximated solution at integration point
    3334              :                                 number approxSolIP = 0.0;
    3335            0 :                                 for(size_t sh = 0; sh < num_sh; ++sh)
    3336              :                                 {
    3337              :                                         //      get value at shape point (e.g. corner for P1 fct)
    3338              :                                         //      and add shape fct at ip * value at shape
    3339            0 :                                         const number valSH = DoFRef((*m_pGridFct), ind[sh]);
    3340            0 :                                         approxSolIP += valSH * rTrialSpace.shape(sh, vLocIP[ip]);
    3341              :                                 }
    3342              : 
    3343              :                                 //      get function value at ip
    3344            0 :                                 vValue[ip] = approxSolIP;
    3345              : 
    3346              :                         }
    3347              : 
    3348              :                         }
    3349            0 :                         UG_CATCH_THROW("StdFuncIntegrand::evaluate: trial space missing.");
    3350            0 :                 }
    3351              : };
    3352              : 
    3353              : 
    3354              : template <typename TGridFunction>
    3355            0 : number StdFuncIntegralOnVertex(TGridFunction& gridFct,
    3356              :                                                            size_t fct,
    3357              :                                                            int si)
    3358              : {
    3359              : //      integrate elements of subset
    3360              :         typedef typename TGridFunction::template dim_traits<0>::grid_base_object grid_base_object;
    3361              :         typedef typename TGridFunction::template dim_traits<0>::const_iterator const_iterator;
    3362              : 
    3363              :         //      reset the result
    3364              :         number integral = 0;
    3365              : 
    3366              : //      note: this iterator is for the base elements, e.g. Face and not
    3367              : //                      for the special type, e.g. Triangle, Quadrilateral
    3368              :         const_iterator iter = gridFct.template begin<grid_base_object>(si);
    3369              :         const_iterator iterEnd = gridFct.template end<grid_base_object>(si);
    3370              : 
    3371              : //      iterate over all elements
    3372            0 :         for(; iter != iterEnd; ++iter)
    3373              :         {
    3374              :         //      get element
    3375              :                 grid_base_object* pElem = *iter;
    3376              : 
    3377              :                 std::vector<DoFIndex> ind;  //    aux. index array
    3378              :                 gridFct.dof_indices(pElem, fct, ind);
    3379              : 
    3380              :         //      compute approximated solution at integration point
    3381              :                 number value = 0.0;
    3382            0 :                 for(size_t sh = 0; sh < ind.size(); ++sh)
    3383              :                 {
    3384            0 :                         value += DoFRef(gridFct, ind[sh]);
    3385              :                 }
    3386              : 
    3387              :         //      add to global sum
    3388            0 :                 integral += value;
    3389              : 
    3390              :         } // end elem
    3391              : 
    3392              : //      return the summed integral contributions of all elements
    3393            0 :         return integral;
    3394              : }
    3395              : 
    3396              : template <typename TGridFunction>
    3397              : number StdFuncIntegralOnVertex(SmartPtr<TGridFunction> spGridFct, size_t fct, int si)
    3398              : { return StdFuncIntegralOnVertex(*spGridFct, fct, si); }
    3399              : 
    3400              : 
    3401              : template <typename TGridFunction>
    3402            0 : number Integral(TGridFunction& gridFct, const char* cmp,
    3403              :                 const char* subsets, int quadOrder)
    3404              : {
    3405              : //      get function id of name
    3406              :         const size_t fct = gridFct.fct_id_by_name(cmp);
    3407              : 
    3408              : //      check that function exists
    3409            0 :         UG_COND_THROW(fct >= gridFct.num_fct(), "L2Norm: Function space does not contain"
    3410              :                                 " a function with name " << cmp << ".");
    3411              : 
    3412              : //      read subsets
    3413            0 :         SubsetGroup ssGrp(gridFct.domain()->subset_handler());
    3414            0 :         if(subsets != NULL)
    3415              :         {
    3416            0 :                 ssGrp.add(TokenizeString(subsets));
    3417            0 :                 if(!SameDimensionsInAllSubsets(ssGrp))
    3418            0 :                         UG_THROW("IntegrateSubsets: Subsets '"<<subsets<<"' do not have same dimension."
    3419              :                                          "Can not integrate on subsets of different dimensions.");
    3420              :         }
    3421              :         else
    3422              :         {
    3423              :         //      add all subsets and remove lower dim subsets afterwards
    3424            0 :                 ssGrp.add_all();
    3425            0 :                 RemoveLowerDimSubsets(ssGrp);
    3426              :         }
    3427              : 
    3428              :         // \TODO: This should be generalite in IntegrateSubset instead of doing it directly here
    3429              :         bool bOnlyVertex = true;
    3430            0 :         for(size_t s = 0; s < ssGrp.size(); ++s)
    3431            0 :                 if(ssGrp.dim(s) != 0) bOnlyVertex = false;
    3432              : 
    3433            0 :         if(bOnlyVertex)
    3434              :         {
    3435              :                 number value = 0;
    3436            0 :                 for(size_t s = 0; s < ssGrp.size(); ++s)
    3437            0 :                         value += StdFuncIntegralOnVertex(gridFct, fct, ssGrp[s]);
    3438              : 
    3439              : #ifdef UG_PARALLEL
    3440              :         // sum over processes
    3441              :         if(pcl::NumProcs() > 1)
    3442              :         {
    3443              :                 pcl::ProcessCommunicator com;
    3444              :                 number local = value;
    3445              :                 com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
    3446              :         }
    3447              : #endif
    3448            0 :                 return value;
    3449              :         }
    3450              : 
    3451              :         StdFuncIntegrand<TGridFunction> integrand(&gridFct, fct);
    3452            0 :         return IntegrateSubsets(integrand, gridFct, subsets, quadOrder);
    3453              : }
    3454              : 
    3455              : template <typename TGridFunction>
    3456            0 : number Integral(SmartPtr<TGridFunction> spGridFct, const char* cmp,
    3457              :                 const char* subsets, int quadOrder)
    3458            0 : { return Integral(*spGridFct, cmp, subsets, quadOrder); }
    3459              : 
    3460              : 
    3461              : template <typename TGridFunction>
    3462            0 : number Integral(SmartPtr<TGridFunction> spGridFct, const char* cmp,
    3463              :                 const char* subsets)
    3464              : {
    3465            0 :         return Integral(spGridFct, cmp, subsets, 1);
    3466              : }
    3467              : template <typename TGridFunction>
    3468            0 : number Integral(SmartPtr<TGridFunction> spGridFct, const char* cmp)
    3469              : {
    3470            0 :         return Integral(spGridFct, cmp, NULL, 1);
    3471              : }
    3472              : 
    3473              : 
    3474              : ////////////////////////////////////////////////////////////////////////////////
    3475              : ////////////////////////////////////////////////////////////////////////////////
    3476              : // Generic Boundary Integration Routine
    3477              : ////////////////////////////////////////////////////////////////////////////////
    3478              : ////////////////////////////////////////////////////////////////////////////////
    3479              : 
    3480              : template <int WorldDim, int dim, typename TConstIterator>
    3481            0 : number IntegralNormalComponentOnManifoldUsingFV1Geom(TConstIterator iterBegin,
    3482              :                                        TConstIterator iterEnd,
    3483              :                                        typename domain_traits<WorldDim>::position_accessor_type& aaPos,
    3484              :                                        const ISubsetHandler* ish,
    3485              :                                        IIntegrand<MathVector<WorldDim>, WorldDim>& integrand,
    3486              :                                        const SubsetGroup& bndSSGrp)
    3487              : {
    3488              : //      reset the result
    3489              :         number integral = 0;
    3490              : 
    3491              : //      note: this iterator is for the base elements, e.g. Face and not
    3492              : //                      for the special type, e.g. Triangle, Quadrilateral
    3493              :         TConstIterator iter = iterBegin;
    3494              : 
    3495              : //      this is the base element type (e.g. Face). This is the type when the
    3496              : //      iterators above are dereferenciated.
    3497              :         typedef typename domain_traits<dim>::grid_base_object grid_base_object;
    3498              : 
    3499              : //      create a FV1 Geometry
    3500            0 :         DimFV1Geometry<dim> geo;
    3501              : 
    3502              : //      specify, which subsets are boundary
    3503            0 :         for(size_t s = 0; s < bndSSGrp.size(); ++s)
    3504              :         {
    3505              :         //      get subset index
    3506              :                 const int bndSubset = bndSSGrp[s];
    3507              : 
    3508              :         //      request this subset index as boundary subset. This will force the
    3509              :         //      creation of boundary subsets when calling geo.update
    3510            0 :                 geo.add_boundary_subset(bndSubset);
    3511              :         }
    3512              : 
    3513              : //      vector of corner coordinates of element corners (to be filled for each elem)
    3514              :         std::vector<MathVector<WorldDim> > vCorner;
    3515              : 
    3516              : //      iterate over all elements
    3517            0 :         for(; iter != iterEnd; ++iter)
    3518              :         {
    3519              :         //      get element
    3520              :                 grid_base_object* pElem = *iter;
    3521              : 
    3522              :         //      get all corner coordinates
    3523              :                 CollectCornerCoordinates(vCorner, *pElem, aaPos, true);
    3524              : 
    3525              :         //      compute bf and grads at bip for element
    3526              :                 try{
    3527            0 :                         geo.update(pElem, &vCorner[0], ish);
    3528              :                 }
    3529            0 :                 UG_CATCH_THROW("IntegralNormalComponentOnManifold: "
    3530              :                                         "Cannot update Finite Volume Geometry.");
    3531              : 
    3532              :         //      specify, which subsets are boundary
    3533            0 :                 for(size_t s = 0; s < bndSSGrp.size(); ++s)
    3534              :                 {
    3535              :                 //      get subset index
    3536              :                         const int bndSubset = bndSSGrp[s];
    3537              : 
    3538              :                 //      get all bf of this subset
    3539              :                         typedef typename DimFV1Geometry<dim>::BF BF;
    3540              :                         const std::vector<BF>& vBF = geo.bf(bndSubset);
    3541              : 
    3542              :                 //      loop boundary faces
    3543            0 :                         for(size_t b = 0; b < vBF.size(); ++b)
    3544              :                         {
    3545              :                         //      get bf
    3546              :                                 const BF& bf = vBF[b];
    3547              : 
    3548              :                         //      value
    3549              :                                 MathVector<WorldDim> value;
    3550              : 
    3551              :                         //      jacobian
    3552              :                                 MathMatrix<dim, WorldDim> JT;
    3553            0 :                                 Inverse(JT, bf.JTInv());
    3554              : 
    3555              :                         //      compute integrand values at integration points
    3556              :                                 try
    3557              :                                 {
    3558            0 :                                         integrand.values(&value, &(bf.global_ip()),
    3559              :                                                                          pElem, &vCorner[0], &(bf.local_ip()),
    3560              :                                                                          &(JT),
    3561              :                                                                          1);
    3562              :                                 }
    3563            0 :                                 UG_CATCH_THROW("IntegralNormalComponentOnManifold: Unable to compute values of "
    3564              :                                                                 "integrand at integration point.");
    3565              : 
    3566              :                         //      sum up contribution (normal includes area)
    3567            0 :                                 integral += VecDot(value, bf.normal());
    3568              : 
    3569              :                         } // end bf
    3570              :                 } // end bnd subsets
    3571              :         } // end elem
    3572              : 
    3573              : //      return the summed integral contributions of all elements
    3574            0 :         return integral;
    3575            0 : }
    3576              : 
    3577              : 
    3578              : template <int WorldDim, int dim, typename TConstIterator>
    3579            0 : number IntegralNormalComponentOnManifoldGeneral(
    3580              :                 TConstIterator iterBegin,
    3581              :                 TConstIterator iterEnd,
    3582              :                 typename domain_traits<WorldDim>::position_accessor_type& aaPos,
    3583              :                 const ISubsetHandler* ish,
    3584              :                 IIntegrand<MathVector<WorldDim>, WorldDim>& integrand,
    3585              :                 const SubsetGroup& bndSSGrp,
    3586              :                 int quadOrder,
    3587              :                 Grid& grid)
    3588              : {
    3589              : //      reset the result
    3590              :         number integral = 0;
    3591              : 
    3592              : //      note: this iterator is for the base elements, e.g. Face and not
    3593              : //                      for the special type, e.g. Triangle, Quadrilateral
    3594              :         TConstIterator iter = iterBegin;
    3595              : 
    3596              : //      this is the base element type (e.g. Face). This is the type when the
    3597              : //      iterators above are dereferenciated.
    3598              :         typedef typename domain_traits<dim>::element_type Element;
    3599              :         typedef typename domain_traits<dim>::side_type Side;
    3600              : 
    3601              : //      vector of corner coordinates of element corners (to be filled for each elem)
    3602              :         std::vector<MathVector<WorldDim> > vCorner;
    3603              :         std::vector<int> vSubsetIndex;
    3604              : 
    3605              : //      iterate over all elements
    3606            0 :         for(; iter != iterEnd; ++iter)
    3607              :         {
    3608              :         //      get element
    3609              :                 Element* pElem = *iter;
    3610              : 
    3611              :         //      get all corner coordinates
    3612              :                 CollectCornerCoordinates(vCorner, *pElem, aaPos, true);
    3613              : 
    3614              :         //      get reference object id
    3615            0 :                 const ReferenceObjectID elemRoid = pElem->reference_object_id();
    3616              : 
    3617              :         //      get sides
    3618              :                 typename Grid::traits<Side>::secure_container vSide;
    3619              :                 grid.associated_elements_sorted(vSide, pElem);
    3620            0 :                 vSubsetIndex.resize(vSide.size());
    3621            0 :                 for(size_t i = 0; i < vSide.size(); ++i)
    3622            0 :                         vSubsetIndex[i] = ish->get_subset_index(vSide[i]);
    3623              : 
    3624              :                 DimReferenceMapping<dim, WorldDim>& rMapping
    3625              :                         = ReferenceMappingProvider::get<dim, WorldDim>(elemRoid, vCorner);
    3626              : 
    3627              :                 const DimReferenceElement<dim>& rRefElem
    3628              :                         = ReferenceElementProvider::get<dim>(elemRoid);
    3629              : 
    3630              :         //      loop sub elements
    3631            0 :                 for(size_t side = 0; side < vSide.size(); ++side)
    3632              :                 {
    3633              :                 //      check if side used
    3634            0 :                         if(!bndSSGrp.contains(vSubsetIndex[side])) continue;
    3635              : 
    3636              :                 //      get side
    3637              :                         Side* pSide = vSide[side];
    3638              : 
    3639            0 :                         std::vector<MathVector<WorldDim> > vSideCorner(rRefElem.num(dim-1, side, 0));
    3640            0 :                         std::vector<MathVector<dim> > vLocalSideCorner(rRefElem.num(dim-1, side, 0));
    3641            0 :                         for(size_t co = 0; co < vSideCorner.size(); ++co){
    3642            0 :                                 vSideCorner[co] = vCorner[rRefElem.id(dim-1, side, 0, co)];
    3643              :                                 vLocalSideCorner[co] = rRefElem.corner(rRefElem.id(dim-1, side, 0, co));
    3644              :                         }
    3645              : 
    3646              :                 //      side quad rule
    3647            0 :                         const ReferenceObjectID sideRoid = pSide->reference_object_id();
    3648              :                         const QuadratureRule<dim-1>& rSideQuadRule
    3649            0 :                                         = QuadratureRuleProvider<dim-1>::get(sideRoid, quadOrder);
    3650              : 
    3651              :                 //      normal
    3652              :                         MathVector<WorldDim> Normal;
    3653            0 :                         ElementNormal<WorldDim>(sideRoid, Normal, &vSideCorner[0]);
    3654              : 
    3655              :                 //      quadrature points
    3656              :                         const number* vWeight = rSideQuadRule.weights();
    3657              :                         const size_t nip = rSideQuadRule.size();
    3658            0 :                         std::vector<MathVector<dim> > vLocalIP(nip);
    3659            0 :                         std::vector<MathVector<dim> > vGlobalIP(nip);
    3660              : 
    3661              :                         DimReferenceMapping<dim-1, dim>& map
    3662              :                                 = ReferenceMappingProvider::get<dim-1, dim>(sideRoid, vLocalSideCorner);
    3663              : 
    3664            0 :                         for(size_t ip = 0; ip < nip; ++ip)
    3665            0 :                                 map.local_to_global(vLocalIP[ip], rSideQuadRule.point(ip));
    3666              : 
    3667            0 :                         for(size_t ip = 0; ip < nip; ++ip)
    3668            0 :                                 rMapping.local_to_global(vGlobalIP[ip], vLocalIP[ip]);
    3669              : 
    3670              :                 //      compute transformation matrices
    3671            0 :                         std::vector<MathMatrix<dim-1, WorldDim> > vJT(nip);
    3672            0 :                         map.jacobian_transposed(&(vJT[0]), rSideQuadRule.points(), nip);
    3673              : 
    3674            0 :                         std::vector<MathMatrix<dim, WorldDim> > vElemJT(nip);
    3675            0 :                         rMapping.jacobian_transposed(&(vElemJT[0]), &vLocalIP[0], nip);
    3676              : 
    3677            0 :                         std::vector<MathVector<WorldDim> > vValue(nip);
    3678              : 
    3679              :                 //      compute integrand values at integration points
    3680              :                         try
    3681              :                         {
    3682            0 :                                 integrand.values(&vValue[0], &vGlobalIP[0],
    3683              :                                                                  pElem, &vCorner[0], &vLocalIP[0],
    3684              :                                                                  &(vElemJT[0]),
    3685              :                                                                  nip);
    3686              :                         }
    3687            0 :                         UG_CATCH_THROW("IntegralNormalComponentOnManifold: Unable to compute values of "
    3688              :                                                         "integrand at integration point.");
    3689              : 
    3690              :                 //      loop integration points
    3691            0 :                         for(size_t ip = 0; ip < nip; ++ip)
    3692              :                         {
    3693              :                         //      get quadrature weight
    3694            0 :                                 const number weightIP = vWeight[ip];
    3695              : 
    3696              :                         //      get determinate of mapping
    3697            0 :                                 const number det = SqrtGramDeterminant(vJT[ip]);
    3698              : 
    3699              :                         //      add contribution of integration point
    3700            0 :                                 integral +=  VecDot(vValue[ip], Normal) * weightIP * det;
    3701              :                         }
    3702              :                 } // end bf
    3703              :         } // end elem
    3704              : 
    3705              : //      return the summed integral contributions of all elements
    3706            0 :         return integral;
    3707            0 : }
    3708              : 
    3709              : template <typename TGridFunction, int dim>
    3710            0 : number IntegralNormalComponentOnManifoldSubset(SmartPtr<IIntegrand<MathVector<TGridFunction::dim>, TGridFunction::dim> > spIntegrand,
    3711              :                                  SmartPtr<TGridFunction> spGridFct,
    3712              :                                  int si, const SubsetGroup& bndSSGrp, int quadOrder)
    3713              : {
    3714              : //      integrate elements of subset
    3715              :         typedef typename TGridFunction::template dim_traits<dim>::grid_base_object grid_base_object;
    3716              :         typedef typename TGridFunction::template dim_traits<dim>::const_iterator const_iterator;
    3717              :         static const int WorldDim = TGridFunction::dim;
    3718              : 
    3719            0 :         spIntegrand->set_subset(si);
    3720              : 
    3721            0 :         if(quadOrder == 1)
    3722              :                 return IntegralNormalComponentOnManifoldUsingFV1Geom<WorldDim,dim,const_iterator>
    3723            0 :                                         (spGridFct->template begin<grid_base_object>(si),
    3724              :                          spGridFct->template end<grid_base_object>(si),
    3725            0 :                          spGridFct->domain()->position_accessor(),
    3726            0 :                          spGridFct->domain()->subset_handler().get(),
    3727              :                          *spIntegrand, bndSSGrp);
    3728              :         else{
    3729              :                 UG_LOG(" #### IntegralNormalComponentOnManifoldSubset ####:\n")
    3730              :                 return IntegralNormalComponentOnManifoldGeneral<WorldDim,dim,const_iterator>
    3731            0 :                                         (spGridFct->template begin<grid_base_object>(si),
    3732              :                          spGridFct->template end<grid_base_object>(si),
    3733            0 :                          spGridFct->domain()->position_accessor(),
    3734            0 :                          spGridFct->domain()->subset_handler().get(),
    3735            0 :                          *spIntegrand, bndSSGrp, quadOrder, *spGridFct->domain()->grid());
    3736              :         }
    3737              : }
    3738              : 
    3739              : template <typename TGridFunction>
    3740            0 : number IntegralNormalComponentOnManifoldSubsets(
    3741              :                 SmartPtr<IIntegrand<MathVector<TGridFunction::dim>, TGridFunction::dim> > spIntegrand,
    3742              :                 SmartPtr<TGridFunction> spGridFct,
    3743              :                 const char* BndSubsets, const char* InnerSubsets,
    3744              :                 int quadOrder)
    3745              : {
    3746              : //      world dimensions
    3747              :         static const int dim = TGridFunction::dim;
    3748              : 
    3749              : //      read subsets
    3750            0 :         SubsetGroup innerSSGrp(spGridFct->domain()->subset_handler());
    3751            0 :         if(InnerSubsets != NULL)
    3752              :         {
    3753            0 :                 innerSSGrp.add(TokenizeString(InnerSubsets));
    3754            0 :                 if(!SameDimensionsInAllSubsets(innerSSGrp))
    3755            0 :                         UG_THROW("IntegralNormalComponentOnManifold: Subsets '"<<InnerSubsets<<"' do not have same dimension."
    3756              :                                  "Can not integrate on subsets of different dimensions.");
    3757              :         }
    3758              :         else
    3759              :         {
    3760              :         //      add all subsets and remove lower dim subsets afterwards
    3761            0 :                 innerSSGrp.add_all();
    3762            0 :                 RemoveLowerDimSubsets(innerSSGrp);
    3763              :         }
    3764              : 
    3765              : //      read subsets
    3766            0 :         SubsetGroup bndSSGrp(spGridFct->domain()->subset_handler());
    3767            0 :         if(BndSubsets != NULL)
    3768            0 :                 bndSSGrp.add(TokenizeString(BndSubsets));
    3769              :         else
    3770            0 :                 UG_THROW("IntegralNormalComponentOnManifold: No boundary subsets passed.");
    3771              : 
    3772              : //      reset value
    3773              :         number value = 0;
    3774              : 
    3775              : //      loop subsets
    3776            0 :         for(size_t i = 0; i < innerSSGrp.size(); ++i)
    3777              :         {
    3778              :         //      get subset index
    3779              :                 const int si = innerSSGrp[i];
    3780              : 
    3781              :         //      check dimension
    3782            0 :                 if(innerSSGrp.dim(i) != dim && innerSSGrp.dim(i) != DIM_SUBSET_EMPTY_GRID)
    3783            0 :                         UG_THROW("IntegralNormalComponentOnManifold: Dimension of inner subset is "<<
    3784              :                                  innerSSGrp.dim(i)<<", but only World Dimension "<<dim<<
    3785              :                                  " subsets can be used for inner subsets.");
    3786              : 
    3787              :         //      integrate elements of subset
    3788            0 :                 switch(innerSSGrp.dim(i))
    3789              :                 {
    3790              :                         case DIM_SUBSET_EMPTY_GRID: break;
    3791            0 :                         case dim: value += IntegralNormalComponentOnManifoldSubset<TGridFunction, dim>(spIntegrand, spGridFct, si, bndSSGrp, quadOrder); break;
    3792            0 :                         default: UG_THROW("IntegralNormalComponentOnManifold: Dimension "<<innerSSGrp.dim(i)<<" not supported. "
    3793              :                                           " World dimension is "<<dim<<".");
    3794              :                 }
    3795              :         }
    3796              : 
    3797              : #ifdef UG_PARALLEL
    3798              :         // sum over processes
    3799              :         if(pcl::NumProcs() > 1)
    3800              :         {
    3801              :                 pcl::ProcessCommunicator com;
    3802              :                 number local = value;
    3803              :                 com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
    3804              :         }
    3805              : #endif
    3806              : 
    3807              : //      return the result
    3808            0 :         return value;
    3809              : }
    3810              : 
    3811              : template <typename TGridFunction>
    3812            0 : number IntegralNormalComponentOnManifold(
    3813              :                 SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spData,
    3814              :                 SmartPtr<TGridFunction> spGridFct,
    3815              :                 const char* BndSubset, const char* InnerSubset,
    3816              :                 number time,
    3817              :                 int quadOrder)
    3818              : {
    3819            0 :         SmartPtr<IIntegrand<MathVector<TGridFunction::dim>, TGridFunction::dim> > spIntegrand
    3820            0 :                 = make_sp(new UserDataIntegrand<MathVector<TGridFunction::dim>, TGridFunction>(spData, &(*spGridFct), time));
    3821              : 
    3822            0 :         return IntegralNormalComponentOnManifoldSubsets(spIntegrand, spGridFct, BndSubset, InnerSubset, quadOrder);
    3823              : }
    3824              : 
    3825              : template <typename TGridFunction>
    3826            0 : number IntegralNormalComponentOnManifold(
    3827              :                 SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spData,
    3828              :                 SmartPtr<TGridFunction> spGridFct,
    3829              :                 const char* BndSubset, const char* InnerSubset,
    3830              :                 number time)
    3831            0 : {return IntegralNormalComponentOnManifold(spData, spGridFct, BndSubset, InnerSubset, time, 1);}
    3832              : 
    3833              : template <typename TGridFunction>
    3834            0 : number IntegralNormalComponentOnManifold(
    3835              :                 SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spData,
    3836              :                 SmartPtr<TGridFunction> spGridFct,
    3837              :                 const char* BndSubset,
    3838              :                 number time)
    3839            0 : {return IntegralNormalComponentOnManifold(spData, spGridFct, BndSubset, NULL, time, 1);}
    3840              : 
    3841              : template <typename TGridFunction>
    3842            0 : number IntegralNormalComponentOnManifold(
    3843              :                 SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spData,
    3844              :                 SmartPtr<TGridFunction> spGridFct,
    3845              :                 const char* BndSubset, const char* InnerSubset)
    3846            0 : {return IntegralNormalComponentOnManifold(spData, spGridFct, BndSubset, InnerSubset, 0.0, 1);}
    3847              : 
    3848              : template <typename TGridFunction>
    3849            0 : number IntegralNormalComponentOnManifold(
    3850              :                 SmartPtr<UserData<MathVector<TGridFunction::dim>, TGridFunction::dim> > spData,
    3851              :                 SmartPtr<TGridFunction> spGridFct,
    3852              :                 const char* BndSubset)
    3853            0 : {return IntegralNormalComponentOnManifold(spData, spGridFct, BndSubset, NULL, 0.0, 1);}
    3854              : 
    3855              : ///////////////
    3856              : // lua data
    3857              : ///////////////
    3858              : 
    3859              : #ifdef UG_FOR_LUA
    3860              : template <typename TGridFunction>
    3861            0 : number IntegralNormalComponentOnManifold(
    3862              :                 const char* luaFct, SmartPtr<TGridFunction> spGridFct,
    3863              :                 const char* BndSubset, const char* InnerSubset,
    3864              :                 number time, int quadOrder)
    3865              : {
    3866              :         static const int dim = TGridFunction::dim;
    3867            0 :         SmartPtr<UserData<MathVector<dim>, dim> > sp =
    3868              :                         LuaUserDataFactory<MathVector<dim>, dim>::create(luaFct);
    3869            0 :         return IntegralNormalComponentOnManifold(sp, spGridFct, BndSubset, InnerSubset, time, quadOrder);
    3870              : }
    3871              : 
    3872              : template <typename TGridFunction>
    3873            0 : number IntegralNormalComponentOnManifold(
    3874              :                 const char* luaFct, SmartPtr<TGridFunction> spGridFct,
    3875              :                 const char* BndSubset, const char* InnerSubset,
    3876              :                 number time)
    3877            0 : {return IntegralNormalComponentOnManifold(luaFct, spGridFct, BndSubset, InnerSubset, time, 1);}
    3878              : 
    3879              : template <typename TGridFunction>
    3880            0 : number IntegralNormalComponentOnManifold(
    3881              :                 const char* luaFct, SmartPtr<TGridFunction> spGridFct,
    3882              :                 const char* BndSubset,
    3883              :                 number time)
    3884            0 : {return IntegralNormalComponentOnManifold(luaFct, spGridFct, BndSubset, NULL, time, 1);}
    3885              : 
    3886              : template <typename TGridFunction>
    3887            0 : number IntegralNormalComponentOnManifold(
    3888              :                 const char* luaFct, SmartPtr<TGridFunction> spGridFct,
    3889              :                 const char* BndSubset, const char* InnerSubset)
    3890            0 : {return IntegralNormalComponentOnManifold(luaFct, spGridFct, BndSubset, InnerSubset, 0.0, 1);}
    3891              : 
    3892              : template <typename TGridFunction>
    3893            0 : number IntegralNormalComponentOnManifold(
    3894              :                 const char* luaFct, SmartPtr<TGridFunction> spGridFct,
    3895              :                 const char* BndSubset)
    3896            0 : {return IntegralNormalComponentOnManifold(luaFct, spGridFct, BndSubset, NULL, 0.0, 1);}
    3897              : #endif
    3898              : 
    3899              : ////////////////////////////////////////////////////////////////////////////////
    3900              : // Boundary Integral
    3901              : ////////////////////////////////////////////////////////////////////////////////
    3902              : /// Integrates a component over some boundary subsets
    3903              : /**
    3904              :  * This function integrates \f$ -c \cdot \vec{n} \f$ over some selected
    3905              :  * boundary subsets, where c is a component of the grid function u. The
    3906              :  * integral is taken over all boundary subset manifold geometric objects
    3907              :  *
    3908              :  * @param u                             a grid function
    3909              :  * @param cmp                   the component c which should be integrated
    3910              :  * @param BndSubset             a comma-separated string of symbolic boundary subset names
    3911              :  * @return      the integral
    3912              :  */
    3913              : 
    3914              : template <typename TGridFunction>
    3915            0 : number IntegrateNormalComponentOnManifold(TGridFunction& u, const char* cmp,
    3916              :                                    const char* BndSubset)
    3917              : {
    3918              : //      get function id of name
    3919              :         const size_t fct = u.fct_id_by_name(cmp);
    3920              : 
    3921              : //      check that function exists
    3922            0 :         if(fct >= u.num_fct())
    3923            0 :                 UG_THROW("IntegrateNormalComponentOnManifold: Function space does not contain"
    3924              :                                 " a function with name " << cmp << ".");
    3925              : 
    3926              :         if(u.local_finite_element_id(fct) != LFEID(LFEID::LAGRANGE, TGridFunction::dim, 1))
    3927            0 :                 UG_THROW("IntegrateNormalComponentOnManifold:"
    3928              :                                  "Only implemented for Lagrange P1 functions.");
    3929              : 
    3930              : //      read bnd subsets
    3931            0 :         SubsetGroup bndSSGrp(u.domain()->subset_handler());
    3932            0 :         bndSSGrp.add(TokenizeString(BndSubset));
    3933              : 
    3934              : //      reset value
    3935              :         number value = 0;
    3936              : 
    3937              : //      loop subsets
    3938            0 :         for(size_t i = 0; i < bndSSGrp.size(); ++i)
    3939              :         {
    3940              :         //      get subset index
    3941              :                 const int si = bndSSGrp[i];
    3942              : 
    3943              :         //      skip if function is not defined in subset
    3944            0 :                 if(!u.is_def_in_subset(fct, si)) continue;
    3945              : 
    3946              :         //      create integration kernel
    3947              :                 static const int dim = TGridFunction::dim;
    3948              : 
    3949              :         //      integrate elements of subset
    3950              :                 typedef typename domain_traits<dim>::grid_base_object grid_base_object;
    3951              : 
    3952              :         //      get iterators for all elems on subset
    3953              :                 typedef typename TGridFunction::template dim_traits<dim>::const_iterator const_iterator;
    3954              :                 const_iterator iter = u.template begin<grid_base_object>();
    3955              :                 const_iterator iterEnd = u.template end<grid_base_object>();
    3956              : 
    3957              :         //      create a FV1 Geometry
    3958            0 :                 DimFV1Geometry<dim> geo;
    3959              : 
    3960              :         //      specify, which subsets are boundary
    3961            0 :                 for(size_t s = 0; s < bndSSGrp.size(); ++s)
    3962              :                 {
    3963              :                 //      get subset index
    3964              :                         const int bndSubset = bndSSGrp[s];
    3965              : 
    3966              :                 //      request this subset index as boundary subset. This will force the
    3967              :                 //      creation of boundary subsets when calling geo.update
    3968            0 :                         geo.add_boundary_subset(bndSubset);
    3969              :                 }
    3970              : 
    3971              :         //      vector of corner coordinates of element corners (to be filled for each elem)
    3972              :                 std::vector<MathVector<dim> > vCorner;
    3973              : 
    3974              :         //      loop elements of subset
    3975            0 :                 for( ; iter != iterEnd; ++iter)
    3976              :                 {
    3977              :                 //      get element
    3978              :                         grid_base_object* elem = *iter;
    3979              : 
    3980              :                 //      get all corner coordinates
    3981            0 :                         CollectCornerCoordinates(vCorner, *elem, u.domain()->position_accessor(), true);
    3982              : 
    3983              :                 //      compute bf and grads at bip for element
    3984              :                         try{
    3985            0 :                                 geo.update(elem, &vCorner[0], u.domain()->subset_handler().get());
    3986              :                         }
    3987            0 :                         UG_CATCH_THROW("IntegrateNormalComponenOnManifold: "
    3988              :                                                 "Cannot update Finite Volume Geometry.");
    3989              : 
    3990              :                 //      get fct multi-indices of element
    3991              :                         std::vector<DoFIndex> ind;
    3992              :                         u.dof_indices(elem, fct, ind);
    3993              : 
    3994              :                 //      specify, which subsets are boundary
    3995            0 :                         for(size_t s = 0; s < bndSSGrp.size(); ++s)
    3996              :                         {
    3997              :                         //      get subset index
    3998              :                                 const int bndSubset = bndSSGrp[s];
    3999              : 
    4000              :                         //      get all bf of this subset
    4001              :                                 typedef typename DimFV1Geometry<dim>::BF BF;
    4002              :                                 const std::vector<BF>& vBF = geo.bf(bndSubset);
    4003              : 
    4004              :                         //      loop boundary faces
    4005            0 :                                 for(size_t b = 0; b < vBF.size(); ++b)
    4006              :                                 {
    4007              :                                 //      get bf
    4008              :                                         const BF& bf = vBF[b];
    4009              : 
    4010              :                                 //      get normal on bf
    4011              :                                         const MathVector<dim>& normal = bf.normal();
    4012              : 
    4013              :                                 //      check multi indices
    4014              :                                         UG_ASSERT(ind.size() == bf.num_sh(),
    4015              :                                                   "IntegrateNormalComponentOnManifold::values: Wrong number of"
    4016              :                                                           " multi indices, ind: "<<ind.size() << ", bf.num_sh: "
    4017              :                                                           << bf.num_sh());
    4018              : 
    4019              :                                         MathVector<dim> val; VecSet(val, 0.0);
    4020            0 :                                         for(size_t sh = 0; sh < bf.num_sh(); ++sh)
    4021              :                                         {
    4022            0 :                                                 const number fctVal = DoFRef(u, ind[sh]);
    4023              :                                             const MathVector<dim>& ip = bf.global_ip();
    4024              :                                                 VecScaleAdd(val, 1.0, val, fctVal, ip);
    4025              :                                         }
    4026              : 
    4027              :                                         //      sum up contributions
    4028            0 :                                         value -= VecDot(val, normal);
    4029              :                                 }
    4030              :                         }
    4031              :                 }
    4032              :         }
    4033              : 
    4034              : #ifdef UG_PARALLEL
    4035              :         // sum over processes
    4036              :         if(pcl::NumProcs() > 1)
    4037              :         {
    4038              :                 pcl::ProcessCommunicator com;
    4039              :                 number local = value;
    4040              :                 com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
    4041              :         }
    4042              : #endif
    4043              : 
    4044              : //      return the result
    4045            0 :         return value;
    4046              : }
    4047              : 
    4048              : /// Integrates the Flux of a component over some boundary subsets
    4049              : /**
    4050              :  * This function integrates \f$ - \nabla c \cdot \vec{n} \f$ over some selected
    4051              :  * boundary subsets. In order to compute the gradient of a function a world-
    4052              :  * dimension element must be given and, thus, some "inner" subsets have to be
    4053              :  * specified to indicate the full-dimensional subsets. The integral sum is then
    4054              :  * taken over all boundary subset manifold geometric objects, that are part of
    4055              :  * an element of the scheduled "inner" elements
    4056              :  *
    4057              :  * @param u                             a grid function
    4058              :  * @param cmp                   the component, whose gradient should be integrated
    4059              :  * @param BndSubset             a comma-separated string of symbolic boundary subset names
    4060              :  * @param InnerSubset   a comma-separated string of symbolic inner subset names
    4061              :  * @return      the integral
    4062              :  */
    4063              : template <typename TGridFunction>
    4064            0 : number IntegrateNormalGradientOnManifold(TGridFunction& u, const char* cmp,
    4065              :                                    const char* BndSubset, const char* InnerSubset = NULL)
    4066              : {
    4067              : //      get function id of name
    4068              :         const size_t fct = u.fct_id_by_name(cmp);
    4069              : 
    4070              : //      check that function exists
    4071            0 :         if(fct >= u.num_fct())
    4072            0 :                 UG_THROW("IntegrateNormalGradientOnManifold: Function space does not contain"
    4073              :                                 " a function with name " << cmp << ".");
    4074              : 
    4075              :         if(u.local_finite_element_id(fct) != LFEID(LFEID::LAGRANGE, TGridFunction::dim, 1))
    4076            0 :                 UG_THROW("IntegrateNormalGradientOnManifold:"
    4077              :                                  "Only implemented for Lagrange P1 functions.");
    4078              : 
    4079              : //      read subsets
    4080            0 :         SubsetGroup innerSSGrp(u.domain()->subset_handler());
    4081            0 :         if(InnerSubset != NULL)
    4082            0 :                 innerSSGrp.add(TokenizeString(InnerSubset));
    4083              :         else // add all if no subset specified
    4084            0 :                 innerSSGrp.add_all();
    4085              : 
    4086              : //      read bnd subsets
    4087            0 :         SubsetGroup bndSSGrp(u.domain()->subset_handler());
    4088            0 :         if(InnerSubset != NULL){
    4089            0 :                 bndSSGrp.add(TokenizeString(BndSubset));
    4090              :         }
    4091              :         else{
    4092            0 :                 UG_THROW("IntegrateNormalGradientOnManifold: No boundary subsets specified. Aborting.");
    4093              :         }
    4094              : 
    4095              : //      reset value
    4096              :         number value = 0;
    4097              : 
    4098              : //      loop subsets
    4099            0 :         for(size_t i = 0; i < innerSSGrp.size(); ++i)
    4100              :         {
    4101              :         //      get subset index
    4102              :                 const int si = innerSSGrp[i];
    4103              : 
    4104              :         //      skip if function is not defined in subset
    4105            0 :                 if(!u.is_def_in_subset(fct, si)) continue;
    4106              : 
    4107              : 
    4108            0 :                 if (innerSSGrp.dim(i) != TGridFunction::dim)
    4109            0 :                         UG_THROW("IntegrateNormalGradientOnManifold: Element dimension does not match world dimension!");
    4110              : 
    4111              :         //      create integration kernel
    4112              :                 static const int dim = TGridFunction::dim;
    4113              : 
    4114              :         //      integrate elements of subset
    4115              :                 typedef typename domain_traits<dim>::grid_base_object grid_base_object;
    4116              : 
    4117              :         //      get iterators for all elems on subset
    4118              :                 typedef typename TGridFunction::template dim_traits<dim>::const_iterator const_iterator;
    4119              :                 const_iterator iter = u.template begin<grid_base_object>();
    4120              :                 const_iterator iterEnd = u.template end<grid_base_object>();
    4121              : 
    4122              :         //      create a FV1 Geometry
    4123            0 :                 DimFV1Geometry<dim> geo;
    4124              : 
    4125              :         //      specify, which subsets are boundary
    4126            0 :                 for(size_t s = 0; s < bndSSGrp.size(); ++s)
    4127              :                 {
    4128              :                 //      get subset index
    4129              :                         const int bndSubset = bndSSGrp[s];
    4130              : 
    4131              :                 //      request this subset index as boundary subset. This will force the
    4132              :                 //      creation of boundary subsets when calling geo.update
    4133            0 :                         geo.add_boundary_subset(bndSubset);
    4134              :                 }
    4135              : 
    4136              :         //      vector of corner coordinates of element corners (to be filled for each elem)
    4137              :                 std::vector<MathVector<dim> > vCorner;
    4138              : 
    4139              :         //      loop elements of subset
    4140            0 :                 for( ; iter != iterEnd; ++iter)
    4141              :                 {
    4142              :                 //      get element
    4143              :                         grid_base_object* elem = *iter;
    4144              : 
    4145              :                 //      get all corner coordinates
    4146            0 :                         CollectCornerCoordinates(vCorner, *elem, u.domain()->position_accessor(), true);
    4147              : 
    4148              :                 //      compute bf and grads at bip for element
    4149              :                         try{
    4150            0 :                                 geo.update(elem, &vCorner[0], u.domain()->subset_handler().get());
    4151              :                         }
    4152            0 :                         UG_CATCH_THROW("IntegrateNormalGradientOnManifold: "
    4153              :                                                 "Cannot update Finite Volume Geometry.");
    4154              : 
    4155              :                 //      get fct multi-indeces of element
    4156              :                         std::vector<DoFIndex> ind;
    4157              :                         u.dof_indices(elem, fct, ind);
    4158              : 
    4159              :                 //      specify, which subsets are boundary
    4160            0 :                         for(size_t s = 0; s < bndSSGrp.size(); ++s)
    4161              :                         {
    4162              :                         //      get subset index
    4163              :                                 const int bndSubset = bndSSGrp[s];
    4164              : 
    4165              :                         //      get all bf of this subset
    4166              :                                 typedef typename DimFV1Geometry<dim>::BF BF;
    4167              :                                 const std::vector<BF>& vBF = geo.bf(bndSubset);
    4168              : 
    4169              :                         //      loop boundary faces
    4170            0 :                                 for(size_t b = 0; b < vBF.size(); ++b)
    4171              :                                 {
    4172              :                                 //      get bf
    4173              :                                         const BF& bf = vBF[b];
    4174              : 
    4175              :                                 //      get normal on bf
    4176              :                                         const MathVector<dim>& normal = bf.normal();
    4177              : 
    4178              :                                 //      check multi indices
    4179              :                                         UG_ASSERT(ind.size() == bf.num_sh(),
    4180              :                                                   "IntegrateNormalGradientOnManifold::values: Wrong number of"
    4181              :                                                           " multi indices, ind: "<<ind.size() << ", bf.num_sh: "
    4182              :                                                           << bf.num_sh());
    4183              : 
    4184              :                                 //      compute gradient of solution at bip
    4185              :                                         MathVector<dim> grad; VecSet(grad, 0.0);
    4186            0 :                                         for(size_t sh = 0; sh < bf.num_sh(); ++sh)
    4187              :                                         {
    4188            0 :                                                 const number fctVal = DoFRef(u, ind[sh]);
    4189              : 
    4190              :                                                 VecScaleAdd(grad, 1.0, grad, fctVal, bf.global_grad(sh));
    4191              :                                         }
    4192              : 
    4193              :                                 //      sum up contributions
    4194            0 :                                         value -= VecDot(grad, normal);
    4195              :                                 }
    4196              :                         }
    4197              :                 }
    4198              :         }
    4199              : 
    4200              : #ifdef UG_PARALLEL
    4201              :         // sum over processes
    4202              :         if(pcl::NumProcs() > 1)
    4203              :         {
    4204              :                 pcl::ProcessCommunicator com;
    4205              :                 number local = value;
    4206              :                 com.allreduce(&local, &value, 1, PCL_DT_DOUBLE, PCL_RO_SUM);
    4207              :         }
    4208              : #endif
    4209              : 
    4210              : //      return the result
    4211            0 :         return value;
    4212              : }
    4213              : 
    4214              : } // namespace ug
    4215              : 
    4216              : #endif /*__H__UG__LIB_DISC__FUNCTION_SPACES__INTEGRATE__*/
        

Generated by: LCOV version 2.0-1