Discontinuous Galerkin Library
#include "dg/algorithm.h"
stencil.h
Go to the documentation of this file.
1#pragma once
2
3#include <cusp/coo_matrix.h>
4#include "xspacelib.h"
5#ifdef MPI_VERSION
6#include "mpi_projection.h" // for convert function
7#endif // MPI_VERSION
8
12namespace dg
13{
14namespace create
15{
17namespace detail
18{
19template<class real_type>
20 void set_boundary(
21 cusp::array1d<real_type, cusp::host_memory>& values,
22 cusp::array1d<int, cusp::host_memory>& column_indices,
23 dg::bc bcx,
24 int num_cols)
25{
26 for( unsigned k=0; k<values.size(); k++)
27 {
28 if( column_indices[k] < 0 )
29 {
30 if( bcx == dg::NEU || bcx == dg::NEU_DIR)
31 column_indices[k] = -(column_indices[k]+1);
32 else if( bcx == dg::DIR || bcx == dg::DIR_NEU)
33 {
34 column_indices[k] = -(column_indices[k]+1);
35 values[k] *= -1;
36 }
37 else if( bcx == dg::PER)
38 column_indices[k] += num_cols;
39 }
40 else if( column_indices[k] >= num_cols)
41 {
42 if( bcx == dg::NEU || bcx == dg::DIR_NEU)
43 column_indices[k] = 2*num_cols-1-column_indices[k];
44 else if( bcx == dg::DIR || bcx == dg::NEU_DIR)
45 {
46 column_indices[k] = 2*num_cols-1-column_indices[k];
47 values[k] *= -1;
48 }
49 else if( bcx == dg::PER)
50 column_indices[k] -= num_cols;
51 }
52 }
53}
54
55template<class real_type>
56cusp::csr_matrix<int, real_type, cusp::host_memory> window_stencil(
57 unsigned stencil_size,
58 const RealGrid1d<real_type>& local,
59 const RealGrid1d<real_type>& global,
60 dg::bc bcx)
61{
62 cusp::array1d<real_type, cusp::host_memory> values;
63 cusp::array1d<int, cusp::host_memory> row_offsets;
64 cusp::array1d<int, cusp::host_memory> column_indices;
65
66 unsigned num_rows = local.size();
67 unsigned num_cols = global.size();
68 unsigned radius = stencil_size/2;
69 int L0 = round((local.x0() - global.x0())/global.h())*global.n();
70
71 row_offsets.push_back(0);
72 for( unsigned k=0; k<num_rows; k++)
73 {
74 row_offsets.push_back(stencil_size + row_offsets[k]);
75 for( unsigned l=0; l<stencil_size; l++)
76 {
77 column_indices.push_back( L0 + (int)(k + l) - (int)radius);
78 values.push_back( 1.0);
79 }
80 }
81 set_boundary( values, column_indices, bcx, num_cols);
82
83 cusp::csr_matrix<int, real_type, cusp::host_memory> A(
84 num_rows, num_cols, values.size());
85 A.row_offsets = row_offsets;
86 A.column_indices = column_indices;
87 A.values = values;
88 return A;
89}
90
91template<class real_type>
92cusp::csr_matrix<int, real_type, cusp::host_memory> limiter_stencil(
93 const RealGrid1d<real_type>& local,
94 const RealGrid1d<real_type>& global,
95 dg::bc bcx)
96{
97 cusp::array1d<real_type, cusp::host_memory> values;
98 cusp::array1d<int, cusp::host_memory> row_offsets;
99 cusp::array1d<int, cusp::host_memory> column_indices;
100
101 unsigned num_rows = local.size();
102 unsigned num_cols = global.size();
103 int L0 = round((local.x0() - global.x0())/global.h())*global.n();
104 // We need the first two lines of forward
105 dg::Operator<real_type> forward = local.dlt().forward();
106 // and the second column of backward
107 dg::Operator<real_type> backward = local.dlt().backward();
108 if( global.n() == 1)
109 throw dg::Error( dg::Message(_ping_) << "Limiter stencil not possible for n==1!");
110
111
112 row_offsets.push_back( 0);
113 for( unsigned k=0; k<local.N(); k++)
114 {
115 row_offsets.push_back(row_offsets[row_offsets.size()-1] + 3*local.n());
116 for( unsigned j=1; j<local.n(); j++)
117 row_offsets.push_back(row_offsets[row_offsets.size()-1]);
118 // Order is important
119 for( unsigned j=0; j<local.n(); j++)
120 {
121 column_indices.push_back( L0 + (int)((k-1)*global.n() + j) );
122 values.push_back( forward(0, j ));
123 }
124 for( unsigned j=0; j<local.n(); j++)
125 {
126 column_indices.push_back( L0 + (int)(k*global.n() + j ));
127 values.push_back( forward(1, j ));
128 }
129 for( unsigned j=0; j<local.n(); j++)
130 {
131 column_indices.push_back( L0 + (int)((k+1)*global.n() + j));
132 values.push_back( backward(j, 1) );
133 }
134 }
135 assert( row_offsets.size() == num_rows+1);
136 set_boundary( values, column_indices, bcx, num_cols);
137
138 cusp::csr_matrix<int, real_type, cusp::host_memory> A(
139 num_rows, num_cols, values.size());
140 A.row_offsets = row_offsets;
141 A.column_indices = column_indices;
142 A.values = values;
143 return A;
144}
145
146template<class real_type>
147cusp::csr_matrix< int, real_type, cusp::host_memory> identity_matrix( const RealGrid1d<real_type>& local, const RealGrid1d<real_type>& global)
148{
149 cusp::csr_matrix<int,real_type,cusp::host_memory> A( local.size(),
150 global.size(), local.size());
151 int L0 = round((local.x0() - global.x0())/global.h())*global.n();
152 A.row_offsets[0] = 0;
153 for( unsigned i=0; i<local.size(); i++)
154 {
155 A.row_offsets[i+1] = 1 + A.row_offsets[i];
156 A.column_indices[i] = L0 + i;
157 A.values[i] = 1.;
158 }
159 return A;
160}
161
162} //namespace detail
164
167
182template<class real_type>
184 unsigned window_size,
185 const RealGrid1d<real_type>& g,
186 dg::bc bcx)
187{
188 return detail::window_stencil( window_size, g, g, bcx);
189}
190
205template<class real_type>
207 const RealGrid1d<real_type>& g,
208 dg::bc bound)
209{
210 return detail::limiter_stencil( g, g, bound);
211}
212
213
214
234template<class real_type>
236 std::array<int,2> window_size,
238 dg::bc bcx, dg::bc bcy)
239{
240 auto mx = detail::window_stencil(window_size[0], g.gx(), g.gx(), bcx);
241 auto my = detail::window_stencil(window_size[1], g.gy(), g.gy(), bcy);
242 return dg::tensorproduct( my, mx);
243}
244
247template<class real_type>
249 enum coo3d direction,
251 dg::bc bound)
252{
253 if( direction == dg::coo3d::x)
254 {
255 auto mx = detail::limiter_stencil(g.gx(), g.gx(), bound);
256 auto einsy = detail::identity_matrix( g.gy(), g.gy());
257 return dg::tensorproduct( einsy, mx);
258 }
259 auto my = detail::limiter_stencil(g.gy(), g.gy(), bound);
260 auto einsx = detail::identity_matrix( g.gx(), g.gx());
261 return dg::tensorproduct( my, einsx);
262}
263
266template<class real_type>
268 enum coo3d direction,
270 dg::bc bound)
271{
272 if( direction == dg::coo3d::x)
273 {
274 auto mx = detail::limiter_stencil(g.gx(), g.gx(), bound);
275 auto einsy = detail::identity_matrix( g.gy(), g.gy());
276 auto einsz = detail::identity_matrix( g.gz(), g.gz());
277 auto temp = dg::tensorproduct( einsy, mx);
278 return dg::tensorproduct( einsz, temp);
279 }
280 if( direction == dg::coo3d::y)
281 {
282 auto einsx = detail::identity_matrix( g.gx(), g.gx());
283 auto my = detail::limiter_stencil(g.gy(), g.gy(), bound);
284 auto einsz = detail::identity_matrix( g.gz(), g.gz());
285 return dg::tensorproduct( einsz, dg::tensorproduct( my, einsx));
286 }
287 auto mz = detail::limiter_stencil(g.gz(), g.gz(), bound);
288 auto einsy = detail::identity_matrix( g.gy(), g.gy());
289 auto einsx = detail::identity_matrix( g.gx(), g.gx());
290 return dg::tensorproduct( mz, dg::tensorproduct( einsy, einsx));
291}
292
312template<class real_type>
314 std::array<int,2> window_size,
316 dg::bc bcx, dg::bc bcy)
317{
318 auto mx = detail::window_stencil(window_size[0], g.gx(), g.gx(), bcx);
319 auto my = detail::window_stencil(window_size[1], g.gy(), g.gy(), bcy);
320 auto mz = detail::identity_matrix( g.gz(), g.gz());
321 return dg::tensorproduct( mz, dg::tensorproduct( my, mx));
322}
323
324#ifdef MPI_VERSION
326template<class real_type>
328 std::array<int,2> window_size,
330 dg::bc bcx, dg::bc bcy)
331{
332 auto mx = detail::window_stencil(window_size[0], g.local().gx(), g.global().gx(), bcx);
333 auto my = detail::window_stencil(window_size[1], g.local().gy(), g.global().gy(), bcy);
334 auto local = dg::tensorproduct( my, mx);
335 return dg::convert( local, g);
336}
337
339template<class real_type>
341 std::array<int,2> window_size,
343 dg::bc bcx, dg::bc bcy)
344{
345 auto mx = detail::window_stencil(window_size[0], g.local().gx(), g.global().gx(), bcx);
346 auto my = detail::window_stencil(window_size[1], g.local().gy(), g.global().gy(), bcy);
347 auto mz = detail::identity_matrix( g.local().gz(), g.global().gz());
348 auto out = dg::tensorproduct( mz, dg::tensorproduct( my, mx));
349 return dg::convert( out, g);
350}
351
354template<class real_type>
356 enum coo3d direction,
358 dg::bc bound)
359{
360 if( direction == dg::coo3d::x)
361 {
362 auto mx = detail::limiter_stencil(g.local().gx(), g.global().gx(), bound);
363 auto einsy = detail::identity_matrix( g.local().gy(), g.global().gy());
364 auto local = dg::tensorproduct( einsy, mx);
365 return dg::convert( (dg::IHMatrix)local, g);
366 }
367 auto my = detail::limiter_stencil(g.local().gy(), g.global().gy(), bound);
368 auto einsx = detail::identity_matrix( g.local().gx(), g.global().gx());
369 auto local = dg::tensorproduct( my, einsx);
370 return dg::convert( local, g);
371}
372
375template<class real_type>
377 enum coo3d direction,
379 dg::bc bound)
380{
381 if( direction == dg::coo3d::x)
382 {
383 auto mx = detail::limiter_stencil(g.local().gx(), g.global().gx(), bound);
384 auto einsy = detail::identity_matrix( g.local().gy(), g.global().gy());
385 auto einsz = detail::identity_matrix( g.local().gz(), g.global().gz());
386 auto local = dg::tensorproduct( einsz, dg::tensorproduct( einsy, mx));
387 return dg::convert( local, g);
388 }
389 if( direction == dg::coo3d::y)
390 {
391 auto einsx = detail::identity_matrix( g.local().gx(), g.global().gx());
392 auto my = detail::limiter_stencil(g.local().gy(), g.global().gy(), bound);
393 auto einsz = detail::identity_matrix( g.local().gz(), g.global().gz());
394 auto local = dg::tensorproduct( einsz, dg::tensorproduct( my, einsx));
395 return dg::convert( local, g);
396 }
397 auto mz = detail::limiter_stencil(g.local().gz(), g.global().gz(), bound);
398 auto einsy = detail::identity_matrix( g.local().gy(), g.global().gy());
399 auto einsx = detail::identity_matrix( g.local().gx(), g.global().gx());
400 auto local = dg::tensorproduct( mz, dg::tensorproduct( einsy, einsx));
401 return dg::convert( local, g);
402}
403
404#endif // MPI_VERSION
405
407} // namespace create
408} // namespace dg
class intended for the use in throw statements
Definition: exceptions.h:83
small class holding a stringstream
Definition: exceptions.h:29
#define _ping_
Definition: exceptions.h:12
coo3d
3d contra- and covariant coordinates
Definition: enums.h:177
bc
Switch between boundary conditions.
Definition: enums.h:15
direction
Direction of a discrete derivative.
Definition: enums.h:97
@ y
y direction
@ x
x direction
@ 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
Operator< T > tensorproduct(const Operator< T > &op1, const Operator< T > &op2)
Form the tensor product between two operators.
Definition: operator_tensor.h:27
dg::MIHMatrix_t< real_type > convert(const dg::IHMatrix_t< real_type > &global, const ConversionPolicy &policy)
Convert a (row-distributed) matrix with local row and global column indices to a row distributed MPI ...
Definition: mpi_projection.h:75
dg::MIHMatrix_t< real_type > window_stencil(std::array< int, 2 > window_size, const aRealMPITopology3d< real_type > &g, dg::bc bcx, dg::bc bcy)
A 2d centered window stencil.
Definition: stencil.h:340
dg::IHMatrix_t< real_type > limiter_stencil(const RealGrid1d< real_type > &g, dg::bc bound)
A stencil for the dg Slope limiter.
Definition: stencil.h:206
dg::MIHMatrix_t< real_type > limiter_stencil(enum coo3d direction, const aRealMPITopology3d< real_type > &g, dg::bc bound)
A stencil for the dg Slope limiter.
Definition: stencil.h:376
dg::IHMatrix_t< real_type > window_stencil(unsigned window_size, const RealGrid1d< real_type > &g, dg::bc bcx)
A 1d centered window stencil.
Definition: stencil.h:183
IHMatrix_t< double > IHMatrix
Definition: typedefs.h:47
cusp::csr_matrix< int, real_type, cusp::host_memory > IHMatrix_t
Definition: typedefs.h:37
Useful MPI typedefs and overloads of interpolation and projection.
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...
Distributed memory matrix class.
Definition: mpi_matrix.h:219
1D grid
Definition: grid.h:80
2D MPI abstract grid class
Definition: mpi_grid.h:45
const RealGrid2d< real_type > & local() const
Return a non-MPI grid local for the calling process.
Definition: mpi_grid.h:252
const RealGrid2d< real_type > & global() const
Return the global non-MPI grid.
Definition: mpi_grid.h:262
3D MPI Grid class
Definition: mpi_grid.h:329
const RealGrid3d< real_type > & global() const
Return the global non-MPI grid.
Definition: mpi_grid.h:562
const RealGrid3d< real_type > & local() const
Return a non-MPI grid local for the calling process.
Definition: mpi_grid.h:560
An abstract base class for two-dimensional grids.
Definition: grid.h:277
const RealGrid1d< real_type > & gy() const
The y-axis grid.
Definition: grid.h:379
const RealGrid1d< real_type > & gx() const
The x-axis grid.
Definition: grid.h:377
An abstract base class for three-dimensional grids.
Definition: grid.h:523
const RealGrid1d< real_type > & gz() const
The z-axis grid.
Definition: grid.h:664
const RealGrid1d< real_type > & gx() const
The x-axis grid.
Definition: grid.h:660
const RealGrid1d< real_type > & gy() const
The y-axis grid.
Definition: grid.h:662
utility functions