Discontinuous Galerkin Library
#include "dg/algorithm.h"
dx.h
Go to the documentation of this file.
1#pragma once
2
3#include <cassert>
4
6#include "grid.h"
7#include "functions.h"
8#include "operator.h"
9#include "weights.h"
10
11//What happens for N=1?
15namespace dg
16{
17namespace create
18{
21
22
35template<class real_type>
36EllSparseBlockMat<real_type> dx_symm(int n, int N, real_type h, bc bcx)
37{
38
39 Operator<real_type> l = create::lilj<real_type>(n);
40 Operator<real_type> r = create::rirj<real_type>(n);
41 Operator<real_type> lr = create::lirj<real_type>(n);
42 Operator<real_type> rl = create::rilj<real_type>(n);
43 Operator<real_type> d = create::pidxpj<real_type>(n);
44 Operator<real_type> t = create::pipj_inv<real_type>(n);
45 t *= 2./h;
46
47 Operator< real_type> a = 1./2.*t*(d-d.transpose());
48 //bcx = PER
49 Operator<real_type> a_bound_right(a), a_bound_left(a);
50 //left boundary
51 if( bcx == DIR || bcx == DIR_NEU )
52 a_bound_left += 0.5*t*l;
53 else if (bcx == NEU || bcx == NEU_DIR)
54 a_bound_left -= 0.5*t*l;
55 //right boundary
56 if( bcx == DIR || bcx == NEU_DIR)
57 a_bound_right -= 0.5*t*r;
58 else if( bcx == NEU || bcx == DIR_NEU)
59 a_bound_right += 0.5*t*r;
60 if( bcx == PER ) //periodic bc
61 a_bound_left = a_bound_right = a;
62 Operator<real_type> b = t*(1./2.*rl);
63 Operator<real_type> bp = t*(-1./2.*lr); //pitfall: T*-m^T is NOT -(T*m)^T
64 //transform to XSPACE
65 RealGrid1d<real_type> g( 0,1, n, N);
66 Operator<real_type> backward=g.dlt().backward();
67 Operator<real_type> forward=g.dlt().forward();
68 a = backward*a*forward, a_bound_left = backward*a_bound_left*forward;
69 b = backward*b*forward, a_bound_right = backward*a_bound_right*forward;
70 bp = backward*bp*forward;
71 //assemble the matrix
72 if( bcx != PER)
73 {
74 EllSparseBlockMat<real_type> A(N, N, 3, 6, n);
75 for( int i=0; i<n; i++)
76 for( int j=0; j<n; j++)
77 {
78 A.data[(0*n+i)*n+j] = bp(i,j);
79 A.data[(1*n+i)*n+j] = a(i,j);
80 A.data[(2*n+i)*n+j] = b(i,j);
81 A.data[(3*n+i)*n+j] = a_bound_left(i,j);
82 A.data[(4*n+i)*n+j] = a_bound_right(i,j);
83 A.data[(5*n+i)*n+j] = 0; //to invalidate periodic entries
84 }
85 A.data_idx[0*3+0] = 3; //a_bound_left
86 A.cols_idx[0*3+0] = 0;
87 A.data_idx[0*3+1] = 2; //b
88 A.cols_idx[0*3+1] = 1;
89 A.data_idx[0*3+2] = 5; //0
90 A.cols_idx[0*3+2] = 1; //prevent unnecessary data fetch
91 for( int i=1; i<N-1; i++)
92 for( int d=0; d<3; d++)
93 {
94 A.data_idx[i*3+d] = d; //bp, a, b
95 A.cols_idx[i*3+d] = i+d-1;
96 }
97 A.data_idx[(N-1)*3+0] = 0; //bp
98 A.cols_idx[(N-1)*3+0] = N-2;
99 A.data_idx[(N-1)*3+1] = 4; //a_bound_right
100 A.cols_idx[(N-1)*3+1] = N-1;
101 A.data_idx[(N-1)*3+2] = 5; //0
102 A.cols_idx[(N-1)*3+2] = N-1; //prevent unnecessary data fetch
103 return A;
104
105 }
106 else //periodic
107 {
108 EllSparseBlockMat<real_type> A(N, N, 3, 3, n);
109 for( int i=0; i<n; i++)
110 for( int j=0; j<n; j++)
111 {
112 A.data[(0*n+i)*n+j] = bp(i,j);
113 A.data[(1*n+i)*n+j] = a(i,j);
114 A.data[(2*n+i)*n+j] = b(i,j);
115 }
116 for( int i=0; i<N; i++)
117 for( int d=0; d<3; d++)
118 {
119 A.data_idx[i*3+d] = d; //bp, a, b
120 A.cols_idx[i*3+d] = (i+d-1+N)%N;
121 }
122 return A;
123 }
124};
125
137template<class real_type>
138EllSparseBlockMat<real_type> dx_plus( int n, int N, real_type h, bc bcx )
139{
140
141 Operator<real_type> l = create::lilj<real_type>(n);
142 Operator<real_type> r = create::rirj<real_type>(n);
143 Operator<real_type> lr = create::lirj<real_type>(n);
144 Operator<real_type> rl = create::rilj<real_type>(n);
145 Operator<real_type> d = create::pidxpj<real_type>(n);
146 Operator<real_type> t = create::pipj_inv<real_type>(n);
147 t *= 2./h;
148 Operator<real_type> a = t*(-l-d.transpose());
149 //if( dir == backward) a = -a.transpose();
150 Operator<real_type> a_bound_left = a; //PER, NEU and NEU_DIR
151 Operator<real_type> a_bound_right = a; //PER, DIR and NEU_DIR
152 if( bcx == dg::DIR || bcx == dg::DIR_NEU)
153 a_bound_left = t*(-d.transpose());
154 if( bcx == dg::NEU || bcx == dg::DIR_NEU)
155 a_bound_right = t*(d);
156 Operator<real_type> b = t*rl;
157 //transform to XSPACE
158 RealGrid1d<real_type> g( 0,1, n, N);
159 Operator<real_type> backward=g.dlt().backward();
160 Operator<real_type> forward=g.dlt().forward();
161 a = backward*a*forward, a_bound_left = backward*a_bound_left*forward;
162 b = backward*b*forward, a_bound_right = backward*a_bound_right*forward;
163 //assemble the matrix
164 if( bcx != PER)
165 {
166 EllSparseBlockMat<real_type> A(N, N, 2, 5, n);
167 for( int i=0; i<n; i++)
168 for( int j=0; j<n; j++)
169 {
170 A.data[(0*n+i)*n+j] = a(i,j);
171 A.data[(1*n+i)*n+j] = b(i,j);
172 A.data[(2*n+i)*n+j] = a_bound_left(i,j);
173 A.data[(3*n+i)*n+j] = a_bound_right(i,j);
174 A.data[(4*n+i)*n+j] = 0; //to invalidate periodic entries
175 }
176 A.data_idx[0*2+0] = 2; //a_bound_left
177 A.cols_idx[0*2+0] = 0;
178 A.data_idx[0*2+1] = 1; //b
179 A.cols_idx[0*2+1] = 1;
180 for( int i=1; i<N-1; i++) //a
181 for( int d=0; d<2; d++)
182 {
183 A.data_idx[i*2+d] = d; //a, b
184 A.cols_idx[i*2+d] = i+d; //0,1
185 }
186 A.data_idx[(N-1)*2+0] = 3; //a_bound_right
187 A.cols_idx[(N-1)*2+0] = N-1;
188 A.data_idx[(N-1)*2+1] = 4; //0
189 A.cols_idx[(N-1)*2+1] = N-1; //prevent unnecessary data fetch
190 return A;
191
192 }
193 else //periodic
194 {
195 EllSparseBlockMat<real_type> A(N, N, 2, 2, n);
196 for( int i=0; i<n; i++)
197 for( int j=0; j<n; j++)
198 {
199 A.data[(0*n+i)*n+j] = a(i,j);
200 A.data[(1*n+i)*n+j] = b(i,j);
201 }
202 for( int i=0; i<N; i++)
203 for( int d=0; d<2; d++)
204 {
205 A.data_idx[i*2+d] = d; //a, b
206 A.cols_idx[i*2+d] = (i+d+N)%N;
207 }
208 return A;
209 }
210};
211
223template<class real_type>
224EllSparseBlockMat<real_type> dx_minus( int n, int N, real_type h, bc bcx )
225{
226 Operator<real_type> l = create::lilj<real_type>(n);
227 Operator<real_type> r = create::rirj<real_type>(n);
228 Operator<real_type> lr = create::lirj<real_type>(n);
229 Operator<real_type> rl = create::rilj<real_type>(n);
230 Operator<real_type> d = create::pidxpj<real_type>(n);
231 Operator<real_type> t = create::pipj_inv<real_type>(n);
232 t *= 2./h;
233 Operator<real_type> a = t*(l+d);
234 //if( dir == backward) a = -a.transpose();
235 Operator<real_type> a_bound_right = a; //PER, NEU and DIR_NEU
236 Operator<real_type> a_bound_left = a; //PER, DIR and DIR_NEU
237 if( bcx == dg::DIR || bcx == dg::NEU_DIR)
238 a_bound_right = t*(-d.transpose());
239 if( bcx == dg::NEU || bcx == dg::NEU_DIR)
240 a_bound_left = t*d;
241 Operator<real_type> bp = -t*lr;
242 //transform to XSPACE
243 RealGrid1d<real_type> g( 0,1, n, N);
244 Operator<real_type> backward=g.dlt().backward();
245 Operator<real_type> forward=g.dlt().forward();
246 a = backward*a*forward, a_bound_left = backward*a_bound_left*forward;
247 bp = backward*bp*forward, a_bound_right = backward*a_bound_right*forward;
248
249 //assemble the matrix
250 if(bcx != dg::PER)
251 {
252 EllSparseBlockMat<real_type> A(N, N, 2, 5, n);
253 for( int i=0; i<n; i++)
254 for( int j=0; j<n; j++)
255 {
256 A.data[(0*n+i)*n+j] = bp(i,j);
257 A.data[(1*n+i)*n+j] = a(i,j);
258 A.data[(2*n+i)*n+j] = a_bound_left(i,j);
259 A.data[(3*n+i)*n+j] = a_bound_right(i,j);
260 A.data[(4*n+i)*n+j] = 0; //to invalidate periodic entries
261 }
262 A.data_idx[0*2+0] = 2; //a_bound_left
263 A.cols_idx[0*2+0] = 0;
264 A.data_idx[0*2+1] = 4; //0
265 A.cols_idx[0*2+1] = 0; //prevent data fetch
266 for( int i=1; i<N-1; i++) //a
267 for( int d=0; d<2; d++)
268 {
269 A.data_idx[i*2+d] = d; //bp, a
270 A.cols_idx[i*2+d] = i+d-1;
271 }
272 A.data_idx[(N-1)*2+0] = 0; //bp
273 A.cols_idx[(N-1)*2+0] = N-2;
274 A.data_idx[(N-1)*2+1] = 3; //a_bound_right
275 A.cols_idx[(N-1)*2+1] = N-1;
276 return A;
277
278 }
279 else //periodic
280 {
281 EllSparseBlockMat<real_type> A(N, N, 2, 2, n);
282 for( int i=0; i<n; i++)
283 for( int j=0; j<n; j++)
284 {
285 A.data[(0*n+i)*n+j] = bp(i,j);
286 A.data[(1*n+i)*n+j] = a(i,j);
287 }
288 for( int i=0; i<N; i++)
289 for( int d=0; d<2; d++)
290 {
291 A.data_idx[i*2+d] = d; //bp, a
292 A.cols_idx[i*2+d] = (i+d-1+N)%N; //-1, 0
293 }
294 return A;
295 }
296};
297
309template<class real_type>
310EllSparseBlockMat<real_type> jump( int n, int N, real_type h, bc bcx)
311{
312 Operator<real_type> l = create::lilj<real_type>(n);
313 Operator<real_type> r = create::rirj<real_type>(n);
314 Operator<real_type> lr = create::lirj<real_type>(n);
315 Operator<real_type> rl = create::rilj<real_type>(n);
316 Operator<real_type> a = l+r;
317 Operator<real_type> a_bound_left = a;//DIR and PER
318 if( bcx == NEU || bcx == NEU_DIR)
319 a_bound_left = r;
320 Operator<real_type> a_bound_right = a; //DIR and PER
321 if( bcx == NEU || bcx == DIR_NEU)
322 a_bound_right = l;
323 Operator<real_type> b = -rl;
324 Operator<real_type> bp = -lr;
325 //transform to XSPACE
326 Operator<real_type> t = create::pipj_inv<real_type>(n);
327 t *= 2./h;
328 RealGrid1d<real_type> g( 0,1, n, N);
329 Operator<real_type> backward=g.dlt().backward();
330 Operator<real_type> forward=g.dlt().forward();
331 a = backward*t*a*forward, a_bound_left = backward*t*a_bound_left*forward;
332 b = backward*t*b*forward, a_bound_right = backward*t*a_bound_right*forward;
333 bp = backward*t*bp*forward;
334 //assemble the matrix
335 if(bcx != dg::PER)
336 {
337 EllSparseBlockMat<real_type> A(N, N, 3, 6, n);
338 for( int i=0; i<n; i++)
339 for( int j=0; j<n; j++)
340 {
341 A.data[(0*n+i)*n+j] = bp(i,j);
342 A.data[(1*n+i)*n+j] = a(i,j);
343 A.data[(2*n+i)*n+j] = b(i,j);
344 A.data[(3*n+i)*n+j] = a_bound_left(i,j);
345 A.data[(4*n+i)*n+j] = a_bound_right(i,j);
346 A.data[(5*n+i)*n+j] = 0; //to invalidate periodic entries
347 }
348 A.data_idx[0*3+0] = 3; //a_bound_left
349 A.cols_idx[0*3+0] = 0;
350 A.data_idx[0*3+1] = 2; //b
351 A.cols_idx[0*3+1] = 1;
352 A.data_idx[0*3+2] = 5; //0
353 A.cols_idx[0*3+2] = 1; //prevent unnecessary data fetch
354 for( int i=1; i<N-1; i++) //a
355 for( int d=0; d<3; d++)
356 {
357 A.data_idx[i*3+d] = d; //bp, a, b
358 A.cols_idx[i*3+d] = i+d-1;
359 }
360 A.data_idx[(N-1)*3+0] = 0; //bp
361 A.cols_idx[(N-1)*3+0] = N-2;
362 A.data_idx[(N-1)*3+1] = 4; //a_bound_right
363 A.cols_idx[(N-1)*3+1] = N-1;
364 A.data_idx[(N-1)*3+2] = 5; //0
365 A.cols_idx[(N-1)*3+2] = N-1; //prevent unnecessary data fetch
366 return A;
367
368 }
369 else //periodic
370 {
371 EllSparseBlockMat<real_type> A(N, N, 3, 3, n);
372 for( int i=0; i<n; i++)
373 for( int j=0; j<n; j++)
374 {
375 A.data[(0*n+i)*n+j] = bp(i,j);
376 A.data[(1*n+i)*n+j] = a(i,j);
377 A.data[(2*n+i)*n+j] = b(i,j);
378 }
379 for( int i=0; i<N; i++)
380 for( int d=0; d<3; d++)
381 {
382 A.data_idx[i*3+d] = d; //bp, a, b
383 A.cols_idx[i*3+d] = (i+d-1+N)%N;
384 }
385 return A;
386 }
387};
388
401template<class real_type>
402EllSparseBlockMat<real_type> dx_normed( int n, int N, real_type h, bc bcx, direction dir )
403{
404 if( dir == centered)
405 return create::dx_symm(n, N, h, bcx);
406 else if (dir == forward)
407 return create::dx_plus(n, N, h, bcx);
408 else if (dir == backward)
409 return create::dx_minus(n, N, h, bcx);
411}
413
416
426template<class real_type>
428{
429 return dx_normed( g.n(), g.N(), g.h(), bcx, dir);
430}
431
442template<class real_type>
444{
445 return dx( g, g.bcx(), dir);
446}
447
457template<class real_type>
459{
460 return jump( g.n(), g.N(), g.h(), bcx);
461}
471template<class real_type>
473{
474 return jump( g, g.bcx());
475}
477
478
479} //namespace create
480} //namespace dg
481
Operator transpose() const
Transposition.
Definition: operator.h:152
Some utility functions for the dg::evaluate routines.
base topology classes
EllSparseBlockMat< real_type > dx(const aRealTopology2d< real_type > &g, bc bcx, direction dir=centered)
Create 2d derivative in x-direction.
Definition: derivatives.h:33
bc
Switch between boundary conditions.
Definition: enums.h:15
direction
Direction of a discrete derivative.
Definition: enums.h:97
@ NEU_DIR
Neumann on left, Dirichlet on right boundary.
Definition: enums.h:19
@ PER
periodic boundaries
Definition: enums.h:16
@ NEU
Neumann on both boundaries.
Definition: enums.h:20
@ DIR
homogeneous dirichlet boundaries
Definition: enums.h:17
@ DIR_NEU
Dirichlet on left, Neumann on right boundary.
Definition: enums.h:18
@ backward
backward derivative (cell to the left and current cell)
Definition: enums.h:99
@ forward
forward derivative (cell to the right and current cell)
Definition: enums.h:98
@ centered
centered derivative (cell to the left and right and current cell)
Definition: enums.h:100
EllSparseBlockMat< real_type > dx_normed(int n, int N, real_type h, bc bcx, direction dir)
Create and assemble a host Matrix for normed derivative in 1d.
Definition: dx.h:402
EllSparseBlockMat< real_type > dx_plus(int n, int N, real_type h, bc bcx)
Create and assemble a host Matrix for the forward 1d single derivative.
Definition: dx.h:138
EllSparseBlockMat< real_type > dx_symm(int n, int N, real_type h, bc bcx)
Create and assemble a host Matrix for the centered 1d single derivative.
Definition: dx.h:36
EllSparseBlockMat< real_type > jump(int n, int N, real_type h, bc bcx)
Create and assemble a host Matrix for the jump terms in 1d.
Definition: dx.h:310
EllSparseBlockMat< real_type > dx_minus(int n, int N, real_type h, bc bcx)
Create and assemble a host Matrix for the backward 1d single derivative.
Definition: dx.h:224
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...
Ell Sparse Block Matrix format.
Definition: sparseblockmat.h:46
thrust::host_vector< int > data_idx
has the same size as cols_idx and contains indices into the data array, i.e. the block number
Definition: sparseblockmat.h:128
thrust::host_vector< value_type > data
The data array is of size n*n*num_different_blocks and contains the blocks. The first block is contai...
Definition: sparseblockmat.h:126
thrust::host_vector< int > cols_idx
is of size num_rows*num_blocks_per_line and contains the column indices % n into the vector
Definition: sparseblockmat.h:127
1D grid
Definition: grid.h:80
real_type h() const
cell size
Definition: grid.h:129
bc bcx() const
boundary conditions
Definition: grid.h:147
unsigned n() const
number of polynomial coefficients
Definition: grid.h:141
const DLT< real_type > & dlt() const
the discrete legendre transformation
Definition: grid.h:197
unsigned N() const
number of cells
Definition: grid.h:135
Creation functions for integration weights and their inverse.