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

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2012-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 §7):
      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__OPERATOR__LINEAR_OPERATOR__STD_INJECTION_IMPL__
      34              : #define __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__STD_INJECTION_IMPL__
      35              : 
      36              : #include "std_injection.h"
      37              : 
      38              : namespace ug{
      39              : 
      40              : /**
      41              :  * This functions assembles the interpolation matrix between to
      42              :  * grid levels using only the RegularVertex degrees of freedom.
      43              :  *
      44              :  * \param[out]  mat                     Assembled interpolation matrix that interpolates u -> v
      45              :  * \param[in]   approxSpace             Approximation Space
      46              :  * \param[in]   coarseLevel             Coarse Level index
      47              :  * \param[in]   fineLevel               Fine Level index
      48              :  */
      49              : template <typename TAlgebra>
      50            0 : void AssembleInjectionForP1Lagrange(typename TAlgebra::matrix_type& mat,
      51              :                                     const DoFDistribution& coarseDD,
      52              :                                     const DoFDistribution& fineDD)
      53              : {
      54              :         PROFILE_FUNC_GROUP("gmg");
      55              : //  Allow only lagrange P1 functions
      56            0 :         for(size_t fct = 0; fct < fineDD.num_fct(); ++fct)
      57            0 :                 if(fineDD.local_finite_element_id(fct).type() != LFEID::LAGRANGE ||
      58              :                         fineDD.local_finite_element_id(fct).order() != 1)
      59            0 :                         UG_THROW("AssembleInjectionForP1Lagrange: "
      60              :                                         "Interpolation only implemented for Lagrange P1 functions.");
      61              : 
      62              : //      get MultiGrid
      63            0 :         const MultiGrid& grid = *coarseDD.multi_grid();
      64              : 
      65              : //      get number of dofs on different levels
      66              :         const size_t numFineDoFs = fineDD.num_indices();
      67              :         const size_t numCoarseDoFs = coarseDD.num_indices();
      68              : 
      69              : //      resize matrix
      70            0 :         mat.resize_and_clear(numCoarseDoFs, numFineDoFs);
      71              : 
      72              :         std::vector<size_t> coarseInd, fineInd;
      73              : 
      74              : //      RegularVertex iterators
      75              :         typedef DoFDistribution::traits<RegularVertex>::const_iterator const_iterator;
      76              :         const_iterator iter, iterBegin, iterEnd;
      77              : 
      78            0 :         iterBegin = fineDD.template begin<RegularVertex>();
      79            0 :         iterEnd = fineDD.template end<RegularVertex>();
      80              : 
      81              : //      loop nodes of fine subset
      82            0 :         for(iter = iterBegin; iter != iterEnd; ++iter)
      83              :         {
      84              :         //      get father
      85              :                 GridObject* geomObj = grid.get_parent(*iter);
      86            0 :                 Vertex* vert = dynamic_cast<Vertex*>(geomObj);
      87              : 
      88              :         //      Check if father is RegularVertex
      89            0 :                 if(vert != NULL)
      90              :                 {
      91              :                         // get global indices
      92            0 :                         coarseDD.inner_algebra_indices(vert, coarseInd);
      93              :                 }
      94            0 :                 else continue;
      95              : 
      96              :         //      get global indices
      97            0 :                 fineDD.inner_algebra_indices(*iter, fineInd);
      98              : 
      99            0 :                 for(size_t i = 0; i < coarseInd.size(); ++i)
     100            0 :                         mat(coarseInd[i], fineInd[i]) = 1.0;
     101              :         }
     102            0 : }
     103              : 
     104              : template <int dim, typename TAlgebra>
     105            0 : void AssembleInjectionByAverageOfChildren(typename TAlgebra::matrix_type& mat,
     106              :                                           const DoFDistribution& coarseDD,
     107              :                                           const DoFDistribution& fineDD)
     108              : {
     109              :         PROFILE_FUNC_GROUP("gmg");
     110              : //      get MultiGrid
     111            0 :         const MultiGrid& grid = *coarseDD.multi_grid();
     112              : 
     113              :         std::vector<size_t> coarseInd, fineInd;
     114              : 
     115              : //      RegularVertex iterators
     116              :         typedef typename DoFDistribution::dim_traits<dim>::const_iterator const_iterator;
     117              :         typedef typename DoFDistribution::dim_traits<dim>::grid_base_object Element;
     118              :         const_iterator iter, iterBegin, iterEnd;
     119              : 
     120            0 :         iterBegin = coarseDD.template begin<Element>();
     121            0 :         iterEnd = coarseDD.template end<Element>();
     122              : 
     123              : //      loop elements of coarse subset
     124            0 :         for(iter = iterBegin; iter != iterEnd; ++iter)
     125              :         {
     126              :         //      get element
     127              :                 Element* coarseElem = *iter;
     128              : 
     129              :         //  get children
     130              :                 const size_t numChild = grid.num_children<Element, Element>(coarseElem);
     131            0 :                 if(numChild == 0) continue;
     132              : 
     133              :         // get global indices
     134            0 :                 coarseDD.inner_algebra_indices(coarseElem, coarseInd);
     135              : 
     136            0 :                 for(size_t c = 0; c < numChild; ++c)
     137              :                 {
     138              :                         Element* child = grid.get_child<Element, Element>(coarseElem,  c);
     139              : 
     140            0 :                         fineDD.inner_algebra_indices(child, fineInd);
     141              : 
     142            0 :                         for(size_t i = 0; i < coarseInd.size(); ++i)
     143            0 :                                 mat(coarseInd[i], fineInd[i]) = 1.0/(numChild);
     144              :                 }
     145              :         }
     146            0 : }
     147              : 
     148              : template <typename TAlgebra>
     149            0 : void AssembleInjectionByAverageOfChildren(typename TAlgebra::matrix_type& mat,
     150              :                                           const DoFDistribution& coarseDD,
     151              :                                           const DoFDistribution& fineDD)
     152              : {
     153              : //      get number of dofs on different levels
     154              :         const size_t numFineDoFs = fineDD.num_indices();
     155              :         const size_t numCoarseDoFs = coarseDD.num_indices();
     156              : 
     157              : //      resize matrix
     158            0 :         mat.resize_and_clear(numCoarseDoFs, numFineDoFs);
     159              : 
     160            0 :         if(coarseDD.max_dofs(VERTEX)) AssembleInjectionByAverageOfChildren<0, TAlgebra>(mat, coarseDD, fineDD);
     161            0 :         if(coarseDD.max_dofs(EDGE)) AssembleInjectionByAverageOfChildren<1, TAlgebra>(mat, coarseDD, fineDD);
     162            0 :         if(coarseDD.max_dofs(FACE)) AssembleInjectionByAverageOfChildren<2, TAlgebra>(mat, coarseDD, fineDD);
     163            0 :         if(coarseDD.max_dofs(VOLUME)) AssembleInjectionByAverageOfChildren<3, TAlgebra>(mat, coarseDD, fineDD);
     164            0 : }
     165              : 
     166              : template <typename TDomain, typename TAlgebra>
     167              : template <typename TElem>
     168            0 : void StdInjection<TDomain, TAlgebra>::
     169              : set_identity_on_pure_surface(matrix_type& mat,
     170              :                              const DoFDistribution& coarseDD, const DoFDistribution& fineDD)
     171              : {
     172              :         PROFILE_FUNC_GROUP("gmg");
     173              : 
     174              :         std::vector<size_t> vCoarseIndex, vFineIndex;
     175            0 :         const MultiGrid& mg = *coarseDD.multi_grid();
     176              : 
     177              : //  iterators
     178              :         typedef typename DoFDistribution::traits<TElem>::const_iterator const_iterator;
     179              :         const_iterator iter, iterBegin, iterEnd;
     180              : 
     181              : //  loop subsets on fine level
     182            0 :         for(int si = 0; si < coarseDD.num_subsets(); ++si)
     183              :         {
     184            0 :                 iterBegin = coarseDD.template begin<TElem>(si);
     185            0 :                 iterEnd = coarseDD.template end<TElem>(si);
     186              : 
     187              :         //  loop vertices for fine level subset
     188            0 :                 for(iter = iterBegin; iter != iterEnd; ++iter)
     189              :                 {
     190              :                 //      get element
     191              :                         TElem* coarseElem = *iter;
     192              : 
     193              :                         const size_t numChild = mg.num_children<TElem, TElem>(coarseElem);
     194            0 :                         if(numChild != 0) continue;
     195              : 
     196              :                 //      get indices
     197            0 :                         coarseDD.inner_algebra_indices(coarseElem, vCoarseIndex);
     198            0 :                         fineDD.inner_algebra_indices(coarseElem, vFineIndex);
     199              :                         UG_ASSERT(vCoarseIndex.size() == vFineIndex.size(), "Size mismatch");
     200              : 
     201              :                 //      set identity
     202            0 :                         for(size_t i = 0; i < vCoarseIndex.size(); ++i)
     203            0 :                                 mat(vCoarseIndex[i], vFineIndex[i]) = 1.0;
     204              :                 }
     205              :         }
     206            0 : }
     207              : 
     208              : template <typename TDomain, typename TAlgebra>
     209            0 : void StdInjection<TDomain, TAlgebra>::
     210              : set_identity_on_pure_surface(matrix_type& mat,
     211              :                              const DoFDistribution& coarseDD, const DoFDistribution& fineDD)
     212              : {
     213            0 :         if(coarseDD.max_dofs(VERTEX)) set_identity_on_pure_surface<Vertex>(mat, coarseDD, fineDD);
     214            0 :         if(coarseDD.max_dofs(EDGE)) set_identity_on_pure_surface<Edge>(mat, coarseDD, fineDD);
     215            0 :         if(coarseDD.max_dofs(FACE)) set_identity_on_pure_surface<Face>(mat, coarseDD, fineDD);
     216            0 :         if(coarseDD.max_dofs(VOLUME)) set_identity_on_pure_surface<Volume>(mat, coarseDD, fineDD);
     217            0 : }
     218              : 
     219              : ////////////////////////////////////////////////////////////////////////////////
     220              : ////////////////////////////////////////////////////////////////////////////////
     221              : //      StdInjection
     222              : ////////////////////////////////////////////////////////////////////////////////
     223              : ////////////////////////////////////////////////////////////////////////////////
     224              : 
     225              : 
     226              : template <typename TDomain, typename TAlgebra>
     227              : void StdInjection<TDomain, TAlgebra>::
     228              : set_approximation_space(SmartPtr<ApproximationSpace<TDomain> > approxSpace)
     229              : {
     230            0 :         m_spApproxSpace = approxSpace;
     231              : }
     232              : 
     233              : template <typename TDomain, typename TAlgebra>
     234            0 : void StdInjection<TDomain, TAlgebra>::
     235              : set_levels(GridLevel coarseLevel, GridLevel fineLevel)
     236              : {
     237            0 :         m_fineLevel = fineLevel;
     238            0 :         m_coarseLevel = coarseLevel;
     239              : 
     240            0 :         if(m_fineLevel.level() - m_coarseLevel.level() != 1)
     241            0 :                 UG_THROW("StdInjection::set_levels:"
     242              :                                 " Can only project between successive level.");
     243            0 : }
     244              : 
     245              : template <typename TDomain, typename TAlgebra>
     246            0 : void StdInjection<TDomain, TAlgebra>::init()
     247              : {
     248              :         PROFILE_FUNC_GROUP("gmg");
     249            0 :         if(!m_spApproxSpace.valid())
     250            0 :                 UG_THROW("StdInjection::init: "
     251              :                                 "Approximation Space not set. Cannot init Projection.");
     252              : 
     253              : //      check only lagrange P1 functions
     254              :         bool P1LagrangeOnly = true;
     255            0 :         for(size_t fct = 0; fct < m_spApproxSpace->num_fct(); ++fct)
     256            0 :                 if(m_spApproxSpace->local_finite_element_id(fct).type() != LFEID::LAGRANGE ||
     257              :                                 m_spApproxSpace->local_finite_element_id(fct).order() != 1)
     258              :                         P1LagrangeOnly = false;
     259              : 
     260              :         try{
     261            0 :                 if(P1LagrangeOnly)
     262              :                 {
     263              :                         AssembleInjectionForP1Lagrange<TAlgebra>
     264            0 :                         (m_matrix,
     265            0 :                          *m_spApproxSpace->dof_distribution(m_coarseLevel),
     266            0 :                          *m_spApproxSpace->dof_distribution(m_fineLevel));
     267              :                 }
     268              :                 else
     269              :                 {
     270              :                         AssembleInjectionByAverageOfChildren<TAlgebra>
     271            0 :                         (m_matrix,
     272            0 :                          *m_spApproxSpace->dof_distribution(m_coarseLevel),
     273            0 :                          *m_spApproxSpace->dof_distribution(m_fineLevel));
     274              :                 }
     275              : 
     276            0 :         } UG_CATCH_THROW("StdInjection::init():"
     277              :                                                 " Cannot assemble interpolation matrix.");
     278              : 
     279            0 :         if(m_coarseLevel.is_surface()){
     280            0 :                 set_identity_on_pure_surface(m_matrix, *m_spApproxSpace->dof_distribution(m_coarseLevel), *m_spApproxSpace->dof_distribution(m_fineLevel));
     281              :         }
     282              : 
     283              :         #ifdef UG_PARALLEL
     284              :                 m_matrix.set_storage_type(PST_CONSISTENT);
     285              :         #endif
     286              : 
     287            0 :         m_bInit = true;
     288            0 : }
     289              : 
     290              : template <typename TDomain, typename TAlgebra>
     291            0 : void StdInjection<TDomain, TAlgebra>::
     292              : prolongate(vector_type& uFine, const vector_type& uCoarse)
     293              : {
     294              :         PROFILE_FUNC_GROUP("gmg");
     295              : //      Check, that operator is initiallized
     296            0 :         if(!m_bInit)
     297            0 :                 UG_THROW("StdInjection::apply:"
     298              :                                 " Operator not initialized.");
     299              : 
     300              : //      Some Assertions
     301              :         UG_ASSERT(uFine.size() >= m_matrix.num_rows(),
     302              :                           "Vector [size= " << uFine.size() << "] and Rows [size= "
     303              :                           << m_matrix.num_rows() <<"] sizes have to match!");
     304              :         UG_ASSERT(uCoarse.size() >= m_matrix.num_cols(),     "Vector [size= "
     305              :                           << uCoarse.size() << "] and Cols [size= " <<
     306              :                           m_matrix.num_cols() <<"] sizes have to match!");
     307              : 
     308              : //      Apply matrix
     309            0 :         if(!m_matrix.apply_transposed(uFine, uCoarse))
     310              :                 UG_THROW("StdInjection::apply: Cannot apply matrix.");
     311            0 : }
     312              : 
     313              : template <typename TDomain, typename TAlgebra>
     314            0 : void StdInjection<TDomain, TAlgebra>::
     315              : do_restrict(vector_type& uCoarse, const vector_type& uFine)
     316              : {
     317              :         PROFILE_FUNC_GROUP("gmg");
     318              : //      Check, that operator is initialized
     319            0 :         if(!m_bInit)
     320            0 :                 UG_THROW("StdInjection::apply_transposed:"
     321              :                                 "Operator not initialized.");
     322              : 
     323              : //      Some Assertions
     324              :         UG_ASSERT(uFine.size() >= m_matrix.num_cols(),
     325              :                           "Vector [size= " << uFine.size() << "] and Cols [size= "
     326              :                           << m_matrix.num_cols() <<"] sizes have to match!");
     327              :         UG_ASSERT(uCoarse.size() >= m_matrix.num_rows(),     "Vector [size= "
     328              :                           << uCoarse.size() << "] and Rows [size= " <<
     329              :                           m_matrix.num_rows() <<"] sizes have to match!");
     330              : 
     331              : //      Apply matrix
     332              :         try{
     333            0 :                 m_matrix.apply_ignore_zero_rows(uCoarse, 1.0, uFine);
     334              :         }
     335              :         UG_CATCH_THROW("StdInjection::apply_transposed:"
     336              :                                                 " Cannot apply transposed matrix.");
     337            0 : }
     338              : 
     339              : 
     340              : template <typename TDomain, typename TAlgebra>
     341              : SmartPtr<ITransferOperator<TDomain, TAlgebra> >
     342            0 : StdInjection<TDomain, TAlgebra>::clone()
     343              : {
     344            0 :         SmartPtr<StdInjection> op(new StdInjection);
     345            0 :         op->set_approximation_space(m_spApproxSpace);
     346            0 :         return op;
     347              : }
     348              : 
     349              : } // end namespace ug
     350              : 
     351              : #endif /* __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__STD_INJECTION_IMPL__ */
        

Generated by: LCOV version 2.0-1