Extension: Matrix functions
#include "dg/matrix/matrix.h"
tensorelliptic.h
Go to the documentation of this file.
1#pragma once
2
3#include <cassert>
4
5#include "dg/algorithm.h"
6
11namespace dg{
12namespace mat{
13
23template< class Geometry, class Matrix, class Container>
25{
26 using container_type = Container;
27 using geometry_type = Geometry;
28 using matrix_type = Matrix;
40 TensorElliptic( const Geometry& g, direction dir = dg::centered, value_type jfactor=1.):
41 TensorElliptic( g, g.bcx(), g.bcy(), dir, jfactor)
42 {
43 }
54 TensorElliptic( const Geometry& g, bc bcx, bc bcy, direction dir = dg::centered, value_type jfactor=1.)
55 {
56 m_jfactor=jfactor;
57 m_laplaceM_chi.construct( g, bcx, bcy, dir, jfactor);
58 m_laplaceM_iota.construct( g, bcx, bcy, dir, jfactor);
59 dg::blas2::transfer( dg::create::dx( g, inverse( bcx), inverse(dir)), m_leftx);
60 dg::blas2::transfer( dg::create::dy( g, inverse( bcy), inverse(dir)), m_lefty);
61 dg::blas2::transfer( dg::create::dx( g, bcx, dir), m_rightx);
62 dg::blas2::transfer( dg::create::dy( g, bcy, dir), m_righty);
63 dg::blas2::transfer( dg::create::jumpX( g, bcx), m_jumpX);
64 dg::blas2::transfer( dg::create::jumpY( g, bcy), m_jumpY);
65
66 dg::assign( dg::evaluate( dg::one, g), m_temp);
67 m_tempx = m_tempy = m_tempxy = m_tempyx = m_iota = m_helper = m_temp;
68
69 m_chi=g.metric();
70 m_metric=g.metric();
71 m_vol=dg::tensor::volume(m_chi); //sqrt(g)
72 dg::tensor::scal( m_chi, m_vol); //m_chi = sqrt(g) g^{ij}
73 dg::assign( dg::evaluate(dg::one, g), m_sigma);
74 }
76 template<class ...Params>
77 void construct( Params&& ...ps)
78 {
79 //construct and swap
80 *this = TensorElliptic( std::forward<Params>( ps)...);
81 }
82
84 const Container& weights()const {return m_laplaceM_chi.weights();}
90 const Container& precond()const {return m_laplaceM_chi.precond();}
96 template<class ContainerType0>
97 void set_chi( const ContainerType0& chi) {m_laplaceM_chi.set_chi(chi); }
103 template<class ContainerType0>
104 void set_iota( const ContainerType0& iota) {m_iota=iota; }
113 void variation(const Container& phi, const value_type& alpha, const Container& chi, Container& varphi)
114 {
115// tensor part
116 dg::blas2::symv( m_rightx, phi, m_tempx); //R_x*f
117 dg::blas2::symv(-1.0, m_leftx, m_tempx, 0.0, m_helper); //L_x R_x *f
118 dg::blas2::symv(-1.0, m_righty, m_tempx, 0.0, m_tempyx); //R_y R_x*f
119 dg::blas2::symv( m_righty, phi, m_tempy); //R_y*f
120 dg::blas2::symv(-1.0, m_lefty, m_tempy, 0.0, m_temp); //L_y R_y *f
121 dg::blas2::symv(-1.0, m_rightx, m_tempy, 0.0, m_tempxy); //R_x R_y *f
122
123 dg::blas2::symv( m_jfactor, m_jumpX, phi, 1., m_helper);
124 dg::blas2::symv( m_jfactor, m_jumpY, phi, 1., m_temp);
125
126 dg::blas1::pointwiseDot(alpha, m_temp, m_temp, alpha, m_helper, m_helper, 0., varphi);
127 dg::blas1::pointwiseDot(alpha, m_tempxy, m_tempxy, alpha, m_tempyx, m_tempyx, 1., varphi);
128 dg::blas1::pointwiseDot(varphi, chi, varphi);
129
130 //laplacian part
131 dg::blas2::symv(m_laplaceM_iota, phi, m_temp);
132 dg::blas1::pointwiseDot(alpha/2., chi, m_temp, m_temp, -1., varphi); //varphi-= alpha *chi/2 (lap phi)^2
133
134 //elliptic part
135 tensor::multiply2d( m_metric, m_tempx, m_tempy, m_temp, m_helper);
136 dg::blas1::pointwiseDot( 1., m_temp, m_tempx, 1., m_helper, m_tempy, 0., m_temp); //m_temp = |nabla phi|^2
137 dg::blas1::axpby(-0.5, m_temp, -0.5, varphi);
138 dg::blas1::pointwiseDot(chi, varphi, varphi);
139
140 }
141
142 template<class ContainerType0, class ContainerType1>
143 void operator()( const ContainerType0& x, ContainerType1& y){
144 symv( 1, x, 0, y);
145 }
146
147 template<class ContainerType0, class ContainerType1>
148 void symv( const ContainerType0& x, ContainerType1& y){
149 symv( 1, x, 0, y);
150 }
164 template<class ContainerType0, class ContainerType1>
165 void symv( value_type alpha, const ContainerType0& x, value_type beta, ContainerType1& y)
166 {
167 //tensor term first
168 dg::blas2::symv( m_rightx, x, m_helper); //R_x*f
169 dg::blas2::symv(-1.0, m_leftx, m_helper, 0.0, m_tempx); //L_x R_x *f
170 dg::blas2::symv(-1.0, m_righty, m_helper, 0.0, m_tempyx); //R_y R_x*f
171 dg::blas2::symv( m_righty, x, m_helper); //R_y*f
172 dg::blas2::symv(-1.0, m_lefty, m_helper, 0.0, m_tempy); //L_y R_y *f
173 dg::blas2::symv(-1.0, m_rightx, m_helper, 0.0, m_tempxy); //R_x R_y *f
174
175 dg::blas2::symv( m_jfactor, m_jumpX, x, 1., m_tempx);
176 dg::blas2::symv( m_jfactor, m_jumpY, x, 1., m_tempy);
177
178 //multiply sqrt(g) iota
179 dg::blas1::pointwiseDot( 1., m_tempx, m_iota, m_vol, 0., m_tempx);
180 dg::blas1::pointwiseDot( 1., m_tempyx, m_iota, m_vol, 0., m_tempyx);
181 dg::blas1::pointwiseDot( 1., m_tempy, m_iota, m_vol, 0., m_tempy);
182 dg::blas1::pointwiseDot( 1., m_tempxy, m_iota, m_vol, 0., m_tempxy);
183
184 dg::blas2::symv( m_rightx, m_tempx, m_helper);
185 dg::blas2::symv(-1.0, m_leftx, m_helper, 0.0, m_temp); //L_x R_x
186 dg::blas2::symv( m_leftx, m_tempyx, m_helper);
187 dg::blas2::symv(-1.0, m_lefty, m_helper, 1.0, m_temp); //L_y L_x
188 dg::blas2::symv( m_righty, m_tempy, m_helper);
189 dg::blas2::symv(-1.0, m_lefty, m_helper, 1.0, m_temp); //L_y R_y
190 dg::blas2::symv( m_lefty, m_tempxy, m_helper);
191 dg::blas2::symv(-1.0, m_leftx, m_helper, 1.0, m_temp); //L_x L_y
192
193 dg::blas2::symv( m_jfactor, m_jumpX, m_tempx, 1., m_temp);
194 dg::blas2::symv( m_jfactor, m_jumpY, m_tempy, 1., m_temp);
195
196 dg::blas1::pointwiseDivide(m_temp, m_vol, m_temp); //multiply sqrt(g)^(-1)
197
198 //-lap (iota lap f) term
199 dg::blas2::symv( m_laplaceM_iota, x, m_tempx);
200 dg::blas1::pointwiseDot( m_iota, m_tempx, m_tempx);
201 dg::blas2::symv(-1.0, m_laplaceM_iota, m_tempx, 2.0, m_temp);
202
203 //elliptic term - div (chi nabla f)
204 dg::blas2::symv(1.0, m_laplaceM_chi, x, 1., m_temp);
205
206 dg::blas1::axpby(alpha, m_temp, beta, y);
207
208 }
209
210 private:
211 bc inverse( bc bound)
212 {
213 if( bound == DIR) return NEU;
214 if( bound == NEU) return DIR;
215 if( bound == DIR_NEU) return NEU_DIR;
216 if( bound == NEU_DIR) return DIR_NEU;
217 return PER;
218 }
219 direction inverse( direction dir)
220 {
221 if( dir == forward) return backward;
222 if( dir == backward) return forward;
223 return centered;
224 }
225 Elliptic<Geometry, Matrix, Container> m_laplaceM_chi, m_laplaceM_iota;
226 Matrix m_leftx, m_lefty, m_rightx, m_righty, m_jumpX, m_jumpY;
227 Container m_temp, m_tempx, m_tempy, m_tempxy, m_tempyx, m_iota, m_helper;
228 SparseTensor<Container> m_chi;
229 SparseTensor<Container> m_metric;
230 Container m_sigma, m_vol;
231 value_type m_jfactor;
232};
233
234
235} //namespace mat
237template< class G, class M, class V>
238struct TensorTraits< mat::TensorElliptic<G, M, V> >
239{
241 using tensor_category = SelfMadeMatrixTag;
242};
244} //namespace dg
245
void assign(const from_ContainerType &from, ContainerType &to, Params &&... ps)
static DG_DEVICE double one(double x)
void axpby(get_value_type< ContainerType > alpha, const ContainerType1 &x, get_value_type< ContainerType > beta, ContainerType &y)
void pointwiseDivide(get_value_type< ContainerType > alpha, const ContainerType1 &x1, const ContainerType2 &x2, get_value_type< ContainerType > beta, ContainerType &y)
void pointwiseDot(get_value_type< ContainerType > alpha, const ContainerType1 &x1, const ContainerType2 &x2, get_value_type< ContainerType > beta, ContainerType &y)
void transfer(const MatrixType &x, AnotherMatrixType &y)
void symv(MatrixType &&M, const ContainerType1 &x, ContainerType2 &y)
EllSparseBlockMat< real_type > dx(const aRealTopology2d< real_type > &g, bc bcx, direction dir=centered)
EllSparseBlockMat< real_type > jumpX(const aRealTopology2d< real_type > &g, bc bcx)
EllSparseBlockMat< real_type > dy(const aRealTopology2d< real_type > &g, bc bcy, direction dir=centered)
direction
EllSparseBlockMat< real_type > jumpY(const aRealTopology2d< real_type > &g, bc bcy)
backward
centered
thrust::host_vector< real_type > evaluate(UnaryOp f, const RealGrid1d< real_type > &g)
Elliptic2d< Geometry, Matrix, Container > Elliptic
void multiply2d(const ContainerTypeL &lambda, const SparseTensor< ContainerType0 > &t, const ContainerType1 &in0, const ContainerType2 &in1, const ContainerTypeM &mu, ContainerType3 &out0, ContainerType4 &out1)
ContainerType volume(const SparseTensor< ContainerType > &t)
void scal(SparseTensor< ContainerType0 > &t, const ContainerType1 &mu)
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
Classes for Krylov space approximations of a Matrix-Vector product.
NotATensorTag tensor_category
Matrix class that represents the arbitrary polarization operator.
Definition: tensorelliptic.h:25
void symv(value_type alpha, const ContainerType0 &x, value_type beta, ContainerType1 &y)
apply operator
Definition: tensorelliptic.h:165
const Container & weights() const
Definition: tensorelliptic.h:84
Container container_type
Definition: tensorelliptic.h:26
TensorElliptic(const Geometry &g, direction dir=dg::centered, value_type jfactor=1.)
Construct TensorElliptic operator.
Definition: tensorelliptic.h:40
Geometry geometry_type
Definition: tensorelliptic.h:27
void set_iota(const ContainerType0 &iota)
Set Iota in the above formula.
Definition: tensorelliptic.h:104
void construct(Params &&...ps)
Perfect forward parameters to one of the constructors.
Definition: tensorelliptic.h:77
TensorElliptic()
empty object ( no memory allocation)
Definition: tensorelliptic.h:31
const Container & precond() const
Preconditioner to use in conjugate gradient solvers.
Definition: tensorelliptic.h:90
TensorElliptic(const Geometry &g, bc bcx, bc bcy, direction dir=dg::centered, value_type jfactor=1.)
Construct TensorElliptic operator.
Definition: tensorelliptic.h:54
void operator()(const ContainerType0 &x, ContainerType1 &y)
Definition: tensorelliptic.h:143
void set_chi(const ContainerType0 &chi)
Set Chi in the above formula.
Definition: tensorelliptic.h:97
void variation(const Container &phi, const value_type &alpha, const Container &chi, Container &varphi)
compute the variational of the operator (psi_2 in gf theory):
Definition: tensorelliptic.h:113
get_value_type< Container > value_type
Definition: tensorelliptic.h:29
void symv(const ContainerType0 &x, ContainerType1 &y)
Definition: tensorelliptic.h:148
Matrix matrix_type
Definition: tensorelliptic.h:28