www.mooseframework.org
AEFVSlopeLimitingOneD.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "AEFVSlopeLimitingOneD.h"
11 
13 
16 {
18  params.addClassDescription("One-dimensional slope limiting to get the limited slope of cell "
19  "average variable for the advection equation using a cell-centered "
20  "finite volume method.");
21  params.addRequiredCoupledVar("u", "constant monomial variable");
22  MooseEnum scheme("none minmod mc superbee", "none");
23  params.addParam<MooseEnum>("scheme", scheme, "TVD-type slope limiting scheme");
24  return params;
25 }
26 
28  : SlopeLimitingBase(parameters), _u(getVar("u", 0)), _scheme(getParam<MooseEnum>("scheme"))
29 {
30 }
31 
32 std::vector<RealGradient>
34 {
35  // you should know how many equations you are solving and assign this number
36  // e.g. = 1 (for the advection equation)
37  unsigned int nvars = 1;
38 
39  const Elem * elem = _current_elem;
40 
41  // index of conserved variable
42  unsigned int iv;
43 
44  // index of sides around an element
45  unsigned int is;
46 
47  // index of the neighbor element
48  unsigned int in;
49 
50  // number of sides surrounding an element = 2 in 1D
51  unsigned int nside = elem->n_sides();
52 
53  // number of reconstruction stencils = 3 in 1D
54  unsigned int nsten = nside + 1;
55 
56  // vector for the gradients of primitive variables
57  std::vector<RealGradient> ugrad(nvars, RealGradient(0., 0., 0.));
58 
59  // array to store center coordinates of this cell and its neighbor cells
60  std::vector<Real> xc(nsten, 0.);
61 
62  // the first always stores the current cell
63  xc[0] = elem->vertex_average()(0);
64 
65  // array for the cell-average values in the current cell and its neighbors
66  std::vector<std::vector<Real>> ucell(nsten, std::vector<Real>(nvars, 0.));
67 
68  // central slope:
69  // u_{i+1} - u {i-1}
70  // -----------------
71  // x_{i+1} - x_{i-1}
72 
73  // left-side slope:
74  // u_{i} - u {i-1}
75  // ---------------
76  // x_{i} - x_{i-1}
77 
78  // right-side slope:
79  // u_{i+1} - u {i}
80  // ---------------
81  // x_{i+1} - x_{i}
82 
83  // array to store the central and one-sided slopes, where the first should be central slope
84  std::vector<std::vector<Real>> sigma(nsten, std::vector<Real>(nvars, 0.));
85 
86  // get the cell-average variable in the central cell
87  if (_is_implicit)
88  ucell[0][0] = _u->getElementalValue(elem);
89  else
90  ucell[0][0] = _u->getElementalValueOld(elem);
91 
92  // a flag to indicate the boundary side of the current cell
93 
94  unsigned int bflag = 0;
95 
96  // loop over the sides to compute the one-sided slopes
97 
98  for (is = 0; is < nside; is++)
99  {
100  in = is + 1;
101 
102  // when the current element is an internal cell
103  if (elem->neighbor_ptr(is) != NULL)
104  {
105  const Elem * neig = elem->neighbor_ptr(is);
106  if (this->hasBlocks(neig->subdomain_id()))
107  {
108  xc[in] = neig->vertex_average()(0);
109 
110  // get the cell-average variable in this neighbor cell
111  if (_is_implicit)
112  ucell[in][0] = _u->getElementalValue(neig);
113  else
114  ucell[in][0] = _u->getElementalValueOld(neig);
115 
116  // calculate the one-sided slopes of primitive variables
117 
118  for (iv = 0; iv < nvars; iv++)
119  sigma[in][iv] = (ucell[0][iv] - ucell[in][iv]) / (xc[0] - xc[in]);
120  }
121  else
122  bflag = in;
123  }
124  // when the current element is at the boundary,
125  // we choose not to construct the slope in 1D just for convenience.
126  else
127  {
128  bflag = in;
129  }
130  }
131 
132  // calculate the slope of the current element
133  // according to the choice of the slope limiter algorithm
134 
135  switch (_scheme)
136  {
137  // first-order, zero slope
138  case 0:
139  break;
140 
141  // ==============
142  // minmod limiter
143  // ==============
144  case 1:
145 
146  if (bflag == 0)
147  {
148  for (iv = 0; iv < nvars; iv++)
149  {
150  if ((sigma[1][iv] * sigma[2][iv]) > 0.)
151  {
152  if (std::abs(sigma[1][iv]) < std::abs(sigma[2][iv]))
153  ugrad[iv](0) = sigma[1][iv];
154  else
155  ugrad[iv](0) = sigma[2][iv];
156  }
157  }
158  }
159  break;
160 
161  // ===========================================
162  // MC (monotonized central-difference limiter)
163  // ===========================================
164  case 2:
165 
166  if (bflag == 0)
167  {
168  for (iv = 0; iv < nvars; iv++)
169  sigma[0][iv] = (ucell[1][iv] - ucell[2][iv]) / (xc[1] - xc[2]);
170 
171  for (iv = 0; iv < nvars; iv++)
172  {
173  if (sigma[0][iv] > 0. && sigma[1][iv] > 0. && sigma[2][iv] > 0.)
174  ugrad[iv](0) = std::min(sigma[0][iv], 2. * std::min(sigma[1][iv], sigma[2][iv]));
175  else if (sigma[0][iv] < 0. && sigma[1][iv] < 0. && sigma[2][iv] < 0.)
176  ugrad[iv](0) = std::max(sigma[0][iv], 2. * std::max(sigma[1][iv], sigma[2][iv]));
177  }
178  }
179  break;
180 
181  // ================
182  // Superbee limiter
183  // ================
184  case 3:
185 
186  if (bflag == 0)
187  {
188  for (iv = 0; iv < nvars; iv++)
189  {
190  Real sigma1 = 0.;
191  Real sigma2 = 0.;
192 
193  // calculate sigma1 with minmod
194  if (sigma[2][iv] > 0. && sigma[1][iv] > 0.)
195  sigma1 = std::min(sigma[2][iv], 2. * sigma[1][iv]);
196  else if (sigma[2][iv] < 0. && sigma[1][iv] < 0.)
197  sigma1 = std::max(sigma[2][iv], 2. * sigma[1][iv]);
198 
199  // calculate sigma2 with minmod
200  if (sigma[2][iv] > 0. && sigma[1][iv] > 0.)
201  sigma2 = std::min(2. * sigma[2][iv], sigma[1][iv]);
202  else if (sigma[2][iv] < 0. && sigma[1][iv] < 0.)
203  sigma2 = std::max(2. * sigma[2][iv], sigma[1][iv]);
204 
205  // calculate sigma with maxmod
206  if (sigma1 > 0. && sigma2 > 0.)
207  ugrad[iv](0) = std::max(sigma1, sigma2);
208  else if (sigma1 < 0. && sigma2 < 0.)
209  ugrad[iv](0) = std::min(sigma1, sigma2);
210  }
211  }
212  break;
213 
214  default:
215  mooseError("Unknown 1D TVD-type slope limiter scheme");
216  break;
217  }
218 
219  return ugrad;
220 }
One-dimensional slope limiting to get the limited slope of cell average variable for the advection eq...
static InputParameters validParams()
static InputParameters validParams()
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
MooseVariable * _u
the input variable
MooseEnum _scheme
One-D slope limiting scheme.
OutputData getElementalValue(const Elem *elem, unsigned int idx=0) const
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
PetscErrorCode PetscInt const PetscInt IS * is
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
Base class for slope limiting to limit the slopes of cell average variables.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
OutputData getElementalValueOld(const Elem *elem, unsigned int idx=0) const
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
bool hasBlocks(const SubdomainName &name) const
registerMooseObject("RdgApp", AEFVSlopeLimitingOneD)
virtual std::vector< RealGradient > limitElementSlope() const override
compute the limited slope of the cell
AEFVSlopeLimitingOneD(const InputParameters &parameters)