20#include "dune/istl/preconditioners.hh"
21#include "dune/istl/solvers.hh"
23#include <boost/fusion/sequence.hpp>
32 template <
class X,
class Y>
54 template<
class X,
class Y>
55 class UzawaSolver :
public Dune::InverseOperator<LinearProductSpace<typename X::field_type,
56 boost::fusion::vector<X,Y>>,
57 LinearProductSpace<typename X::field_type,
58 boost::fusion::vector<X,Y>>>
89 UzawaSolver (Dune::LinearOperator<X,X>& A_, Dune::InverseOperator<X,X>& invA_,
90 Dune::LinearOperator<X,Y>& B_, Dune::LinearOperator<Y,X>& Bt_,
91 Dune::Preconditioner<Y,Y>& precS_,
92 double reduction_,
int maxit_,
int verbose_)
98 , reduction(reduction_)
115 using namespace Dune;
122 InverseOperatorResult resA;
124 std::cout <<
"=== UzawaSolver\n";
127 X& u(component<0>(x));
128 Y& p(component<1>(x));
129 X const& f(component<0>(b));
130 Y const& g(component<1>(b));
144 invA.apply(xtmp2,Btp,resA);
146 double energy = spX.dot(xtmp,xtmp2);
152 A.applyscaleadd(-1,u,xtmp);
153 Bt.applyscaleadd(-1,p,xtmp);
156 invA.apply(xtmp2,xtmp,resA);
160 B.applyscaleadd(1,u,r);
173 double sigma = spY.dot(r,rBar);
174 double sigma0 = sigma;
179 for ( ; i<maxit && sigma>reduction*reduction*energy; i++)
184 invA.apply(z,xtmp,resA);
188 double alpha = sigma / spY.dot(q,Sq);
191 auto fu = std::async([&]()
197 energy += alpha*sigma;
206 double sigmaNew = spY.dot(r,rBar);
207 double beta = sigmaNew / sigma;
209 q *= beta; q += rBar;
214 std::printf(
"%5s %14s %14s\n",
"Iter",
"Preco. Res.",
"Rate");
215 std::printf(
"%5d %14.4e %14.4e\n",i,std::sqrt(sigma),std::sqrt(beta));
222 res.reduction = std::sqrt(sigma/sigma0);
223 res.converged = res.reduction<=reduction;
224 res.conv_rate = std::pow(res.reduction,1.0/i);
225 res.elapsed = watch.elapsed();
228 printf(
"=== rate=%g, time=%g, time/it=%g, iter=%d\n",res.conv_rate,res.elapsed,res.elapsed/i,i);
231 virtual void apply (
Domain& x,
Range& b,
double reduction_, Dune::InverseOperatorResult& res)
233 reduction = reduction_;
234 this->
apply(x,b,res);
239 Dune::InverseOperatorResult tmpResult;
240 apply(x,b,tmpResult);
248 virtual Dune::SolverCategory::Category
category()
const override
250 return Dune::SolverCategory::sequential;
254 Dune::SeqScalarProduct<X> spX;
255 Dune::SeqScalarProduct<Y> spY;
257 Dune::LinearOperator<X,X>& A;
258 Dune::InverseOperator<X,X>& invA;
260 Dune::LinearOperator<X,Y>& B;
261 Dune::LinearOperator<Y,X>& Bt;
262 Dune::Preconditioner<Y,Y>& precS;
279 template <
class MatA,
class SolA,
class MatB,
class MatBt,
class PrecS>
280 auto uzawa(MatA& A, SolA& invA, MatB& B, MatBt& Bt, PrecS& precS,
281 double reduction=1e-3,
int maxit=1000,
int verbose=0)
283 using X =
typename MatA::domain_type;
284 using Y =
typename MatB::range_type;
298 template <
class Scalar,
class Sequence>
305 using Seq = vector<X,Y>;
307 Y(component<1>(z))));
318 template <
class Scalar,
class Sequence>
323 using X = std::remove_const_t<typename std::remove_const_t<typename Z::Component<0>>::Component<0>>;
324 using Y = std::remove_const_t<typename std::remove_const_t<typename Z::Component<1>>::Component<0>>;
325 using Seq = boost::fusion::vector<X,Y>;
327 component<0>(component<1>(z))));
A scope guard object that automatically closes a timing section on destruction.
An inexact Uzawa type solver for solving symmetric saddle point systems.
UzawaSolver(Dune::LinearOperator< X, X > &A_, Dune::InverseOperator< X, X > &invA_, Dune::LinearOperator< X, Y > &B_, Dune::LinearOperator< Y, X > &Bt_, Dune::Preconditioner< Y, Y > &precS_, double reduction_, int maxit_, int verbose_)
Constructor.
void apply(Domain &x, Range &b)
virtual Dune::SolverCategory::Category category() const override
returns the category of the operator
LinearProductSpace< typename X::field_type, boost::fusion::vector< X, Y > > domain_type
The domain type of the Uzawa iteration.
virtual void apply(Domain &x, Range &b, double reduction_, Dune::InverseOperatorResult &res)
virtual void apply(Domain &x, Range &b, Dune::InverseOperatorResult &res) override
Solves the saddle point system .
void applyPreconditioner(Dune::Preconditioner< X, Y > &p, X &x, Y &y)
Convenience function for simple application of preconditioners. Calls pre(), apply(),...
auto unnestUzawa(LinearProductSpace< Scalar, Sequence > const &z)
Convenience function for unpacking Uzawa domain/range results.
auto uzawa(MatA &A, SolA &invA, MatB &B, MatBt &Bt, PrecS &precS, double reduction=1e-3, int maxit=1000, int verbose=0)
Convenience function for constructing an UzawaSolver. \tparem MatA derived from Dune::LinearOperator<...
auto nestUzawa(LinearProductSpace< Scalar, Sequence > const &z)
Convenience function for creating Uzawa domain/range arguments.