Extension: Matrix functions
#include "dg/matrix/matrix.h"
Loading...
Searching...
No Matches
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
87 const Container& weights()const {return m_laplaceM_chi.weights();}
93 const Container& precond()const {return m_laplaceM_chi.precond();}
99 template<class ContainerType0>
100 void set_chi( const ContainerType0& chi) {m_laplaceM_chi.set_chi(chi); }
106 template<class ContainerType0>
107 void set_iota( const ContainerType0& iota) {m_iota=iota; }
116 void variation(const Container& phi, const value_type& alpha, const Container& chi, Container& varphi)
117 {
118// tensor part
119 dg::blas2::symv( m_rightx, phi, m_tempx); //R_x*f
120 dg::blas2::symv(-1.0, m_leftx, m_tempx, 0.0, m_helper); //L_x R_x *f
121 dg::blas2::symv(-1.0, m_righty, m_tempx, 0.0, m_tempyx); //R_y R_x*f
122 dg::blas2::symv( m_righty, phi, m_tempy); //R_y*f
123 dg::blas2::symv(-1.0, m_lefty, m_tempy, 0.0, m_temp); //L_y R_y *f
124 dg::blas2::symv(-1.0, m_rightx, m_tempy, 0.0, m_tempxy); //R_x R_y *f
125
126 dg::blas2::symv( m_jfactor, m_jumpX, phi, 1., m_helper);
127 dg::blas2::symv( m_jfactor, m_jumpY, phi, 1., m_temp);
128
129 dg::blas1::pointwiseDot(alpha, m_temp, m_temp, alpha, m_helper, m_helper, 0., varphi);
130 dg::blas1::pointwiseDot(alpha, m_tempxy, m_tempxy, alpha, m_tempyx, m_tempyx, 1., varphi);
131 dg::blas1::pointwiseDot(varphi, chi, varphi);
132
133 //laplacian part
134 dg::blas2::symv(m_laplaceM_iota, phi, m_temp);
135 dg::blas1::pointwiseDot(alpha/2., chi, m_temp, m_temp, -1., varphi); //varphi-= alpha *chi/2 (lap phi)^2
136
137 //elliptic part
138 tensor::multiply2d( m_metric, m_tempx, m_tempy, m_temp, m_helper);
139 dg::blas1::pointwiseDot( 1., m_temp, m_tempx, 1., m_helper, m_tempy, 0., m_temp); //m_temp = |nabla phi|^2
140 dg::blas1::axpby(-0.5, m_temp, -0.5, varphi);
141 dg::blas1::pointwiseDot(chi, varphi, varphi);
142
143 }
144
145 template<class ContainerType0, class ContainerType1>
146 void operator()( const ContainerType0& x, ContainerType1& y){
147 symv( 1, x, 0, y);
148 }
149
150 template<class ContainerType0, class ContainerType1>
151 void symv( const ContainerType0& x, ContainerType1& y){
152 symv( 1, x, 0, y);
153 }
167 template<class ContainerType0, class ContainerType1>
168 void symv( value_type alpha, const ContainerType0& x, value_type beta, ContainerType1& y)
169 {
170 //tensor term first
171 dg::blas2::symv( m_rightx, x, m_helper); //R_x*f
172 dg::blas2::symv(-1.0, m_leftx, m_helper, 0.0, m_tempx); //L_x R_x *f
173 dg::blas2::symv(-1.0, m_righty, m_helper, 0.0, m_tempyx); //R_y R_x*f
174 dg::blas2::symv( m_righty, x, m_helper); //R_y*f
175 dg::blas2::symv(-1.0, m_lefty, m_helper, 0.0, m_tempy); //L_y R_y *f
176 dg::blas2::symv(-1.0, m_rightx, m_helper, 0.0, m_tempxy); //R_x R_y *f
177
178 dg::blas2::symv( m_jfactor, m_jumpX, x, 1., m_tempx);
179 dg::blas2::symv( m_jfactor, m_jumpY, x, 1., m_tempy);
180
181 //multiply sqrt(g) iota
182 dg::blas1::pointwiseDot( 1., m_tempx, m_iota, m_vol, 0., m_tempx);
183 dg::blas1::pointwiseDot( 1., m_tempyx, m_iota, m_vol, 0., m_tempyx);
184 dg::blas1::pointwiseDot( 1., m_tempy, m_iota, m_vol, 0., m_tempy);
185 dg::blas1::pointwiseDot( 1., m_tempxy, m_iota, m_vol, 0., m_tempxy);
186
187 dg::blas2::symv( m_rightx, m_tempx, m_helper);
188 dg::blas2::symv(-1.0, m_leftx, m_helper, 0.0, m_temp); //L_x R_x
189 dg::blas2::symv( m_leftx, m_tempyx, m_helper);
190 dg::blas2::symv(-1.0, m_lefty, m_helper, 1.0, m_temp); //L_y L_x
191 dg::blas2::symv( m_righty, m_tempy, m_helper);
192 dg::blas2::symv(-1.0, m_lefty, m_helper, 1.0, m_temp); //L_y R_y
193 dg::blas2::symv( m_lefty, m_tempxy, m_helper);
194 dg::blas2::symv(-1.0, m_leftx, m_helper, 1.0, m_temp); //L_x L_y
195
196 dg::blas2::symv( m_jfactor, m_jumpX, m_tempx, 1., m_temp);
197 dg::blas2::symv( m_jfactor, m_jumpY, m_tempy, 1., m_temp);
198
199 dg::blas1::pointwiseDivide(m_temp, m_vol, m_temp); //multiply sqrt(g)^(-1)
200
201 //-lap (iota lap f) term
202 dg::blas2::symv( m_laplaceM_iota, x, m_tempx);
203 dg::blas1::pointwiseDot( m_iota, m_tempx, m_tempx);
204 dg::blas2::symv(-1.0, m_laplaceM_iota, m_tempx, 2.0, m_temp);
205
206 //elliptic term - div (chi nabla f)
207 dg::blas2::symv(1.0, m_laplaceM_chi, x, 1., m_temp);
208
209 dg::blas1::axpby(alpha, m_temp, beta, y);
210
211 }
212
213 private:
214 bc inverse( bc bound)
215 {
216 if( bound == DIR) return NEU;
217 if( bound == NEU) return DIR;
218 if( bound == DIR_NEU) return NEU_DIR;
219 if( bound == NEU_DIR) return DIR_NEU;
220 return PER;
221 }
222 direction inverse( direction dir)
223 {
224 if( dir == forward) return backward;
225 if( dir == backward) return forward;
226 return centered;
227 }
228 Elliptic<Geometry, Matrix, Container> m_laplaceM_chi, m_laplaceM_iota;
229 Matrix m_leftx, m_lefty, m_rightx, m_righty, m_jumpX, m_jumpY;
230 Container m_temp, m_tempx, m_tempy, m_tempxy, m_tempyx, m_iota, m_helper;
231 SparseTensor<Container> m_chi;
232 SparseTensor<Container> m_metric;
233 Container m_sigma, m_vol;
234 value_type m_jfactor;
235};
236
237
238} //namespace mat
240template< class G, class M, class V>
241struct TensorTraits< mat::TensorElliptic<G, M, V> >
242{
244 using tensor_category = SelfMadeMatrixTag;
245};
247} //namespace dg
248
DG_DEVICE T one(T x, Ts ...xs)
void axpby(value_type alpha, const ContainerType1 &x, value_type1 beta, ContainerType &y)
void pointwiseDot(value_type alpha, const ContainerType1 &x1, const ContainerType2 &x2, value_type1 beta, ContainerType &y)
void assign(const from_ContainerType &from, ContainerType &to, Params &&... ps)
void pointwiseDivide(value_type alpha, const ContainerType1 &x1, const ContainerType2 &x2, value_type1 beta, ContainerType &y)
void transfer(const MatrixType &x, AnotherMatrixType &y)
void symv(MatrixType &&M, const ContainerType1 &x, ContainerType2 &y)
auto dx(const Topology &g, dg::bc bc, dg::direction dir=centered)
auto dy(const Topology &g, dg::bc bc, dg::direction dir=centered)
auto jumpY(const Topology &g, bc bc)
direction
auto jumpX(const Topology &g, bc bc)
backward
centered
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
auto evaluate(Functor &&f, const Topology &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)
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:168
const Container & weights() const
Return the weights making the operator self-adjoint.
Definition tensorelliptic.h:87
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:107
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:93
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:146
void set_chi(const ContainerType0 &chi)
Set Chi in the above formula.
Definition tensorelliptic.h:100
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:116
get_value_type< Container > value_type
Definition tensorelliptic.h:29
void symv(const ContainerType0 &x, ContainerType1 &y)
Definition tensorelliptic.h:151
Matrix matrix_type
Definition tensorelliptic.h:28