LCOV - code coverage report
Current view: top level - ugbase/lib_algebra/operator/interface - constrained_linear_iterator.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 73 0
Test Date: 2026-06-01 23:54:59 Functions: 0.0 % 117 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2010-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Markus Breit
       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__LIB_ALGEBRA__OPERATOR__INTERFACE__CONSTRAINED_LINEAR_ITERATOR__
      34              : #define __H__LIB_ALGEBRA__OPERATOR__INTERFACE__CONSTRAINED_LINEAR_ITERATOR__
      35              : 
      36              : #include "common/util/smart_pointer.h"
      37              : #include "lib_algebra/operator/interface/linear_iterator.h"
      38              : #include "lib_disc/function_spaces/grid_function.h"
      39              : #include "lib_disc/spatial_disc/domain_disc_interface.h"
      40              : #include "preconditioner.h"
      41              : 
      42              : #include <type_traits>
      43              : 
      44              : namespace ug {
      45              : 
      46              : 
      47              : /**
      48              :  * This class is a template for constraint-respecting versions of
      49              :  * any linear iterator derived from ILinearIterator. This includes
      50              :  * linear solvers as well as preconditioners.
      51              :  * The derived ILinearIterator class must have a constructor
      52              :  * without arguments.
      53              :  * The handled constraints must implement the two methods:
      54              :  *     adjust_correction(),
      55              :  *     adjust_defect().
      56              :  *
      57              :  * @note This class may have lost its use:
      58              :  *       Constraints are now usually implemented in such a way that
      59              :  *       that both defect and correction is always zero in constrained
      60              :  *       DoFs.
      61              :  */
      62              : template <typename TDomain, typename TAlgebra, typename TLinIt, typename = void>
      63              : class ConstrainedLinearIterator : public TLinIt
      64              : {
      65              :         public:
      66              :                 typedef GridFunction<TDomain, TAlgebra> gf_type;
      67              :                 typedef typename TAlgebra::vector_type vector_type;
      68              :                 typedef TLinIt base_type;
      69              : 
      70              :                 using TLinIt::init;
      71              : 
      72              :         public:
      73              :                 ///     constructor
      74            0 :                 ConstrainedLinearIterator(SmartPtr<IDomainDiscretization<TAlgebra> > domDisc)
      75            0 :                 : base_type(), m_spDomDisc(domDisc), m_time(0.0)
      76            0 :                 {}
      77              : 
      78              :                 /// clone constructor
      79            0 :                 ConstrainedLinearIterator(const ConstrainedLinearIterator<TDomain, TAlgebra, TLinIt> &parent)
      80            0 :                 : base_type(parent), m_spDomDisc(parent.m_spDomDisc), m_time(parent.m_time)
      81            0 :                 {}
      82              : 
      83              :                 ///     clone
      84            0 :                 virtual SmartPtr<ILinearIterator<vector_type> > clone()
      85              :                 {
      86            0 :                         return make_sp(new ConstrainedLinearIterator<TDomain, TAlgebra, TLinIt>(*this));
      87              :                 }
      88              : 
      89              :                 ///     destructor
      90            0 :                 virtual ~ConstrainedLinearIterator(){}
      91              : 
      92              :         protected:
      93              :                 /// @copydoc ILinearIterator::name()
      94            0 :                 virtual const char* name() const
      95              :                 {
      96            0 :                         return base_type::name();
      97              :                 }
      98              : 
      99            0 :                 virtual bool init(SmartPtr<ILinearOperator<vector_type,vector_type> > J, const vector_type& u)
     100              :                 {
     101            0 :                         return base_type::init(J, u);
     102              :                 }
     103              : 
     104            0 :                 virtual bool init(SmartPtr<ILinearOperator<vector_type,vector_type> > L)
     105              :                 {
     106            0 :                         return base_type::init(L);
     107              :                 }
     108              : 
     109            0 :                 virtual bool apply(vector_type& c, const vector_type& d)
     110              :                 {
     111              :                         // perform normal step
     112            0 :                         if (!base_type::apply(c, d)) return false;
     113              : 
     114              :                         // apply constraints on correction
     115            0 :                         if (!m_spDomDisc.valid())
     116            0 :                                 UG_THROW("Domain discretization passed to ConstrainedLinearIterator is not valid.\n"
     117              :                                                  "Cannot apply any constraints.")
     118              : 
     119            0 :                         gf_type* gf = dynamic_cast<gf_type*>(&c);
     120            0 :                         if (gf && gf->dof_distribution().valid())
     121              :                         {
     122            0 :                                 size_t nConstr = m_spDomDisc->num_constraints();
     123              : 
     124              :                                 // first Dirichlet (hanging nodes might be constrained by Dirichlet nodes)
     125            0 :                                 for (size_t i = 0; i < nConstr; i++)
     126            0 :                                         if (m_spDomDisc->constraint(i)->type() & CT_DIRICHLET)
     127            0 :                                                 m_spDomDisc->constraint(i)->adjust_correction(c, gf->dof_distribution(), CT_DIRICHLET, m_time);
     128              : 
     129              :                                 // then other interpolation
     130            0 :                                 for (size_t i = 0; i < nConstr; i++)
     131            0 :                                         if (m_spDomDisc->constraint(i)->type() & CT_CONSTRAINTS)
     132            0 :                                                 m_spDomDisc->constraint(i)->adjust_correction(c, gf->dof_distribution(), CT_CONSTRAINTS, m_time);
     133              : 
     134              :                                 // then hanging nodes
     135            0 :                                 for (size_t i = 0; i < nConstr; i++)
     136            0 :                                         if (m_spDomDisc->constraint(i)->type() & CT_HANGING)
     137            0 :                                                 m_spDomDisc->constraint(i)->adjust_correction(c, gf->dof_distribution(), CT_HANGING, m_time);
     138              : 
     139              :                                 // and Dirichlet again (Dirichlet nodes might also be hanging)
     140            0 :                                 for (size_t i = 0; i < nConstr; i++)
     141            0 :                                         if (m_spDomDisc->constraint(i)->type() & CT_DIRICHLET)
     142            0 :                                                 m_spDomDisc->constraint(i)->adjust_correction(c, gf->dof_distribution(), CT_DIRICHLET, m_time);
     143              :                         }
     144            0 :                         else UG_THROW("Vector is not a grid function. This is not supported.")
     145              : 
     146              :                         return true;
     147              :                 }
     148              : 
     149            0 :                 virtual bool apply_update_defect(vector_type& c, vector_type& d)
     150              :                 {
     151              :                         apply_update_defect_impl<TLinIt> impl(*this);
     152            0 :                         return impl(c, d);
     153              :                 }
     154              : 
     155              :         private:
     156              :                 template <typename S, typename = void>//, typename otherDummy = void>
     157              :                 struct apply_update_defect_impl
     158              :                 {
     159              :                         ConstrainedLinearIterator& cli;
     160              : 
     161            0 :                         explicit apply_update_defect_impl(ConstrainedLinearIterator& _cli)
     162            0 :                         : cli(_cli) {}
     163              : 
     164            0 :                         bool operator()(vector_type& c, vector_type& d)
     165              :                         {
     166              :                                 // FIXME: This implementation is not correct.
     167              :                                 // As the defect is calculated from possibly erroneous corrections, there is no telling
     168              :                                 // how to adjust the defect. Except for setting it to zero everywhere, which, by the way,
     169              :                                 // is NOT what adjust_defect does, in general. We would need something like
     170              :                                 // adjust_defect_linearSolver() here to distinguish between the non-linear defect and
     171              :                                 // the residual in the linear solver.
     172              :                                 // We CANNOT use our own apply() here and then update the defect ourselves as the
     173              :                                 // ILinearIterator does not have an update method nor any way of applying the underlying
     174              :                                 // linear operator.
     175              : 
     176              :                                 // perform normal step
     177            0 :                                 if (!cli.base_type::apply_update_defect(c, d)) return false;
     178              : 
     179              :                                 // apply constraints on correction and defect
     180            0 :                                 if (!cli.m_spDomDisc.valid())
     181            0 :                                         UG_THROW("Domain discretization passed to ConstrainedLinearIterator is not valid.\n"
     182              :                                                          "Cannot apply any constraints.")
     183              : 
     184            0 :                                 gf_type* gf = dynamic_cast<gf_type*>(&c);
     185            0 :                                 if (gf && gf->dof_distribution().valid())
     186              :                                 {
     187            0 :                                         size_t nConstr = cli.m_spDomDisc->num_constraints();
     188              : 
     189              :                                 // corrections
     190              :                                         // first Dirichlet (hanging nodes might be constrained by Dirichlet nodes)
     191            0 :                                         for (size_t i = 0; i < nConstr; i++)
     192            0 :                                                 if (cli.m_spDomDisc->constraint(i)->type() & CT_DIRICHLET)
     193            0 :                                                         cli.m_spDomDisc->constraint(i)->adjust_correction(c, gf->dof_distribution(), CT_DIRICHLET, cli.m_time);
     194              : 
     195              :                                         // then other interpolation
     196            0 :                                         for (size_t i = 0; i < nConstr; i++)
     197            0 :                                                 if (cli.m_spDomDisc->constraint(i)->type() & CT_CONSTRAINTS)
     198            0 :                                                         cli.m_spDomDisc->constraint(i)->adjust_correction(c, gf->dof_distribution(), CT_CONSTRAINTS, cli.m_time);
     199              : 
     200              :                                         // then hanging nodes
     201            0 :                                         for (size_t i = 0; i < nConstr; i++)
     202            0 :                                                 if (cli.m_spDomDisc->constraint(i)->type() & CT_HANGING)
     203            0 :                                                         cli.m_spDomDisc->constraint(i)->adjust_correction(c, gf->dof_distribution(), CT_HANGING, cli.m_time);
     204              : 
     205              :                                         // and Dirichlet again (Dirichlet nodes might also be hanging)
     206            0 :                                         for (size_t i = 0; i < nConstr; i++)
     207            0 :                                                 if (cli.m_spDomDisc->constraint(i)->type() & CT_DIRICHLET)
     208            0 :                                                         cli.m_spDomDisc->constraint(i)->adjust_correction(c, gf->dof_distribution(), CT_DIRICHLET, cli.m_time);
     209              : 
     210              :                                 // residuals
     211              :                                         // hanging nodes first
     212            0 :                                         for (size_t i = 0; i < nConstr; i++)
     213            0 :                                                 if (cli.m_spDomDisc->constraint(i)->type() & CT_HANGING)
     214            0 :                                                         cli.m_spDomDisc->constraint(i)->adjust_linear_residual(d, c, gf->dof_distribution(), CT_HANGING, cli.m_time);
     215              : 
     216              :                                         // then other constraints
     217            0 :                                         for (size_t i = 0; i < nConstr; i++)
     218            0 :                                                 if (cli.m_spDomDisc->constraint(i)->type() & CT_CONSTRAINTS)
     219            0 :                                                         cli.m_spDomDisc->constraint(i)->adjust_linear_residual(d, c, gf->dof_distribution(), CT_CONSTRAINTS, cli.m_time);
     220              : 
     221              :                                         // and Dirichlet last
     222            0 :                                         for (size_t i = 0; i < nConstr; i++)
     223            0 :                                                 if (cli.m_spDomDisc->constraint(i)->type() & CT_DIRICHLET)
     224            0 :                                                         cli.m_spDomDisc->constraint(i)->adjust_linear_residual(d, c, gf->dof_distribution(), CT_DIRICHLET, cli.m_time);
     225              : 
     226              :                                 }
     227            0 :                                 else UG_THROW("Vector is not a grid function. This is not supported.")
     228              : 
     229              :                                 return true;
     230              :                         }
     231              :                 };
     232              : 
     233              : 
     234              :                 // special implementation for IPreconditioner
     235              :                 template <typename S>
     236              :                 struct apply_update_defect_impl<S, 
     237              :                          typename std::enable_if<std::is_base_of<IPreconditioner<TAlgebra>, S>::value>::type>
     238              :                 {
     239              :                         ConstrainedLinearIterator& cli;
     240              : 
     241              :                         explicit apply_update_defect_impl(ConstrainedLinearIterator& _cli)
     242              :                         : cli(_cli) {}
     243              : 
     244              :                         bool operator()(vector_type& c, vector_type& d)
     245              :                         {
     246              :                                 // apply precond and constraints
     247              :                                 if (!cli.apply(c, d)) return false;
     248              : 
     249              :                                 // calculate new defect from preconditioner defect operator
     250              :                                 cli.m_spDefectOperator->apply_sub(d, c);
     251              : 
     252              :                                 return true;
     253              :                         }
     254              :                 };
     255              : 
     256              :                 friend struct apply_update_defect_impl<TLinIt>;
     257              : 
     258              : 
     259              :         public:
     260              :                 /// @copydoc ILinearIterator::supports_parallel()
     261            0 :                 virtual bool supports_parallel() const
     262              :                 {
     263            0 :                         return base_type::supports_parallel();
     264              :                 }
     265              : 
     266              :                 /// setter for time
     267            0 :                 void set_time(number time)
     268              :                 {
     269            0 :                         m_time = time;
     270            0 :                 };
     271              : 
     272              :         protected:
     273              :                 SmartPtr<ILinearIterator<vector_type> > m_spLinIt;
     274              :                 SmartPtr<IDomainDiscretization<TAlgebra> > m_spDomDisc;
     275              :                 number m_time;
     276              : };
     277              : 
     278              : 
     279              : 
     280              : 
     281              : } // end namespace ug
     282              : 
     283              : 
     284              : #endif // __H__LIB_ALGEBRA__OPERATOR__INTERFACE__CONSTRAINED_LINEAR_ITERATOR__
        

Generated by: LCOV version 2.0-1