Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 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 : 12 : registerMooseObject("RdgApp", AEFVSlopeLimitingOneD); 13 : 14 : InputParameters 15 98 : AEFVSlopeLimitingOneD::validParams() 16 : { 17 98 : InputParameters params = SlopeLimitingBase::validParams(); 18 98 : 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 196 : params.addRequiredCoupledVar("u", "constant monomial variable"); 22 196 : MooseEnum scheme("none minmod mc superbee", "none"); 23 196 : params.addParam<MooseEnum>("scheme", scheme, "TVD-type slope limiting scheme"); 24 98 : return params; 25 98 : } 26 : 27 49 : AEFVSlopeLimitingOneD::AEFVSlopeLimitingOneD(const InputParameters & parameters) 28 98 : : SlopeLimitingBase(parameters), _u(getVar("u", 0)), _scheme(getParam<MooseEnum>("scheme")) 29 : { 30 49 : } 31 : 32 : std::vector<RealGradient> 33 45400 : AEFVSlopeLimitingOneD::limitElementSlope() const 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 45400 : 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 45400 : unsigned int nside = elem->n_sides(); 52 : 53 : // number of reconstruction stencils = 3 in 1D 54 45400 : unsigned int nsten = nside + 1; 55 : 56 : // vector for the gradients of primitive variables 57 45400 : std::vector<RealGradient> ugrad(nvars, RealGradient(0., 0., 0.)); 58 : 59 : // array to store center coordinates of this cell and its neighbor cells 60 45400 : std::vector<Real> xc(nsten, 0.); 61 : 62 : // the first always stores the current cell 63 45400 : xc[0] = elem->vertex_average()(0); 64 : 65 : // array for the cell-average values in the current cell and its neighbors 66 45400 : 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 45400 : std::vector<std::vector<Real>> sigma(nsten, std::vector<Real>(nvars, 0.)); 85 : 86 : // get the cell-average variable in the central cell 87 45400 : if (_is_implicit) 88 27400 : ucell[0][0] = _u->getElementalValue(elem); 89 : else 90 18000 : 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 136200 : for (is = 0; is < nside; is++) 99 : { 100 90800 : in = is + 1; 101 : 102 : // when the current element is an internal cell 103 90800 : if (elem->neighbor_ptr(is) != NULL) 104 : { 105 : const Elem * neig = elem->neighbor_ptr(is); 106 89892 : if (this->hasBlocks(neig->subdomain_id())) 107 : { 108 89852 : xc[in] = neig->vertex_average()(0); 109 : 110 : // get the cell-average variable in this neighbor cell 111 89852 : if (_is_implicit) 112 54252 : ucell[in][0] = _u->getElementalValue(neig); 113 : else 114 35600 : ucell[in][0] = _u->getElementalValueOld(neig); 115 : 116 : // calculate the one-sided slopes of primitive variables 117 : 118 179704 : for (iv = 0; iv < nvars; iv++) 119 89852 : 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 45400 : switch (_scheme) 136 : { 137 : // first-order, zero slope 138 : case 0: 139 : break; 140 : 141 : // ============== 142 : // minmod limiter 143 : // ============== 144 4000 : case 1: 145 : 146 4000 : if (bflag == 0) 147 : { 148 7840 : for (iv = 0; iv < nvars; iv++) 149 : { 150 3920 : if ((sigma[1][iv] * sigma[2][iv]) > 0.) 151 : { 152 320 : if (std::abs(sigma[1][iv]) < std::abs(sigma[2][iv])) 153 40 : ugrad[iv](0) = sigma[1][iv]; 154 : else 155 280 : ugrad[iv](0) = sigma[2][iv]; 156 : } 157 : } 158 : } 159 : break; 160 : 161 : // =========================================== 162 : // MC (monotonized central-difference limiter) 163 : // =========================================== 164 4000 : case 2: 165 : 166 4000 : if (bflag == 0) 167 : { 168 7840 : for (iv = 0; iv < nvars; iv++) 169 3920 : sigma[0][iv] = (ucell[1][iv] - ucell[2][iv]) / (xc[1] - xc[2]); 170 : 171 7840 : for (iv = 0; iv < nvars; iv++) 172 : { 173 3920 : if (sigma[0][iv] > 0. && sigma[1][iv] > 0. && sigma[2][iv] > 0.) 174 110 : ugrad[iv](0) = std::min(sigma[0][iv], 2. * std::min(sigma[1][iv], sigma[2][iv])); 175 3845 : else if (sigma[0][iv] < 0. && sigma[1][iv] < 0. && sigma[2][iv] < 0.) 176 70 : 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 6000 : case 3: 185 : 186 6000 : if (bflag == 0) 187 : { 188 11680 : for (iv = 0; iv < nvars; iv++) 189 : { 190 5840 : Real sigma1 = 0.; 191 5840 : Real sigma2 = 0.; 192 : 193 : // calculate sigma1 with minmod 194 5840 : if (sigma[2][iv] > 0. && sigma[1][iv] > 0.) 195 150 : sigma1 = std::min(sigma[2][iv], 2. * sigma[1][iv]); 196 5690 : else if (sigma[2][iv] < 0. && sigma[1][iv] < 0.) 197 70 : sigma1 = std::max(sigma[2][iv], 2. * sigma[1][iv]); 198 : 199 : // calculate sigma2 with minmod 200 5840 : if (sigma[2][iv] > 0. && sigma[1][iv] > 0.) 201 230 : sigma2 = std::min(2. * sigma[2][iv], sigma[1][iv]); 202 5690 : else if (sigma[2][iv] < 0. && sigma[1][iv] < 0.) 203 70 : sigma2 = std::max(2. * sigma[2][iv], sigma[1][iv]); 204 : 205 : // calculate sigma with maxmod 206 5840 : if (sigma1 > 0. && sigma2 > 0.) 207 150 : ugrad[iv](0) = std::max(sigma1, sigma2); 208 5690 : else if (sigma1 < 0. && sigma2 < 0.) 209 70 : ugrad[iv](0) = std::min(sigma1, sigma2); 210 : } 211 : } 212 : break; 213 : 214 0 : default: 215 0 : mooseError("Unknown 1D TVD-type slope limiter scheme"); 216 : break; 217 : } 218 : 219 45400 : return ugrad; 220 45400 : }