Alamo
MUSCL.H
Go to the documentation of this file.
1//
2// This header defines :code:`Numeric::Advect::MUSCL`, a second-order finite-volume
3// advection operator using piecewise-linear MUSCL reconstruction with a selectable
4// slope limiter.
5//
6// The operator is written as a GPU-safe functor:
7//
8// .. code-block:: c++
9//
10// rhs = muscl(phi, velocity, i, j, k, comp, DX, options, stencil);
11//
12// It reconstructs left and right states of :math:`\phi` at cell faces, selects
13// the upwind state using face-centered velocities obtained by averaging neighboring
14// cell-centered velocity values, and returns either
15// :math:`-\nabla\cdot(\phi\mathbf{u})` or
16// :math:`-\nabla\cdot(\phi\mathbf{u}) + \phi\nabla\cdot\mathbf{u}` depending on
17// :code:`Numeric::Advect::Options::form`.
18//
19// This implementation assumes collocated cell-centered data:
20// :code:`phi_location = Set::HC::Cell` and
21// :code:`velocity_location = Set::HC::Cell`. It requires two ghost cells in each
22// coordinate direction because the limited reconstruction reaches to
23// :math:`i\pm2`, :math:`j\pm2`, and :math:`k\pm2`.
24//
25
26#ifndef NUMERIC_ADVECT_MUSCL_H
27#define NUMERIC_ADVECT_MUSCL_H
28
29#include "Advect.H"
30#include "Limiter/Limiter.H"
31#include "Limiter/Koren.H"
32#include "Limiter/MC.H"
33#include "Limiter/MinMod.H"
34#include "Limiter/Superbee.H"
35#include "Limiter/UMIST.H"
36#include "Limiter/VanAlbada.H"
37#include "Limiter/VanLeer.H"
38
39namespace Numeric
40{
41namespace Advect
42{
43class MUSCL
44{
45public:
46 static constexpr const char* name = "muscl";
49
57
58 static void Parse(MUSCL& value, IO::ParmParse& pp)
59 {
60 // flux limiter
67 Limiter::UMIST>("limiter",value.limiter);
68 }
69
70 AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
71 int NGhost() const
72 {
73 return 2;
74 }
75
76 template<class Phi>
77 AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
78 Set::Scalar Slope( Phi const& phi,
79 int ilo, int jlo, int klo,
80 int ic, int jc, int kc,
81 int ihi, int jhi, int khi,
82 int comp) const
83 {
84 return limiter( phi(ilo,jlo,klo,comp),
85 phi(ic,jc,kc,comp),
86 phi(ihi,jhi,khi,comp));
87 }
88
89 template<class Phi, class Velocity>
90 AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
91 Set::Scalar operator()( Phi const& phi,
92 Velocity const& velocity,
93 int i, int j, int k,
94 int comp,
95 const Set::Scalar* DX,
96 Options options = {},
97 std::array<Numeric::StencilType, AMREX_SPACEDIM> stencil = Numeric::DefaultType) const
98 {
99 (void)stencil;
100
101 Set::Scalar div_phi_u = 0.0;
102 Set::Scalar div_u = 0.0;
103
104 Set::Scalar phi_c = phi(i,j,k,comp);
105
106 Set::Scalar phi_xm = phi(i-1,j,k,comp);
107 Set::Scalar phi_xp = phi(i+1,j,k,comp);
108 Set::Scalar slope_xm = Slope(phi, i-2,j,k, i-1,j,k, i,j,k, comp);
109 Set::Scalar slope_x = Slope(phi, i-1,j,k, i,j,k, i+1,j,k, comp);
110 Set::Scalar slope_xp = Slope(phi, i,j,k, i+1,j,k, i+2,j,k, comp);
111
112 Set::Scalar ux_xlo = 0.5 * (velocity(i-1,j,k,0) + velocity(i,j,k,0));
113 Set::Scalar ux_xhi = 0.5 * (velocity(i,j,k,0) + velocity(i+1,j,k,0));
114
115 Set::Scalar phi_xlo_l = Util::Clamp(phi_xm + 0.5 * slope_xm, phi_xm, phi_c);
116 Set::Scalar phi_xlo_r = Util::Clamp(phi_c - 0.5 * slope_x, phi_xm, phi_c);
117 Set::Scalar phi_xhi_l = Util::Clamp(phi_c + 0.5 * slope_x, phi_c, phi_xp);
118 Set::Scalar phi_xhi_r = Util::Clamp(phi_xp - 0.5 * slope_xp, phi_c, phi_xp);
119
120 Set::Scalar flux_xlo = ux_xlo * (ux_xlo >= 0.0 ? phi_xlo_l : phi_xlo_r);
121 Set::Scalar flux_xhi = ux_xhi * (ux_xhi >= 0.0 ? phi_xhi_l : phi_xhi_r);
122 div_phi_u += (flux_xhi - flux_xlo) / DX[0];
123 div_u += (ux_xhi - ux_xlo) / DX[0];
124
125#if AMREX_SPACEDIM >= 2
126 Set::Scalar phi_ym = phi(i,j-1,k,comp);
127 Set::Scalar phi_yp = phi(i,j+1,k,comp);
128 Set::Scalar slope_ym = Slope(phi, i,j-2,k, i,j-1,k, i,j,k, comp);
129 Set::Scalar slope_y = Slope(phi, i,j-1,k, i,j,k, i,j+1,k, comp);
130 Set::Scalar slope_yp = Slope(phi, i,j,k, i,j+1,k, i,j+2,k, comp);
131
132 Set::Scalar uy_ylo = 0.5 * (velocity(i,j-1,k,1) + velocity(i,j,k,1));
133 Set::Scalar uy_yhi = 0.5 * (velocity(i,j,k,1) + velocity(i,j+1,k,1));
134
135 Set::Scalar phi_ylo_l = Util::Clamp(phi_ym + 0.5 * slope_ym, phi_ym, phi_c);
136 Set::Scalar phi_ylo_r = Util::Clamp(phi_c - 0.5 * slope_y, phi_ym, phi_c);
137 Set::Scalar phi_yhi_l = Util::Clamp(phi_c + 0.5 * slope_y, phi_c, phi_yp);
138 Set::Scalar phi_yhi_r = Util::Clamp(phi_yp - 0.5 * slope_yp, phi_c, phi_yp);
139
140 Set::Scalar flux_ylo = uy_ylo * (uy_ylo >= 0.0 ? phi_ylo_l : phi_ylo_r);
141 Set::Scalar flux_yhi = uy_yhi * (uy_yhi >= 0.0 ? phi_yhi_l : phi_yhi_r);
142 div_phi_u += (flux_yhi - flux_ylo) / DX[1];
143 div_u += (uy_yhi - uy_ylo) / DX[1];
144#endif
145
146#if AMREX_SPACEDIM == 3
147 Set::Scalar phi_zm = phi(i,j,k-1,comp);
148 Set::Scalar phi_zp = phi(i,j,k+1,comp);
149 Set::Scalar slope_zm = Slope(phi, i,j,k-2, i,j,k-1, i,j,k, comp);
150 Set::Scalar slope_z = Slope(phi, i,j,k-1, i,j,k, i,j,k+1, comp);
151 Set::Scalar slope_zp = Slope(phi, i,j,k, i,j,k+1, i,j,k+2, comp);
152
153 Set::Scalar uz_zlo = 0.5 * (velocity(i,j,k-1,2) + velocity(i,j,k,2));
154 Set::Scalar uz_zhi = 0.5 * (velocity(i,j,k,2) + velocity(i,j,k+1,2));
155
156 Set::Scalar phi_zlo_l = Util::Clamp(phi_zm + 0.5 * slope_zm, phi_zm, phi_c);
157 Set::Scalar phi_zlo_r = Util::Clamp(phi_c - 0.5 * slope_z, phi_zm, phi_c);
158 Set::Scalar phi_zhi_l = Util::Clamp(phi_c + 0.5 * slope_z, phi_c, phi_zp);
159 Set::Scalar phi_zhi_r = Util::Clamp(phi_zp - 0.5 * slope_zp, phi_c, phi_zp);
160
161 Set::Scalar flux_zlo = uz_zlo * (uz_zlo >= 0.0 ? phi_zlo_l : phi_zlo_r);
162 Set::Scalar flux_zhi = uz_zhi * (uz_zhi >= 0.0 ? phi_zhi_l : phi_zhi_r);
163 div_phi_u += (flux_zhi - flux_zlo) / DX[2];
164 div_u += (uz_zhi - uz_zlo) / DX[2];
165#endif
166
167 if (options.form == Form::Conservative) return -div_phi_u;
168 return -div_phi_u + phi_c * div_u;
169 }
170
171 template<class Phi, class Velocity>
172 AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE
173 Set::Scalar Scalar( Phi const& phi,
174 Velocity const& velocity,
175 int i, int j, int k,
176 int comp,
177 const Set::Scalar* DX,
178 Options options = {},
179 std::array<Numeric::StencilType, AMREX_SPACEDIM> stencil = Numeric::DefaultType) const
180 {
181 return (*this)(phi, velocity, i, j, k, comp, DX, options, stencil);
182 }
183};
184}
185}
186
187#endif
void select(std::string name, PTRTYPE *&ic_eta, Args &&... args)
Definition ParmParse.H:1064
static constexpr const char * name
Definition MUSCL.H:46
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE Set::Scalar Scalar(Phi const &phi, Velocity const &velocity, int i, int j, int k, int comp, const Set::Scalar *DX, Options options={}, std::array< Numeric::StencilType, AMREX_SPACEDIM > stencil=Numeric::DefaultType) const
Definition MUSCL.H:173
static constexpr Set::HC velocity_location
Definition MUSCL.H:48
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE int NGhost() const
Definition MUSCL.H:71
static void Parse(MUSCL &value, IO::ParmParse &pp)
Definition MUSCL.H:58
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE Set::Scalar Slope(Phi const &phi, int ilo, int jlo, int klo, int ic, int jc, int kc, int ihi, int jhi, int khi, int comp) const
Definition MUSCL.H:78
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE Set::Scalar operator()(Phi const &phi, Velocity const &velocity, int i, int j, int k, int comp, const Set::Scalar *DX, Options options={}, std::array< Numeric::StencilType, AMREX_SPACEDIM > stencil=Numeric::DefaultType) const
Definition MUSCL.H:91
static constexpr Set::HC phi_location
Definition MUSCL.H:47
Limiter::Limiter< Limiter::MC, Limiter::MinMod, Limiter::Superbee, Limiter::VanLeer, Limiter::VanAlbada, Limiter::Koren, Limiter::UMIST > limiter
Definition MUSCL.H:56
This namespace contains some numerical tools.
Definition Advect.H:14
static std::array< StencilType, AMREX_SPACEDIM > DefaultType
Definition Stencil.H:23
amrex::Real Scalar
Definition Base.H:19
Hypercube
Definition Set.H:31
@ Cell
Definition Set.H:32
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE T Clamp(T value, T lo, T hi)
Definition Util.H:383