Discontinuous Galerkin Library
#include "dg/algorithm.h"
andersonacc.h
Go to the documentation of this file.
1#pragma once
2
3#include <functional>
4#include "blas.h"
5#include "topology/operator.h"
6
7namespace dg{
9//const double m_EPS = 2.2204460492503131e-16;
10namespace detail{
11
12// delete 1st column and shift everything to the left once
13template<class ContainerType, class value_type>
14void QRdelete1( std::vector<ContainerType>& Q, dg::Operator<value_type>& R, unsigned mMax)
15{
16 for(unsigned i = 0; i<mMax-1;i++){
17 value_type temp = sqrt(R(i,i+1)*R(i,i+1)+R(i+1,i+1)*R(i+1,i+1));
18 value_type c = R(i,i+1)/temp;
19 value_type s = R(i+1,i+1)/temp;
20 R(i,i+1) = temp;
21 R(i+1,i+1) = 0;
22 if (i < mMax-2) {
23 for (unsigned j = i+2; j < mMax; j++){
24 temp = c * R(i,j) + s * R(i+1,j);
25 R(i+1,j) = - s * R(i,j) + c * R(i+1,j);
26 R(i,j) = temp;
27 }
28 }
29 dg::blas1::subroutine( [c,s]DG_DEVICE( double& qi, double& qip) {
30 double tmp = c*qi + s*qip;
31 qip = - s*qi + c*qip;
32 qi = tmp;
33 }, Q[i], Q[i+1]);
34 // Q(i + 1) = s ∗ Q(ℓ, i) + c ∗ Q(ℓ, i + 1).
35 // Q(i) = c ∗ Q(ℓ, i) + s ∗ Q(ℓ, i + 1).
36 } //Check for error in keeping the last row.!!!
37 for(unsigned i = 0; i<mMax-1;i++)
38 for(unsigned j = 0; j < mMax-1; j++)
39 R(i,j) = R(i,j+1);
40 return;
41}
42
43}//namespace detail
45
46
47
59template<class ContainerType>
61{
63 using container_type = ContainerType;
73 AndersonAcceleration(const ContainerType& copyable):
86 AndersonAcceleration(const ContainerType& copyable, unsigned mMax ):
87 m_g_old( copyable), m_fval( copyable), m_f_old(copyable),
88 m_DG( mMax, copyable), m_Q( m_DG),
89 m_gamma( mMax, 0.),
90 m_R( mMax), m_mMax( mMax)
91 {
92 }
93
100 template<class ...Params>
101 void construct( Params&& ...ps)
102 {
103 //construct and swap
104 *this = AndersonAcceleration( std::forward<Params>( ps)...);
105 }
106
108 const ContainerType& copyable() const{ return m_fval;}
110 void set_throw_on_fail( bool throw_on_fail){
111 m_throw_on_fail = throw_on_fail;
112 }
113
143 template<class MatrixType, class ContainerType0, class ContainerType1, class ContainerType2>
144 unsigned solve( MatrixType&& f, ContainerType0& x, const ContainerType1& b,
145 const ContainerType2& weights,
146 value_type rtol, value_type atol, unsigned max_iter,
147 value_type damping, unsigned restart, bool verbose);
148
149 private:
150 ContainerType m_g_old, m_fval, m_f_old;
151 std::vector<ContainerType> m_DG, m_Q;
152 std::vector<value_type> m_gamma;
154
155 unsigned m_mMax;
156 bool m_throw_on_fail = true;
157};
159
160template<class ContainerType>
161template<class MatrixType, class ContainerType0, class ContainerType1, class ContainerType2>
163 MatrixType&& func, ContainerType0& x, const ContainerType1& b, const ContainerType2& weights,
164 value_type rtol, value_type atol, unsigned max_iter,
165 value_type damping, unsigned restart, bool verbose )
166{
167#ifdef MPI_VERSION
168 int rank;
169 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
170#endif //MPI
171 if (m_mMax == 0){
172 if(verbose)DG_RANK0 std::cout<< "No acceleration will occur" << std::endl;
173 }
174
175 unsigned mAA = 0;
176 value_type nrmb = sqrt( dg::blas2::dot( b, weights, b));
177 value_type tol = atol+rtol*nrmb;
178 if(verbose)DG_RANK0 std::cout << "Solve with mMax = "<<m_mMax<<" rtol = "
179 <<rtol<<" atol = "<<atol<< " tol = " << tol <<" max_iter = "<<max_iter
180 <<" damping = "<<damping<<" restart = "<<restart<<std::endl;
181
182 ContainerType0& m_gval = x;
183 // - use weights for orthogonalization (works because minimization is also true if V_m is unitary in the W scalar product
184 for(unsigned iter=0;iter < max_iter; iter++)
185 {
186 if ( restart != 0 && iter % (restart) == 0) {
187 mAA = 0;
188 if(verbose)DG_RANK0 std::cout << "Iter = " << iter << std::endl;
189 }
190
191 dg::apply( std::forward<MatrixType>(func), x, m_fval);
192 dg::blas1::axpby( -1., b, 1., m_fval); //f(x) = func - b (residual)
193 value_type res_norm = sqrt(dg::blas2::dot(m_fval,weights,m_fval)); //l2norm(m_fval)
194
195 if(verbose)DG_RANK0 std::cout << "res_norm = " << res_norm << " Against tol = " << tol << std::endl;
196 // Test for stopping
197 if (res_norm <= tol){
198 if(verbose)DG_RANK0 std::cout << "Terminate with residual norm = " << res_norm << std::endl;
199 return iter+1;
200 }
201
202 dg::blas1::axpby(1.,x,-damping,m_fval,m_gval); // m_gval = x - damping*m_fval
203 // Without acceleration, x = g(x) is the next approximate solution.
204 if( m_mMax == 0) continue;
205
206 if( iter == 0)
207 {
208 std::swap(m_fval,m_f_old);
209 dg::blas1::copy(m_gval,m_g_old);
210 continue;
211 }
212
213 // Apply Anderson acceleration.
214
215 if (mAA < m_mMax) {
216
217 dg::blas1::axpby(1.,m_fval,-1.,m_f_old, m_Q[mAA]); //Q = m_fval-m_f_old;
218 dg::blas1::axpby(1.,m_gval,-1.,m_g_old,m_DG[mAA]); //Update m_DG = [m_DG m_gval-m_g_old];
219
220 } else {
221
222 std::rotate(m_DG.begin(), m_DG.begin() + 1, m_DG.end()); //Rotate to the left hopefully this works... otherwise for i = 0 .. mMax-2 m_DG[i] = m_DG[i+1], and finally m_DG[mMax-1] = update...
223 dg::blas1::axpby(1.,m_gval,-1.,m_g_old,m_DG[m_mMax-1]); //Update last m_DG entry
224
225 detail::QRdelete1(m_Q,m_R,m_mMax); // If the column dimension of Q is mMax, delete the first column (the oldest vector) and shift composition to the left
226 dg::blas1::axpby(1.,m_fval,-1.,m_f_old, m_Q[m_mMax-1]); //Q = m_fval-m_f_old;
227 mAA = m_mMax-1; // mAA = m_mMax-1
228
229 }
230
231
232 // update the QR decomposition to incorporate the new column.
233 // MW: This is modified Gram-Schmidt which delivers a reduced QR-factorization
234 for (unsigned j = 0; j < mAA; j++) {
235 m_R(j,mAA) = dg::blas2::dot(m_Q[j],weights,m_Q[mAA]); //Q(:,j)’*Q(mAA); //Changed mAA -> mAA-1
236
237 dg::blas1::axpby(-m_R(j,mAA),m_Q[j],1.,m_Q[mAA]); //m_Q[mAA] = Q(mAA) - R(j,mAA)*Q(:,j);
238 }
239 m_R(mAA,mAA) = sqrt(dg::blas2::dot(m_Q[mAA],weights,m_Q[mAA]));
240 dg::blas1::scal(m_Q[mAA], 1./m_R(mAA,mAA));
241
242 //Calculate condition number of R to figure whether to keep going or call QR delete to reduce Q and R.
243 //value_type condDF = cond(R,mAA+1);
244 //Here should be the check for whether to proceed.
245
246 //Solve least squares problem.
247 for(int i = (int)mAA; i>=0; i--){
248 m_gamma[i] = dg::blas2::dot(m_Q[i],weights,m_fval);
249 for(int j = i + 1; j < (int)mAA+1; j++){
250 m_gamma[i] = DG_FMA( -m_R(i,j), m_gamma[j], m_gamma[i]) ;
251 }
252 m_gamma[i] /= m_R(i,i);
253 }
254
255 std::swap(m_fval,m_f_old);
256 dg::blas1::copy(m_gval,m_g_old);
257
258 //Update new approximate solution x = m_gval - m_DG*gamma
259 //for (unsigned i = 0; i < mAA+1; i++) {
260 // dg::blas1::axpby(-m_gamma[i],m_DG[i],1.,x);
261 //}
262 // ATTENTION: x is an alias for gval
264 std::vector<value_type>{m_gamma.begin(), m_gamma.begin()+mAA+1},
265 1., x);
266
267 mAA++;
268 }
269 if( m_throw_on_fail)
270 {
271 throw dg::Fail( tol, Message(_ping_)
272 <<"After "<<max_iter<<" Anderson iterations with rtol "<<rtol<<" atol "<<atol<<" damping "<<damping<<" restart "<<restart);
273 }
274 return max_iter;
275
276}
278//
283template<class ContainerType>
285
286}//namespace dg
#define _ping_
Definition: exceptions.h:12
#define DG_DEVICE
Expands to __host__ __device__ if compiled with nvcc else is empty.
Definition: functions.h:9
void apply(get_value_type< ContainerType1 > alpha, MatrixType &&M, const ContainerType1 &x, get_value_type< ContainerType1 > beta, ContainerType2 &y)
; (alias for dg::blas2::symv)
Definition: blas2.h:461
void copy(const ContainerTypeIn &source, ContainerTypeOut &target)
Definition: blas1.h:164
void axpby(get_value_type< ContainerType > alpha, const ContainerType1 &x, get_value_type< ContainerType > beta, ContainerType &y)
Definition: blas1.h:231
void subroutine(Subroutine f, ContainerType &&x, ContainerTypes &&... xs)
; Customizable and generic blas1 function
Definition: blas1.h:618
void scal(ContainerType &x, get_value_type< ContainerType > alpha)
Definition: blas1.h:185
void gemv(get_value_type< ContainerType1 > alpha, MatrixType &&M, const ContainerType1 &x, get_value_type< ContainerType1 > beta, ContainerType2 &y)
; (alias for symv)
Definition: blas2.h:299
get_value_type< MatrixType > dot(const ContainerType1 &x, const MatrixType &m, const ContainerType2 &y)
; Binary reproducible general dot product
Definition: blas2.h:85
@ x
x direction
std::vector< const ContainerType * > asPointers(const std::vector< ContainerType > &in)
Convert a vector of vectors to a vector of pointers.
Definition: densematrix.h:100
auto asDenseMatrix(const std::vector< const ContainerType * > &in)
Lightweight DenseMatrix for dg::blas2::gemv.
Definition: densematrix.h:70
MPI_Vector< thrust::host_vector< real_type > > weights(const aRealMPITopology2d< real_type > &g)
Nodal weight coefficients.
Definition: mpi_weights.h:22
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
Definition: tensor_traits.h:38
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...
Anderson Acceleration of Fixed Point/Richardson Iteration for the nonlinear equation .
Definition: andersonacc.h:61
const ContainerType & copyable() const
Return an object of same size as the object used for construction.
Definition: andersonacc.h:108
AndersonAcceleration(const ContainerType &copyable)
Allocate memory for Fixed point iteration.
Definition: andersonacc.h:73
AndersonAcceleration(const ContainerType &copyable, unsigned mMax)
Allocate memory for the object.
Definition: andersonacc.h:86
get_value_type< ContainerType > value_type
the value type of the time variable (float or double)
Definition: andersonacc.h:62
AndersonAcceleration()=default
Allocate nothing, Call construct method before usage.
unsigned solve(MatrixType &&f, ContainerType0 &x, const ContainerType1 &b, const ContainerType2 &weights, value_type rtol, value_type atol, unsigned max_iter, value_type damping, unsigned restart, bool verbose)
Solve the system in the given norm.
void set_throw_on_fail(bool throw_on_fail)
Set or unset a throw on failure-to-converge.
Definition: andersonacc.h:110
void construct(Params &&...ps)
Perfect forward parameters to one of the constructors.
Definition: andersonacc.h:101
ContainerType container_type
Definition: andersonacc.h:63
Indicate failure to converge.
Definition: exceptions.h:126
#define DG_RANK0
Definition: typedefs.h:147