Discontinuous Galerkin Library
#include "dg/algorithm.h"
average_mpi.h
Go to the documentation of this file.
1#pragma once
2
3#include "mpi.h"
4#include "average.h"
5#include "mpi_grid.h"
6#include "mpi_weights.h"
7
11namespace dg{
12
14template<class container>
15void simple_mpi_average( unsigned nx, unsigned ny, const container& in0, const container& in1, container& out, MPI_Comm comm)
16{
17 const double* in0_ptr = thrust::raw_pointer_cast( in0.data());
18 const double* in1_ptr = thrust::raw_pointer_cast( in1.data());
19 double* out_ptr = thrust::raw_pointer_cast( out.data());
20 dg::View<const container> in0_view( in0_ptr, nx), in1_view( in1_ptr, nx);
21 dg::View<container> out_view( out_ptr, nx);
22 dg::blas1::pointwiseDot( 1., in0_view, in1_view, 0, out_view);
23 for( unsigned i=1; i<ny; i++)
24 {
25 in0_view.construct( in0_ptr+i*nx, nx);
26 in1_view.construct( in1_ptr+i*nx, nx);
27 dg::blas1::pointwiseDot( 1., in0_view, in1_view, 1, out_view);
28 }
29 static thrust::host_vector<double> send_buf;
30 send_buf.resize( nx);
31 dg::assign( out_view, send_buf);
32 MPI_Allreduce(MPI_IN_PLACE, send_buf.data(), nx, MPI_DOUBLE, MPI_SUM, comm);
33 dg::assign( send_buf, out);
34}
36
43template< class container>
44struct Average<MPI_Vector<container> >
45{
46
58 Average( const aMPITopology2d& g, enum coo2d direction, std::string mode = "exact") : m_mode( mode)
59 {
60 m_nx = g.local().Nx()*g.nx(), m_ny = g.local().Ny()*g.ny();
61 m_w=dg::construct<MPI_Vector<container>>(dg::create::weights(g, direction));
62 m_temp = m_w;
63 int remain_dims[] = {false,false}; //true true false
64 m_transpose = false;
65 unsigned size1d = 0;
67 {
68 dg::blas1::scal( m_w, 1./g.lx());
69 dg::blas1::scal( m_temp, 1./g.lx());
70 size1d = m_ny;
71 remain_dims[0] = true;
72 if( "simple" == mode)
73 dg::transpose( m_nx, m_ny, m_temp.data(), m_w.data());
74 }
75 else
76 {
77 m_transpose = true;
78 remain_dims[1] = true;
79 dg::blas1::scal( m_w, 1./g.ly());
80 dg::blas1::scal( m_temp, 1./g.ly());
81 if( "exact" == mode)
82 dg::transpose( m_nx, m_ny, m_temp.data(), m_w.data());
83 size1d = m_nx;
84 }
85
86 //Now get the reduction communicator
87 MPI_Cart_sub( g.communicator(), remain_dims, &m_comm);
88 exblas::mpi_reduce_communicator( m_comm, &m_comm_mod, &m_comm_mod_reduce);
89 // ... and the one perpendicular to it
90 for( unsigned i=0; i<2; i++)
91 remain_dims[i] = !remain_dims[i];
92 MPI_Comm comm2;
93 MPI_Cart_sub( g.communicator(), remain_dims, &comm2);
94 // with that construct the reduce mpi vec
95 thrust::host_vector<double> t1d( size1d);
96 m_temp1d = MPI_Vector<container>( dg::construct<container>( t1d), comm2);
97 if( !("exact"==mode || "simple" == mode))
98 throw dg::Error( dg::Message( _ping_) << "Mode must either be exact or simple!");
99 }
100
102 Average( const aMPITopology3d& g, enum coo3d direction, std::string mode = "exact") : m_mode( mode)
103 {
104 m_w = dg::construct<MPI_Vector<container>>(dg::create::weights(g, direction));
105 m_temp = m_w;
106 m_transpose = false;
107 unsigned nx = g.nx()*g.local().Nx(), ny = g.ny()*g.local().Ny(), nz = g.nz()*g.local().Nz();
108 int remain_dims[] = {false,false,false};
109 m_transpose = false;
110 if( direction == dg::coo3d::x) {
111 dg::blas1::scal( m_w, 1./g.lx());
112 dg::blas1::scal( m_temp, 1./g.lx());
113 m_nx = nx, m_ny = ny*nz;
114 remain_dims[0] = true;
115 if( "simple" == mode)
116 dg::transpose( m_nx, m_ny, m_temp.data(), m_w.data());
117 }
118 else if( direction == dg::coo3d::z) {
119 m_transpose = true;
120 remain_dims[2] = true;
121 m_nx = nx*ny, m_ny = nz;
122 dg::blas1::scal( m_w, 1./g.lz());
123 dg::blas1::scal( m_temp, 1./g.lz());
124 if( "exact" == mode)
125 dg::transpose( m_nx, m_ny, m_temp.data(), m_w.data());
126 }
127 else if( direction == dg::coo3d::xy) {
128 dg::blas1::scal( m_w, 1./g.lx()/g.ly());
129 dg::blas1::scal( m_temp, 1./g.lx()/g.ly());
130 m_nx = nx*ny, m_ny = nz;
131 remain_dims[0] = remain_dims[1] = true;
132 if( "simple" == mode)
133 dg::transpose( m_nx, m_ny, m_temp.data(), m_w.data());
134 }
135 else if( direction == dg::coo3d::yz) {
136 m_transpose = true;
137 m_nx = nx, m_ny = ny*nz;
138 remain_dims[1] = remain_dims[2] = true;
139 dg::blas1::scal( m_w, 1./g.ly()/g.lz());
140 dg::blas1::scal( m_temp, 1./g.ly()/g.lz());
141 if( "exact" == mode)
142 dg::transpose( m_nx, m_ny, m_temp.data(), m_w.data());
143 }
144 else
145 std::cerr << "Warning: this direction is not implemented\n";
146 //Now get the reduction communicator
147 MPI_Cart_sub( g.communicator(), remain_dims, &m_comm);
148 exblas::mpi_reduce_communicator( m_comm, &m_comm_mod, &m_comm_mod_reduce);
149 // ... and the one perpendicular to it
150 for( unsigned i=0; i<3; i++)
151 remain_dims[i] = !remain_dims[i];
152 MPI_Comm comm2;
153 MPI_Cart_sub( g.communicator(), remain_dims, &comm2);
154 // with that construct the reduce mpi vec
155 thrust::host_vector<double> t1d;
156 if(!m_transpose)
157 t1d = thrust::host_vector<double>( m_ny,0.);
158 else
159 t1d = thrust::host_vector<double>( m_nx,0.);
160 m_temp1d = MPI_Vector<container>( dg::construct<container>( t1d), comm2);
161 if( !("exact"==mode || "simple" == mode))
162 throw dg::Error( dg::Message( _ping_) << "Mode must either be exact or simple!");
163 }
177 void operator() (const MPI_Vector<container>& src, MPI_Vector<container>& res, bool extend = true)
178 {
179 if( !m_transpose)
180 {
181 //temp1d has size m_ny
182 if( "exact" == m_mode)
183 dg::mpi_average( m_nx, m_ny, src.data(), m_w.data(),
184 m_temp1d.data(), m_comm, m_comm_mod, m_comm_mod_reduce);
185 else
186 {
187 dg::transpose( m_nx, m_ny, src.data(), m_temp.data());
188 dg::simple_mpi_average( m_ny, m_nx, m_temp.data(), m_w.data(),
189 m_temp1d.data(), m_comm);
190 }
191
192 if( extend )
193 dg::extend_column( m_nx, m_ny, m_temp1d.data(), res.data());
194 else
195 res = m_temp1d;
196 }
197 else
198 {
199 //temp1d has size m_nx
200 if( "exact" == m_mode)
201 {
202 dg::transpose( m_nx, m_ny, src.data(), m_temp.data());
203 dg::mpi_average( m_ny, m_nx, m_temp.data(), m_w.data(),
204 m_temp1d.data(), m_comm, m_comm_mod, m_comm_mod_reduce);
205 }
206 else
207 dg::simple_mpi_average( m_nx, m_ny, src.data(), m_w.data(),
208 m_temp1d.data(), m_comm);
209
210 if( extend )
211 dg::extend_line( m_nx, m_ny, m_temp1d.data(), res.data());
212 else
213 res = m_temp1d;
214 }
215 }
216 private:
217 unsigned m_nx, m_ny;
218 MPI_Vector<container> m_w, m_temp, m_temp1d;
219 bool m_transpose;
220 MPI_Comm m_comm, m_comm_mod, m_comm_mod_reduce;
221 std::string m_mode;
222};
223
224
225}//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
void assign(const from_ContainerType &from, ContainerType &to, Params &&... ps)
Generic way to assign the contents of a from_ContainerType object to a ContainerType object optionall...
Definition: blas1.h:665
void scal(ContainerType &x, get_value_type< ContainerType > alpha)
Definition: blas1.h:185
void pointwiseDot(get_value_type< ContainerType > alpha, const ContainerType1 &x1, const ContainerType2 &x2, get_value_type< ContainerType > beta, ContainerType &y)
Definition: blas1.h:336
coo3d
3d contra- and covariant coordinates
Definition: enums.h:177
direction
Direction of a discrete derivative.
Definition: enums.h:97
coo2d
2d coordinates
Definition: enums.h:171
@ yz
yz plane
@ xy
xy plane
@ x
x direction
@ z
z direction
@ x
x direction
MPI_Vector< thrust::host_vector< real_type > > weights(const aRealMPITopology2d< real_type > &g)
Nodal weight coefficients.
Definition: mpi_weights.h:22
void extend_column(unsigned nx, unsigned ny, const ContainerType &in, ContainerType &out)
Copy a line into columns of output vector.
Definition: average_dispatch.h:67
void extend_line(unsigned nx, unsigned ny, const ContainerType &in, ContainerType &out)
Copy a line into rows of output vector.
Definition: average_dispatch.h:47
void transpose(unsigned nx, unsigned ny, const ContainerType &in, ContainerType &out)
Transpose vector.
Definition: average_dispatch.h:26
MPI Grid objects.
MPI weights.
static void mpi_reduce_communicator(MPI_Comm comm, MPI_Comm *comm_mod, MPI_Comm *comm_mod_reduce)
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...
Average(const aMPITopology2d &g, enum coo2d direction, std::string mode="exact")
Prepare internal workspace.
Definition: average_mpi.h:58
Average(const aMPITopology3d &g, enum coo3d direction, std::string mode="exact")
Prepare internal workspace.
Definition: average_mpi.h:102
Topological average computations in a Cartesian topology.
Definition: average.h:53
void operator()(const ContainerType &src, ContainerType &res, bool extend=true)
Compute the average as configured in the constructor.
Definition: average.h:156
mpi Vector class
Definition: mpi_vector.h:32
const container & data() const
Get underlying data.
Definition: mpi_vector.h:66
A vector view class, usable in dg functions.
Definition: view.h:43
2D MPI abstract grid class
Definition: mpi_grid.h:45
real_type lx() const
Return global lx.
Definition: mpi_grid.h:80
real_type ly() const
Return global ly.
Definition: mpi_grid.h:86
const RealGrid2d< real_type > & local() const
Return a non-MPI grid local for the calling process.
Definition: mpi_grid.h:252
unsigned nx() const
number of polynomial coefficients in x
Definition: mpi_grid.h:106
unsigned ny() const
number of polynomial coefficients in y
Definition: mpi_grid.h:108
MPI_Comm communicator() const
Return mpi cartesian communicator that is used in this grid.
Definition: mpi_grid.h:138
3D MPI Grid class
Definition: mpi_grid.h:329
real_type lz() const
Return global lz.
Definition: mpi_grid.h:388
real_type lx() const
Return global lx.
Definition: mpi_grid.h:376
unsigned nz() const
number of polynomial coefficients in z
Definition: mpi_grid.h:418
MPI_Comm communicator() const
Return mpi cartesian communicator that is used in this grid.
Definition: mpi_grid.h:459
real_type ly() const
Return global ly.
Definition: mpi_grid.h:382
unsigned ny() const
number of polynomial coefficients in y
Definition: mpi_grid.h:416
const RealGrid3d< real_type > & local() const
Return a non-MPI grid local for the calling process.
Definition: mpi_grid.h:560
unsigned nx() const
number of polynomial coefficients in x
Definition: mpi_grid.h:414