Discontinuous Galerkin Library
#include "dg/algorithm.h"
Loading...
Searching...
No Matches
mpi_grid.h
Go to the documentation of this file.
1#pragma once
2
3#include <cmath>
6#include "dg/enums.h"
7#include "grid.h"
8
13// /*
14// * The rationale behind this is that \c shape is used to create / construct
15// * MPI distributed vectors and for this we need the local shape
16// * Since a MPI communicator is carried by \c MPI_Vector this allows to write
17// * device independent code
18// * @param u axis number
19// */
20// TODO I think it does not matter which boundary condition the communicator has!?
21namespace dg
22{
23
42template<class real_type, size_t Nd>
43struct RealMPIGrid;
45
93template<class real_type, size_t Nd>
95{
96 // ///////////////// TYPE TRAITS ////////////////////////////
97
99 using value_type = real_type;
106 constexpr static unsigned ndim() { return Nd;}
107
108 // ///////////////// TOPOLOGY CONCEPT ////////////////////////////
109
111 unsigned shape(unsigned u=0) const
112 {
113 return m_g.shape(u);
114 }
124 host_vector abscissas(unsigned u=0) const
125 {
126 // We want to be binary exact
127 // Therefore we can't just call local abscissas
128 int dims[Nd], periods[Nd], coords[Nd];
129 mpi_cart_get( m_comm, Nd, dims, periods, coords);
130 real_type global_x0 = m_g.p(u);
131 real_type global_hx = m_g.h(u);
132 thrust::host_vector<real_type> abs(m_l.shape(u));
133 auto aa = dg::DLT<real_type>::abscissas(m_l.n(u));
134 auto idx = increment( partition( m_g.N(u), dims[u]));
135 for( unsigned i=0; i<m_l.N(u); i++)
136 {
137 for( unsigned j=0; j<m_l.n(u); j++)
138 {
139 unsigned coord = idx[coords[u]] + i;
140 real_type xmiddle = DG_FMA( global_hx, (real_type)(coord), global_x0);
141 real_type h2 = global_hx/2.;
142 real_type absj = 1.+aa[j];
143 abs[i*m_l.n(u)+j] = DG_FMA( h2, absj, xmiddle);
144 }
145 }
146 return host_vector{abs, m_comms[u]};
147 }
157 host_vector weights(unsigned u=0) const
158 {
159 if( u >= Nd)
160 throw Error( Message(_ping_)<<"u>Nd not allowed! You typed: "<<u<<" while Nd is "<<Nd);
161 thrust::host_vector<real_type> v( m_l.shape(u));
162 auto ww = dg::DLT<real_type>::weights(m_l.n(u));
163 real_type hu = m_g.h(u); // We need global h here to be binary exact
164 for( unsigned i=0; i<m_l.N(u); i++)
165 for( unsigned j=0; j<m_l.n(u); j++)
166 v[i*m_l.n(u) + j] = hu/2.*ww[j];
167 return host_vector{v, m_comms[u]};
168 }
169 // ///////////////// GETTERS ////////////////////////////
171 std::array<unsigned,Nd> get_shape() const{
172 m_g.get_shape();
173 }
175 std::array<host_vector,Nd> get_abscissas() const{
176 std::array<host_vector,Nd> abs;
177 for( unsigned u=0; u<Nd; u++)
178 abs[u] = abscissas(u);
179 return abs;
180 }
182 std::array<host_vector,Nd> get_weights() const{
183 std::array<host_vector,Nd> w;
184 for( unsigned u=0; u<Nd; u++)
185 w[u] = weights(u);
186 return w;
187 }
189 std::array<real_type,Nd> get_p() const{
190 return m_g.get_p();
191 }
193 std::array<real_type,Nd> get_q() const{
194 return m_g.get_q();
195 }
197 std::array<real_type,Nd> get_l() const{
198 return m_g.get_l();
199 }
201 std::array<real_type,Nd> get_h() const{
202 return m_g.get_h();
203 }
205 std::array<unsigned, Nd> get_N() const
206 {
207 return m_g.get_N();
208 }
210 std::array<unsigned, Nd> get_n() const
211 {
212 return m_g.get_n();
213 }
215 std::array<dg::bc, Nd> get_bc() const
216 {
217 return m_g.get_bc();
218 }
221 std::array<MPI_Comm, Nd> get_comms() const { return m_comms;}
222
224 real_type p( unsigned u=0) const { return m_g.p(u);}
226 real_type q( unsigned u=0) const { return m_g.q(u);}
228 real_type h( unsigned u=0) const { return m_g.h(u);}
230 real_type l( unsigned u=0) const { return m_g.l(u);}
232 unsigned n( unsigned u=0) const { return m_g.n(u);}
234 unsigned N( unsigned u=0) const { return m_g.N(u);}
236 dg::bc bc( unsigned u=0) const { return m_g.bc(u);}
237
243 MPI_Comm comm(unsigned u) const { return m_comms.at(u);}
245 template<size_t Md = Nd>
246 std::enable_if_t<Md==1,MPI_Comm> comm() const { return m_comms.at(0);}
257 MPI_Comm communicator() const{return m_comm;}
258
263 template<size_t Md = Nd>
264 std::enable_if_t<(Md >= 2), MPI_Comm> get_perp_comm() const
265 {
266 return mpi_cart_kron( {m_comms[0], m_comms[1]});
267 }
268
269
271 RealMPIGrid<real_type,1> grid(unsigned u ) const{
272 if( u < Nd)
273 return RealMPIGrid<real_type,1>{ m_g.p(u), m_g.q(u), m_g.n(u), m_g.N(u), m_g.bc(u), m_comms[u]};
274 else
275 throw Error( Message(_ping_)<<"u>Nd not allowed! You typed: "<<u<<" while Nd is "<<Nd);
276 }
278 RealMPIGrid<real_type,1> axis(unsigned u ) const{ return grid(u);} // because we can't decide how to name it ...
283 const RealGrid<real_type,Nd>& local() const {return m_l;}
288 const RealGrid<real_type, Nd>& global() const {return m_g;}
289
291 template<size_t Md = Nd>
292 real_type x0() const {return m_g.x0();}
294 template<size_t Md = Nd>
295 real_type x1() const {return m_g.x1();}
297 template<size_t Md = Nd>
298 real_type y0() const {return m_g.y0();}
300 template<size_t Md = Nd>
301 real_type y1() const {return m_g.y1();}
303 template<size_t Md = Nd>
304 real_type z0() const {return m_g.z0();}
306 template<size_t Md = Nd>
307 real_type z1() const {return m_g.z1();}
308
310 template<size_t Md = Nd>
311 real_type lx() const {return m_g.lx();}
313 template<size_t Md = Nd>
314 real_type ly() const {return m_g.ly();}
316 template<size_t Md = Nd>
317 real_type lz() const {return m_g.lz();}
318
320 template<size_t Md = Nd>
321 real_type hx() const {return m_g.hx();}
323 template<size_t Md = Nd>
324 real_type hy() const {return m_g.hy();}
326 template<size_t Md = Nd>
327 real_type hz() const {return m_g.hz();}
328
330 template<size_t Md = Nd>
331 unsigned nx() const {return m_g.nx();}
333 template<size_t Md = Nd>
334 unsigned ny() const {return m_g.ny();}
336 template<size_t Md = Nd>
337 unsigned nz() const {return m_g.nz();}
338
340 template<size_t Md = Nd>
341 unsigned Nx() const {return m_g.Nx();}
343 template<size_t Md = Nd>
344 unsigned Ny() const {return m_g.Ny();}
346 template<size_t Md = Nd>
347 unsigned Nz() const {return m_g.Nz();}
348
350 template<size_t Md = Nd>
351 dg::bc bcx() const {return m_g.bcx();}
353 template<size_t Md = Nd>
354 dg::bc bcy() const {return m_g.bcy();}
356 template<size_t Md = Nd>
357 dg::bc bcz() const {return m_g.bcz();}
358
360 template<size_t Md = Nd>
362 static_assert( Nd > 0);
363 return grid(0);
364 }
366 template<size_t Md = Nd>
368 static_assert( Nd > 1);
369 return grid(1);
370 }
372 template<size_t Md = Nd>
374 static_assert( Nd > 2);
375 return grid(2);
376 }
377
378 // //////////////////SETTERS/////////////////////////////
380 template<size_t Md = Nd>
381 std::enable_if_t< (Md>=2),void> multiplyCellNumbers( real_type fx, real_type fy)
382 {
383 auto Ns = m_g.get_N();
384 Ns[0] = round(fx*(real_type)m_g.N(0));
385 Ns[1] = round(fy*(real_type)m_g.N(1));
386 if( fx != 1 or fy != 1)
387 set( m_g.get_n(), Ns);
388 }
390 template<size_t Md = Nd>
391 std::enable_if_t<(Md == 1), void> set( unsigned new_n, unsigned new_Nx)
392 {
393 set(std::array{new_n}, std::array{new_Nx});
394 }
396 template<size_t Md = Nd>
397 std::enable_if_t<(Md == 2), void> set( unsigned new_n, unsigned new_Nx,
398 unsigned new_Ny)
399 {
400 set(std::array{new_n,new_n}, std::array{new_Nx,new_Ny});
401 }
403 template<size_t Md = Nd>
404 std::enable_if_t<(Md == 3), void> set( unsigned new_n, unsigned new_Nx,
405 unsigned new_Ny, unsigned new_Nz)
406 {
407 set(std::array{new_n,new_n,1u}, std::array{new_Nx,new_Ny,new_Nz});
408 }
410 void set( unsigned new_n, std::array<unsigned,Nd> new_N)
411 {
412 std::array<unsigned , Nd> tmp;
413 for( unsigned u=0; u<Nd; u++)
414 tmp[u] = new_n;
415 set( tmp, new_N);
416 }
418 void set_axis( unsigned coord, unsigned new_n , unsigned new_N)
419 {
420 auto n = m_g.get_n(), N = m_g.get_N();
421 n[coord] = new_n;
422 N[coord] = new_N;
423 set( n, N);
424 }
426 void set( std::array<unsigned,Nd> new_n, std::array<unsigned,Nd> new_N)
427 {
428 if( new_n==m_g.get_n() && new_N == m_g.get_N())
429 return;
430 do_set(new_n, new_N);
431 }
433 void set_pq( std::array<real_type,Nd> new_p, std::array<real_type,Nd> new_q)
434 {
435 do_set_pq( new_p, new_q);
436 }
438 void set_bcs( std::array<dg::bc,Nd> new_bcs)
439 {
440 do_set( new_bcs);
441 }
442
443 // //////////////////UTILITY/////////////////////////////
448 unsigned size() const { return m_g.size();}
453 unsigned local_size() const { return m_l.size();}
454 // used in conversion policy in interpolation
455
461 void display( std::ostream& os = std::cout) const
462 {
463 os << "GLOBAL GRID \n";
464 m_g.display();
465 os << "LOCAL GRID \n";
466 m_l.display();
467 }
468
470 template<size_t Md = Nd>
471 std::enable_if_t<(Md == 1), bool> contains( real_type x) const
472 {
473 return m_g.contains( x);
474 }
475
477 template<class Vector>
478 bool contains( const Vector& x)const { return m_g.contains(x);}
479
491 bool local2globalIdx( int localIdx, int rank, int& globalIdx)const
492 {
493 // TODO shouldn't this test for m_l.size() ? How is this used?
494 // ATTENTION This function cannot depend on who is calling it
495 // so it cannot depend on m_l
496 if( localIdx < 0 || localIdx >= (int)m_g.size()) return false;
497
498 int dims[Nd], periods[Nd], coords[Nd]; // we need the dims
499 if( mpi_cart_get( m_comm, Nd, dims, periods, coords) != MPI_SUCCESS)
500 return false;
501 // and the coords associated to rank
502 if( mpi_cart_coords( m_comm, rank, Nd, coords) != MPI_SUCCESS)
503 return false;
504 int gIdx[Nd];
505 int current = localIdx;
506 for( unsigned u=0; u<Nd; u++)
507 {
508 auto idx = increment(partition( m_g.N(u), dims[u]));
509 unsigned shapeu = (idx[coords[u]+1] - idx[coords[u]])*m_g.n(u);
510 int lIdx = current %shapeu; // 1d idx
511 current = current / shapeu;
512 gIdx[u] = lIdx + idx[coords[u]]*m_g.n(u);
513 }
514 globalIdx = gIdx[int(Nd)-1]; // prevent overflow if Nd == 0
515 for( int u=int(Nd)-2; u>=0; u--)
516 globalIdx = globalIdx*m_g.shape(u) + gIdx[u];
517 return true;
518 }
519
531 bool global2localIdx( int globalIdx, int& localIdx, int& rank)const
532 {
533 // an exercise in flattening and unflattening indices
534 if( globalIdx < 0 || globalIdx >= (int)m_g.size()) return false;
535
536 int dims[Nd], periods[Nd], coords[Nd];
537 if( dg::mpi_cart_get( m_comm, Nd, dims, periods, coords) != MPI_SUCCESS)
538 return false;
539
540 int lIdx[Nd] = {0}, local_shape[Nd] = {0};
541 int current = globalIdx;
542 // ATTENTION This function cannot depend on who is calling it
543 // so it cannot depend on m_l or current coords
544 for( unsigned u=0; u<Nd; u++)
545 {
546 int gIdx = current%(m_g.shape(u)); // 1d idx
547 current = current / (m_g.shape(u));
548 auto idx = increment(partition( m_g.N(u), dims[u]));
549 // Find coord
550 for( unsigned c=0; c<idx.size()-1; c++)
551 if( unsigned(gIdx)< idx[c+1]*m_g.n(u))
552 {
553 coords[u] = c;
554 lIdx[u] = gIdx - idx[c]*m_g.n(u);
555 local_shape[u] = (idx[c+1]-idx[c])*m_g.n(u);
556 break;
557 }
558 }
559 localIdx = lIdx[int(Nd)-1];
560 for( int u=int(Nd)-2; u>=0; u--)
561 localIdx = localIdx*local_shape[u] + lIdx[u];
562
563 if( mpi_cart_rank( m_comm, coords, &rank) == MPI_SUCCESS )
564 return true;
565 else
566 return false;
567 }
568
578 std::array<unsigned, Nd> start() const
579 {
580 int dims[Nd], periods[Nd], coords[Nd];
581 mpi_cart_get( m_comm, Nd, dims, periods, coords);
582 std::array<unsigned, Nd> start;
583 for( unsigned u=0;u<Nd; u++)
584 {
585 auto idx = increment(partition( m_g.N(u), dims[u]));
586 start[Nd-1-u] = idx[coords[u]]*m_g.n(u);
587 }
588 return start;
589 }
598 std::array<unsigned, Nd> count() const { return m_l.count(); }
599 protected:
601 ~aRealMPITopology() = default;
602
604 aRealMPITopology() = default;
605
618 aRealMPITopology( std::array<real_type,Nd> p, std::array<real_type,Nd> q,
619 std::array<unsigned,Nd> n, std::array<unsigned,Nd> N,
620 std::array<dg::bc,Nd> bcs, std::array<MPI_Comm, Nd> comms) :
621 m_g(p,q,n,N,bcs), m_comms(comms)
622 {
623 // assert dimensionality of Cartesian communicators
624 int ndims;
625 for ( unsigned u=0; u<Nd;u++)
626 {
627 mpi_cartdim_get( m_comms[u], &ndims);
628 assert( (unsigned)ndims == 1);
629 }
630 m_comm = dg::mpi_cart_kron( m_comms);
631 mpi_cartdim_get( m_comm, &ndims);
632 assert( (unsigned)ndims == Nd);
633 // The idea is that every grid gets the same amount and the
634 // rest is distributed to the lowest rank grids
635 int dims[Nd], periods[Nd], coords[Nd];
636 mpi_cart_get( m_comm, Nd, dims, periods, coords);
637 for( unsigned u=0;u<Nd; u++)
638 {
639 auto idx = increment(partition( m_g.N(u), dims[u]));
640 N[u] = idx[coords[u]+1]-idx[coords[u]] ;
641
642 p[u] = m_g.p(u) + m_g.h(u)*idx[coords[u]];
643 q[u] = m_g.p(u) + m_g.h(u)*idx[coords[u] +1];
644 // The local right boundary should be the same as the global right boundary
645 if( coords[u] == dims[u]-1)
646 q[u] = m_g.q(u);
647 }
648 m_l = { p, q, m_g.get_n(), N, m_g.get_bc()};
649 }
651 aRealMPITopology( const std::array< RealMPIGrid<real_type, 1>, Nd>& axes)
652 {
653 std::array<RealGrid<real_type,1>,Nd> globals, locals;
654 for( unsigned u=0; u<Nd; u++)
655 {
656 globals[u] = axes[u].global();
657 locals[u] = axes[u].local();
658 m_comms[u] = axes[u].communicator();
659 }
660 m_g = RealGrid<real_type,Nd>( globals);
661 m_l = RealGrid<real_type,Nd>( locals);
662 m_comm = dg::mpi_cart_kron( {m_comms.begin(), m_comms.end()});
663 }
664
666 aRealMPITopology(const aRealMPITopology& src) = default;
670 virtual void do_set(std::array<unsigned,Nd> new_n, std::array<unsigned,Nd> new_N) =0;
672 virtual void do_set_pq( std::array<real_type, Nd> new_p, std::array<real_type,Nd> new_q) =0;
674 virtual void do_set( std::array<dg::bc, Nd> new_bcs) =0;
675
676 // MW: The shared version of this constructor causes nvcc-12.4 to segfault when constructing a Geometry
677 // Funnily the mpi version works (but let's kill it for now
678 //template< size_t M0, size_t ...Ms>
679 //aRealMPITopology( const aRealMPITopology<real_type,M0>& g0,
680 // const aRealMPITopology<real_type,Ms> & ...gs)
681 //{
682 // auto grid = aRealMPITopology<real_type, Nd - M0>( gs ...);
683 // *this = aRealMPITopology<real_type, Nd>( g0, grid);
684 //}
685 //template< size_t M0, size_t M1>
686 //aRealMPITopology( const aRealMPITopology<real_type,M0>& g0,
687 // const aRealMPITopology<real_type,M1>& g1) : m_g( g0.global(),g1.global()),
688 // m_l( g0.local(), g1.local())
689 //{
690 // static_assert( (M0 + M1) == Nd);
691 // for( unsigned u=0; u<M0; u++)
692 // {
693 // m_comms[u] = g0.comm(u);
694 // }
695 // for( unsigned u=0; u<M1; u++)
696 // {
697 // m_comms[M0+u] = g1.comm(u);
698 // }
699 // m_comm = dg::mpi_cart_kron( {m_comms.begin(), m_comms.end()});
700
701 //}
702
703 //We do not want that because we cannot distinguish if g is meant to be the local or the global grid...
704 //aRealMPITopology( const RealGrid<real_type,Nd> & g, MPI_Comm comm);
705 private:
706 void check_periods( std::array<dg::bc, Nd> bc) const
707 {
708 if constexpr ( Nd > 0) // avoid zero sized array warnings
709 {
710 int rank, dims[Nd], periods[Nd], coords[Nd];
711 mpi_cart_get( m_comm, Nd, dims, periods, coords);
712 MPI_Comm_rank( m_comm, &rank);
713 if( rank == 0)
714 {
715 for( unsigned u=0; u<Nd; u++)
716 {
717 if( bc[u] == dg::PER) assert( periods[u] == true);
718 else assert( periods[u] == false);
719 }
720 }
721 }
722 }
723 std::vector<unsigned> partition( unsigned N, unsigned r) const
724 {
725 // Divide N points as equally as possible among participants r
726 std::vector<unsigned> points(r, N/r );
727 for( unsigned u=0; u<N%r; u++)
728 points[u]++;
729 return points;
730 }
731
732 std::vector<unsigned> increment( const std::vector<unsigned>& partition) const
733 {
734 // replace with std::inclusive_scan ?
735 // return global starting idx and end idex
736 // start = inc[coord], end = inc[coord+1]
737 std::vector<unsigned> inc( partition.size()+1, 0);
738 for( unsigned u=0; u<inc.size(); u++)
739 for( unsigned k=0; k<u; k++)
740 inc[u] += partition[k];
741 return inc;
742 }
743
744 RealGrid<real_type, Nd> m_g, m_l; //global grid, local grid
745 std::array<MPI_Comm, Nd> m_comms; // 1d comms
746 MPI_Comm m_comm; //just an integer...(No, more like an address)
747};
749
750// pure virtual implementations must be declared outside class
751template<class real_type,size_t Nd>
752void aRealMPITopology<real_type,Nd>::do_set( std::array<unsigned,Nd> new_n, std::array<unsigned,Nd> new_N)
753{
754 if constexpr ( Nd > 0) // avoid zero sized array warnings
755 {
756 m_g.set(new_n, new_N);
757 int dims[Nd], periods[Nd], coords[Nd];
758 mpi_cart_get( m_comm, Nd, dims, periods, coords);
759 std::array<unsigned, Nd> N;
760 for( unsigned u=0;u<Nd; u++)
761 {
762 auto idx = increment(partition( m_g.N(u), dims[u]));
763 N[u] = idx[coords[u]+1]-idx[coords[u]] ;
764 }
765 m_l.set( new_n, N);
766 }
767
768}
769template<class real_type,size_t Nd>
770void aRealMPITopology<real_type,Nd>::do_set_pq( std::array<real_type, Nd> x0, std::array<real_type,Nd> x1)
771{
772 if constexpr ( Nd > 0) // avoid zero sized array warnings
773 {
774 m_g.set_pq( x0, x1);
775 int dims[Nd], periods[Nd], coords[Nd];
776 mpi_cart_get( m_comm, Nd, dims, periods, coords);
777 std::array<real_type,Nd> p, q;
778 for( unsigned u=0;u<Nd; u++)
779 {
780 auto idx = increment(partition( m_g.N(u), dims[u]));
781 p[u] = m_g.p(u) + m_g.h(u)*idx[coords[u]];
782 q[u] = m_g.p(u) + m_g.h(u)*idx[coords[u] +1];
783 }
784 m_l.set_pq( p, q);
785 }
786}
787template<class real_type,size_t Nd>
788void aRealMPITopology<real_type,Nd>::do_set( std::array<dg::bc, Nd> bcs)
789{
790 check_periods( bcs);
791 m_g.set_bcs( bcs);
792 m_l.set_bcs( bcs);
793}
794
796
802template<class real_type, size_t Nd>
803struct RealMPIGrid : public aRealMPITopology<real_type,Nd>
804{
806 RealMPIGrid() = default;
807 template<size_t Md = Nd>
808 RealMPIGrid( real_type x0, real_type x1, unsigned n, unsigned N, MPI_Comm
809 comm): aRealMPITopology<real_type,1>( {x0}, {x1},
810 {n}, {N}, {dg::PER}, {comm})
811 { }
814 template<size_t Md = Nd>
815 RealMPIGrid( real_type x0, real_type x1, unsigned n, unsigned Nx, dg::bc bcx, MPI_Comm
816 comm): aRealMPITopology<real_type,1>( {x0}, {x1},
817 {n}, {Nx}, {bcx}, {comm})
818 {}
821 template<size_t Md = Nd>
822 RealMPIGrid( real_type x0, real_type x1, real_type y0, real_type y1,
823 unsigned n, unsigned Nx, unsigned Ny, MPI_Comm comm):
824 aRealMPITopology<real_type,2>(
825 {x0,y0},{x1,y1},{n,n},{Nx,Ny},{dg::PER,dg::PER},
827 { }
828
832 template<size_t Md = Nd>
833 RealMPIGrid( real_type x0, real_type x1, real_type y0, real_type y1,
834 unsigned n, unsigned Nx, unsigned Ny, dg::bc bcx, dg::bc bcy, MPI_Comm
835 comm):
836 aRealMPITopology<real_type,2>(
837 {x0,y0},{x1,y1},{n,n},{Nx,Ny},{bcx,bcy},
839 { }
842 template<size_t Md = Nd>
843 RealMPIGrid( real_type x0, real_type x1, real_type y0, real_type y1,
844 real_type z0, real_type z1, unsigned n, unsigned Nx, unsigned Ny,
845 unsigned Nz, MPI_Comm comm):
846 aRealMPITopology<real_type,3>(
847 {x0,y0,z0},{x1,y1,z1},{n,n,1},{Nx,Ny,Nz},{dg::PER,dg::PER,dg::PER},
849 { }
850
854 template<size_t Md = Nd>
855 RealMPIGrid( real_type x0, real_type x1, real_type y0, real_type y1,
856 real_type z0, real_type z1, unsigned n, unsigned Nx, unsigned Ny,
857 unsigned Nz, dg::bc bcx, dg::bc bcy, dg::bc bcz, MPI_Comm comm):
858 aRealMPITopology<real_type,3>(
859 {x0,y0,z0},{x1,y1,z1},{n,n,1},{Nx,Ny,Nz},{bcx,bcy,bcz},
861 { }
862
864 RealMPIGrid( const std::array<RealMPIGrid<real_type,1>,Nd>& axes) :
865 aRealMPITopology<real_type,Nd>( axes){}
866
873 template<class ...Grid1ds>
874 RealMPIGrid( const RealMPIGrid<real_type,1>& g0, const Grid1ds& ...gs) :
875 aRealMPITopology<real_type,Nd>( std::array<RealMPIGrid<real_type,1>,Nd>{g0, gs...}){}
876
878 RealMPIGrid( std::array<real_type,Nd> p, std::array<real_type,Nd> q,
879 std::array<unsigned,Nd> n, std::array<unsigned,Nd> N,
880 std::array<dg::bc,Nd> bcs, std::array<MPI_Comm,Nd> comms) :
881 aRealMPITopology<real_type,Nd>( p,q,n,N,bcs,comms)
882 {}
883
887 aRealMPITopology<real_type,Nd>(src){ }
888 private:
889 virtual void do_set( std::array<unsigned,Nd> new_n, std::array<unsigned,Nd> new_N) override final{
891 }
892 virtual void do_set_pq( std::array<real_type,Nd> new_x0, std::array<real_type,Nd> new_x1) override final{
894 }
895 virtual void do_set( std::array<dg::bc,Nd> new_bcs) override final{
897 }
898};
899
906template<size_t Nd>
910template<class T>
912template<class T>
914template<class T>
916template<class T>
918template<class T>
920template<class T>
922namespace x{
927template<size_t Nd>
931template<class T>
933template<class T>
935template<class T>
937template<class T>
939template<class T>
941template<class T>
943}//namespace x
945
946}//namespace dg
class intended for the use in throw statements
Definition exceptions.h:83
small class holding a stringstream
Definition exceptions.h:29
enums
#define _ping_
Definition exceptions.h:12
base topology classes
bc
Switch between boundary conditions.
Definition enums.h:15
@ PER
periodic boundaries
Definition enums.h:16
@ x
x direction
dg::RealMPIGrid< double, 1 > MPIGrid1d
Definition mpi_grid.h:903
dg::aRealMPITopology< double, 2 > aMPITopology2d
Definition mpi_grid.h:908
dg::aRealMPITopology< double, 3 > aMPITopology3d
Definition mpi_grid.h:909
dg::RealMPIGrid< double, 3 > MPIGrid3d
Definition mpi_grid.h:905
dg::RealMPIGrid< double, 0 > MPIGrid0d
Definition mpi_grid.h:902
dg::RealMPIGrid< double, 2 > MPIGrid2d
Definition mpi_grid.h:904
std::array< MPI_Comm, Nd > mpi_cart_split_as(MPI_Comm comm)
Same as mpi_cart_split but different return type.
Definition mpi_kron.h:282
MPI_Comm mpi_cart_kron(std::vector< MPI_Comm > comms)
Form a (transposed) Kronecker product among Cartesian communicators.
Definition mpi_kron.h:184
const double n
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...
static std::vector< real_type > abscissas(unsigned n)
Return Gauss-Legendre nodes on the interval [-1,1].
Definition dlt.h:27
static std::vector< real_type > weights(unsigned n)
Return Gauss-Legendre weights.
Definition dlt.h:83
A simple wrapper around a container object and an MPI_Comm.
Definition mpi_vector.h:37
The simplest implementation of aRealTopology.
Definition grid.h:710
The simplest implementation of aRealMPITopology3d.
Definition mpi_grid.h:804
RealMPIGrid()=default
construct an empty grid this leaves the access functions undefined
RealMPIGrid(std::array< real_type, Nd > p, std::array< real_type, Nd > q, std::array< unsigned, Nd > n, std::array< unsigned, Nd > N, std::array< dg::bc, Nd > bcs, std::array< MPI_Comm, Nd > comms)
Construct a topology directly from points and dimensions.
Definition mpi_grid.h:878
RealMPIGrid(real_type x0, real_type x1, real_type y0, real_type y1, real_type z0, real_type z1, unsigned n, unsigned Nx, unsigned Ny, unsigned Nz, MPI_Comm comm)
Construct with equal polynomial coefficients.
Definition mpi_grid.h:843
RealMPIGrid(const std::array< RealMPIGrid< real_type, 1 >, Nd > &axes)
Construct a topology as the product of 1d axes grids.
Definition mpi_grid.h:864
RealMPIGrid(real_type x0, real_type x1, unsigned n, unsigned Nx, dg::bc bcx, MPI_Comm comm)
1D grid
Definition mpi_grid.h:815
RealMPIGrid(const aRealMPITopology< real_type, Nd > &src)
Definition mpi_grid.h:886
RealMPIGrid(const RealMPIGrid< real_type, 1 > &g0, const Grid1ds &...gs)
Construct from given 1d grids Equivalent to RealMPIGrid( std::array{g0,gs...})
Definition mpi_grid.h:874
RealMPIGrid(real_type x0, real_type x1, real_type y0, real_type y1, real_type z0, real_type z1, unsigned n, unsigned Nx, unsigned Ny, unsigned Nz, dg::bc bcx, dg::bc bcy, dg::bc bcz, MPI_Comm comm)
Construct with equal polynomial coefficients.
Definition mpi_grid.h:855
RealMPIGrid(real_type x0, real_type x1, real_type y0, real_type y1, unsigned n, unsigned Nx, unsigned Ny, MPI_Comm comm)
Construct with equal polynomial coefficients.
Definition mpi_grid.h:822
RealMPIGrid(real_type x0, real_type x1, real_type y0, real_type y1, unsigned n, unsigned Nx, unsigned Ny, dg::bc bcx, dg::bc bcy, MPI_Comm comm)
Construct with equal polynomial coefficients.
Definition mpi_grid.h:833
RealMPIGrid(real_type x0, real_type x1, unsigned n, unsigned N, MPI_Comm comm)
Definition mpi_grid.h:808
An abstract base class for MPI distributed Nd-dimensional dG grids.
Definition mpi_grid.h:95
std::array< real_type, Nd > get_h() const
Get grid constant for all axes.
Definition mpi_grid.h:201
std::array< real_type, Nd > get_p() const
Get left boundary point .
Definition mpi_grid.h:189
std::enable_if_t<(Md==3), void > set(unsigned new_n, unsigned new_Nx, unsigned new_Ny, unsigned new_Nz)
Set n and N in a 3-dimensional grid.
Definition mpi_grid.h:404
std::array< host_vector, Nd > get_abscissas() const
Construct abscissas for all axes.
Definition mpi_grid.h:175
virtual void do_set(std::array< dg::bc, Nd > new_bcs)=0
Reset the boundary conditions of the grid.
std::enable_if_t<(Md >=2), void > multiplyCellNumbers(real_type fx, real_type fy)
Multiply the number of cells in the first two dimensions with a given factor.
Definition mpi_grid.h:381
std::array< unsigned, Nd > count() const
Count vector in C-order for dg::file::MPINcHyperslab.
Definition mpi_grid.h:598
real_type l(unsigned u=0) const
Get grid length for axis u.
Definition mpi_grid.h:230
real_type hz() const
Equivalent to h(2)
Definition mpi_grid.h:327
RealMPIGrid< real_type, 1 > gz() const
Equivalent to grid(2)
Definition mpi_grid.h:373
std::enable_if_t<(Md==1), bool > contains(real_type x) const
Check if the grid contains a point.
Definition mpi_grid.h:471
void set_axis(unsigned coord, unsigned new_n, unsigned new_N)
Set n and N for axis coord.
Definition mpi_grid.h:418
MPI_Comm comm(unsigned u) const
Get 1d Cartesian communicator for axis u.
Definition mpi_grid.h:243
std::array< real_type, Nd > get_l() const
Get grid length for all axes.
Definition mpi_grid.h:197
void set(std::array< unsigned, Nd > new_n, std::array< unsigned, Nd > new_N)
Set the number of polynomials and cells.
Definition mpi_grid.h:426
unsigned Ny() const
Equivalent to N(1)
Definition mpi_grid.h:344
dg::bc bcx() const
Equivalent to bc(0)
Definition mpi_grid.h:351
dg::bc bcy() const
Equivalent to bc(1)
Definition mpi_grid.h:354
std::array< unsigned, Nd > get_shape() const
the total number of points of an axis
Definition mpi_grid.h:171
unsigned shape(unsigned u=0) const
the total number of points of an axis
Definition mpi_grid.h:111
real_type z1() const
Equivalent to q(2)
Definition mpi_grid.h:307
aRealMPITopology()=default
default constructor
std::array< host_vector, Nd > get_weights() const
Construct weights for all axes.
Definition mpi_grid.h:182
~aRealMPITopology()=default
disallow deletion through base class pointer
dg::bc bc(unsigned u=0) const
Get boundary condition for axis u.
Definition mpi_grid.h:236
void set(unsigned new_n, std::array< unsigned, Nd > new_N)
Same as set( {new_n, new_n,...}, new_N);
Definition mpi_grid.h:410
aRealMPITopology(const std::array< RealMPIGrid< real_type, 1 >, Nd > &axes)
Construct a topology as the product of 1d axes grids.
Definition mpi_grid.h:651
unsigned n(unsigned u=0) const
Get number of polynomial coefficients for axis u.
Definition mpi_grid.h:232
RealMPIGrid< real_type, 1 > axis(unsigned u) const
An alias for "grid".
Definition mpi_grid.h:278
aRealMPITopology(std::array< real_type, Nd > p, std::array< real_type, Nd > q, std::array< unsigned, Nd > n, std::array< unsigned, Nd > N, std::array< dg::bc, Nd > bcs, std::array< MPI_Comm, Nd > comms)
Construct a topology directly from points and dimensions.
Definition mpi_grid.h:618
std::array< unsigned, Nd > start() const
The global start coordinate in C-order of dg::file::MPINcHyperslab that the local grid represents.
Definition mpi_grid.h:578
dg::bc bcz() const
Equivalent to bc(2)
Definition mpi_grid.h:357
unsigned size() const
The total global number of points.
Definition mpi_grid.h:448
std::enable_if_t< Md==1, MPI_Comm > comm() const
Equivalent to comm(0)
Definition mpi_grid.h:246
unsigned local_size() const
The total local number of points.
Definition mpi_grid.h:453
unsigned Nx() const
Equivalent to N(0)
Definition mpi_grid.h:341
bool contains(const Vector &x) const
Check if the grid contains a point.
Definition mpi_grid.h:478
real_type y0() const
Equivalent to p(2)
Definition mpi_grid.h:298
const RealGrid< real_type, Nd > & global() const
The global grid as a shared memory grid.
Definition mpi_grid.h:288
host_vector weights(unsigned u=0) const
Get the weights of the u axis.
Definition mpi_grid.h:157
unsigned N(unsigned u=0) const
Get number of cells for axis u.
Definition mpi_grid.h:234
real_type ly() const
Equivalent to l(1)
Definition mpi_grid.h:314
virtual void do_set(std::array< unsigned, Nd > new_n, std::array< unsigned, Nd > new_N)=0
Set the number of polynomials and cells.
std::array< real_type, Nd > get_q() const
Get right boundary point .
Definition mpi_grid.h:193
static constexpr unsigned ndim()
Dimensionality == Nd.
Definition mpi_grid.h:106
real_type value_type
value type of abscissas and weights
Definition mpi_grid.h:99
real_type y1() const
Equivalent to q(0)
Definition mpi_grid.h:301
virtual void do_set_pq(std::array< real_type, Nd > new_p, std::array< real_type, Nd > new_q)=0
Reset the boundaries of the grid.
std::array< MPI_Comm, Nd > get_comms() const
Get 1d Cartesian communicator for all axes.
Definition mpi_grid.h:221
MPI_Comm communicator() const
Return Nd dimensional MPI cartesian communicator that is used in this grid.
Definition mpi_grid.h:257
real_type lx() const
Equivalent to l(0)
Definition mpi_grid.h:311
std::enable_if_t<(Md==1), void > set(unsigned new_n, unsigned new_Nx)
Set n and N in a 1-dimensional grid.
Definition mpi_grid.h:391
std::enable_if_t<(Md >=2), MPI_Comm > get_perp_comm() const
MPI Cartesian communicator in the first two dimensions (x and y)
Definition mpi_grid.h:264
host_vector abscissas(unsigned u=0) const
Get the grid abscissas of the u axis.
Definition mpi_grid.h:124
real_type hy() const
Equivalent to h(1)
Definition mpi_grid.h:324
RealMPIGrid< real_type, 1 > gy() const
Equivalent to grid(1)
Definition mpi_grid.h:367
real_type h(unsigned u=0) const
Get grid constant for axis u.
Definition mpi_grid.h:228
real_type z0() const
Equivalent to q(1)
Definition mpi_grid.h:304
std::array< dg::bc, Nd > get_bc() const
Get boundary condition for all axes.
Definition mpi_grid.h:215
RealMPIGrid< real_type, 1 > gx() const
Equivalent to grid(0)
Definition mpi_grid.h:361
std::array< unsigned, Nd > get_n() const
Get number of polynomial coefficients for all axes.
Definition mpi_grid.h:210
void display(std::ostream &os=std::cout) const
Display global and local grid paramters.
Definition mpi_grid.h:461
real_type x0() const
Equivalent to p(0)
Definition mpi_grid.h:292
real_type lz() const
Equivalent to l(2)
Definition mpi_grid.h:317
void set_pq(std::array< real_type, Nd > new_p, std::array< real_type, Nd > new_q)
Reset the boundaries of the grid.
Definition mpi_grid.h:433
aRealMPITopology(const aRealMPITopology &src)=default
real_type hx() const
Equivalent to h(0)
Definition mpi_grid.h:321
aRealMPITopology & operator=(const aRealMPITopology &src)=default
std::array< unsigned, Nd > get_N() const
Get number of cells for all axes.
Definition mpi_grid.h:205
unsigned nx() const
Equivalent to n(0)
Definition mpi_grid.h:331
unsigned Nz() const
Equivalent to N(2)
Definition mpi_grid.h:347
bool global2localIdx(int globalIdx, int &localIdx, int &rank) const
Convert the global index of a vector to a local index and the rank of the containing process.
Definition mpi_grid.h:531
const RealGrid< real_type, Nd > & local() const
The local grid as a shared memory grid.
Definition mpi_grid.h:283
RealMPIGrid< real_type, 1 > grid(unsigned u) const
Get axis u as a 1d grid.
Definition mpi_grid.h:271
void set_bcs(std::array< dg::bc, Nd > new_bcs)
Reset the boundary conditions of the grid.
Definition mpi_grid.h:438
std::enable_if_t<(Md==2), void > set(unsigned new_n, unsigned new_Nx, unsigned new_Ny)
Set n and N in a 2-dimensional grid.
Definition mpi_grid.h:397
real_type p(unsigned u=0) const
Get left boundary point for axis u.
Definition mpi_grid.h:224
real_type q(unsigned u=0) const
Get right boundary point for axis u.
Definition mpi_grid.h:226
real_type x1() const
Equivalent to p(1)
Definition mpi_grid.h:295
unsigned ny() const
Equivalent to n(1)
Definition mpi_grid.h:334
bool local2globalIdx(int localIdx, int rank, int &globalIdx) const
Convert the index of a local vector and the rank of the containing process to a global index.
Definition mpi_grid.h:491
unsigned nz() const
Equivalent to n(2)
Definition mpi_grid.h:337