def viscous_stress_tensor(state, grad_cv): r"""Compute the viscous stress tensor. The viscous stress tensor $\tau$ is defined by: .. math:: \mathbf{\tau} = \mu\left(\nabla{\mathbf{v}} +\left(\nabla{\mathbf{v}}\right)^T\right) + (\mu_B - \frac{2\mu}{3}) \left(\nabla\cdot\mathbf{v}\right) Parameters ---------- state: :class:`~mirgecom.gas_model.FluidState` Full conserved and thermal state of fluid grad_cv: :class:`~mirgecom.fluid.ConservedVars` Gradient of the fluid state Returns ------- numpy.ndarray The viscous stress tensor """ return _compute_viscous_stress_tensor(dim=state.dim, mu=state.viscosity, mu_b=state.bulk_viscosity, grad_v=velocity_gradient( state.cv, grad_cv))
def test_velocity_gradient_eoc(actx_factory, dim): """Test that the velocity gradient converges at the proper rate.""" from mirgecom.fluid import velocity_gradient actx = actx_factory() order = 3 from pytools.convergence import EOCRecorder eoc = EOCRecorder() nel_1d_0 = 4 for hn1 in [1, 2, 3, 4]: nel_1d = hn1 * nel_1d_0 h = 1/nel_1d from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh( a=(1.0,) * dim, b=(2.0,) * dim, nelements_per_axis=(nel_1d,) * dim ) discr = EagerDGDiscretization(actx, mesh, order=order) nodes = thaw(actx, discr.nodes()) zeros = discr.zeros(actx) energy = zeros + 2.5 mass = nodes[dim-1]*nodes[dim-1] velocity = make_obj_array([actx.np.cos(nodes[i]) for i in range(dim)]) mom = mass*velocity q = join_conserved(dim, mass=mass, energy=energy, momentum=mom) cv = split_conserved(dim, q) grad_q = obj_array_vectorize(discr.grad, q) grad_cv = split_conserved(dim, grad_q) grad_v = velocity_gradient(discr, cv, grad_cv) def exact_grad_row(xdata, gdim, dim): exact_grad_row = make_obj_array([zeros for _ in range(dim)]) exact_grad_row[gdim] = -actx.np.sin(xdata) return exact_grad_row comp_err = make_obj_array([ discr.norm(grad_v[i] - exact_grad_row(nodes[i], i, dim), np.inf) for i in range(dim)]) err_max = comp_err.max() eoc.add_data_point(h, err_max) logger.info(eoc) assert ( eoc.order_estimate() >= order - 0.5 or eoc.max_error() < 1e-9 )
def test_velocity_gradient_structure(actx_factory): """Test gradv data structure, verifying usability with other helper routines.""" from mirgecom.fluid import velocity_gradient actx = actx_factory() dim = 3 nel_1d = 4 from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh( a=(1.0,) * dim, b=(2.0,) * dim, nelements_per_axis=(nel_1d,) * dim ) order = 1 discr = EagerDGDiscretization(actx, mesh, order=order) nodes = thaw(actx, discr.nodes()) zeros = discr.zeros(actx) ones = zeros + 1.0 mass = 2*ones energy = zeros + 2.5 velocity_x = nodes[0] + 2*nodes[1] + 3*nodes[2] velocity_y = 4*nodes[0] + 5*nodes[1] + 6*nodes[2] velocity_z = 7*nodes[0] + 8*nodes[1] + 9*nodes[2] velocity = make_obj_array([velocity_x, velocity_y, velocity_z]) mom = mass * velocity cv = make_conserved(dim, mass=mass, energy=energy, momentum=mom) from grudge.op import local_grad grad_cv = local_grad(discr, cv) grad_v = velocity_gradient(cv, grad_cv) tol = 1e-11 exp_result = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] exp_trans = [[1, 4, 7], [2, 5, 8], [3, 6, 9]] exp_trace = 15 assert grad_v.shape == (dim, dim) from meshmode.dof_array import DOFArray assert type(grad_v[0, 0]) == DOFArray def inf_norm(x): return actx.to_numpy(discr.norm(x, np.inf)) assert inf_norm(grad_v - exp_result) < tol assert inf_norm(grad_v.T - exp_trans) < tol assert inf_norm(np.trace(grad_v) - exp_trace) < tol
def test_velocity_gradient_sanity(actx_factory, dim, mass_exp, vel_fac): """Test that the grad(v) returns {0, I} for v={constant, r_xyz}.""" from mirgecom.fluid import velocity_gradient actx = actx_factory() nel_1d = 16 from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(1.0, ) * dim, b=(2.0, ) * dim, nelements_per_axis=(nel_1d, ) * dim) order = 3 discr = EagerDGDiscretization(actx, mesh, order=order) nodes = thaw(actx, discr.nodes()) zeros = discr.zeros(actx) ones = zeros + 1.0 mass = 1 * ones for i in range(mass_exp): mass *= (mass + i) energy = zeros + 2.5 velocity = vel_fac * nodes mom = mass * velocity cv = make_conserved(dim, mass=mass, energy=energy, momentum=mom) from grudge.op import local_grad grad_cv = make_conserved(dim, q=local_grad(discr, cv.join())) grad_v = velocity_gradient(discr, cv, grad_cv) tol = 1e-11 exp_result = vel_fac * np.eye(dim) * ones grad_v_err = [ discr.norm(grad_v[i] - exp_result[i], np.inf) for i in range(dim) ] assert max(grad_v_err) < tol
def viscous_stress_tensor(discr, eos, cv, grad_cv): r"""Compute the viscous stress tensor. The viscous stress tensor $\tau$ is defined by: .. math:: \mathbf{\tau} = \mu\left(\nabla{\mathbf{v}} +\left(\nabla{\mathbf{v}}\right)^T\right) + (\mu_B - \frac{2\mu}{3}) \left(\nabla\cdot\mathbf{v}\right) Parameters ---------- discr: :class:`grudge.eager.EagerDGDiscretization` The discretization to use eos: :class:`~mirgecom.eos.GasEOS` A gas equation of state with a non-empty :class:`~mirgecom.transport.TransportModel`. cv: :class:`~mirgecom.fluid.ConservedVars` Fluid state grad_cv: :class:`~mirgecom.fluid.ConservedVars` Gradient of the fluid state Returns ------- numpy.ndarray The viscous stress tensor """ dim = cv.dim transport = eos.transport_model() mu_b = transport.bulk_viscosity(eos, cv) mu = transport.viscosity(eos, cv) grad_v = velocity_gradient(discr, cv, grad_cv) div_v = np.trace(grad_v) return mu * (grad_v + grad_v.T) + (mu_b - 2 * mu / 3) * div_v * np.eye(dim)