def test_diffusive_heat_flux(actx_factory): """Test diffusive heat flux and values against exact.""" 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 # assemble velocities for simple, unique grad components 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]) # assemble y so that each one has simple, but unique grad components nspecies = 2 * dim y = make_obj_array([ones for _ in range(nspecies)]) for idim in range(dim): ispec = 2 * idim y[ispec] = (ispec + 1) * (idim * dim + 1) * sum( [(iidim + 1) * nodes[iidim] for iidim in range(dim)]) y[ispec + 1] = -y[ispec] massval = 2 mass = massval * ones energy = zeros + 2.5 mom = mass * velocity species_mass = mass * y cv = make_conserved(dim, mass=mass, energy=energy, momentum=mom, species_mass=species_mass) grad_cv = op.local_grad(discr, cv) mu_b = 1.0 mu = 0.5 kappa = 5.0 # assemble d_alpha so that every species has a unique j d_alpha = np.array([(ispec + 1) for ispec in range(nspecies)]) tv_model = SimpleTransport(bulk_viscosity=mu_b, viscosity=mu, thermal_conductivity=kappa, species_diffusivity=d_alpha) eos = IdealSingleGas() gas_model = GasModel(eos=eos, transport=tv_model) fluid_state = make_fluid_state(cv, gas_model) from mirgecom.viscous import diffusive_flux j = diffusive_flux(fluid_state, grad_cv) def inf_norm(x): return actx.to_numpy(discr.norm(x, np.inf)) tol = 1e-10 for idim in range(dim): ispec = 2 * idim exact_dy = np.array([((ispec + 1) * (idim * dim + 1)) * (iidim + 1) for iidim in range(dim)]) exact_j = -massval * d_alpha[ispec] * exact_dy assert inf_norm(j[ispec] - exact_j) < tol exact_j = massval * d_alpha[ispec + 1] * exact_dy assert inf_norm(j[ispec + 1] - exact_j) < tol
def test_poiseuille_fluxes(actx_factory, order, kappa): """Test the viscous fluxes using a Poiseuille input state.""" actx = actx_factory() dim = 2 from pytools.convergence import EOCRecorder e_eoc_rec = EOCRecorder() p_eoc_rec = EOCRecorder() base_pressure = 100000.0 pressure_ratio = 1.001 mu = 42 # arbitrary left_boundary_location = 0 right_boundary_location = 0.1 ybottom = 0. ytop = .02 nspecies = 0 spec_diffusivity = 0 * np.ones(nspecies) transport_model = SimpleTransport(viscosity=mu, thermal_conductivity=kappa, species_diffusivity=spec_diffusivity) xlen = right_boundary_location - left_boundary_location p_low = base_pressure p_hi = pressure_ratio * base_pressure dpdx = (p_low - p_hi) / xlen rho = 1.0 eos = IdealSingleGas(transport_model=transport_model) from mirgecom.initializers import PlanarPoiseuille initializer = PlanarPoiseuille(density=rho, mu=mu) def _elbnd_flux(discr, compute_interior_flux, compute_boundary_flux, int_tpair, boundaries): return (compute_interior_flux(int_tpair) + sum(compute_boundary_flux(btag) for btag in boundaries)) from mirgecom.flux import gradient_flux_central def cv_flux_interior(int_tpair): normal = thaw(actx, discr.normal(int_tpair.dd)) flux_weak = gradient_flux_central(int_tpair, normal) return discr.project(int_tpair.dd, "all_faces", flux_weak) def cv_flux_boundary(btag): boundary_discr = discr.discr_from_dd(btag) bnd_nodes = thaw(actx, boundary_discr.nodes()) cv_bnd = initializer(x_vec=bnd_nodes, eos=eos) bnd_nhat = thaw(actx, discr.normal(btag)) from grudge.trace_pair import TracePair bnd_tpair = TracePair(btag, interior=cv_bnd, exterior=cv_bnd) flux_weak = gradient_flux_central(bnd_tpair, bnd_nhat) return discr.project(bnd_tpair.dd, "all_faces", flux_weak) for nfac in [1, 2, 4]: npts_axis = nfac * (11, 21) box_ll = (left_boundary_location, ybottom) box_ur = (right_boundary_location, ytop) mesh = _get_box_mesh(2, a=box_ll, b=box_ur, n=npts_axis) logger.info(f"Number of {dim}d elements: {mesh.nelements}") discr = EagerDGDiscretization(actx, mesh, order=order) nodes = thaw(actx, discr.nodes()) # compute max element size from grudge.dt_utils import h_max_from_volume h_max = h_max_from_volume(discr) # form exact cv cv = initializer(x_vec=nodes, eos=eos) cv_int_tpair = interior_trace_pair(discr, cv) boundaries = [BTAG_ALL] cv_flux_bnd = _elbnd_flux(discr, cv_flux_interior, cv_flux_boundary, cv_int_tpair, boundaries) from mirgecom.operators import grad_operator grad_cv = make_conserved(dim, q=grad_operator(discr, cv.join(), cv_flux_bnd.join())) xp_grad_cv = initializer.exact_grad(x_vec=nodes, eos=eos, cv_exact=cv) xp_grad_v = 1 / cv.mass * xp_grad_cv.momentum xp_tau = mu * (xp_grad_v + xp_grad_v.transpose()) # sanity check the gradient: relerr_scale_e = 1.0 / discr.norm(xp_grad_cv.energy, np.inf) relerr_scale_p = 1.0 / discr.norm(xp_grad_cv.momentum, np.inf) graderr_e = discr.norm((grad_cv.energy - xp_grad_cv.energy), np.inf) graderr_p = discr.norm((grad_cv.momentum - xp_grad_cv.momentum), np.inf) graderr_e *= relerr_scale_e graderr_p *= relerr_scale_p assert graderr_e < 5e-7 assert graderr_p < 5e-11 zeros = discr.zeros(actx) ones = zeros + 1 pressure = eos.pressure(cv) # grad of p should be dp/dx xp_grad_p = make_obj_array([dpdx * ones, zeros]) grad_p = op.local_grad(discr, pressure) dpscal = 1.0 / np.abs(dpdx) temperature = eos.temperature(cv) tscal = rho * eos.gas_const() * dpscal xp_grad_t = xp_grad_p / (cv.mass * eos.gas_const()) grad_t = op.local_grad(discr, temperature) # sanity check assert discr.norm(grad_p - xp_grad_p, np.inf) * dpscal < 5e-9 assert discr.norm(grad_t - xp_grad_t, np.inf) * tscal < 5e-9 # verify heat flux from mirgecom.viscous import conductive_heat_flux heat_flux = conductive_heat_flux(discr, eos, cv, grad_t) xp_heat_flux = -kappa * xp_grad_t assert discr.norm(heat_flux - xp_heat_flux, np.inf) < 2e-8 # verify diffusive mass flux is zilch (no scalar components) from mirgecom.viscous import diffusive_flux j = diffusive_flux(discr, eos, cv, grad_cv) assert len(j) == 0 xp_e_flux = np.dot(xp_tau, cv.velocity) - xp_heat_flux xp_mom_flux = xp_tau from mirgecom.viscous import viscous_flux vflux = viscous_flux(discr, eos, cv, grad_cv, grad_t) efluxerr = (discr.norm(vflux.energy - xp_e_flux, np.inf) / discr.norm(xp_e_flux, np.inf)) momfluxerr = (discr.norm(vflux.momentum - xp_mom_flux, np.inf) / discr.norm(xp_mom_flux, np.inf)) assert discr.norm(vflux.mass, np.inf) == 0 e_eoc_rec.add_data_point(h_max, efluxerr) p_eoc_rec.add_data_point(h_max, momfluxerr) assert (e_eoc_rec.order_estimate() >= order - 0.5 or e_eoc_rec.max_error() < 3e-9) assert (p_eoc_rec.order_estimate() >= order - 0.5 or p_eoc_rec.max_error() < 2e-12)