diff --git a/mirgecom/multiphysics/thermally_coupled_fluid_wall.py b/mirgecom/multiphysics/thermally_coupled_fluid_wall.py index b91839011..05212524a 100644 --- a/mirgecom/multiphysics/thermally_coupled_fluid_wall.py +++ b/mirgecom/multiphysics/thermally_coupled_fluid_wall.py @@ -75,6 +75,7 @@ make_operator_fluid_states, ) from mirgecom.navierstokes import ( + grad_cv_operator as fluid_grad_cv_operator, grad_t_operator as fluid_grad_t_operator, ns_operator, ) @@ -119,6 +120,10 @@ class _WallOperatorTag: pass +class _GetInterfaceTag: + pass + + def _project_from_base(dcoll, dd_bdry, field): """Project *field* from *DISCR_TAG_BASE* to the same discr. as *dd_bdry*.""" if dd_bdry.discretization_tag is not DISCR_TAG_BASE: @@ -647,7 +652,8 @@ def _kappa_inter_volume_trace_pairs( dcoll, gas_model, fluid_dd, wall_dd, - fluid_state, wall_kappa): + fluid_state, wall_kappa, + comm_tag): """Exchange thermal conductivity across the fluid-wall interface.""" actx = fluid_state.array_context fluid_kappa = fluid_state.thermal_conductivity @@ -662,33 +668,36 @@ def _kappa_inter_volume_trace_pairs( pairwise_kappa = { (fluid_dd, wall_dd): (fluid_kappa, wall_kappa)} return inter_volume_trace_pairs( - dcoll, pairwise_kappa, comm_tag=_KappaInterVolTag) + dcoll, pairwise_kappa, comm_tag=(_KappaInterVolTag, comm_tag)) def _temperature_inter_volume_trace_pairs( dcoll, gas_model, fluid_dd, wall_dd, - fluid_state, wall_temperature): + fluid_state, wall_temperature, + comm_tag): """Exchange temperature across the fluid-wall interface.""" pairwise_temperature = { (fluid_dd, wall_dd): (fluid_state.temperature, wall_temperature)} return inter_volume_trace_pairs( - dcoll, pairwise_temperature, comm_tag=_TemperatureInterVolTag) + dcoll, pairwise_temperature, comm_tag=(_TemperatureInterVolTag, comm_tag)) def _grad_temperature_inter_volume_trace_pairs( dcoll, gas_model, fluid_dd, wall_dd, - fluid_grad_temperature, wall_grad_temperature): + fluid_grad_temperature, wall_grad_temperature, + comm_tag): """Exchange temperature gradient across the fluid-wall interface.""" pairwise_grad_temperature = { (fluid_dd, wall_dd): (fluid_grad_temperature, wall_grad_temperature)} return inter_volume_trace_pairs( - dcoll, pairwise_grad_temperature, comm_tag=_GradTemperatureInterVolTag) + dcoll, pairwise_grad_temperature, + comm_tag=(_GradTemperatureInterVolTag, comm_tag)) def get_interface_boundaries( @@ -706,7 +715,8 @@ def get_interface_boundaries( # FIXME: See if there's a better way to do this _kappa_inter_vol_tpairs=None, _temperature_inter_vol_tpairs=None, - _grad_temperature_inter_vol_tpairs=None): + _grad_temperature_inter_vol_tpairs=None, + comm_tag=None): """ Get the fluid-wall interface boundaries. @@ -803,7 +813,8 @@ def get_interface_boundaries( dcoll, gas_model, fluid_dd, wall_dd, - fluid_state, wall_kappa) + fluid_state, wall_kappa, + comm_tag) else: kappa_inter_vol_tpairs = _kappa_inter_vol_tpairs @@ -812,7 +823,8 @@ def get_interface_boundaries( dcoll, gas_model, fluid_dd, wall_dd, - fluid_state, wall_temperature) + fluid_state, wall_temperature, + comm_tag) else: temperature_inter_vol_tpairs = _temperature_inter_vol_tpairs @@ -823,7 +835,8 @@ def get_interface_boundaries( dcoll, gas_model, fluid_dd, wall_dd, - fluid_grad_temperature, wall_grad_temperature) + fluid_grad_temperature, wall_grad_temperature, + comm_tag) else: grad_temperature_inter_vol_tpairs = _grad_temperature_inter_vol_tpairs else: @@ -909,7 +922,8 @@ def coupled_grad_t_operator( _temperature_inter_vol_tpairs=None, _fluid_operator_states_quad=None, _fluid_interface_boundaries_no_grad=None, - _wall_interface_boundaries_no_grad=None): + _wall_interface_boundaries_no_grad=None, + comm_tag): r""" Compute $\nabla T$ on the fluid and wall subdomains. @@ -1019,7 +1033,8 @@ def coupled_grad_t_operator( use_kappa_weighted_grad_flux_in_fluid=( use_kappa_weighted_grad_flux_in_fluid), _kappa_inter_vol_tpairs=_kappa_inter_vol_tpairs, - _temperature_inter_vol_tpairs=_temperature_inter_vol_tpairs) + _temperature_inter_vol_tpairs=_temperature_inter_vol_tpairs, + comm_tag=comm_tag) else: fluid_interface_boundaries_no_grad = _fluid_interface_boundaries_no_grad wall_interface_boundaries_no_grad = _wall_interface_boundaries_no_grad @@ -1042,13 +1057,14 @@ def coupled_grad_t_operator( time=time, quadrature_tag=quadrature_tag, numerical_flux_func=fluid_numerical_flux_func, dd=fluid_dd, operator_states_quad=_fluid_operator_states_quad, - comm_tag=_FluidGradTag), + comm_tag=(_FluidGradTag, comm_tag)), wall_grad_t_operator( dcoll, wall_kappa, wall_all_boundaries_no_grad, wall_temperature, - quadrature_tag=quadrature_tag, dd=wall_dd, comm_tag=_WallGradTag)) + quadrature_tag=quadrature_tag, dd=wall_dd, + comm_tag=(_WallGradTag, comm_tag))) -def coupled_ns_heat_operator( +def update_coupled_boundary_conditions( dcoll, gas_model, fluid_dd, wall_dd, @@ -1062,11 +1078,10 @@ def coupled_ns_heat_operator( quadrature_tag=DISCR_TAG_BASE, limiter_func=None, fluid_gradient_numerical_flux_func=num_flux_central, - inviscid_numerical_flux_func=inviscid_facial_flux_rusanov, - viscous_numerical_flux_func=viscous_facial_flux_harmonic, - return_gradients=False): + return_gradients=False, + comm_tag=None): r""" - Compute the RHS of the fluid and wall subdomains. + Update the fluid and wall subdomain boundaries. Augments *fluid_boundaries* and *wall_boundaries* with the boundaries for the fluid-wall interface that are needed to enforce continuity of temperature and @@ -1131,13 +1146,13 @@ def coupled_ns_heat_operator( Indicates whether the temperature gradient flux on the fluid side of the interface should be computed using a simple average of temperatures or by weighting the temperature from each side by its respective thermal - conductivity. + conductivity. Not used if *interface_radiation* is `True`. wall_penalty_amount: float Coefficient $c$ for the interior penalty on the heat flux. See :class:`~mirgecom.multiphysics.thermally_coupled_fluid_wall.InterfaceFluidBoundary` - for details. + for details. Not used if *interface_radiation* is `True`. quadrature_tag: @@ -1169,11 +1184,15 @@ def coupled_ns_heat_operator( that filters or limits the produced fluid states. This is used to keep species mass fractions in physical and realizable states, for example. + comm_tag: Hashable + Tag for distributed communication + Returns ------- The tuple `(fluid_rhs, wall_rhs)`. """ + if wall_penalty_amount is None: # FIXME: After verifying the form of the penalty term, figure out what value # makes sense to use as a default here @@ -1192,14 +1211,14 @@ def coupled_ns_heat_operator( dcoll, gas_model, fluid_dd, wall_dd, - fluid_state, wall_kappa) + fluid_state, wall_kappa, comm_tag) # FIXME: Maybe better to project CV and recompute T instead? temperature_inter_vol_tpairs = _temperature_inter_volume_trace_pairs( dcoll, gas_model, fluid_dd, wall_dd, - fluid_state, wall_temperature) + fluid_state, wall_temperature, comm_tag) # Construct boundaries for the fluid-wall interface; no temperature gradient # yet because we need to compute it @@ -1215,7 +1234,8 @@ def coupled_ns_heat_operator( use_kappa_weighted_grad_flux_in_fluid=( use_kappa_weighted_grad_flux_in_fluid), _kappa_inter_vol_tpairs=kappa_inter_vol_tpairs, - _temperature_inter_vol_tpairs=temperature_inter_vol_tpairs) + _temperature_inter_vol_tpairs=temperature_inter_vol_tpairs, + comm_tag=(_GetInterfaceTag, comm_tag)) # Augment the domain boundaries with the interface boundaries (fluid only; # needed for make_operator_fluid_states) @@ -1225,10 +1245,9 @@ def coupled_ns_heat_operator( fluid_all_boundaries_no_grad.update(fluid_interface_boundaries_no_grad) # Get the operator fluid states - fluid_operator_states_quad = make_operator_fluid_states( dcoll, fluid_state, gas_model, fluid_all_boundaries_no_grad, - quadrature_tag, dd=fluid_dd, comm_tag=_FluidOpStatesTag, + quadrature_tag, dd=fluid_dd, comm_tag=(_FluidOpStatesTag, comm_tag), limiter_func=limiter_func) # Compute the temperature gradient for both subdomains @@ -1249,7 +1268,8 @@ def coupled_ns_heat_operator( _temperature_inter_vol_tpairs=temperature_inter_vol_tpairs, _fluid_operator_states_quad=fluid_operator_states_quad, _fluid_interface_boundaries_no_grad=fluid_interface_boundaries_no_grad, - _wall_interface_boundaries_no_grad=wall_interface_boundaries_no_grad) + _wall_interface_boundaries_no_grad=wall_interface_boundaries_no_grad, + comm_tag=comm_tag) # Construct boundaries for the fluid-wall interface, now with the temperature # gradient @@ -1268,7 +1288,8 @@ def coupled_ns_heat_operator( use_kappa_weighted_grad_flux_in_fluid), wall_penalty_amount=wall_penalty_amount, _kappa_inter_vol_tpairs=kappa_inter_vol_tpairs, - _temperature_inter_vol_tpairs=temperature_inter_vol_tpairs) + _temperature_inter_vol_tpairs=temperature_inter_vol_tpairs, + comm_tag=comm_tag) # Augment the domain boundaries with the interface boundaries @@ -1280,33 +1301,326 @@ def coupled_ns_heat_operator( wall_all_boundaries.update(wall_boundaries) wall_all_boundaries.update(wall_interface_boundaries) + if return_gradients: + # compute the fluid gradients as well + fluid_grad_cv = fluid_grad_cv_operator( + dcoll, gas_model, fluid_all_boundaries, fluid_state, + dd=fluid_dd, time=time, quadrature_tag=quadrature_tag, + comm_tag=comm_tag) + + return (fluid_all_boundaries, wall_all_boundaries, + fluid_operator_states_quad, + fluid_grad_cv, + fluid_grad_temperature, + wall_grad_temperature) + else: + return (fluid_all_boundaries, wall_all_boundaries, + fluid_operator_states_quad) + + +def coupled_ns_heat_operator_with_grad( + dcoll, + gas_model, + fluid_dd, wall_dd, + fluid_boundaries, wall_boundaries, + fluid_state, wall_kappa, wall_temperature, + fluid_operator_states_quad, + fluid_grad_cv, fluid_grad_t, wall_grad_t, + *, + time=0., + wall_penalty_amount=None, + quadrature_tag=DISCR_TAG_BASE, + limiter_func=None, + fluid_gradient_numerical_flux_func=num_flux_central, + inviscid_numerical_flux_func=inviscid_facial_flux_rusanov, + viscous_numerical_flux_func=viscous_facial_flux_harmonic, + comm_tag=None): + r""" + Compute the RHS of the fluid and wall subdomains. + + Augments *fluid_boundaries* and *wall_boundaries* with the boundaries for the + fluid-wall interface that are needed to enforce continuity of temperature and + heat flux. + + Parameters + ---------- + + dcoll: class:`~grudge.discretization.DiscretizationCollection` + + A discretization collection encapsulating the DG elements + + gas_model: :class:`~mirgecom.gas_model.GasModel` + + Physical gas model including equation of state, transport, + and kinetic properties as required by fluid state + + fluid_dd: :class:`grudge.dof_desc.DOFDesc` + + DOF descriptor for the fluid volume. + + wall_dd: :class:`grudge.dof_desc.DOFDesc` + + DOF descriptor for the wall volume. + + fluid_boundaries: + + Dictionary of boundary objects for the fluid subdomain, one for each + :class:`~grudge.dof_desc.BoundaryDomainTag` that represents a domain + boundary. + + wall_boundaries: + + Dictionary of boundary objects for the wall subdomain, one for each + :class:`~grudge.dof_desc.BoundaryDomainTag` that represents a domain + boundary. + + fluid_state: :class:`~mirgecom.gas_model.FluidState` + + Fluid state object with the conserved state and dependent + quantities for the fluid volume. + + wall_kappa: float or :class:`meshmode.dof_array.DOFArray` + + Thermal conductivity for the wall volume. + + wall_temperature: :class:`meshmode.dof_array.DOFArray` + + Temperature for the wall volume. + + time: + + Time + + quadrature_tag: + + An identifier denoting a particular quadrature discretization to use during + operator evaluations. + + fluid_gradient_numerical_flux_func: + + Callable function to return the numerical flux to be used when computing + the temperature gradient in the fluid subdomain. Defaults to + :class:`~mirgecom.flux.num_flux_central`. + + inviscid_numerical_flux_func: + + Callable function providing the face-normal flux to be used + for the divergence of the inviscid transport flux. This defaults to + :func:`~mirgecom.inviscid.inviscid_facial_flux_rusanov`. + + viscous_numerical_flux_func: + + Callable function providing the face-normal flux to be used + for the divergence of the viscous transport flux. This defaults to + :func:`~mirgecom.viscous.viscous_facial_flux_harmonic`. + + limiter_func: + + Callable function to be passed to + :func:`~mirgecom.gas_model.make_operator_fluid_states` + that filters or limits the produced fluid states. This is used to keep + species mass fractions in physical and realizable states, for example. + + Returns + ------- + + The tuple `(fluid_rhs, wall_rhs)`. + """ + # Compute the subdomain NS/diffusion operators using the augmented boundaries ns_result = ns_operator( - dcoll, gas_model, fluid_state, fluid_all_boundaries, + dcoll, gas_model, fluid_state, fluid_boundaries, time=time, quadrature_tag=quadrature_tag, dd=fluid_dd, inviscid_numerical_flux_func=inviscid_numerical_flux_func, viscous_numerical_flux_func=viscous_numerical_flux_func, - return_gradients=return_gradients, operator_states_quad=fluid_operator_states_quad, - grad_t=fluid_grad_temperature, comm_tag=_FluidOperatorTag) + grad_cv=fluid_grad_cv, grad_t=fluid_grad_t, + comm_tag=(_FluidOperatorTag, comm_tag)) - if return_gradients: - fluid_rhs, fluid_grad_cv, fluid_grad_temperature = ns_result - else: - fluid_rhs = ns_result + fluid_rhs = ns_result diffusion_result = diffusion_operator( + dcoll, wall_kappa, wall_boundaries, wall_temperature, + penalty_amount=wall_penalty_amount, quadrature_tag=quadrature_tag, + dd=wall_dd, grad_u=wall_grad_t, + comm_tag=(_WallOperatorTag, comm_tag)) + + wall_rhs = diffusion_result + + return fluid_rhs, wall_rhs + + +def coupled_ns_heat_operator( + dcoll, + gas_model, + fluid_dd, wall_dd, + fluid_boundaries, wall_boundaries, + fluid_state, wall_kappa, wall_temperature, + *, + time=0., + interface_noslip=True, + use_kappa_weighted_grad_flux_in_fluid=False, + wall_penalty_amount=None, + quadrature_tag=DISCR_TAG_BASE, + limiter_func=None, + fluid_gradient_numerical_flux_func=num_flux_central, + inviscid_numerical_flux_func=inviscid_facial_flux_rusanov, + viscous_numerical_flux_func=viscous_facial_flux_harmonic, + return_gradients=False): + r""" + Compute the RHS of the fluid and wall subdomains. + + Augments *fluid_boundaries* and *wall_boundaries* with the boundaries for the + fluid-wall interface that are needed to enforce continuity of temperature and + heat flux. + + Parameters + ---------- + + dcoll: class:`~grudge.discretization.DiscretizationCollection` + + A discretization collection encapsulating the DG elements + + gas_model: :class:`~mirgecom.gas_model.GasModel` + + Physical gas model including equation of state, transport, + and kinetic properties as required by fluid state + + fluid_dd: :class:`grudge.dof_desc.DOFDesc` + + DOF descriptor for the fluid volume. + + wall_dd: :class:`grudge.dof_desc.DOFDesc` + + DOF descriptor for the wall volume. + + fluid_boundaries: + + Dictionary of boundary objects for the fluid subdomain, one for each + :class:`~grudge.dof_desc.BoundaryDomainTag` that represents a domain + boundary. + + wall_boundaries: + + Dictionary of boundary objects for the wall subdomain, one for each + :class:`~grudge.dof_desc.BoundaryDomainTag` that represents a domain + boundary. + + fluid_state: :class:`~mirgecom.gas_model.FluidState` + + Fluid state object with the conserved state and dependent + quantities for the fluid volume. + + wall_kappa: float or :class:`meshmode.dof_array.DOFArray` + + Thermal conductivity for the wall volume. + + wall_temperature: :class:`meshmode.dof_array.DOFArray` + + Temperature for the wall volume. + + time: + + Time + + interface_noslip: bool + + If `True`, interface boundaries on the fluid side will be treated as + no-slip walls. If `False` they will be treated as slip walls. + + use_kappa_weighted_grad_flux_in_fluid: bool + + Indicates whether the temperature gradient flux on the fluid side of the + interface should be computed using a simple average of temperatures or by + weighting the temperature from each side by its respective thermal + conductivity. Not used if *interface_radiation* is `True`. + + ambient_temperature: :class:`meshmode.dof_array.DOFArray` + + Ambient temperature of the environment. + + wall_penalty_amount: float + + Coefficient $c$ for the interior penalty on the heat flux. See + :class:`~mirgecom.multiphysics.thermally_coupled_fluid_wall.InterfaceFluidBoundary` + for details. Not used if *interface_radiation* is `True`. + + quadrature_tag: + + An identifier denoting a particular quadrature discretization to use during + operator evaluations. + + fluid_gradient_numerical_flux_func: + + Callable function to return the numerical flux to be used when computing + the temperature gradient in the fluid subdomain. Defaults to + :class:`~mirgecom.flux.num_flux_central`. + + inviscid_numerical_flux_func: + + Callable function providing the face-normal flux to be used + for the divergence of the inviscid transport flux. This defaults to + :func:`~mirgecom.inviscid.inviscid_facial_flux_rusanov`. + + viscous_numerical_flux_func: + + Callable function providing the face-normal flux to be used + for the divergence of the viscous transport flux. This defaults to + :func:`~mirgecom.viscous.viscous_facial_flux_harmonic`. + + limiter_func: + + Callable function to be passed to + :func:`~mirgecom.gas_model.make_operator_fluid_states` + that filters or limits the produced fluid states. This is used to keep + species mass fractions in physical and realizable states, for example. + + Returns + ------- + + The tuple `(fluid_rhs, wall_rhs)`. + """ + # update the boundaries and compute the gradients + (fluid_all_boundaries, + wall_all_boundaries, + fluid_operator_states_quad, + fluid_grad_cv, + fluid_grad_temperature, + wall_grad_temperature) = update_coupled_boundary_conditions( + dcoll=dcoll, + gas_model=gas_model, + fluid_dd=fluid_dd, wall_dd=wall_dd, + fluid_boundaries=fluid_boundaries, + wall_boundaries=wall_boundaries, + interface_noslip=interface_noslip, + fluid_state=fluid_state, + wall_kappa=wall_kappa, + wall_temperature=wall_temperature, + time=time, + wall_penalty_amount=wall_penalty_amount, + quadrature_tag=quadrature_tag, + limiter_func=limiter_func, + return_gradients=True) + + # Compute the subdomain NS/diffusion operators using the augmented boundaries + + fluid_rhs = ns_operator( + dcoll, gas_model, fluid_state, fluid_all_boundaries, + time=time, quadrature_tag=quadrature_tag, dd=fluid_dd, + inviscid_numerical_flux_func=inviscid_numerical_flux_func, + viscous_numerical_flux_func=viscous_numerical_flux_func, + return_gradients=False, + operator_states_quad=fluid_operator_states_quad, + grad_cv=fluid_grad_cv, + grad_t=fluid_grad_temperature, comm_tag=_FluidOperatorTag) + + wall_rhs = diffusion_operator( dcoll, wall_kappa, wall_all_boundaries, wall_temperature, penalty_amount=wall_penalty_amount, quadrature_tag=quadrature_tag, return_grad_u=return_gradients, dd=wall_dd, grad_u=wall_grad_temperature, comm_tag=_WallOperatorTag) - if return_gradients: - wall_rhs, wall_grad_temperature = diffusion_result - else: - wall_rhs = diffusion_result - if return_gradients: return ( fluid_rhs, wall_rhs, fluid_grad_cv, fluid_grad_temperature,