KASKADE 7 development version
comp_step.hh
Go to the documentation of this file.
1#ifndef COMP_STEP
2#define COMP_STEP
3
4#include <memory> // std::unique_ptr
5#include <vector>
6
7#include <boost/timer/timer.hpp>
8#include <boost/fusion/include/at_c.hpp>
9
13#include "linalg/cg.hh"
14#include "linalg/direct.hh"
15#include "linalg/triplet.hh"
16#include "linalg/icc0precond.hh"
19//#include "linalg/preconditionerFactory.hh"
21#include "linalg/chebyshev.hh"
22#include "fem/systemTraits.hh"
23#include "mg/multiGridSolver.hh"
26
27namespace Kaskade
28{
29 template <class,class,class,class> class PreconditionerFactory;
30
31 template <class Functional, class Assembler> class NormalStepPreconditioner;
32 template <class Functional, class Assembler, int components=1> class TangentSpacePreconditioner;
33 template <class Functional, class Assembler, int components=1> class TangentSpacePreconditioner2;
34template <class Functional, class Assembler, int components=1> class NormalStepPreconditioner2;
35template <class Functional, class Assembler, int components=1> class NormalStepPreconditioner3;
36 template <class Functional, class Assembler, int components=1,bool exactConstraint=false> class InexactTangentSpacePreconditioner;
37
38
39 template <class X, class Xstar, int yIdx, int uIdx, int pIdx>
40 class Scaledl2ScalarProduct : public DualPairing<X,Xstar>
41 {
42 typedef typename DualPairing<X,Xstar>::field_type Scalar;
43 public:
44 Scaledl2ScalarProduct(Scalar sy_, Scalar su_, Scalar sp_) : sy(sy_), su(su_), sp(sp_) {}
45
47
48 virtual Scalar operator()(X const& x, Xstar const& y) const { return sy * prod<yIdx>(x,y) + su * prod<uIdx>(x,y) + sp * prod<pIdx>(x,y); }
49
50 private:
51 template <int i> Scalar prod(X const& x, Xstar const& y) const { return boost::fusion::at_c<i>(x.data) * boost::fusion::at_c<i>(y.data); }
52
53 Scalar sy = 1.0, su = 1.0, sp = 1.0;
54 };
55
56
57// template <class Functional, class NormalStepAssembler, class TangentialStepAssembler>
58// class StollReesPreconditioner : public Dune::Preconditioner<typename OptimalControlTraits<Functional,NormalStepAssembler>::Domain, typename OptimalControlTraits<Functional,NormalStepAssembler>::Range>
59// {
60// typedef OptimalControlTraits<Functional,NormalStepAssembler> Traits;
61// typedef OptimalControlTraits<Functional,TangentialStepAssembler> TTraits;
62// typedef typename Functional::Scalar Scalar;
63// typedef MatrixAsTriplet<Scalar> Matrix;
64// typedef SchurComplement_v1<NormalStepAssembler, TangentialStepAssembler,
65// IstlInterfaceDetail::BlockInfo<Traits::adjointId,Traits::adjointId+1,Traits::stateId,Traits::stateId+1>,
66// IstlInterfaceDetail::BlockInfo<Traits::stateId,Traits::stateId+1,Traits::stateId,Traits::stateId+1>
67// > SchurComplement;
68// public:
69// typedef typename Traits::Domain Domain;
70// typedef typename Traits::Range Range;
71// typedef NormalStepAssembler Assembler;
72
73// StollReesPreconditioner()
74// : Myy(nullptr), Muu(nullptr), A(nullptr), B(nullptr), S(nullptr), chebyy(nullptr), chebuu(nullptr)
75// {}
76
77// StollReesPreconditioner(NormalStepAssembler const& normalStepAssembler, TangentialStepAssembler const& tangentialStepAssembler, size_t maxSteps = 50) : StollReesPreconditioner()
78// {
79// update(normalStepAssembler,tangentialStepAssembler,maxSteps);
80// }
81
82// void update(NormalStepAssembler const& normalStepAssembler, TangentialStepAssembler const& tangentialStepAssembler, size_t maxSteps = 50)
83// {
84// Myy.reset( new typename TTraits::NormYOperator(tangentialStepAssembler) );
85// Muu.reset( new typename TTraits::NormUOperator(tangentialStepAssembler) );
86// A.reset( new typename Traits::StateOperator(normalStepAssembler) );
87// B.reset( new typename Traits::ControlOperator(normalStepAssembler) );
88// S.reset( new SchurComplement(normalStepAssembler,tangentialStepAssembler) );
89// chebyy.reset( new ChebyshevPreconditioner<typename TTraits::NormYOperator>(*Myy,maxSteps) );
90// chebuu.reset( new ChebyshevPreconditioner<typename TTraits::NormUOperator>(*Muu,maxSteps) );
91// chebyy->initForMassMatrix_TetrahedralQ1Elements();
92// chebuu->initForMassMatrix_TetrahedralQ1Elements();
93// }
94
95// virtual void pre(Domain&, Range&){}
96// virtual void post(Domain&){}
97
98// virtual void apply(Domain& x, Range const& y)
99// {
100// using namespace boost::fusion;
101
102// typename Traits::VectorY rhsY(at_c<Traits::yIdx>(y.data)), solY(rhsY); solY *= 0;
103// directInverseOperator(*Myy,DirectType::UMFPACK3264,MatrixProperties::GENERAL).apply(rhsY,solY); solY *= 0.5; // scaling for positive definiteness of non-standard inner product
104// rhsY *= -1;
105// Myy->applyscaleadd(1.0,solY,rhsY);
106// at_c<Traits::yIdx>(x.data) = at_c<0>(rhsY.data);
107
108// typename Traits::VectorU rhsU(at_c<Traits::uIdx>(y.data)), solU(rhsU); solU *= 0;
109// chebuu->apply(solU,rhsU); solU *= 0.5;
110// rhsU *= -1;
111// Muu->applyscaleadd(1.0,solU,rhsU);
112// at_c<Traits::uIdx>(x.data) = at_c<0>(rhsU.data);
113
114// typename Traits::VectorP rhsP(at_c<Traits::pIdx>(x.data)), solP(rhsP); solP *= 0;
115// rhsP *= -1;
116// A->applyscaleadd(1.0,solY,rhsP);
117// B->applyscaleadd(1.0,solU,rhsP);
118// at_c<Traits::pIdx>(x.data) = at_c<0>(rhsP.data);
119// }
120
121
122// virtual void apply2(Domain& x, Range const& y)
123// {
124// using namespace boost::fusion;
125
126// typename Traits::VectorY rhsY(at_c<Traits::yIdx>(y.data)), solY(rhsY); solY *= 0;
127// directInverseOperator(*Myy,DirectType::UMFPACK3264,MatrixProperties::GENERAL).apply(rhsY,solY);
128// // chebyy->apply(solY,rhsY);
129
130// typename Traits::VectorU rhsU(at_c<Traits::uIdx>(y.data)), solU(rhsU); solU *= 0;
131// chebuu->apply(solU,rhsU);
132
133// typename Traits::VectorP rhsP(at_c<Traits::pIdx>(y.data)), solP(rhsP); solP *= 0;
134// A->applyscaleadd(-1.0,solY,rhsP);
135// B->applyscaleadd(-1.0,solU,rhsP);
136
137// S->solve(solP,rhsP);
138
139// at_c<Traits::stateId>(x.data) = at_c<0>(solY.data);
140// at_c<Traits::controlId>(x.data) = at_c<0>(solU.data);
141// at_c<Traits::adjointId>(x.data) = at_c<0>(solP.data);
142// }
143
144// private:
145// std::unique_ptr<typename TTraits::NormYOperator> Myy;
146// std::unique_ptr<typename TTraits::NormUOperator> Muu;
147// std::unique_ptr<typename Traits::StateOperator> A;
148// std::unique_ptr<typename Traits::ControlOperator> B;
149// std::unique_ptr<SchurComplement> S;
150// std::unique_ptr<ChebyshevPreconditioner<typename TTraits::NormYOperator> > chebyy;
151// std::unique_ptr<ChebyshevPreconditioner<typename TTraits::NormUOperator> > chebuu;
152// };
153
154
155// template <class Functional,class Assembler>
156// class SchurPreconditioner : public Dune::Preconditioner<typename OptimalControlTraits<Functional,Assembler>::Domain, typename OptimalControlTraits<Functional,Assembler>::Range>
157// {
158// typedef OptimalControlTraits<Functional,Assembler> Traits;
159// typedef typename Functional::Scalar Scalar;
160// typedef MatrixAsTriplet<Scalar> Matrix;
161// typedef SchurPreconditionerDetail::InvertLumpedMatrix<Scalar> Solver;
162// public:
163// SchurPreconditioner(Assembler const& assembler)
164// : Myy(assembler,true), Muu(assembler,true)
165// {
166// std::cout << "Schurpreconditioner: init schur complement...";
167// // compute approximate schur complement
168// typename Traits::StateOperator A(assembler,false);
169// typename Traits::AdjointOperator At(assembler,false);
170// typename Traits::ControlOperator B(assembler,false);
171// typename Traits::ControlOperatorT Bt(assembler,false);
172
173// Matrix s0, s1;
174// Matrix MA = A.template get<Matrix>(), MAT = At.template get<Matrix>(), MMyy = Myy.template get<Matrix>();
175// for(size_t i=0; i<MAT.ridx.size(); ++i)
176// {
177// size_t row = MAT.ridx[i];
178// size_t newIndex = std::abs(std::distance(MMyy.ridx.begin(), std::find(MMyy.ridx.begin(), MMyy.ridx.end(), row)));
179// assert(newIndex < MMyy.ridx.size());
180
181// MAT.data[i] /= MMyy.data[newIndex];
182// }
183
184// std::vector<std::vector<Scalar> > At_cols;
185// MAT.toColumns(At_cols);
186// auto At_cols2(At_cols);
187// for(size_t i=0; i<At_cols.size(); ++i)
188// {
189// MA.ax(At_cols2[i],At_cols[i]);
190// s0.addColumn(At_cols2[i],i);
191// }
192
193// Matrix MB = B.template get<Matrix>(), MBT = Bt.template get<Matrix>(), MMuu = Muu.template get<Matrix>();
194// for(size_t i=0; i<MBT.ridx.size(); ++i)
195// {
196// size_t row = MBT.ridx[i];
197// size_t newIndex = std::abs(std::distance(MMuu.ridx.begin(), std::find(MMuu.ridx.begin(), MMuu.ridx.end(), row)));
198// assert(newIndex < MMuu.ridx.size());
199
200// MBT.data[i] /= MMuu.data[newIndex];
201// }
202
203
204// std::vector<std::vector<Scalar> > Bt_cols;
205// MBT.toColumns(Bt_cols);
206// auto Bt_cols2(Bt_cols);
207// for(size_t i=0; i<Bt_cols.size(); ++i)
208// {
209// MB.ax(Bt_cols2[i],Bt_cols[i]);
210// s1.addColumn(Bt_cols2[i],i);
211// }
212
213// s0 += s1;
214
215// S.reset(new MatrixRepresentedOperator<Matrix,typename Traits::VectorP, typename Traits::VectorP>(std::move(s0)));
216// std::cout << "done" << std::endl;
217// }
218
219// ~SchurPreconditioner(){}
220
221// virtual void pre(typename Traits::Domain&, typename Traits::Range&){}
222// virtual void post(typename Traits::Domain&){}
223
224// virtual void apply(typename Traits::Domain& x, typename Traits::Range const& y)
225// {
226// using namespace boost::fusion;
227
228// typename Traits::VectorY rhsY(at_c<Traits::yIdx>(y.data)), solY(rhsY);
229// Solver solverY(Myy);
230// solverY.apply(solY,rhsY);
231
232// typename Traits::VectorU rhsU(at_c<Traits::uIdx>(y.data)), solU(rhsU);
233// Solver solverU(Muu);
234// solverU.apply(solU,rhsU);
235
236// typename Traits::VectorP rhsP(at_c<Traits::pIdx>(y.data)), solP(rhsP);
237// directInverseOperator(*S,DirectType::UMFPACK3264,MatrixProperties::GENERAL).apply(rhsP,solP);
238
239// at_c<Traits::yIdx>(x.data) = at_c<0>(solY.data);
240// at_c<Traits::uIdx>(x.data) = at_c<0>(solU.data);
241// at_c<Traits::pIdx>(x.data) = at_c<0>(solP.data);
242// }
243
244// private:
245// typename Traits::NormYOperator Myy;
246// typename Traits::NormUOperator Muu;
247// std::unique_ptr<MatrixRepresentedOperator<Matrix,typename Traits::VectorP, typename Traits::VectorP> > S;
248// };
249
250
251// template <class PreconditionerFactory,class VariableSet>
252// class PreconditionerAsPDESolver : public AbstractNormalDirection, public Dune::Preconditioner<typename PreconditionerFactory::Operator::Domain, typename PreconditionerFactory::Operator::Range>
253// {
254// public:
255// typedef typename PreconditionerFactory::Operator::Assembler Assembler;
256// typedef typename PreconditionerFactory::Operator::Domain Domain;
257// typedef typename PreconditionerFactory::Operator::Range Range;
258// typedef Bridge::ConnectedKaskadeLinearization<typename Assembler::Functional::Functional> BridgeLinearization;
259
260// PreconditionerAsPDESolver(PreconditionerFactory& prec_) : prec(prec_)
261// {}
262
263// virtual ~PreconditionerAsPDESolver(){}
264
265// virtual void pre(Domain& x, Range& b){}
266// virtual void post(Domain& x){}
267// virtual void apply(Domain& x, Range const& y)
268// {
269// preconditioner->apply(x,y);
270// // P->apply(x,y);
271// }
272
273// private:
274// virtual void computeCorrectionAndAdjointCorrection(AbstractFunctionSpaceElement& correction, AbstractFunctionSpaceElement& adjointCorrection, AbstractLinearization& linearization)
275// {
276// A.reset(new AssembledGalerkinOperator<Assembler>(dynamic_cast<BridgeLinearization&>(linearization).getValidAssembler()));
277// preconditioner.reset(new NormalStepPreconditioner<typename Assembler::Functional::Functional,Assembler>(dynamic_cast<BridgeLinearization&>(linearization).getValidAssembler()));
278// P.reset(prec.create(*A).release());
279// std::unique_ptr<AbstractFunctionSpaceElement> combinedrhs(correction.clone());
280// linearization.evald(*combinedrhs);
281// VariableSet& conrhs=Bridge::getImpl<VariableSet>(*combinedrhs);
282// Domain x(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(conrhs.descriptions));
283
284// Range y(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(conrhs.descriptions));
285// y = conrhs;
286
287// P->apply(x,y);
288
289// VariableSet& cor=Bridge::getImpl<VariableSet>(correction);
290// cor = x;
291// cor *= -1.0;
292// }
293
294// virtual void computeSimplifiedCorrection(AbstractFunctionSpaceElement& correction,
295// AbstractLinearization const& lin) const
296// {
297// std::unique_ptr<AbstractFunctionSpaceElement> combinedrhs(correction.clone());
298// lin.evald(*combinedrhs);
299// VariableSet& conrhs=Bridge::getImpl<VariableSet>(*combinedrhs);
300
301// Domain x(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(conrhs.descriptions));
302// x *= 0.0;
303// Range y(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(conrhs.descriptions));
304
305// y=conrhs;
306
307// P->apply(x,y);
308
309// VariableSet& cor=Bridge::getImpl<VariableSet>(correction);
310
311// cor = x;
312
313// cor *= -1.0;
314// }
315
316// PreconditionerFactory& prec;
317// std::unique_ptr<Dune::Preconditioner<Domain,Range> > P;
318// std::unique_ptr<NormalStepPreconditioner<typename Assembler::Functional::Functional,Assembler> > preconditioner;
319// std::unique_ptr<AssembledGalerkinOperator<Assembler> > A;
320// };
321
322 template <class Operator, class PrecondAssembler, class PreconditionerFactory, class VariableSet>
323 class PreconditionerAsNormalSolver : public AbstractNormalDirection, public Dune::Preconditioner<typename Operator::Domain, typename Operator::Range>
324 {
325 public:
326 typedef typename Operator::Assembler Assembler;
327 static constexpr int components = Assembler::Grid::dimension;
328 typedef typename Assembler::Functional::Functional Functional;
329 typedef typename PrecondAssembler::Functional::Functional PreconditionerFunctional;
330 typedef OptimalControlTraits<Functional,Assembler> Traits;
331 typedef typename Operator::Domain Domain;
332 typedef typename Operator::Range Range;
334
336
338
339 virtual void pre(Domain &x, Range &b) {}
340 virtual void apply (Domain &v, const Range &d) {
341 //normalStepPreconditioner->apply(v,d);
342 tangentialStepPreconditioner->apply(v,d);
343// P->apply(v,d);
344 }
345
346 virtual void post (Domain &x) {}
347
348 private:
349 virtual void computeCorrectionAndAdjointCorrection(AbstractFunctionSpaceElement& correction, AbstractFunctionSpaceElement& adjointCorrection, AbstractLinearization& lin, AbstractFunctionSpaceElement*,AbstractFunctionSpaceElement*)
350 {
351 A.reset(new Operator(dynamic_cast<BridgeLinearization&>(lin).getValidAssembler()));
352 std::cout << "init P" << std::endl;
353 //if(std::is_same<Operator,NormalStepAssembledGalerkinOperator<Assembler>>::value) std::cout << "normal step operator" << std::endl;
354 // else std::cout << "standard operator" << std::endl;
355 P.reset(new DirectPreconditioner<Operator>(*A));
356 //P.reset(prec.create(*A).release());
357
358 PrecondAssembler assembler(A->getAssembler().spaces());
359 assembler.assemble(linearization(pf,Bridge::getImpl<VariableSet>(lin.getOrigin())));
360 std::cout << "init nsp" << std::endl;
361 normalStepPreconditioner.reset(new NormalStepPreconditioner<PreconditionerFunctional,PrecondAssembler>(assembler));
363 std::cout << "done init p" << std::endl;
364 std::unique_ptr<AbstractFunctionSpaceElement> combinedrhs(correction.clone());
365 std::unique_ptr<AbstractFunctionSpaceElement> derivativerhs(correction.clone());
366 std::unique_ptr<AbstractFunctionSpaceElement> constraintrhs(correction.clone());
367 *derivativerhs *= 0.0;
368 *constraintrhs *= 0.0;
369 lin.evald(*combinedrhs);
370 derivativerhs->axpy(1.0,*combinedrhs,"primal");
371 constraintrhs->axpy(1.0,*combinedrhs,"dual");
372 VariableSet& derrhs=Bridge::getImpl<VariableSet>(*derivativerhs);
373 VariableSet& conrhs=Bridge::getImpl<VariableSet>(*constraintrhs);
374 using namespace boost::fusion;
375
376 Domain x(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(derrhs.descriptions));
377
378 Range y(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(derrhs.descriptions));
379 y = derrhs;
380
381 P->apply(x,y);
382
383 VariableSet& adj=Bridge::getImpl<VariableSet>(adjointCorrection);
384 adj = x;
385 adj *= -1.0;
386
387 std::cout << "adjoint correction: " << x*x << std::endl;
388
389 x *= 0;
390 y = conrhs;
391 P->apply(x,y);
392
393
394 VariableSet& cor=Bridge::getImpl<VariableSet>(correction);
395 cor = x;
396 cor *= -1.0;
397 }
398
399
400 virtual void computeSimplifiedCorrection(AbstractFunctionSpaceElement& correction,
401 AbstractLinearization const& lin, AbstractFunctionSpaceElement* residual) const
402 {
403
404 std::unique_ptr<AbstractFunctionSpaceElement> combinedrhs(correction.clone());
405 std::unique_ptr<AbstractFunctionSpaceElement> constraintrhs(correction.clone());
406 *constraintrhs *= 0.0;
407 lin.evald(*combinedrhs);
408 constraintrhs->axpy(1.0,*combinedrhs,"dual");
409 if(residual != nullptr) *constraintrhs += *residual;
410 VariableSet& conrhs=Bridge::getImpl<VariableSet>(*constraintrhs);
411 std::cout << "RHS 2=" << boost::fusion::at_c<2>(conrhs.data).coefficients()*boost::fusion::at_c<2>(conrhs.data).coefficients() << std::endl;
412
413 Domain x(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(conrhs.descriptions));
414 x *= 0.0;
415 Range y(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(conrhs.descriptions));
416
417 y=conrhs;
418
419 P->apply(x,y);
420
421 VariableSet& cor=Bridge::getImpl<VariableSet>(correction);
422 cor = x;
423 cor *= -1.0;
424 }
425
426 PreconditionerFunctional const& pf;
427 PreconditionerFactory& prec;
428 std::unique_ptr<Dune::Preconditioner<Domain,Range> > P;
429 std::unique_ptr<Operator> A;
430 std::unique_ptr<NormalStepPreconditioner<PreconditionerFunctional,PrecondAssembler> > normalStepPreconditioner;
431 std::unique_ptr<InexactTangentSpacePreconditioner<PreconditionerFunctional,PrecondAssembler,components> > tangentialStepPreconditioner;
432};
433
434 template <class Assembler_, class PrecondAssembler, class Domain_, class Range_, class VariableSet, int components=Assembler_::Grid::dimension>
435 class PPCGAsNormalSolver : public AbstractNormalDirection, public Dune::Preconditioner<Domain_, Range_>
436 {
437 public:
438 typedef Domain_ Domain;
439 typedef Range_ Range;
440 typedef Assembler_ Assembler;
441 typedef typename Assembler::Functional::Functional Functional;
442 typedef typename PrecondAssembler::Functional::Functional PreconditionerFunctional;
443 typedef OptimalControlTraits<Functional,Assembler> Traits;
444 typedef typename Traits::Scalar Scalar;
446 typedef IterateType::CG<Domain,Range> Solver;
447
448 PPCGAsNormalSolver(PreconditionerFunctional const& pf_, double relativeAccuracy_=1e-9, size_t maxSteps_=2000, int verbosity_=1, double eps_ = 1e-15)
449 : pf(pf_), initialRelativeAccuracy(relativeAccuracy_), relativeAccuracy(initialRelativeAccuracy), eps(eps_), maxSteps(maxSteps_), verbosity(verbosity_)
450 {}
451
453 virtual void pre(Domain &x, Range &b) {}
454 virtual void post (Domain &x) {}
455
456 virtual void apply (Domain &v, const Range &d)
457 {
458 normalStepPreconditioner->apply(v,d);
459 //tangentialStepPreconditioner->apply(v,d);
460 }
461
462 virtual void setRelativeAccuracy(double relativeAccuracy_)
463 {
464 relativeAccuracy = std::min(relativeAccuracy_,initialRelativeAccuracy);
465 }
466
467 virtual void setEps(double eps_) { eps = eps_; }
468
469 void setMultiGridSteps(size_t mgSteps_) { mgSteps = mgSteps_; }
470 void setMultiGridSmoothingSteps(size_t mgSmoothingSteps_) { mgSmoothingSteps = mgSmoothingSteps_; }
471 void setChebyshevSteps(size_t chebySteps_) { chebySteps = chebySteps_; }
472
473 private:
474 void setNormalStepParameters() const
475 {
476 normalStepPreconditioner->setParameter(mgSteps, mgSmoothingSteps, chebySteps, 1e-9);
477 }
478
479 void setTangentialStepParameters() const
480 {
481 normalStepPreconditioner->setParameter(mgSteps, mgSmoothingSteps, chebySteps, 1e-9);
482// normalStepPreconditioner->setParameter(mgStepsT, mgSmoothingStepsT, chebyStepsT, 0);
483 }
484
485 virtual void computeCorrectionAndAdjointCorrection(AbstractFunctionSpaceElement& correction, AbstractFunctionSpaceElement& adjointCorrection, AbstractLinearization& lin, AbstractFunctionSpaceElement* correctionResidual, AbstractFunctionSpaceElement* adjointResidual)
486 {
487 A.reset(new AssembledGalerkinOperator<Assembler>(dynamic_cast<BridgeLinearization&>(lin).getValidAssembler()));
488
489 PrecondAssembler assembler(A->getAssembler().spaces());
490 assembler.assemble(linearization(pf,Bridge::getImpl<VariableSet>(lin.getOrigin())),PrecondAssembler::MATRIX);
491 //normalStepPreconditioner.reset(new NormalStepPreconditioner<Functional,Assembler>(dynamic_cast<BridgeLinearization&>(lin).getValidAssembler(), false, sqrt(relativeAccuracy)));
492 std::unique_ptr<AbstractFunctionSpaceElement> combinedrhs(correction.clone());
493 std::unique_ptr<AbstractFunctionSpaceElement> derivativerhs(correction.clone());
494 std::unique_ptr<AbstractFunctionSpaceElement> constraintrhs(correction.clone());
495 *derivativerhs *= 0.0;
496 *constraintrhs *= 0.0;
497 lin.evald(*combinedrhs);
498 // rhs for computation of adjoint correction
499 derivativerhs->axpy(1.0,*combinedrhs,"primal");
500 VariableSet& derrhs=Bridge::getImpl<VariableSet>(*derivativerhs);
501 // rhs for computation of correction
502 constraintrhs->axpy(1.0,*combinedrhs,"dual");
503 VariableSet& conrhs=Bridge::getImpl<VariableSet>(*constraintrhs);
504
505 // compute adjoint correction
506 if(verbosity > 0) std::cout << "computing adjoint correction" << std::endl;
507 Domain x(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(derrhs.descriptions));
508 Range y(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(derrhs.descriptions));
509 y = derrhs;
510
511 StrakosTichyEnergyErrorTerminationCriterion<double> terminationCriterion(relativeAccuracy,maxSteps,eps);
512 terminationCriterion.lookahead(10);
513 normalStepPreconditioner.reset(new NormalStepPreconditioner3<PreconditionerFunctional,PrecondAssembler,components>(assembler,conrhs.descriptions,derrhs.descriptions));
514 setNormalStepParameters();
515 //tangentialStepPreconditioner.reset(new TangentSpacePreconditioner2<PreconditionerFunctional,PrecondAssembler,components>(assembler,conrhs.descriptions,derrhs.descriptions, mgSteps, mgSmoothingSteps, chebySteps));
516 Solver solver(*A, *normalStepPreconditioner, dualPairing, terminationCriterion, verbosity, eps);
517 solver.apply(x,y);
518 VariableSet& adj=Bridge::getImpl<VariableSet>(adjointCorrection);
519 adj = x;
520 adj *= -1.0;
521
522 if( adjointResidual != nullptr )
523 {
524 y = derrhs;
525 A->applyscaleadd(-1.0,x,y);
526 Bridge::getImpl<VariableSet>(*adjointResidual) = y;
527 }
528
529 x = 0;
530 y = conrhs;
531
532 // compute initial iterate
533 Domain x1(x); x1 = 0;
534 typename Traits::VectorP rhs(boost::fusion::at_c<Traits::adjointId>(y.data));
535 typename Traits::VectorY sol(Traits::CreateVectorY::init(derrhs.descriptions));
536 normalStepPreconditioner->applyStatePreconditioner(sol,rhs);
537 boost::fusion::at_c<Traits::stateId>(x1.data) = boost::fusion::at_c<0>(sol.data);
538 A->applyscaleadd(-1.0,x1,y);
539 // compute correction
540 if(verbosity > 0) std::cout << "computing correction" << std::endl;
541 solver.apply(x,y);
542
543 x += x1;
544
545 // compute residual
546 if(correctionResidual != nullptr)
547 {
548 y = conrhs;
549 A->applyscaleadd(-1.0,x,y);
550 Bridge::getImpl<VariableSet>(*correctionResidual) = y;
551 }
552
553 VariableSet& cor=Bridge::getImpl<VariableSet>(correction);
554 cor = x;
555 cor *= -1.0;
556
557 setTangentialStepParameters();
558 }
559
560
561 virtual void computeSimplifiedCorrection(AbstractFunctionSpaceElement& correction,
562 AbstractLinearization const& lin, AbstractFunctionSpaceElement* correctionResidual) const
563 {
564 setNormalStepParameters();
565 std::unique_ptr<AbstractFunctionSpaceElement> combinedrhs(correction.clone());
566 std::unique_ptr<AbstractFunctionSpaceElement> constraintrhs(correction.clone());
567 *constraintrhs *= 0.0;
568 lin.evald(*combinedrhs);
569 constraintrhs->axpy(1.0,*combinedrhs,"dual");
570 using namespace boost::fusion;
571 if(correctionResidual != nullptr) constraintrhs->axpy(-1.0,*correctionResidual,"dual");
572 VariableSet& conrhs=Bridge::getImpl<VariableSet>(*constraintrhs);
573
574 Domain x(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(conrhs.descriptions));
575 Range y(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(conrhs.descriptions));
576
577 y=conrhs;
578
579 // compute initial iterate
580 Domain x1(x); x1 = 0;
581 typename Traits::VectorP rhs(boost::fusion::at_c<Traits::adjointId>(y.data));
582 typename Traits::VectorY sol(Traits::CreateVectorY::init(conrhs.descriptions));
583 normalStepPreconditioner->applyStatePreconditioner(sol,rhs);
584 boost::fusion::at_c<Traits::stateId>(x1.data) = boost::fusion::at_c<0>(sol.data);
585 A->applyscaleadd(-1.0,x1,y);
586
587 // compute correction
588 StrakosTichyEnergyErrorTerminationCriterion<double> terminationCriterion(relativeAccuracy,maxSteps,eps);
589 terminationCriterion.lookahead(15);
590 Solver solver(*A, *normalStepPreconditioner, dualPairing, terminationCriterion, verbosity, eps);
591 solver.apply(x,y);
592
593 x += x1;
594
595 VariableSet& cor=Bridge::getImpl<VariableSet>(correction);
596 cor = x;
597 cor *= -1.0;
598 }
599
600 PreconditionerFunctional const& pf;
601 mutable std::unique_ptr<NormalStepPreconditioner3<PreconditionerFunctional,PrecondAssembler,components> > normalStepPreconditioner;
602 std::unique_ptr<AssembledGalerkinOperator<Assembler> > A;
603 DefaultDualPairing<Domain,Range> dualPairing;
604 Scalar initialRelativeAccuracy, relativeAccuracy, eps;
605 size_t maxSteps;
606 int verbosity;
607 size_t mgSteps = 500, mgSmoothingSteps = 25, chebySteps = 50;
608 size_t mgStepsT = 20, mgSmoothingStepsT = 20, chebyStepsT = 50;
609 };
610
611 template <class Assembler_, class PrecondAssembler, class Domain_, class Range_, class VariableSet, int components=Assembler_::Grid::dimension>
612 class DirectNormalSolver : public AbstractNormalDirection, public Dune::Preconditioner<Domain_, Range_>
613 {
614 public:
615 typedef Domain_ Domain;
616 typedef Range_ Range;
617 typedef Assembler_ Assembler;
618 typedef typename Assembler::Functional::Functional Functional;
619 typedef typename PrecondAssembler::Functional::Functional PreconditionerFunctional;
620 typedef OptimalControlTraits<Functional,Assembler> Traits;
621 typedef typename Traits::Scalar Scalar;
623
625 : directType(directType_), properties(properties_), verbosity(verbosity_)
626 {}
627
629 virtual void pre(Domain &x, Range &b) {}
630 virtual void post (Domain &x) {}
631
632 virtual void apply (Domain &v, const Range &d) { directSolver.apply(d,v); }
633
634 virtual void setRelativeAccuracy(double){}
635
636 private:
637 virtual void computeCorrectionAndAdjointCorrection(AbstractFunctionSpaceElement& correction, AbstractFunctionSpaceElement& adjointCorrection, AbstractLinearization& lin,
638 AbstractFunctionSpaceElement* normalStepResidual, AbstractFunctionSpaceElement* adjointResidual)
639 {
640 A.reset(new AssembledGalerkinOperator<Assembler>(dynamic_cast<BridgeLinearization&>(lin).getValidAssembler()));
641
642 std::unique_ptr<AbstractFunctionSpaceElement> combinedrhs(correction.initZeroVector());
643 std::unique_ptr<AbstractFunctionSpaceElement> derivativerhs(correction.initZeroVector());
644 std::unique_ptr<AbstractFunctionSpaceElement> constraintrhs(correction.initZeroVector());
645 lin.evald(*combinedrhs);
646 // rhs for computation of adjoint correction
647 derivativerhs->axpy(1.0,*combinedrhs,"primal");
648 VariableSet& derrhs=Bridge::getImpl<VariableSet>(*derivativerhs);
649 // rhs for computation of correction
650 constraintrhs->axpy(1.0,*combinedrhs,"dual");
651 VariableSet& conrhs=Bridge::getImpl<VariableSet>(*constraintrhs);
652
653 // compute adjoint correction
654 if(verbosity > 0) std::cout << "PrecondType::DIRECT NORMAL SOLVER: Computing adjoint correction." << std::endl;
655 Domain x(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(derrhs.descriptions));
656 Range y(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(derrhs.descriptions));
657 y = derrhs;
658
660 directSolver.apply(y,x);
661 VariableSet& adj=Bridge::getImpl<VariableSet>(adjointCorrection);
662 adj = x;
663 adj *= -1.0;
664
665 if( adjointResidual != nullptr )
666 {
667 y = derrhs;
668 A->applyscaleadd(-1.0,x,y);
669 Bridge::getImpl<VariableSet>(*adjointResidual) = y;
670 }
671
672 x = 0;
673 y = conrhs;
674 // compute correction
675 if(verbosity > 0) std::cout << "PrecondType::DIRECT NORMAL SOLVER: Computing correction." << std::endl;
676 directSolver.apply(y,x);
677
678 VariableSet& cor=Bridge::getImpl<VariableSet>(correction);
679 cor = x;
680 cor *= -1.0;
681
682 if( normalStepResidual != nullptr )
683 {
684 y = conrhs;
685 A->applyscaleadd(-1.0,x,y);
686 Bridge::getImpl<VariableSet>(*normalStepResidual) = y;
687 }
688 }
689
690
691 virtual void computeSimplifiedCorrection(AbstractFunctionSpaceElement& correction,
692 AbstractLinearization const& lin, AbstractFunctionSpaceElement* residual) const
693 {
694 if( verbosity > 0 ) std::cout << "PrecondType::DIRECT NORMAL SOLVER: Computing simplified correction." << std::endl;
695 std::unique_ptr<AbstractFunctionSpaceElement> combinedrhs(correction.initZeroVector());
696 std::unique_ptr<AbstractFunctionSpaceElement> constraintrhs(correction.initZeroVector());
697 lin.evald(*combinedrhs);
698 constraintrhs->axpy(1.0,*combinedrhs,"dual");
699 using namespace boost::fusion;
700 if(residual!=nullptr) constraintrhs->axpy(1.0,*residual,"dual");
701 VariableSet& conrhs=Bridge::getImpl<VariableSet>(*constraintrhs);
702
703 Domain x(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(conrhs.descriptions));
704 Range y(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(conrhs.descriptions));
705
706 y=conrhs;
707 directSolver.apply(y,x);
708 VariableSet& cor=Bridge::getImpl<VariableSet>(correction);
709 cor = x;
710 cor *= -1.0;
711 }
712
713// std::unique_ptr<TangentSpacePreconditioner<PreconditionerFunctional,PrecondAssembler,components> > tangentialStepPreconditioner;
714 std::unique_ptr<AssembledGalerkinOperator<Assembler> > A;
715 DirectType directType;
716 MatrixProperties properties;
717 int verbosity;
719 };
720
721
722
723 template <class Functional, class Assembler>
724 class NormalStepPreconditioner : public Dune::Preconditioner<typename OptimalControlTraits<Functional,Assembler>::Domain, typename OptimalControlTraits<Functional,Assembler>::Range>
725 {
726 typedef OptimalControlTraits<Functional,Assembler> Traits;
727 typedef typename Traits::Scalar Scalar;
728 typedef typename Assembler::Grid Grid;
729 public:
730 NormalStepPreconditioner(Assembler const& assembler, bool onlyLowerTriangle=false, Scalar tolerance=1e-6)
731 : Mu(assembler,onlyLowerTriangle),
732 B(assembler,false), A(assembler,false),
733 PA(new DirectPreconditioner<typename Traits::StateOperator>(A)),
734 cheb(Mu,30),
735 tol(tolerance)//,
736 {
738 }
739
741
742 virtual void pre(typename Traits::Domain&, typename Traits::Range&){}
743 virtual void post(typename Traits::Domain&){}
744
745 virtual void apply(typename Traits::Domain& x, typename Traits::Range const& y)
746 {
747 using namespace boost::fusion;
748 typename Traits::VectorY rhsY(at_c<Traits::yIdx>(y.data));
749 typename Traits::VectorP dp(at_c<Traits::pIdx>(y.data));
750 PA->apply(dp,rhsY);
751
752 typename Traits::VectorU rhsU(at_c<Traits::uIdx>(y.data));
753 typename Traits::VectorU du(rhsU);
754 B.applyscaleaddTransposed(-1.0,dp,rhsU);
755 //Lu.apply(du,rhsU);
756 //PMu->apply(du,rhsU);
757 cheb.apply(du,rhsU);
758
759 //cg.apply(du,rhsU);
760
761 typename Traits::VectorP rhsP(at_c<Traits::pIdx>(y.data));
762 typename Traits::VectorY dy(at_c<Traits::yIdx>(y.data));
763 B.applyscaleadd(-1.0,du,rhsP);
764 PA->apply(dy,rhsP);
765
766 at_c<Traits::yIdx>(x.data) = at_c<0>(dy.data);
767 at_c<Traits::uIdx>(x.data) = at_c<0>(du.data);
768 at_c<Traits::pIdx>(x.data) = at_c<0>(dp.data);
769 }
770
771 void applyStatePreconditioner(typename Traits::VectorY& x, typename Traits::VectorP const& y)
772 {
773// directInverseOperator(A,DirectType::UMFPACK3264,MatrixProperties::GENERAL).apply(y,x);
774 PA->apply(x,y);
775 }
776
777 void applyAdjointPreconditioner(typename Traits::VectorP& x, typename Traits::VectorY const& y)
778 {
779 PA->apply(x,y);
780 }
781
782 private:
783 typename Traits::NormUOperator Mu;
784 typename Traits::ControlOperator B;
785 typename Traits::StateOperator A;
786
787 std::unique_ptr<typename Traits::StatePreconditioner> PA;
788// std::unique_ptr<typename Traits::AdjointPreconditioner> PAt;
790 Scalar tol;
791 };
792
793 template <class Functional, class Assembler, int components>
794 class TangentSpacePreconditioner : public Dune::Preconditioner<typename OptimalControlTraits<Functional,Assembler>::Domain, typename OptimalControlTraits<Functional,Assembler>::Range>
795 {
796 typedef typename Assembler::Scalar Scalar;
797 typedef OptimalControlTraits<Functional,Assembler> Traits;
798 typedef typename Assembler::Grid Grid;
799 static constexpr int dim = Functional::dim;
800
801 public:
802 TangentSpacePreconditioner(Assembler const& assembler, bool onlyLowerTriangle=false)
803 : grid(boost::fusion::at_c<0>(assembler.spaces())->gridManager().grid()),
804 At(assembler,onlyLowerTriangle),
805 Mu(assembler,onlyLowerTriangle), Bt(assembler,onlyLowerTriangle),
806 B(assembler,onlyLowerTriangle), A(assembler,onlyLowerTriangle),
807 PA(new DirectPreconditioner<typename Traits::StateOperator>(A)),
808 PAt(new DirectPreconditioner<typename Traits::AdjointOperator>(At)),
809 cheb(Mu,50)
810 {
812 }
813
815
816 virtual void pre(typename Traits::Domain&, typename Traits::Range&){}
817 virtual void post(typename Traits::Domain&){}
818
819 virtual void apply(typename Traits::Domain& x, typename Traits::Range const& y)
820 {
821 std::cout << "in preconditioner" << std::endl;
822 std::cout << "adjoint equation" << std::endl;
823 using namespace boost::fusion;
824 std::cout << "read rhs" << std::endl;
825 typename Traits::VectorY rhsY(at_c<Traits::yIdx>(y.data));
826 std::cout << "init dp" << std::endl;
827 typename Traits::VectorP dp(at_c<Traits::pIdx>(y.data));
828 std::cout << "solve" << std::endl;
829 PAt->apply(dp,rhsY);
830
831 std::cout << "control equation" << std::endl;
832 std::cout << "read rhs" << std::endl;
833 typename Traits::VectorU rhsU(at_c<Traits::uIdx>(y.data));
834 std::cout << "init du" << std::endl;
835 typename Traits::VectorU du(rhsU);
836 std::cout << "apply Bt" << std::endl;
837 Bt.applyscaleadd(-1.0,dp,rhsU);
838 std::cout << "invert Mu" << std::endl;
839// directInverseOperator(Mu,DirectType::UMFPACK3264,MatrixProperties::GENERAL).apply(rhsU,du);
840 cheb.apply(du,rhsU);
841
842 std::cout << "state equation" << std::endl;
843 typename Traits::Range tmpY(y);
844 std::cout << "read rhs " << std::endl;
845 typename Traits::VectorP rhsP(at_c<Traits::pIdx>(y.data));
846 std::cout << "init dy" << std::endl;
847 typename Traits::VectorY dy(at_c<Traits::yIdx>(y.data));
848 std::cout << "apply B" << std::endl;
849 B.applyscaleadd(-1.0,du,rhsP);
850 std::cout << "solve" << std::endl;
851 PA->apply(dy,rhsP);
852
853 at_c<Traits::yIdx>(x.data) = at_c<0>(dy.data);
854 at_c<Traits::uIdx>(x.data) = at_c<0>(du.data);
855 at_c<Traits::pIdx>(x.data) = at_c<0>(dp.data);
856 }
857
858 void applyStatePreconditioner(typename Traits::VectorY& x, typename Traits::VectorP const& y)
859 {
860 PA->apply(x,y);
861 }
862
863 void applyAdjointPreconditioner(typename Traits::VectorP& x, typename Traits::VectorY const& y)
864 {
865 PAt->apply(x,y);
866 }
867
868 private:
869 Grid const& grid;
870
871 typename Traits::AdjointOperator At;
872 typename Traits::NormUOperator Mu;
873 typename Traits::ControlOperatorT Bt;
874 typename Traits::ControlOperator B;
875 typename Traits::StateOperator A;
876
877 std::unique_ptr<typename Traits::StatePreconditioner> PA;
878 std::unique_ptr<typename Traits::AdjointPreconditioner> PAt;
880 //std::unique_ptr<typename Traits::NormUPreconditioner> PMu;
881 };
882
883 template <class Functional, class Assembler, int components>
884 class TangentSpacePreconditioner2 : public Dune::Preconditioner<typename OptimalControlTraits<Functional,Assembler>::Domain, typename OptimalControlTraits<Functional,Assembler>::Range>
885 {
886 typedef typename Assembler::Scalar Scalar;
887 typedef OptimalControlTraits<Functional,Assembler> Traits;
888 typedef typename Assembler::Grid Grid;
890 typedef typename Functional::AnsatzVars AnsatzVariableSetDesc;
891 typedef typename Functional::TestVars TestVariableSetDesc;
892 static constexpr int dim = Functional::dim;
893
894 public:
895 TangentSpacePreconditioner2(Assembler const& assembler, AnsatzVariableSetDesc const& ansatzVars, TestVariableSetDesc const& testVars,
896 size_t mgSteps = 10, size_t mgSmoothingSteps = 10, size_t chebySteps = 10, bool onlyLowerTriangle=false)
897 : At(assembler,onlyLowerTriangle),
898 Mu(assembler,onlyLowerTriangle), Bt(assembler,onlyLowerTriangle),
899 B(assembler,onlyLowerTriangle), A(assembler,onlyLowerTriangle),
900 cheb(Mu,chebySteps),
901 mgA( A, boost::fusion::at_c<0>(assembler.spaces())->gridManager().grid(), typename MGPreconditioner::Parameter(mgSteps,mgSmoothingSteps) ),
902 mgAt( At, boost::fusion::at_c<0>(assembler.spaces())->gridManager().grid(), typename MGPreconditioner::Parameter(mgSteps,mgSmoothingSteps) ),
903 avar(ansatzVars), tvar(testVars)
904 {
906 }
907
909
910 virtual void pre(typename Traits::Domain&, typename Traits::Range&){}
911 virtual void post(typename Traits::Domain&){}
912
913 virtual void apply(typename Traits::Domain& x, typename Traits::Range const& y)
914 {
915 using namespace boost::fusion;
916 typename Traits::VectorY rhsY(at_c<Traits::yIdx>(y.data));
917 typename Traits::VectorP dp(at_c<Traits::pIdx>(y.data));
918
919 typename Traits::AnsatzVariableSetDescription::VariableSet tmpx(avar);
920 typename Traits::TestVariableSetDescription::VariableSet tmpy(tvar);
921 at_c<Traits::yIdx>(tmpy.data).coefficients() = at_c<0>(rhsY.data);
922 mgAt.apply(at_c<Traits::pIdx>(tmpx.data).coefficients(),at_c<Traits::yIdx>(tmpy.data).coefficients());
923 at_c<0>(dp.data) = at_c<Traits::pIdx>(tmpx.data).coefficients();
924
925 typename Traits::VectorU rhsU(at_c<Traits::uIdx>(y.data));
926 typename Traits::VectorU du(rhsU);
927 Bt.applyscaleadd(-1.0,dp,rhsU);
928 cheb.apply(du,rhsU);
929
930 typename Traits::VectorP rhsP(at_c<Traits::pIdx>(y.data));
931 typename Traits::VectorY dy(at_c<Traits::yIdx>(y.data));
932 B.applyscaleadd(-1.0,du,rhsP);
933
934 at_c<Traits::pIdx>(tmpy.data).coefficients() = at_c<0>(rhsP.data);
935 mgA.apply(at_c<Traits::yIdx>(tmpx.data).coefficients(),at_c<Traits::pIdx>(tmpy.data).coefficients());
936 at_c<0>(dy.data) = at_c<Traits::yIdx>(tmpx.data).coefficients();
937
938 at_c<Traits::yIdx>(x.data) = at_c<0>(dy.data);
939 at_c<Traits::uIdx>(x.data) = at_c<0>(du.data);
940 at_c<Traits::pIdx>(x.data) = at_c<0>(dp.data);
941 }
942
943 void applyStatePreconditioner(typename Traits::VectorY& x, typename Traits::VectorP const& y)
944 {
945 using namespace boost::fusion;
946 typename Traits::AnsatzVariableSetDescription::VariableSet tmpx(avar);
947 typename Traits::TestVariableSetDescription::VariableSet tmpy(tvar);
948 at_c<Traits::pIdx>(tmpy.data).coefficients() = at_c<0>(y.data);
949 mgA.apply(at_c<Traits::yIdx>(tmpx.data).coefficients(),at_c<Traits::pIdx>(tmpy.data).coefficients());
950 at_c<0>(x.data) = at_c<Traits::yIdx>(tmpx.data).coefficients();
951 }
952
953 void applyAdjointPreconditioner(typename Traits::VectorP& x, typename Traits::VectorY const& y)
954 {
955 using namespace boost::fusion;
956 typename Traits::AnsatzVariableSetDescription::VariableSet tmpx(avar);
957 typename Traits::TestVariableSetDescription::VariableSet tmpy(tvar);
958 at_c<Traits::yIdx>(tmpy.data).coefficients() = at_c<0>(y.data);
959 mgAt.apply(at_c<Traits::pIdx>(tmpx.data).coefficients(),at_c<Traits::yIdx>(tmpy.data).coefficients());
960 at_c<0>(x.data) = at_c<Traits::pIdx>(tmpx.data).coefficients();
961 }
962
963 private:
964 typename Traits::AdjointOperator At;
965 typename Traits::NormUOperator Mu;
966 typename Traits::ControlOperatorT Bt;
967 typename Traits::ControlOperator B;
968 typename Traits::StateOperator A;
969
971 MGPreconditioner mgA, mgAt;
972 AnsatzVariableSetDesc avar;
973 TestVariableSetDesc tvar;
974 };
975
976// template <class Functional, class Assembler, int components>
977// class NormalStepPreconditioner2 : public Dune::Preconditioner<typename OptimalControlTraits<Functional,Assembler>::Domain, typename OptimalControlTraits<Functional,Assembler>::Range>
978// {
979// typedef typename Assembler::Scalar Scalar;
980// typedef OptimalControlTraits<Functional,Assembler> Traits;
981// typedef typename Assembler::Grid Grid;
982// typedef MultiGridSolver<Grid,components> MGSolver;
983// typedef typename Functional::AnsatzVars AnsatzVariableSetDesc;
984// typedef typename Functional::TestVars TestVariableSetDesc;
985// static constexpr int dim = Functional::dim;
986
987// public:
988// NormalStepPreconditioner2(Assembler const& assembler, AnsatzVariableSetDesc const& ansatzVars, TestVariableSetDesc const& testVars,
989// size_t mgSteps = 500, size_t mgSmoothingSteps = 10, size_t chebySteps = 20, double relativeAccuracy = 1e-6, bool onlyLowerTriangle=false)
990// : At(assembler,onlyLowerTriangle),
991// Mu(assembler,onlyLowerTriangle), Bt(assembler,onlyLowerTriangle),
992// B(assembler,onlyLowerTriangle), A(assembler,onlyLowerTriangle),
993// cheb(Mu,chebySteps),
994// mgA( A, boost::fusion::at_c<0>(assembler.spaces())->gridManager().grid(), typename MGSolver::Parameter(mgSteps,mgSmoothingSteps,relativeAccuracy) ),
995// mgAt( At, boost::fusion::at_c<0>(assembler.spaces())->gridManager().grid(), typename MGSolver::Parameter(mgSteps,mgSmoothingSteps,relativeAccuracy) ),
996// avar(ansatzVars), tvar(testVars)
997// {
998// cheb.initForMassMatrix_TetrahedralQ1Elements();
999// }
1000
1001// virtual ~NormalStepPreconditioner2(){}
1002
1003// void setParameter(size_t mgSteps, size_t mgSmoothingSteps, size_t chebySteps, double relativeAccuracy)
1004// {
1005// mgA.setParameter(typename MGSolver::Parameter(mgSteps,mgSmoothingSteps,relativeAccuracy));
1006// mgAt.setParameter(typename MGSolver::Parameter(mgSteps,mgSmoothingSteps,relativeAccuracy));
1007// cheb.setSteps(chebySteps);
1008// }
1009
1010// virtual void pre(typename Traits::Domain&, typename Traits::Range&){}
1011// virtual void post(typename Traits::Domain&){}
1012
1013// virtual void apply(typename Traits::Domain& x, typename Traits::Range const& y)
1014// {
1015// using namespace boost::fusion;
1016// typename Traits::VectorY rhsY(at_c<Traits::yIdx>(y.data));
1017// typename Traits::VectorP dp(at_c<Traits::pIdx>(y.data));
1018
1019// typename Traits::AnsatzVariableSetDescription::VariableSet tmpx(avar);
1020// typename Traits::TestVariableSetDescription::VariableSet tmpy(tvar);
1021// at_c<Traits::yIdx>(tmpy.data).coefficients() = at_c<0>(rhsY.data);
1022// mgAt.apply(at_c<Traits::pIdx>(tmpx.data).coefficients(),at_c<Traits::yIdx>(tmpy.data).coefficients());
1023// at_c<0>(dp.data) = at_c<Traits::pIdx>(tmpx.data).coefficients();
1024
1025// typename Traits::VectorU rhsU(at_c<Traits::uIdx>(y.data));
1026// typename Traits::VectorU du(rhsU);
1027// Bt.applyscaleadd(-1.0,dp,rhsU);
1028// cheb.apply(du,rhsU);
1029
1030// typename Traits::VectorP rhsP(at_c<Traits::pIdx>(y.data));
1031// typename Traits::VectorY dy(at_c<Traits::yIdx>(y.data));
1032// B.applyscaleadd(-1.0,du,rhsP);
1033
1034// at_c<Traits::pIdx>(tmpy.data).coefficients() = at_c<0>(rhsP.data);
1035// mgA.apply(at_c<Traits::yIdx>(tmpx.data).coefficients(),at_c<Traits::pIdx>(tmpy.data).coefficients());
1036// at_c<0>(dy.data) = at_c<Traits::yIdx>(tmpx.data).coefficients();
1037
1038// at_c<Traits::yIdx>(x.data) = at_c<0>(dy.data);
1039// at_c<Traits::uIdx>(x.data) = at_c<0>(du.data);
1040// at_c<Traits::pIdx>(x.data) = at_c<0>(dp.data);
1041// }
1042
1043// void applyStatePreconditioner(typename Traits::VectorY& x, typename Traits::VectorP const& y)
1044// {
1045// using namespace boost::fusion;
1046// typename Traits::AnsatzVariableSetDescription::VariableSet tmpx(avar);
1047// typename Traits::TestVariableSetDescription::VariableSet tmpy(tvar);
1048// at_c<Traits::pIdx>(tmpy.data).coefficients() = at_c<0>(y.data);
1049// mgA.apply(at_c<Traits::yIdx>(tmpx.data).coefficients(),at_c<Traits::pIdx>(tmpy.data).coefficients());
1050// at_c<0>(x.data) = at_c<Traits::yIdx>(tmpx.data).coefficients();
1051// }
1052
1053// void applyAdjointPreconditioner(typename Traits::VectorP& x, typename Traits::VectorY const& y)
1054// {
1055// using namespace boost::fusion;
1056// typename Traits::AnsatzVariableSetDescription::VariableSet tmpx(avar);
1057// typename Traits::TestVariableSetDescription::VariableSet tmpy(tvar);
1058// at_c<Traits::yIdx>(tmpy.data).coefficients() = at_c<0>(y.data);
1059// mgAt.apply(at_c<Traits::pIdx>(tmpx.data).coefficients(),at_c<Traits::yIdx>(tmpy.data).coefficients());
1060// at_c<0>(x.data) = at_c<Traits::pIdx>(tmpx.data).coefficients();
1061// }
1062
1063// private:
1064// typename Traits::AdjointOperator At;
1065// typename Traits::NormUOperator Mu;
1066// typename Traits::ControlOperatorT Bt;
1067// typename Traits::ControlOperator B;
1068// typename Traits::StateOperator A;
1069
1070// ChebyshevPreconditioner<typename Traits::NormUOperator> cheb;
1071// MGSolver mgA, mgAt;
1072// AnsatzVariableSetDesc avar;
1073// TestVariableSetDesc tvar;
1074// };
1075
1076
1077 template <class Functional, class Assembler, int components>
1078 class NormalStepPreconditioner3 : public Dune::Preconditioner<typename OptimalControlTraits<Functional,Assembler>::Domain, typename OptimalControlTraits<Functional,Assembler>::Range>
1079 {
1080 typedef typename Assembler::Scalar Scalar;
1081 typedef OptimalControlTraits<Functional,Assembler> Traits;
1082 typedef typename Assembler::Grid Grid;
1084 typedef typename Functional::AnsatzVars AnsatzVariableSetDesc;
1085 typedef typename Functional::TestVars TestVariableSetDesc;
1086 static constexpr int dim = Functional::dim;
1087
1088 public:
1089 NormalStepPreconditioner3(Assembler const& assembler, AnsatzVariableSetDesc const& ansatzVars, TestVariableSetDesc const& testVars,
1090 size_t mgSteps = 500, size_t mgSmoothingSteps = 10, size_t chebySteps = 20, double relativeAccuracy = 1e-6, bool onlyLowerTriangle=false)
1091 :
1092 Mu(assembler,onlyLowerTriangle), B(assembler,onlyLowerTriangle), Bt(B), A(assembler,onlyLowerTriangle),
1093 cheb(Mu,chebySteps),
1094 mgA( A, boost::fusion::at_c<0>(assembler.spaces())->gridManager().grid(), typename MGSolver::Parameter(mgSteps,mgSmoothingSteps,relativeAccuracy) ),
1095 mgAt( A, boost::fusion::at_c<0>(assembler.spaces())->gridManager().grid(), typename MGSolver::Parameter(mgSteps,mgSmoothingSteps,relativeAccuracy), true ),
1096 avar(ansatzVars), tvar(testVars)
1097 {
1099 }
1100
1102
1103 void setParameter(size_t mgSteps, size_t mgSmoothingSteps, size_t chebySteps, double relativeAccuracy)
1104 {
1105 mgA.setParameter(typename MGSolver::Parameter(mgSteps,mgSmoothingSteps,relativeAccuracy));
1106 mgAt.setParameter(typename MGSolver::Parameter(mgSteps,mgSmoothingSteps,relativeAccuracy));
1107 cheb.setSteps(chebySteps);
1108 }
1109
1110 virtual void pre(typename Traits::Domain&, typename Traits::Range&){}
1111 virtual void post(typename Traits::Domain&){}
1112
1113 virtual void apply(typename Traits::Domain& x, typename Traits::Range const& y)
1114 {
1115 using namespace boost::fusion;
1116 typename Traits::VectorY rhsY(at_c<Traits::yIdx>(y.data));
1117 typename Traits::VectorP dp(at_c<Traits::pIdx>(y.data));
1118
1119 typename Traits::AnsatzVariableSetDescription::VariableSet tmpx(avar);
1120 typename Traits::TestVariableSetDescription::VariableSet tmpy(tvar);
1121 at_c<Traits::yIdx>(tmpy.data).coefficients() = at_c<0>(rhsY.data);
1122 mgAt.apply(at_c<Traits::pIdx>(tmpx.data).coefficients(),at_c<Traits::yIdx>(tmpy.data).coefficients());
1123 at_c<0>(dp.data) = at_c<Traits::pIdx>(tmpx.data).coefficients();
1124
1125 typename Traits::VectorU rhsU(at_c<Traits::uIdx>(y.data));
1126 typename Traits::VectorU du(rhsU);
1127 Bt.applyscaleadd(-1.0,dp,rhsU);
1128 cheb.apply(du,rhsU);
1129
1130 typename Traits::VectorP rhsP(at_c<Traits::pIdx>(y.data));
1131 typename Traits::VectorY dy(at_c<Traits::yIdx>(y.data));
1132 B.applyscaleadd(-1.0,du,rhsP);
1133
1134 at_c<Traits::pIdx>(tmpy.data).coefficients() = at_c<0>(rhsP.data);
1135 mgA.apply(at_c<Traits::yIdx>(tmpx.data).coefficients(),at_c<Traits::pIdx>(tmpy.data).coefficients());
1136 at_c<0>(dy.data) = at_c<Traits::yIdx>(tmpx.data).coefficients();
1137
1138 at_c<Traits::yIdx>(x.data) = at_c<0>(dy.data);
1139 at_c<Traits::uIdx>(x.data) = at_c<0>(du.data);
1140 at_c<Traits::pIdx>(x.data) = at_c<0>(dp.data);
1141 }
1142
1143 void applyStatePreconditioner(typename Traits::VectorY& x, typename Traits::VectorP const& y)
1144 {
1145 using namespace boost::fusion;
1146 typename Traits::AnsatzVariableSetDescription::VariableSet tmpx(avar);
1147 typename Traits::TestVariableSetDescription::VariableSet tmpy(tvar);
1148 at_c<Traits::pIdx>(tmpy.data).coefficients() = at_c<0>(y.data);
1149 mgA.apply(at_c<Traits::yIdx>(tmpx.data).coefficients(),at_c<Traits::pIdx>(tmpy.data).coefficients());
1150 at_c<0>(x.data) = at_c<Traits::yIdx>(tmpx.data).coefficients();
1151 }
1152
1153 void applyAdjointPreconditioner(typename Traits::VectorP& x, typename Traits::VectorY const& y)
1154 {
1155 using namespace boost::fusion;
1156 typename Traits::AnsatzVariableSetDescription::VariableSet tmpx(avar);
1157 typename Traits::TestVariableSetDescription::VariableSet tmpy(tvar);
1158 at_c<Traits::yIdx>(tmpy.data).coefficients() = at_c<0>(y.data);
1159 mgAt.apply(at_c<Traits::pIdx>(tmpx.data).coefficients(),at_c<Traits::yIdx>(tmpy.data).coefficients());
1160 at_c<0>(x.data) = at_c<Traits::pIdx>(tmpx.data).coefficients();
1161 }
1162
1163 private:
1164 typename Traits::NormUOperator Mu;
1165 typename Traits::ControlOperator B;
1167 typename Traits::StateOperator A;
1168
1170 MGSolver mgA, mgAt;
1171 AnsatzVariableSetDesc avar;
1172 TestVariableSetDesc tvar;
1173 };
1174
1175 template <class Functional, class Assembler, int components, bool exactConstraint>
1176 class InexactTangentSpacePreconditioner : public Dune::Preconditioner<typename OptimalControlTraits<Functional,Assembler>::Domain, typename OptimalControlTraits<Functional,Assembler>::Range>
1177 {
1178 typedef typename Assembler::Scalar Scalar;
1179 typedef OptimalControlTraits<Functional,Assembler> Traits;
1180 typedef typename Assembler::Grid Grid;
1181 static constexpr int dim = Functional::dim;
1183 typedef Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,components,components> > BCRSMat;
1184 typedef typename Functional::AnsatzVars AnsatzVariableSetDesc;
1185 typedef typename Functional::TestVars TestVariableSetDesc;
1186 typedef MatrixRepresentedOperator< MatrixAsTriplet<double>, typename Traits::VectorP, typename Traits::VectorY > AdjointOperator;
1187
1188 public:
1189 InexactTangentSpacePreconditioner(Assembler const& assembler, AnsatzVariableSetDesc aDesc, TestVariableSetDesc tdesc, size_t mgSteps = 10, size_t mgSmoothingSteps = 10, size_t chebySteps = 10, bool onlyLowerTriangle=false)
1190 : grid(boost::fusion::at_c<0>(assembler.spaces())->gridManager().grid()),
1191 Mu(assembler,onlyLowerTriangle),
1192 B(assembler,onlyLowerTriangle),
1193 A(assembler,onlyLowerTriangle),
1194 At(assembler,onlyLowerTriangle),
1195 cheb(Mu,chebySteps),
1196 mgA( A, grid, typename MGPreconditioner::Parameter(mgSteps,mgSmoothingSteps) ),
1197 mgAt( At, grid, typename MGPreconditioner::Parameter(mgSteps,mgSmoothingSteps) ),
1198 mgAExact(A,grid, typename MultiGridSolver<Grid,components>::Parameter(500,25,1e-9)),
1199 mgAtExact(At, grid, typename MultiGridSolver<Grid,components>::Parameter(500,25,1e-9)),
1200 ansatzDescription(aDesc), testDescription(tdesc)
1201 {
1202 timerA.stop(), timerAt.stop(), timerMu.stop(), timerB.stop(), timerCopy.stop();
1204 }
1205
1207
1208 virtual void pre(typename Traits::Domain&, typename Traits::Range&){}
1209 virtual void post(typename Traits::Domain&)
1210 {
1211 std::cout << "timer A : " << boost::timer::format(timerA.elapsed()) << std::endl;
1212 std::cout << "timer At: " << boost::timer::format(timerAt.elapsed()) << std::endl;
1213 std::cout << "timer Mu: " << boost::timer::format(timerMu.elapsed()) << std::endl;
1214 std::cout << "timer B : " << boost::timer::format(timerB.elapsed()) << std::endl;
1215 std::cout << "timer cp: " << boost::timer::format(timerCopy.elapsed()) << std::endl;
1216 }
1217
1218 virtual void apply(typename Traits::Domain& x, typename Traits::Range const& y)
1219 {
1220 using namespace boost::fusion;
1221 timerCopy.resume();
1222 std::cout << "inexact adjoint equation" << std::endl;
1223 std::cout << "read rhs1 " << std::endl;
1224 typename Traits::VectorY rhsY(at_c<Traits::yIdx>(y.data));
1225 std::cout << "init dp1" << std::endl;
1226 typename Traits::VectorP dp(at_c<Traits::pIdx>(y.data));
1227// std::cout << "read dp2" << std::endl;
1228// typename Functional::AnsatzVars::VariableSet mgAx(ansatzDescription);
1229// std::cout << "read rhs2" << std::endl;
1230// typename Functional::TestVars::VariableSet mgAy(testDescription);
1231// std::cout << "copy" << std::endl;
1232// at_c<Traits::yIdx>(mgAy.data).coefficients() = at_c<Traits::yIdx>(y.data);
1233 timerCopy.stop();
1234 timerAt.resume();
1235 std::cout << "solve" << std::endl;
1237// if( exactConstraint ) mgAtExact.apply( at_c<Traits::pIdx>(mgAx.data).coefficients(), at_c<Traits::yIdx>(mgAy.data).coefficients() );
1238// else mgAt.apply(at_c<Traits::pIdx>(mgAx.data).coefficients(), at_c<Traits::yIdx>(mgAy.data).coefficients());
1239 timerAt.stop();
1240 timerCopy.resume();
1241// std::cout << "copy" << std::endl;
1242// at_c<0>(dp.data) = at_c<Traits::pIdx>(mgAx.data).coefficients();
1243 // mgAt.apply(at_c<Traits::pIdx>(x.data),at_c<0>(rhsY.data));
1244
1245 std::cout << "control equation" << std::endl;
1246 typename Traits::VectorU rhsU(at_c<Traits::uIdx>(y.data));
1247 typename Traits::VectorU du(rhsU);
1248 timerCopy.stop();
1249 timerB.resume();
1250 B.applyscaleaddTransposed(-1.0,dp,rhsU);
1251 timerB.stop();
1252 timerMu.resume();
1253 cheb.apply(du,rhsU);
1254 timerMu.stop();
1255
1256 std::cout << "adjoint equation" << std::endl;
1257 timerCopy.resume();
1258 typename Traits::Range tmpY(y);
1259 typename Traits::VectorP rhsP(at_c<Traits::pIdx>(y.data));
1260 timerCopy.stop();
1261 timerB.resume();
1262 std::cout << "apply B" << std::endl;
1263 B.applyscaleadd(-1.0,du,rhsP);
1264 timerB.stop();
1265 timerCopy.resume();
1266 std::cout << "read dp2" << std::endl;
1267 typename Functional::AnsatzVars::VariableSet mgAx(ansatzDescription);
1268 std::cout << "read rhs2" << std::endl;
1269 typename Functional::TestVars::VariableSet mgAy(testDescription);
1270 at_c<Traits::pIdx>(tmpY.data) = at_c<0>(rhsP.data);
1271 at_c<Traits::pIdx>(mgAy.data) = at_c<0>(rhsP.data);
1272 timerCopy.stop();
1273 timerA.resume();
1274 std::cout << "invert A" << std::endl;
1275 if( exactConstraint ) mgAExact.apply(at_c<Traits::yIdx>(mgAx.data).coefficients(),at_c<Traits::pIdx>(mgAy.data).coefficients());
1276 else mgA.apply(at_c<Traits::yIdx>(mgAx.data).coefficients(),at_c<Traits::pIdx>(mgAy.data).coefficients());
1277 timerA.stop();
1278 timerCopy.resume();
1279 at_c<Traits::yIdx>(x.data) = at_c<Traits::yIdx>(mgAx.data).coefficients();
1280 at_c<Traits::uIdx>(x.data) = at_c<0>(du.data);
1281 at_c<Traits::pIdx>(x.data) = at_c<0>(dp.data);
1282 timerCopy.stop();
1283 }
1284
1285 void applyStatePreconditioner(typename Traits::VectorY& x, typename Traits::VectorP const& y)
1286 {
1287 std::cout << "apply state preconditioner" << std::endl;
1288 using namespace boost::fusion;
1289 typename Functional::AnsatzVars::VariableSet mgAx(ansatzDescription);
1290 typename Functional::TestVars::VariableSet mgAy(testDescription);
1291 at_c<Traits::pIdx>(mgAy.data) = at_c<0>(y.data);
1292 mgA.apply(at_c<Traits::yIdx>(mgAx.data).coefficients(),at_c<Traits::pIdx>(mgAy.data).coefficients());
1293 at_c<0>(x.data) = at_c<Traits::yIdx>(mgAx.data).coefficients();
1294 }
1295
1296 void applyAdjointPreconditioner(typename Traits::VectorP& x, typename Traits::VectorY const& y)
1297 {
1298 std::cout << "apply adjoint preconditioner" << std::endl;
1299 abort();
1300 // PAt->apply(x,y);
1301 }
1302
1303 private:
1304 Grid const& grid;
1305
1306 typename Traits::NormUOperator Mu;
1307 typename Traits::ControlOperator B;
1308 typename Traits::StateOperator A;
1309 typename Traits::AdjointOperator At;
1311 MGPreconditioner mgA, mgAt;
1312 MultiGridSolver<Grid,components> mgAExact, mgAtExact;
1313 AnsatzVariableSetDesc ansatzDescription;
1314 TestVariableSetDesc testDescription;
1315 boost::timer::cpu_timer timerA, timerAt, timerMu, timerB, timerCopy;
1316 };
1317
1318 template <class Functional, class Assembler, int components, bool exactConstraint>
1319 class InexactTangentSpacePreconditionerILU : public Dune::Preconditioner<typename OptimalControlTraits<Functional,Assembler>::Domain, typename OptimalControlTraits<Functional,Assembler>::Range>
1320 {
1321 typedef typename Assembler::Scalar Scalar;
1322 typedef OptimalControlTraits<Functional,Assembler> Traits;
1323 typedef typename Assembler::Grid Grid;
1324 static constexpr int dim = Functional::dim;
1326 typedef Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,components,components> > BCRSMat;
1327 typedef typename Functional::AnsatzVars AnsatzVariableSetDesc;
1328 typedef typename Functional::TestVars TestVariableSetDesc;
1329 typedef MatrixRepresentedOperator< MatrixAsTriplet<double>, typename Traits::VectorP, typename Traits::VectorY > AdjointOperator;
1330
1331 public:
1332 InexactTangentSpacePreconditionerILU(Assembler const& assembler, AnsatzVariableSetDesc const& aDesc, TestVariableSetDesc const& tdesc, size_t mgSteps = 10, size_t mgSmoothingSteps = 10, size_t chebySteps = 10, bool onlyLowerTriangle=false)
1333 : grid(boost::fusion::at_c<0>(assembler.spaces())->gridManager().grid()),
1334 Mu(assembler,onlyLowerTriangle),
1335 B(assembler,onlyLowerTriangle),
1336 A(assembler,onlyLowerTriangle),
1337 At(assembler,onlyLowerTriangle),
1338 cheb(Mu,chebySteps),
1339 mgA( A, grid, typename MGPreconditioner::Parameter(mgSteps,mgSmoothingSteps) ),
1340 mgAt( At, grid, typename MGPreconditioner::Parameter(mgSteps,mgSmoothingSteps) ),
1341 mgAExact(A,grid, typename MultiGridSolver<Grid,components>::Parameter(500,25,1e-9)),
1342 mgAtExact(At, grid, typename MultiGridSolver<Grid,components>::Parameter(500,25,1e-9)),
1343 ansatzDescription(aDesc), testDescription(tdesc)
1344 {
1345 timerA.stop(), timerAt.stop(), timerMu.stop(), timerB.stop(), timerCopy.stop();
1347 }
1348
1350
1351 virtual void pre(typename Traits::Domain&, typename Traits::Range&){}
1352 virtual void post(typename Traits::Domain&)
1353 {
1354 std::cout << "timer A : " << boost::timer::format(timerA.elapsed()) << std::endl;
1355 std::cout << "timer At: " << boost::timer::format(timerAt.elapsed()) << std::endl;
1356 std::cout << "timer Mu: " << boost::timer::format(timerMu.elapsed()) << std::endl;
1357 std::cout << "timer B : " << boost::timer::format(timerB.elapsed()) << std::endl;
1358 std::cout << "timer cp: " << boost::timer::format(timerCopy.elapsed()) << std::endl;
1359 }
1360
1361 virtual void apply(typename Traits::Domain& x, typename Traits::Range const& y)
1362 {
1363 using namespace boost::fusion;
1364 timerCopy.resume();
1365 typename Traits::VectorY rhsY(at_c<Traits::yIdx>(y.data));
1366 typename Traits::VectorP dp(at_c<Traits::pIdx>(y.data));
1367 typename Functional::AnsatzVars::VariableSet mgAx(ansatzDescription);
1368 typename Functional::TestVars::VariableSet mgAy(testDescription);
1369 at_c<Traits::yIdx>(mgAy.data) = at_c<Traits::yIdx>(y.data);
1370 timerCopy.stop();
1371 timerAt.resume();
1372 if( exactConstraint ) mgAtExact.apply( at_c<Traits::pIds>(mgAx.data).coefficients(), at_c<Traits::yIdx>(mgAy.data).coefficients() );
1373 else mgAt.apply(at_c<Traits::pIdx>(mgAx.data).coefficients(), at_c<Traits::yIdx>(mgAy.data).coefficients());
1374 timerAt.stop();
1375 timerCopy.resume();
1376 at_c<0>(dp.data) = at_c<Traits::pIdx>(mgAx.data).coefficients();
1377 // mgAt.apply(at_c<Traits::pIdx>(x.data),at_c<0>(rhsY.data));
1378
1379 typename Traits::VectorU rhsU(at_c<Traits::uIdx>(y.data));
1380 typename Traits::VectorU du(rhsU);
1381 timerCopy.stop();
1382 timerB.resume();
1383 B.applyscaleaddTransposed(-1.0,dp,rhsU);
1384 timerB.stop();
1385 timerMu.resume();
1386 cheb.apply(du,rhsU);
1387 timerMu.stop();
1388
1389 timerCopy.resume();
1390 typename Traits::Range tmpY(y);
1391 typename Traits::VectorP rhsP(at_c<Traits::pIdx>(y.data));
1392 timerCopy.stop();
1393 timerB.resume();
1394 B.applyscaleadd(-1.0,du,rhsP);
1395 timerB.stop();
1396 timerCopy.resume();
1397 at_c<Traits::pIdx>(tmpY.data) = at_c<0>(rhsP.data);
1398 at_c<Traits::pIdx>(mgAy.data) = at_c<0>(rhsP.data);
1399 timerCopy.stop();
1400 timerA.resume();
1401 if( exactConstraint ) mgAExact.apply(at_c<Traits::yIdx>(mgAx.data).coefficients(),at_c<Traits::pIdx>(mgAy.data).coefficients());
1402 else mgA.apply(at_c<Traits::yIdx>(mgAx.data).coefficients(),at_c<Traits::pIdx>(mgAy.data).coefficients());
1403 timerA.stop();
1404 timerCopy.resume();
1405 at_c<Traits::yIdx>(x.data) = at_c<Traits::yIdx>(mgAx.data).coefficients();
1406 at_c<Traits::uIdx>(x.data) = at_c<0>(du.data);
1407 at_c<Traits::pIdx>(x.data) = at_c<0>(dp.data);
1408 timerCopy.stop();
1409 }
1410
1411 void applyStatePreconditioner(typename Traits::VectorY& x, typename Traits::VectorP const& y)
1412 {
1413 using namespace boost::fusion;
1414 typename Functional::AnsatzVars::VariableSet mgAx(ansatzDescription);
1415 typename Functional::TestVars::VariableSet mgAy(testDescription);
1416 at_c<Traits::pIdx>(mgAy.data) = at_c<0>(y.data);
1417 mgA.apply(at_c<Traits::yIdx>(mgAx.data).coefficients(),at_c<Traits::pIdx>(mgAy.data).coefficients());
1418 at_c<0>(x.data) = at_c<Traits::yIdx>(mgAx.data).coefficients();
1419 }
1420
1421 void applyAdjointPreconditioner(typename Traits::VectorP& x, typename Traits::VectorY const& y)
1422 {
1423 // PAt->apply(x,y);
1424 }
1425
1426 private:
1427 Grid const& grid;
1428
1429 typename Traits::NormUOperator Mu;
1430 typename Traits::ControlOperator B;
1431 typename Traits::StateOperator A;
1432 typename Traits::AdjointOperator At;
1434 MGPreconditioner mgA, mgAt;
1435 MultiGridSolver<Grid,components> mgAExact, mgAtExact;
1436 AnsatzVariableSetDesc const& ansatzDescription;
1437 TestVariableSetDesc const& testDescription;
1438 boost::timer::cpu_timer timerA, timerAt, timerMu, timerB, timerCopy;
1439 };
1440// template <class PreconditionerFactory_, class PDEPreconditionerFactory, class VariableSet>
1441// class OptimalControlNormalSolver : public AbstractNormalDirection, public Dune::Preconditioner<typename PreconditionerFactory_::Operator::Domain,typename PreconditionerFactory_::Operator::Range>
1442// {
1443// public:
1444
1445// typedef typename PreconditionerFactory_::Operator::Assembler Assembler;
1446// typedef typename PreconditionerFactory_::Operator::Domain Domain;
1447// typedef typename PreconditionerFactory_::Operator::Range Range;
1448// // typedef typename VariableSet::Descriptions::template CoefficientVectorRepresentation<>::type Domain;
1449// // typedef Domain Range;
1450// typedef typename Assembler::Functional::Functional Functional;
1451// typedef Bridge::ConnectedKaskadeLinearization<Functional> BridgeLinearization;
1452
1453// static constexpr int yIdx = Functional::yIdx;
1454// static constexpr int uIdx = Functional::uIdx;
1455// static constexpr int pIdx = Functional::lIdx;
1456// typedef AssembledGalerkinOperator<Assembler,pIdx,pIdx+1,yIdx,yIdx+1> StateOperator;
1457// typedef AssembledGalerkinOperator<Assembler,pIdx,pIdx+1,uIdx,uIdx+1> ControlOperator;
1458// typedef AssembledGalerkinOperator<Assembler,yIdx,yIdx+1,pIdx,pIdx+1> AdjointOperator;
1459// typedef AssembledGalerkinOperator<Assembler,uIdx,uIdx+1,uIdx,uIdx+1> NormUOperator;
1460// typedef AssembledGalerkinOperator<Assembler,yIdx,yIdx+1,yIdx,yIdx+1> NormYOperator;
1461// typedef AssembledGalerkinOperator<Assembler,uIdx,uIdx+1,pIdx,pIdx+1> ControlOperatorT;
1462// typedef typename VariableSet::Descriptions::template CoefficientVectorRepresentation<yIdx,yIdx+1> CreateVectorY;
1463// typedef typename CreateVectorY::type VectorY;
1464// typedef typename VariableSet::Descriptions::template CoefficientVectorRepresentation<uIdx,uIdx+1> CreateVectorU;
1465// typedef typename CreateVectorU::type VectorU;
1466// typedef typename VariableSet::Descriptions::template CoefficientVectorRepresentation<pIdx,pIdx+1> CreateVectorP;
1467// typedef typename CreateVectorP::type VectorP;
1468
1469// typedef PreconditionerFactory<Assembler,VectorU,VectorU,double> UPrecondFactory;
1470// typedef PreconditionerFactory<Assembler,VectorP,VectorY,double> AdjointPrecondFactory;
1471// typedef PreconditionerFactory<Assembler,VectorY,VectorP,double> PDEPrecondFactory;
1472
1473// virtual ~OptimalControlNormalSolver() {}
1474
1475// OptimalControlNormalSolver(PreconditionerFactory_& prec_, PDEPreconditionerFactory& pdePrec_)
1476// : A(nullptr), preconditioner(nullptr), tolerance(1e-6), maxSteps(100)
1477// {}
1478
1479// virtual void pre(Domain &x, Range &b) {}
1480// virtual void post (Domain &x) {}
1481
1482// virtual void apply(Domain &x, Range const& y)
1483// {
1484// preconditioner->apply(x,y);
1485// }
1486
1487// private:
1488// void solveAdjointEquation(AbstractFunctionSpaceElement& adjointCorrection, VariableSet const& variableSet) const
1489// {
1490// using namespace boost::fusion;
1491// VectorY adjointRhs(CreateVectorY::init(variableSet.descriptions));
1492// at_c<0>(adjointRhs.data) = at_c<yIdx>(variableSet.data).coefficients();
1493// VectorP adjointSolution(CreateVectorP::init(variableSet.descriptions));
1494
1495// preconditioner->applyAdjointPreconditioner(adjointSolution,adjointRhs);
1496// adjointSolution *= -1.0;
1497
1498// VariableSet& adj=Bridge::getImpl<VariableSet>(adjointCorrection);
1499// at_c<pIdx>(adj.data).coefficients() = at_c<0>(adjointSolution.data);
1500// }
1501
1502// void solveSystem(AbstractFunctionSpaceElement& correction, VariableSet const& variableSet) const
1503// {
1504// using namespace boost::fusion;
1505
1506// Domain x(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(variableSet.descriptions));
1507// x *= 0.0;
1508// Range y(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(variableSet.descriptions));
1509// y = variableSet;
1510
1511// // compute initial iterate
1512// VectorY tmpY(CreateVectorY::init(variableSet.descriptions));
1513// VectorP tmpRhs(CreateVectorP::init(variableSet.descriptions));
1514// at_c<0>(tmpRhs.data) = at_c<pIdx>(y.data);
1515// preconditioner->applyStatePreconditioner(tmpY,tmpRhs);
1516// at_c<yIdx>(x.data) = at_c<0>(tmpY.data);
1517
1518// // compute dn
1519// DefaultDualPairing<Domain,Range> dualpairing;
1520// Dune::InverseOperatorResult res;
1521// TPCG<Domain,Range> tpcg(*A, *preconditioner, dualpairing, tolerance, maxSteps, 1);
1522// tpcg.apply(x,y,res);
1523// // directInverseOperator(*A,DirectType::UMFPACK3264,MatrixProperties::GENERAL).apply(y,x);
1524
1525
1526// VariableSet& cor=Bridge::getImpl<VariableSet>(correction);
1527// cor = x;
1528// cor *= -1.0;
1529// }
1530
1531// virtual void computeCorrectionAndAdjointCorrection(AbstractFunctionSpaceElement& correction, AbstractFunctionSpaceElement& adjointCorrection, AbstractLinearization& linearization)
1532// {
1533// using namespace boost::fusion;
1534
1535// Assembler& assembler = dynamic_cast<BridgeLinearization&>(linearization).getValidAssembler();
1536// boost::timer::cpu_timer timer1;
1537// preconditioner.reset(new NormalStepPreconditioner<Functional,Assembler>(assembler));
1538// std::cout << "preconditioner reset: " << boost::timer::format(timer1.elapsed());
1539// boost::timer::cpu_timer timer2;
1540// A.reset(new AssembledGalerkinOperator<Assembler>(assembler));
1541// std::cout << "A reset: " << boost::timer::format(timer2.elapsed());
1542
1543// std::unique_ptr<AbstractFunctionSpaceElement> combinedrhs(correction.clone()), derivativerhs(correction.clone()), constraintrhs(correction.clone());
1544// *derivativerhs *= 0.0;
1545// *constraintrhs *= 0.0;
1546// linearization.evald(*combinedrhs);
1547// derivativerhs->axpy(1.0,*combinedrhs,"primal");
1548// constraintrhs->axpy(1.0,*combinedrhs,"dual");
1549
1550// // compute dy_n
1551//#ifdef TESTOUTPUT
1552// boost::timer::cpu_timer systemTimer;
1553//#endif
1554// solveSystem(correction, Bridge::getImpl<VariableSet>(*constraintrhs));
1555//#ifdef TESTOUTPUT
1556// std::cout << "computation of normal step: " << boost::timer::format(systemTimer.elapsed());
1557// boost::timer::cpu_timer adjointTimer;
1558//#endif
1559// // compute dp
1560// solveAdjointEquation(adjointCorrection, Bridge::getImpl<VariableSet>(*derivativerhs));
1561//#ifdef TESTOUTPUT
1562// std::cout << "computation of adjoint variable: " << boost::timer::format(adjointTimer.elapsed());
1563//#endif
1564// }
1565
1566
1567// virtual void computeSimplifiedCorrection(AbstractFunctionSpaceElement& correction,
1568// AbstractLinearization const& lin) const
1569// {
1570//#ifdef TESTOUTPUT
1571// boost::timer::cpu_timer timer;
1572//#endif
1573// std::unique_ptr<AbstractFunctionSpaceElement> combinedrhs(correction.clone()), constraintrhs(correction.clone());
1574// *constraintrhs *= 0.0;
1575// lin.evald(*combinedrhs);
1576// constraintrhs->axpy(1.0,*combinedrhs,"dual");
1577
1578// solveSystem(correction,Bridge::getImpl<VariableSet>(*constraintrhs));
1579//#ifdef TESTOUTPUT
1580// std::cout << "computation of simplified normal step: " << boost::timer::format(timer.elapsed());
1581//#endif
1582// }
1583
1584// std::unique_ptr<AssembledGalerkinOperator<Assembler> > A;
1585// std::unique_ptr<NormalStepPreconditioner<Functional,Assembler> > preconditioner;
1586// double tolerance;
1587// size_t maxSteps;
1588// };
1589
1590
1591// template <class Operator, class VariableSet>
1592// class CGasNormalSolver : public AbstractNormalDirection, public Dune::Preconditioner<typename Operator::Domain,typename Operator::Range>
1593// {
1594// public:
1595
1596// typedef typename Operator::Assembler Assembler;
1597// typedef typename Assembler::Functional::Functional Functional;
1598// typedef typename Operator::Domain Domain;
1599// typedef typename Operator::Range Range;
1600// typedef typename Operator::Scalar Scalar;
1601// typedef Bridge::ConnectedKaskadeLinearization<typename Assembler::Functional::Functional> BridgeLinearization;
1602
1603// virtual ~CGasNormalSolver() {}
1604
1605// CGasNormalSolver(Scalar accuracy_, int maxSteps_, int verbose_=0)
1606// : P(nullptr), P2(nullptr), accuracy(accuracy_), maxSteps(maxSteps_), verbose(verbose_)
1607// {}
1608
1609// // CGasNormalSolver(Dune::Preconditioner<Domain,Range>& preconditioner, Scalar accuracy_, int maxSteps_, int verbose_=0)
1610// // : P(&preconditioner), accuracy(accuracy_), maxSteps(maxSteps_), verbose(verbose_)
1611// // {}
1612// //
1613// // void setPreconditioner(Dune::Preconditioner<Domain,Range>& preconditioner)
1614// // {
1615// // P = &preconditioner;
1616// // }
1617
1618// virtual void pre(Domain &x, Range &b) {}
1619// virtual void apply (Domain &v, const Range &d)
1620// {
1621// P2->apply(v,d);
1622// }
1623// virtual void post (Domain &x) {}
1624
1625// private:
1626
1627// virtual void computeCorrectionAndAdjointCorrection(AbstractFunctionSpaceElement& correction, AbstractFunctionSpaceElement& adjointCorrection, AbstractLinearization& linearization)
1628// {
1629// /// ToDo: ???????????
1630// A.reset(new AssembledGalerkinOperator<Assembler>(dynamic_cast<BridgeLinearization&>(linearization).getValidAssembler()));
1631
1632// //P.reset(prec.create(*A).release());
1633// P.reset(new NormalStepPreconditioner<Functional,Assembler>(dynamic_cast<BridgeLinearization&>(linearization).getValidAssembler()));
1634// P2.reset(new InexactTangentSpacePreconditioner<Functional,Assembler>(dynamic_cast<BridgeLinearization&>(linearization).getValidAssembler()));
1635// std::unique_ptr<AbstractFunctionSpaceElement> combinedrhs(correction.clone());
1636// std::unique_ptr<AbstractFunctionSpaceElement> derivativerhs(correction.clone());
1637// std::unique_ptr<AbstractFunctionSpaceElement> constraintrhs(correction.clone());
1638// *derivativerhs *= 0.0;
1639// *constraintrhs *= 0.0;
1640// linearization.evald(*combinedrhs);
1641// derivativerhs->axpy(1.0,*combinedrhs,"primal");
1642// constraintrhs->axpy(1.0,*combinedrhs,"dual");
1643// VariableSet& derrhs=Bridge::getImpl<VariableSet>(*derivativerhs);
1644// VariableSet& conrhs=Bridge::getImpl<VariableSet>(*constraintrhs);
1645// Domain x(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(derrhs.descriptions));
1646// x *= 0.0;
1647
1648// Range y(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(derrhs.descriptions));
1649// y = derrhs;
1650
1651// DefaultDualPairing<Domain,Range> dualpairing;
1652// TPCG<Domain,Range> tpcg(*A, *P, dualpairing, accuracy, maxSteps, verbose);
1653// Dune::InverseOperatorResult res;
1654
1655// tpcg.apply(x,y,res);
1656
1657// VariableSet& adj=Bridge::getImpl<VariableSet>(adjointCorrection);
1658// adj = x;
1659// adj *= -1.0;
1660
1661// y = conrhs;
1662
1663// tpcg.apply(x,y,res);
1664
1665
1666// VariableSet& cor=Bridge::getImpl<VariableSet>(correction);
1667// cor = x;
1668// cor *= -1.0;
1669// }
1670
1671
1672// virtual void computeSimplifiedCorrection(AbstractFunctionSpaceElement& correction,
1673// AbstractLinearization const& lin) const
1674// {
1675// /// ToDo:
1676// std::unique_ptr<AbstractFunctionSpaceElement> combinedrhs(correction.clone());
1677// std::unique_ptr<AbstractFunctionSpaceElement> constraintrhs(correction.clone());
1678// *constraintrhs *= 0.0;
1679// lin.evald(*combinedrhs);
1680// constraintrhs->axpy(1.0,*combinedrhs,"dual");
1681// VariableSet& conrhs=Bridge::getImpl<VariableSet>(*constraintrhs);
1682
1683// Domain x(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(conrhs.descriptions));
1684// x *= 0.0;
1685// Range y(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(conrhs.descriptions));
1686
1687// y=conrhs;
1688
1689// DefaultDualPairing<Domain,Range> dualpairing;
1690// TPCG<Domain,Range> tpcg(*A, *P, dualpairing, accuracy, maxSteps, verbose);
1691// Dune::InverseOperatorResult res;
1692
1693// tpcg.apply(x,y,res);
1694
1695// VariableSet& cor=Bridge::getImpl<VariableSet>(correction);
1696// cor = x;
1697// cor *= -1.0;
1698// }
1699
1700// Scalar accuracy;
1701// int maxSteps, verbose;
1702// std::unique_ptr<Dune::Preconditioner<Domain,Range> > P;
1703// std::unique_ptr<InexactTangentSpacePreconditioner<Functional,Assembler> > P2;
1704// // std::unique_ptr<Dune::Preconditioner<Domain,Range> > P;
1705// std::unique_ptr<AssembledGalerkinOperator<Assembler> > A;
1706// };
1707
1708 template <class> class ProjectionOnTangentSpace;
1709 template <class,int,int,int,int> class MGProjectionOnTangentSpace;
1710
1711 template <class FSE, class CoeffVector, int rbegin, int rend>
1713 {
1714 static void apply(FSE const& fse, CoeffVector& v)
1715 {
1716 boost::fusion::at_c<rbegin>(v.data) = boost::fusion::at_c<rbegin>(fse.data).coefficients();
1718 }
1719 };
1720
1721 template <class FSE, class CoeffVector, int rbegin>
1722 struct CopyFromFunctionSpaceElement<FSE,CoeffVector,rbegin,rbegin>
1723 {
1724 static void apply(FSE const&, CoeffVector&) {}
1725 };
1726
1727 template <class FSE, class CoeffVector, int rbegin, int rend>
1729 {
1730 static void apply(CoeffVector const& v, FSE& fse)
1731 {
1732 boost::fusion::at_c<rbegin>(fse.data).coefficients() += boost::fusion::at_c<rbegin>(v.data);
1734 }
1735 };
1736
1737 template <class FSE, class CoeffVector, int rbegin>
1738 struct AddToFunctionSpaceElement<FSE,CoeffVector,rbegin,rbegin>
1739 {
1740 static void apply(CoeffVector const&, FSE&) {}
1741 };
1742
1743 template<int rbegin, int rend, class FSE, class CoeffVector>
1744 void copyFromFunctionSpaceElement(FSE const& fse, CoeffVector& coeffVector)
1745 {
1747 }
1748
1749 template<int rbegin, int rend, class FSE, class CoeffVector>
1750 void addToFunctionSpaceElement(CoeffVector const& coeffVector,FSE& fse)
1751 {
1753 }
1754
1755 template <class Assembler, class Lin, int rbegin, int rend, int cbegin, int cend>
1757 {
1758 static_assert(cbegin<=cend,"incompatible template arguments");
1759 static_assert(rbegin<=rend,"incompatible template arguments");
1760 typedef typename Assembler::Functional::Functional Functional;
1761 boost::timer::cpu_timer t1;
1762 AssembledGalerkinOperator<Assembler,rbegin,rend,cbegin,cend> gop(dynamic_cast<Bridge::ConnectedKaskadeLinearization<Functional>&>(lin.getTangentialLinearization()).getValidAssembler());
1763 std::cout << "gop init: " << boost::timer::format(t1.elapsed()) << std::endl;
1764 boost::timer::cpu_timer t2;
1765 typename Functional::AnsatzVars::template CoefficientVectorRepresentation<rbegin,rend>::type tmpy
1766 (Functional::AnsatzVars::template CoefficientVectorRepresentation<rbegin,rend>::init(dynamic_cast<Bridge::Vector<typename Functional::AnsatzVars::VariableSet> const& >(x).get().descriptions));
1767 typename Functional::TestVars::template CoefficientVectorRepresentation<cbegin,cend>::type tmpx
1768 (Functional::TestVars::template CoefficientVectorRepresentation<cbegin,cend>::init(dynamic_cast<Bridge::Vector<typename Functional::AnsatzVars::VariableSet> const& >(x).get().descriptions));
1769 std::cout << "init vecs: " << boost::timer::format(t2.elapsed()) << std::endl;
1770 boost::timer::cpu_timer t3;
1771 auto const& tx = dynamic_cast<Bridge::Vector<typename Functional::AnsatzVars::VariableSet> const& >(x).get();
1772 copyFromFunctionSpaceElement<cbegin,cend>(tx,tmpx);
1773 std::cout << "copy1: " << boost::timer::format(t3.elapsed()) << std::endl;
1774 // boost::fusion::at_c<0>(tmpx.data) = boost::fusion::at_c<0>(dynamic_cast<Bridge::Vector<typename Functional::AnsatzVars::VariableSet> const& >(x).get().data).coefficients();
1775// boost::fusion::at_c<1>(tmpx.data) = boost::fusion::at_c<1>(dynamic_cast<Bridge::Vector<typename Functional::AnsatzVars::VariableSet> const& >(x).get().data).coefficients();
1776 boost::timer::cpu_timer t4;
1777 gop.apply(tmpx,tmpy);
1778 std::cout << "gop apply: " << boost::timer::format(t4.elapsed()) << std::endl;
1779
1780 boost::timer::cpu_timer t5;
1781 auto& ty = dynamic_cast<Bridge::Vector<typename Functional::AnsatzVars::VariableSet>& >(y).get();
1782 addToFunctionSpaceElement<rbegin,rend>(tmpy,ty);
1783 std::cout << "copy2: " << boost::timer::format(t5.elapsed()) << std::endl;
1784 // boost::fusion::at_c<0>(dynamic_cast<Bridge::Vector<typename Functional::AnsatzVars::VariableSet>& >(y).get().data).coefficients() += boost::fusion::at_c<0>(tmpy.data);
1785// boost::fusion::at_c<1>(dynamic_cast<Bridge::Vector<typename Functional::AnsatzVars::VariableSet>& >(y).get().data).coefficients() += boost::fusion::at_c<1>(tmpy.data);
1786 }
1787
1788 template<class Assembler, class Preconditioner, class VariableSet, int components = 1, CGImplementationType cgImpl = CGImplementationType::HYBRID>
1790 {
1791 public:
1792 typedef typename Preconditioner::Domain Domain;
1793 typedef typename Preconditioner::Range Range;
1794 typedef typename Preconditioner::Assembler NormalStepAssembler;
1795 typedef OptimalControlTraits<typename Assembler::Functional::Functional,Assembler> Traits;
1796 typedef double Scalar;
1798 typedef typename Assembler::Functional::Functional Functional;
1799 static constexpr int yIdx = Traits::yIdx;
1800 static constexpr int uIdx = Traits::uIdx;
1801 static constexpr int pIdx = Traits::pIdx;
1805 typedef typename Assembler::Functional::Functional TF;
1806
1807 ProjectedAPCGSolver(Preconditioner& P_, Scalar accuracy_, int verbose_ = 0, size_t maxSteps_ = 500, double eps_ = 1e-12)
1808 : P(P_), accuracy(accuracy_), eps(eps_), verbose(verbose_), maxSteps(maxSteps_), terminationCriterion(new StrakosTichyEnergyErrorTerminationCriterion<double>(accuracy,maxSteps,eps))
1809 {}
1810
1812
1813 virtual void setRelativeAccuracy(double accuracy_) final
1814 {
1815 if(verbose > 0) std::cout << "TANGENTIAL SPACE: updating relative accuracy from " << accuracy << " to " << accuracy_ << std::endl;
1816 accuracy=accuracy_;
1817 }
1818
1819 void usePreconditionerForNorm() { terminationCriterion.reset(new StrakosTichyPTerminationCriterion<double>(accuracy,maxSteps,eps)); }
1820
1821 void setLookAHead(size_t d) { terminationCriterion->lookahead(d); }
1822
1823 virtual int nSolutionVectors() const final { return 2; }
1824 virtual bool localConvergenceLikely() final
1825 {
1826 return !encounteredNonConvexity;
1827 }
1828
1830 {
1831 return *localtmpvec;
1832 }
1833
1834 virtual void setEps(double eps_) { eps = eps_; }
1835
1836 virtual void setLipschitzConstant(double omega) { omegaL = omega; }
1837
1838 private:
1839 virtual int computeBasis(std::vector<std::shared_ptr<AbstractFunctionSpaceElement> >& correction,
1841 AbstractFunctionSpaceElement const& normalStep,
1842 double nu0, AbstractFunctionSpaceElement* residual)
1843 {
1844 using namespace boost::fusion;
1845
1846 auto& normalAssembler = dynamic_cast<NormalBridgeLinearization&>(lin.getNormalLinearization()).getValidAssembler();
1847 auto& tangentialAssembler = dynamic_cast<TangentialBridgeLinearization&>(lin.getTangentialLinearization()).getValidAssembler();
1848
1849 std::cout << "assemblers: normal: " << normalAssembler.nrows(0,1) << ", " << normalAssembler.nrows(1,2) << ", " << normalAssembler.nrows(2,3) << std::endl;
1850 std::cout << "assemblers: tangential: " << tangentialAssembler.nrows(0,1) << ", " << tangentialAssembler.nrows(1,2) << ", " << tangentialAssembler.nrows(2,3) << std::endl;
1851
1852 LagrangeOperator<NormalStepAssembler,Assembler,yIdx,uIdx,pIdx> M(normalAssembler,tangentialAssembler);
1853
1854
1855 Range rhs( dynamic_cast<NormalBridgeLinearization&>(lin.getNormalLinearization()).getValidAssembler().rhs() );
1856 at_c<pIdx>(rhs.data) *= 0.;
1857 VariableSet xv = Bridge::getImpl<VariableSet>(normalStep);
1858 at_c<pIdx>(xv.data) *= 0.;
1859 Domain x(xv);
1860// Domain x(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(xv.descriptions));
1861 M.applyscaleadd(nu0,x,rhs);
1862 x *= 0;
1863 at_c<pIdx>(rhs.data) *= 0.;
1864
1865/* std::unique_ptr<AbstractFunctionSpaceElement> combinedrhs(normalStep.clone());
1866 std::unique_ptr<AbstractFunctionSpaceElement> derivativerhs(normalStep.clone());
1867 *derivativerhs *= 0.0;
1868 std::cout << "begin computation of basis" << std::endl;
1869 boost::timer::cpu_timer evalTimer;
1870 // derivativerhs = L_x(x_0,p_0)+nu_0 L_xx(x_0,p_0)dn
1871 lin.evald(*combinedrhs);
1872 std::cout << "evalTimer: " << boost::timer::format(evalTimer.elapsed()) << std::endl;
1873 boost::timer::cpu_timer evalTimer2;
1874 derivativerhs->axpy(1.0,*combinedrhs,"primal");
1875 std::cout << "evalTimer2: " << boost::timer::format(evalTimer2.elapsed()) << std::endl;
1876 *combinedrhs *= 0.0;
1877 boost::timer::cpu_timer evalTimer3;
1878 ddxpy_template<Assembler,LagrangeLinearization,0,2,0,2>(lin,*combinedrhs,normalStep);
1879// lin.ddxpy(*combinedrhs,normalStep,0,2,0,2);
1880 std::cout << "evalTimer3: " << boost::timer::format(evalTimer3.elapsed()) << std::endl;
1881 boost::timer::cpu_timer evalTimer4;
1882 derivativerhs->axpy(nu0,*combinedrhs,"primal");
1883 std::cout << "evalTimer4: " << boost::timer::format(evalTimer4.elapsed()) << std::endl;
1884 VariableSet& derrhs=Bridge::getImpl<VariableSet>(*derivativerhs);
1885 Domain x(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(derrhs.descriptions));*/
1886
1888
1889/* MatrixAsTriplet<double> mat;
1890 lin.getNormalLinearization().getMatrixBlocks(mat);
1891 typedef typename VariableSet::Descriptions::template CoefficientVectorRepresentation<>::type Vec;
1892 MatrixRepresentedOperator<MatrixAsTriplet<double>, Vec, Vec> PP(mat);
1893 AlwaysRegularizeWithThetaGuess<MatrixRepresentedOperator<MatrixAsTriplet<double>, Vec, Vec>,Vec> f(PP,getImpl<Vec>(normalStep),nu0,omegaL);*/
1894 Solver solver(M, P, dualpairing, *terminationCriterion, verbose, eps);
1895 Dune::InverseOperatorResult res;
1896// Range y(VariableSet::Descriptions::template CoefficientVectorRepresentation<>::init(derrhs.descriptions));
1897// y=derrhs;
1898 solver.apply(x, rhs, res);
1899 encounteredNonConvexity = solver.encounteredNonConvexity();
1900
1901/* if(residual != nullptr)
1902 {
1903 y = derrhs;
1904 M.applyscaleadd(-1.0,x,y);
1905 derrhs = y;
1906 Bridge::getImpl<VariableSet>(*residual) = derrhs;
1907 }*/
1908
1909
1910 VariableSet& cor=Bridge::getImpl<VariableSet>(*(correction[0]));
1911 cor = x;
1912 cor *= -1.0;
1913
1914 // project on tangent space
1915// if(solver.getSolutionEnergyNormEstimate() > eps)
1916// {
1917// projection.reset(new Projection (dynamic_cast<NormalBridgeLinearization&>(lin.getNormalLinearization()).getValidAssembler()));
1918// projection->apply(cor);
1919// }
1920
1921 return 1;
1922 }
1923
1924 Preconditioner& P;
1925 double accuracy, eps;
1926 int verbose;
1927 std::unique_ptr<AbstractFunctionSpaceElement> localtmpvec;
1928 std::unique_ptr<Projection> projection;
1929 size_t maxSteps;
1930 bool encounteredNonConvexity = false;
1931 std::unique_ptr<PCGTerminationCriterion<double> > terminationCriterion;
1932 double omegaL;
1933 };
1934
1936 {
1937 template <class Arg>
1938 void projectOnConstraint(Arg&) const {}
1939 };
1940
1941 template <class Preconditioner>
1943 {
1945 };
1946
1947 template <class Assembler> class ProjectionOnTangentSpace;
1948
1949 template <class Functional, class Assembler, int components>
1950 struct ChooseProjectionPolicy<InexactTangentSpacePreconditioner<Functional,Assembler,components> >
1951 {
1953 };
1954
1955 template <class Assembler>
1957 {
1958 typedef typename Assembler::Functional::Functional Functional;
1959 typedef OptimalControlTraits<Functional,Assembler> Traits;
1960 public:
1961 ProjectionOnTangentSpace(Assembler const& assembler)
1962 : A(assembler,false), B(assembler,false),
1963 PA(new DirectPreconditioner<typename Traits::StateOperator>(A))
1964 {}
1965
1966 template <class VarSetDesc>
1967 void apply(VarSetDesc& x)
1968 {
1969 using namespace boost::fusion;
1970 typename Traits::VectorP rhsP(at_c<Traits::pIdx>(x.data));
1971 rhsP *= 0.0;
1972 typename Traits::VectorU du(at_c<Traits::uIdx>(x.data));
1973 typename Traits::VectorY dy(at_c<Traits::yIdx>(x.data));
1974 B.applyscaleadd(-1.0,du,rhsP);
1975 PA->apply(dy,rhsP);
1976
1977 at_c<Traits::yIdx>(x.data) = at_c<0>(dy.data);
1978 }
1979
1980 private:
1981 typename Traits::StateOperator A;
1982 typename Traits::ControlOperator B;
1983
1984 std::unique_ptr<typename Traits::StatePreconditioner> PA;
1985 };
1986
1987 template <class Assembler, int nComponents, int stateId, int controlId, int adjointId>
1989 {
1990 typedef typename Assembler::Functional::Functional Functional;
1991 typedef OptimalControlTraits<Functional,Assembler> Traits;
1992 public:
1994 : A(assembler,false), B(assembler,false),
1995 mgSolver(A, assembler.getGridManager().grid(), parameter)
1996 {}
1997
1998 template <class VarSet>
1999 void apply(VarSet& x)
2000 {
2001 using namespace boost::fusion;
2002
2003 VarSet y(x.descriptions);
2004
2005 typename Traits::VectorP rhsP(Traits::CreateVectorP::init(x.descriptions));
2006 typename Traits::VectorU du(Traits::CreateVectorU::init(x.descriptions));
2007 at_c<0>(du.data) = at_c<Traits::controlId>(x.data).coefficients();
2008 B.applyscaleadd(-1.0,du,rhsP);
2009 at_c<Traits::adjointId>(y.data) = at_c<Traits::adjointId>(x.data);
2010 mgSolver.apply(at_c<stateId>(x.data).coefficients(),at_c<Traits::adjointId>(y.data).coefficients());
2011 }
2012
2013 private:
2014 typename Traits::StateOperator A;
2015 typename Traits::ControlOperator B;
2017 };
2018
2019} // namespace Kaskade
2020#endif
Abstract Vector for function space algorithms.
virtual std::unique_ptr< AbstractFunctionSpaceElement > clone() const =0
Construction of a vector of the same type.
virtual std::unique_ptr< AbstractFunctionSpaceElement > initZeroVector() const =0
Construction of a vector of the same type.
virtual void evald(AbstractFunctionSpaceElement &g, int rbegin=0, int rend=-1) const =0
Evaluate derivative.
virtual AbstractFunctionSpaceElement const & getOrigin() const =0
Get point of linearization.
Class that models the functionality of a (possibly inexact) linear solver.
An adaptor presenting a Dune::LinearOperator <domain_type,range_type> interface to a contiguous sub-b...
virtual void apply(Domain const &x, Range &b) const
compute
typename Assembler::TestVariableSetDescription::template CoefficientVector< firstRow, lastRow > Range
Mathematical Vector that supports copy-on-write, implements AbstractFunctionSpaceElement.
regularized preconditioned conjugate gradient method
void setSteps(size_t steps)
Definition: chebyshev.hh:143
void initForMassMatrix_TetrahedralQ1Elements()
Init spectral bounds for the mass matrix arising from tetrahedral discretization of the domain and li...
Definition: chebyshev.hh:133
virtual void apply(Domain &x, Range const &y)
Definition: chebyshev.hh:68
virtual void setRelativeAccuracy(double)
Definition: comp_step.hh:634
Bridge::ConnectedKaskadeLinearization< typename Assembler::Functional::Functional > BridgeLinearization
Definition: comp_step.hh:622
DirectNormalSolver(PreconditionerFunctional const &pf_, DirectType directType_=DirectType::UMFPACK3264, MatrixProperties properties_=MatrixProperties::GENERAL, int verbosity_=1)
Definition: comp_step.hh:624
virtual void post(Domain &x)
Definition: comp_step.hh:630
PrecondAssembler::Functional::Functional PreconditionerFunctional
Definition: comp_step.hh:619
Assembler::Functional::Functional Functional
Definition: comp_step.hh:618
virtual void apply(Domain &v, const Range &d)
Definition: comp_step.hh:632
OptimalControlTraits< Functional, Assembler > Traits
Definition: comp_step.hh:620
virtual void pre(Domain &x, Range &b)
Definition: comp_step.hh:629
Abstract base class for dual pairing of and its dual space .
virtual void apply(typename Traits::Domain &x, typename Traits::Range const &y)
Definition: comp_step.hh:1218
void applyStatePreconditioner(typename Traits::VectorY &x, typename Traits::VectorP const &y)
Definition: comp_step.hh:1285
virtual void post(typename Traits::Domain &)
Definition: comp_step.hh:1209
InexactTangentSpacePreconditioner(Assembler const &assembler, AnsatzVariableSetDesc aDesc, TestVariableSetDesc tdesc, size_t mgSteps=10, size_t mgSmoothingSteps=10, size_t chebySteps=10, bool onlyLowerTriangle=false)
Definition: comp_step.hh:1189
void applyAdjointPreconditioner(typename Traits::VectorP &x, typename Traits::VectorY const &y)
Definition: comp_step.hh:1296
virtual void pre(typename Traits::Domain &, typename Traits::Range &)
Definition: comp_step.hh:1208
InexactTangentSpacePreconditionerILU(Assembler const &assembler, AnsatzVariableSetDesc const &aDesc, TestVariableSetDesc const &tdesc, size_t mgSteps=10, size_t mgSmoothingSteps=10, size_t chebySteps=10, bool onlyLowerTriangle=false)
Definition: comp_step.hh:1332
virtual void post(typename Traits::Domain &)
Definition: comp_step.hh:1352
void applyAdjointPreconditioner(typename Traits::VectorP &x, typename Traits::VectorY const &y)
Definition: comp_step.hh:1421
virtual void apply(typename Traits::Domain &x, typename Traits::Range const &y)
Definition: comp_step.hh:1361
virtual void pre(typename Traits::Domain &, typename Traits::Range &)
Definition: comp_step.hh:1351
void applyStatePreconditioner(typename Traits::VectorY &x, typename Traits::VectorP const &y)
Definition: comp_step.hh:1411
InverseOperator::Domain Domain
Definition: direct.hh:555
AbstractLinearization & getTangentialLinearization()
AbstractLinearization & getNormalLinearization()
MGProjectionOnTangentSpace(Assembler const &assembler, typename MultiGridSolver< typename Assembler::Grid, nComponents >::Parameter parameter=typename MultiGridSolver< typename Assembler::Grid, nComponents >::Parameter(500, 25, 1e-9))
Definition: comp_step.hh:1993
Operator with matrix-representation and coordinate mappings.
void setParameter(Parameter p)
void apply(CoeffVector &solution, CoeffVector &rightHand)
void applyAdjointPreconditioner(typename Traits::VectorP &x, typename Traits::VectorY const &y)
Definition: comp_step.hh:1153
virtual void apply(typename Traits::Domain &x, typename Traits::Range const &y)
Definition: comp_step.hh:1113
void setParameter(size_t mgSteps, size_t mgSmoothingSteps, size_t chebySteps, double relativeAccuracy)
Definition: comp_step.hh:1103
virtual void pre(typename Traits::Domain &, typename Traits::Range &)
Definition: comp_step.hh:1110
virtual void post(typename Traits::Domain &)
Definition: comp_step.hh:1111
void applyStatePreconditioner(typename Traits::VectorY &x, typename Traits::VectorP const &y)
Definition: comp_step.hh:1143
NormalStepPreconditioner3(Assembler const &assembler, AnsatzVariableSetDesc const &ansatzVars, TestVariableSetDesc const &testVars, size_t mgSteps=500, size_t mgSmoothingSteps=10, size_t chebySteps=20, double relativeAccuracy=1e-6, bool onlyLowerTriangle=false)
Definition: comp_step.hh:1089
NormalStepPreconditioner(Assembler const &assembler, bool onlyLowerTriangle=false, Scalar tolerance=1e-6)
Definition: comp_step.hh:730
virtual void post(typename Traits::Domain &)
Definition: comp_step.hh:743
void applyAdjointPreconditioner(typename Traits::VectorP &x, typename Traits::VectorY const &y)
Definition: comp_step.hh:777
void applyStatePreconditioner(typename Traits::VectorY &x, typename Traits::VectorP const &y)
Definition: comp_step.hh:771
virtual void pre(typename Traits::Domain &, typename Traits::Range &)
Definition: comp_step.hh:742
virtual void apply(typename Traits::Domain &x, typename Traits::Range const &y)
Definition: comp_step.hh:745
PrecondAssembler::Functional::Functional PreconditionerFunctional
Definition: comp_step.hh:442
void setMultiGridSmoothingSteps(size_t mgSmoothingSteps_)
Definition: comp_step.hh:470
virtual void setEps(double eps_)
Definition: comp_step.hh:467
void setMultiGridSteps(size_t mgSteps_)
Definition: comp_step.hh:469
virtual void pre(Domain &x, Range &b)
Definition: comp_step.hh:453
PPCGAsNormalSolver(PreconditionerFunctional const &pf_, double relativeAccuracy_=1e-9, size_t maxSteps_=2000, int verbosity_=1, double eps_=1e-15)
Definition: comp_step.hh:448
virtual void post(Domain &x)
Definition: comp_step.hh:454
OptimalControlTraits< Functional, Assembler > Traits
Definition: comp_step.hh:443
Assembler::Functional::Functional Functional
Definition: comp_step.hh:441
virtual void apply(Domain &v, const Range &d)
Definition: comp_step.hh:456
Bridge::ConnectedKaskadeLinearization< typename Assembler::Functional::Functional > BridgeLinearization
Definition: comp_step.hh:445
IterateType::CG< Domain, Range > Solver
Definition: comp_step.hh:446
virtual void setRelativeAccuracy(double relativeAccuracy_)
Definition: comp_step.hh:462
void setChebyshevSteps(size_t chebySteps_)
Definition: comp_step.hh:471
virtual void pre(Domain &x, Range &b)
Definition: comp_step.hh:339
PrecondAssembler::Functional::Functional PreconditionerFunctional
Definition: comp_step.hh:329
PreconditionerAsNormalSolver(PreconditionerFunctional const &pf_, PreconditionerFactory &prec_)
Definition: comp_step.hh:337
Bridge::ConnectedKaskadeLinearization< typename Assembler::Functional::Functional > BridgeLinearization
Definition: comp_step.hh:333
virtual void apply(Domain &v, const Range &d)
Definition: comp_step.hh:340
virtual void post(Domain &x)
Definition: comp_step.hh:346
Assembler::Functional::Functional Functional
Definition: comp_step.hh:328
OptimalControlTraits< Functional, Assembler > Traits
Definition: comp_step.hh:330
MGProjectionOnTangentSpace< NormalStepAssembler, components, Traits::stateId, Traits::controlId, Traits::adjointId > Projection
Definition: comp_step.hh:1797
Assembler::Functional::Functional TF
Definition: comp_step.hh:1805
static constexpr int uIdx
Definition: comp_step.hh:1800
Bridge::ConnectedKaskadeLinearization< typename NormalStepAssembler::Functional::Functional > NormalBridgeLinearization
Definition: comp_step.hh:1803
virtual bool localConvergenceLikely() final
Definition: comp_step.hh:1824
Preconditioner::Range Range
Definition: comp_step.hh:1793
Preconditioner::Assembler NormalStepAssembler
Definition: comp_step.hh:1794
virtual AbstractFunctionSpaceElement & getCorrectRhs() final
Definition: comp_step.hh:1829
virtual void setRelativeAccuracy(double accuracy_) final
Specify accuracy that should be achieved.
Definition: comp_step.hh:1813
OptimalControlTraits< typename Assembler::Functional::Functional, Assembler > Traits
Definition: comp_step.hh:1795
static constexpr int yIdx
Definition: comp_step.hh:1799
CGBase< Domain, Range, cgImpl > Solver
Definition: comp_step.hh:1802
ProjectedAPCGSolver(Preconditioner &P_, Scalar accuracy_, int verbose_=0, size_t maxSteps_=500, double eps_=1e-12)
Definition: comp_step.hh:1807
virtual void setEps(double eps_)
Definition: comp_step.hh:1834
Bridge::ConnectedKaskadeLinearization< typename Assembler::Functional::Functional > TangentialBridgeLinearization
Definition: comp_step.hh:1804
Assembler::Functional::Functional Functional
Definition: comp_step.hh:1798
static constexpr int pIdx
Definition: comp_step.hh:1801
Preconditioner::Domain Domain
Definition: comp_step.hh:1792
virtual void setLipschitzConstant(double omega)
Definition: comp_step.hh:1836
virtual int nSolutionVectors() const final
The maximal number of solution vectors, returned by basis.
Definition: comp_step.hh:1823
ProjectionOnTangentSpace(Assembler const &assembler)
Definition: comp_step.hh:1961
virtual Scalar operator()(X const &x, Xstar const &y) const
Definition: comp_step.hh:48
Scaledl2ScalarProduct(Scalar sy_, Scalar su_, Scalar sp_)
Definition: comp_step.hh:44
Relative energy error termination criterion according to Strakos, Tichy: Error estimation in precondi...
Relative error termination criterion based on the norm induced by the preconditioner,...
void applyAdjointPreconditioner(typename Traits::VectorP &x, typename Traits::VectorY const &y)
Definition: comp_step.hh:953
virtual void apply(typename Traits::Domain &x, typename Traits::Range const &y)
Definition: comp_step.hh:913
virtual void post(typename Traits::Domain &)
Definition: comp_step.hh:911
void applyStatePreconditioner(typename Traits::VectorY &x, typename Traits::VectorP const &y)
Definition: comp_step.hh:943
virtual void pre(typename Traits::Domain &, typename Traits::Range &)
Definition: comp_step.hh:910
TangentSpacePreconditioner2(Assembler const &assembler, AnsatzVariableSetDesc const &ansatzVars, TestVariableSetDesc const &testVars, size_t mgSteps=10, size_t mgSmoothingSteps=10, size_t chebySteps=10, bool onlyLowerTriangle=false)
Definition: comp_step.hh:895
virtual void post(typename Traits::Domain &)
Definition: comp_step.hh:817
virtual void apply(typename Traits::Domain &x, typename Traits::Range const &y)
Definition: comp_step.hh:819
void applyAdjointPreconditioner(typename Traits::VectorP &x, typename Traits::VectorY const &y)
Definition: comp_step.hh:863
TangentSpacePreconditioner(Assembler const &assembler, bool onlyLowerTriangle=false)
Definition: comp_step.hh:802
void applyStatePreconditioner(typename Traits::VectorY &x, typename Traits::VectorP const &y)
Definition: comp_step.hh:858
virtual void pre(typename Traits::Domain &, typename Traits::Range &)
Definition: comp_step.hh:816
virtual void applyscaleadd(Scalar alpha, Domain const &x, Range &b) const
A class for storing a heterogeneous collection of FunctionSpaceElement s.
Definition: variables.hh:341
Descriptions const & descriptions
Descriptions of variable set, of type VariableSetDescription (lots of useful infos)
Definition: variables.hh:510
DirectType
Available direct solvers for linear equation systems.
Definition: enums.hh:35
@ UMFPACK3264
NO LONGER SUPPORTED.
MatrixProperties
Characterizations of sparse matrix properties.
Definition: enums.hh:76
Dune::FieldVector< T, n > min(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise minimum.
Definition: fixdune.hh:122
InverseLinearOperator< DirectSolver< typename AssembledGalerkinOperator< GOP, firstRow, lastRow, firstCol, lastCol >::Domain, typename AssembledGalerkinOperator< GOP, firstRow, lastRow, firstCol, lastCol >::Range > > directInverseOperator(AssembledGalerkinOperator< GOP, firstRow, lastRow, firstCol, lastCol > const &A, DirectType directType, MatrixProperties properties)
Definition: direct.hh:618
void copyFromFunctionSpaceElement(FSE const &fse, CoeffVector &coeffVector)
Definition: comp_step.hh:1744
void ddxpy_template(Lin &lin, AbstractFunctionSpaceElement &y, AbstractFunctionSpaceElement const &x)
Definition: comp_step.hh:1756
void addToFunctionSpaceElement(CoeffVector const &coeffVector, FSE &fse)
Definition: comp_step.hh:1750
Bridge classes that connect low level FE algorithms to higher level algorithms.
static void apply(CoeffVector const &v, FSE &fse)
Definition: comp_step.hh:1730
DefaultProjectionPolicy type
Definition: comp_step.hh:1944
static void apply(FSE const &fse, CoeffVector &v)
Definition: comp_step.hh:1714
void projectOnConstraint(Arg &) const
Definition: comp_step.hh:1938