FVInterfaceKernels System
For an overview of MOOSE FV please see Finite Volume Design Decisions in MOOSE.
FVInterfaceKernels communicate data across interfaces between subdomains. The user defines the orientation of an interface with subdomain1 and subdomain2. variable1 must be defined on subdomain1, and variable2 must be defined on subdomain2. If variable2 is omitted, variable1 is used on both sides.
During initial setup, MOOSE verifies that every boundary face assigned to an FVInterfaceKernel connects the configured subdomain1 and subdomain2 sets. This reports malformed or overextended interface sidesets before residual evaluation begins.
Developer contract
Derived FVInterfaceKernel objects operate entirely in the user-defined side-1/side-2 orientation. computeQpResidual() returns the residual contribution \(r\) for variable1 on subdomain1. The base class multiplies \(r\) by the face area and coordinate factor, adds it to variable1, and adds \(-r\) to variable2 when both variables belong to the same nonlinear system. A derived object does not need to determine which user-defined side is represented by FaceInfo::elem.
The protected side-oriented accessors are:
normal(), which points from side 1 toward side 2;elem1()andelem2(), which return the elements on sides 1 and 2;centroid1()andcentroid2(), which return their centroids;elemArg1()andelemArg2(), which create element functor arguments; andfaceArg1()andfaceArg2(), which create explicitly one-sided face functor arguments. The checkedfaceArg1(functor)andfaceArg2(functor)overloads also verify that the functor is defined on the requested logical side.
interpolateValue(method, value1, value2) interpolates a value from each user-defined side while accounting for the geometric orientation of the current FaceInfo. For example, a diffusion interface can evaluate and interpolate its coefficients without any geometric orientation branch:
ADReal
FVFooInterface::computeQpResidual()
{
const auto state = determineState();
const auto coefficient = interpolateValue(
_interp_method, _coefficient1(elemArg1(), state), _coefficient2(elemArg2(), state));
Point one_over_gradient_support = centroid1() - centroid2();
one_over_gradient_support /= one_over_gradient_support.norm_sq();
const auto gradient = (var1().getElemValue(&elem1(), state) -
var2().getElemValue(&elem2(), state)) *
one_over_gradient_support;
return -coefficient * normal() * gradient;
}
Use the checked faceArg1(functor) or faceArg2(functor) overloads when a functor must be evaluated from one particular side rather than interpolated across the interface. These overloads preserve the requested logical side and report an error if the functor is not defined there. The no-functor overloads remain available when constructing a one-sided argument that is not immediately tied to a particular functor. This distinction is important for discontinuous or block-restricted functors.
When using an FVInterfaceKernel to connect variables that belong to different nonlinear systems, create two kernels with flipped variable, subdomain, and material-property parameters. An interface kernel contributes only to the system containing variable1. For an example, see:
[Mesh<<<{"href": "../Mesh/index.html"}>>>]
[gmg]
type = CartesianMeshGenerator<<<{"description": "This CartesianMeshGenerator creates a non-uniform Cartesian mesh.", "href": "../../source/meshgenerators/CartesianMeshGenerator.html"}>>>
dim<<<{"description": "The dimension of the mesh to be generated"}>>> = 1
ix<<<{"description": "Number of grids in all intervals in the X direction (default to all one)"}>>> = '50 50'
dx<<<{"description": "Intervals in the X direction"}>>> = '1 1'
subdomain_id<<<{"description": "Block IDs (default to all zero)"}>>> = '0 1'
[]
[sds]
type = SideSetsBetweenSubdomainsGenerator<<<{"description": "MeshGenerator that creates a sideset composed of the nodes located between two or more subdomains.", "href": "../../source/meshgenerators/SideSetsBetweenSubdomainsGenerator.html"}>>>
input<<<{"description": "The mesh we want to modify"}>>> = gmg
new_boundary<<<{"description": "The list of boundary names to create on the supplied subdomain"}>>> = 'between'
paired_block<<<{"description": "The paired set of blocks for which to draw a sideset between"}>>> = '1'
primary_block<<<{"description": "The primary set of blocks for which to draw a sideset between"}>>> = '0'
[]
[]
[Problem<<<{"href": "../Problem/index.html"}>>>]
nl_sys_names = 'u v'
error_on_jacobian_nonzero_reallocation = true
[]
[Variables<<<{"href": "../Variables/index.html"}>>>]
[u]
type = MooseVariableFVReal<<<{"description": "Base class for Moose variables. This should never be the terminal object type", "href": "../../source/variables/MooseVariableFV.html"}>>>
solver_sys<<<{"description": "If this variable is a solver variable, this is the solver system to which it should be added."}>>> = 'u'
block<<<{"description": "The list of blocks (ids or names) that this object will be applied"}>>> = 0
[]
[v]
type = MooseVariableFVReal<<<{"description": "Base class for Moose variables. This should never be the terminal object type", "href": "../../source/variables/MooseVariableFV.html"}>>>
solver_sys<<<{"description": "If this variable is a solver variable, this is the solver system to which it should be added."}>>> = 'v'
block<<<{"description": "The list of blocks (ids or names) that this object will be applied"}>>> = 1
[]
[]
[FVKernels<<<{"href": "../FVKernels/index.html"}>>>]
[diff_u]
type = FVDiffusion<<<{"description": "Computes residual for diffusion operator for finite volume method.", "href": "../../source/fvkernels/FVDiffusion.html"}>>>
variable<<<{"description": "The name of the variable that this residual object operates on"}>>> = u
coeff<<<{"description": "diffusion coefficient. A functor is any of the following: a variable, a functor material property, a function, a postprocessor or a number."}>>> = 3.0
[]
[force_u]
type = FVBodyForce<<<{"description": "Demonstrates the multiple ways that scalar values can be introduced into finite volume kernels, e.g. (controllable) constants, functions, and postprocessors.", "href": "../../source/fvkernels/FVBodyForce.html"}>>>
variable<<<{"description": "The name of the variable that this residual object operates on"}>>> = u
function<<<{"description": "A function that describes the body force"}>>> = 5
[]
[diff_v]
type = FVDiffusion<<<{"description": "Computes residual for diffusion operator for finite volume method.", "href": "../../source/fvkernels/FVDiffusion.html"}>>>
variable<<<{"description": "The name of the variable that this residual object operates on"}>>> = v
coeff<<<{"description": "diffusion coefficient. A functor is any of the following: a variable, a functor material property, a function, a postprocessor or a number."}>>> = 1.0
[]
[force_v]
type = FVBodyForce<<<{"description": "Demonstrates the multiple ways that scalar values can be introduced into finite volume kernels, e.g. (controllable) constants, functions, and postprocessors.", "href": "../../source/fvkernels/FVBodyForce.html"}>>>
variable<<<{"description": "The name of the variable that this residual object operates on"}>>> = v
function<<<{"description": "A function that describes the body force"}>>> = 5
[]
[]
[FVInterfaceKernels<<<{"href": "index.html"}>>>]
[diff_ik]
type = FVDiffusionInterface<<<{"description": "Computes the residual for diffusion operator across an interface for the finite volume method.", "href": "../../source/fviks/FVDiffusionInterface.html"}>>>
variable1<<<{"description": "The name of the first variable that this interface kernel applies to"}>>> = u
variable2<<<{"description": "The name of the second variable that this interface kernel applies to. If not supplied, variable1 will be used."}>>> = v
boundary<<<{"description": "The list of boundary IDs from the mesh where this object applies"}>>> = 'between'
coeff1<<<{"description": "The diffusion coefficient on the 1st subdomain"}>>> = 3
coeff2<<<{"description": "The diffusion coefficient on the 2nd subdomain"}>>> = 1
subdomain1<<<{"description": "The subdomains on the 1st side of the boundary."}>>> = 0
subdomain2<<<{"description": "The subdomains on the 2nd side of the boundary."}>>> = 1
[]
[diff_ik_v]
type = FVDiffusionInterface<<<{"description": "Computes the residual for diffusion operator across an interface for the finite volume method.", "href": "../../source/fviks/FVDiffusionInterface.html"}>>>
variable1<<<{"description": "The name of the first variable that this interface kernel applies to"}>>> = v
variable2<<<{"description": "The name of the second variable that this interface kernel applies to. If not supplied, variable1 will be used."}>>> = u
boundary<<<{"description": "The list of boundary IDs from the mesh where this object applies"}>>> = 'between'
coeff1<<<{"description": "The diffusion coefficient on the 1st subdomain"}>>> = 1
coeff2<<<{"description": "The diffusion coefficient on the 2nd subdomain"}>>> = 3
subdomain1<<<{"description": "The subdomains on the 1st side of the boundary."}>>> = 1
subdomain2<<<{"description": "The subdomains on the 2nd side of the boundary."}>>> = 0
[]
[]
[FVBCs<<<{"href": "../FVBCs/index.html"}>>>]
[left_u]
type = FVDirichletBC<<<{"description": "Defines a Dirichlet boundary condition for finite volume method.", "href": "../../source/fvbcs/FVDirichletBC.html"}>>>
variable<<<{"description": "The name of the variable that this boundary condition applies to"}>>> = u
boundary<<<{"description": "The list of boundary IDs from the mesh where this object applies"}>>> = left
value<<<{"description": "value to enforce at the boundary face"}>>> = 0
[]
[right_v]
type = FVDirichletBC<<<{"description": "Defines a Dirichlet boundary condition for finite volume method.", "href": "../../source/fvbcs/FVDirichletBC.html"}>>>
variable<<<{"description": "The name of the variable that this boundary condition applies to"}>>> = v
boundary<<<{"description": "The list of boundary IDs from the mesh where this object applies"}>>> = right
value<<<{"description": "value to enforce at the boundary face"}>>> = 1
[]
[]
[Preconditioning<<<{"href": "../Preconditioning/index.html"}>>>]
[u]
type = SMP<<<{"description": "Single matrix preconditioner (SMP) builds a preconditioner using user defined off-diagonal parts of the Jacobian.", "href": "../../source/preconditioners/SingleMatrixPreconditioner.html"}>>>
nl_sys<<<{"description": "The nonlinear system whose linearization this preconditioner should be applied to."}>>> = u
petsc_options<<<{"description": "Singleton PETSc options"}>>> = '-snes_monitor'
petsc_options_iname<<<{"description": "Names of PETSc name/value pairs"}>>> = '-pc_type -pc_hypre_type'
petsc_options_value<<<{"description": "Values of PETSc name/value pairs (must correspond with \"petsc_options_iname\""}>>> = 'hypre boomeramg'
[]
[v]
type = SMP<<<{"description": "Single matrix preconditioner (SMP) builds a preconditioner using user defined off-diagonal parts of the Jacobian.", "href": "../../source/preconditioners/SingleMatrixPreconditioner.html"}>>>
nl_sys<<<{"description": "The nonlinear system whose linearization this preconditioner should be applied to."}>>> = v
petsc_options<<<{"description": "Singleton PETSc options"}>>> = '-snes_monitor'
petsc_options_iname<<<{"description": "Names of PETSc name/value pairs"}>>> = '-pc_type -pc_hypre_type'
petsc_options_value<<<{"description": "Values of PETSc name/value pairs (must correspond with \"petsc_options_iname\""}>>> = 'hypre boomeramg'
[]
[]
[Executioner<<<{"href": "../Executioner/index.html"}>>>]
type = SteadySolve2
solve_type = 'NEWTON'
first_nl_sys_to_solve = 'u'
second_nl_sys_to_solve = 'v'
number_of_iterations = 200
nl_abs_tol = 1e-10
[]
[Outputs<<<{"href": "../Outputs/index.html"}>>>]
print_nonlinear_residuals<<<{"description": "Enable printing of nonlinear residuals to the screen (Console)"}>>> = false
print_linear_residuals<<<{"description": "Enable printing of linear residuals to the screen (Console)"}>>> = false
exodus<<<{"description": "Output the results using the default settings for Exodus output."}>>> = true
[](test/tests/fviks/diffusion/multisystem.i)