FVInterfaceKernels System
For an overview of MOOSE FV please see Finite Volume Design Decisions in MOOSE.
FVInterfaceKernels
are meant to communicate data at interfaces between subdomains. An FVInterfaceKernel
may contribute to the residuals/Jacobians of a single variable, specified with the parameter variable1
, or to multiple variables by also using the variable2
parameter. There are two additional critical/required parameters: subdomain1
and subdomain2
. In cases for which an FVInterfaceKernel
is operating on two variables, subdomain1
should correspond to the subdomain(s) neighboring the boundary
parameter that variable1
lives on, and similarly for subdomain2
and variable2
. By checking the subdomain
parameters against the subdomain IDs of the FaceInfo::elem
and FaceInfo::neighbor
members a FVInterfaceKernel
developer can be sure that they are fetching and using sensical data. For instance, a developer may want to create an FVInterfaceKernel
that uses prop1
on the subdomain1
side of the boundary
and prop2
on the subdomain2
side of the boundary. However, MOOSE only provides these APIs for fetching material properties: get(AD)MaterialProperty
and getNeighbor(AD)MaterialProperty
. The return value of get(AD)MaterialProperty
will always correspond to a material property evaluation on the FaceInfo::elem
side of a (inter)face, while the return value of getNeighbor(AD)MaterialProperty
will always correspond to a material property evaluation on the FaceInfo::neighbor
side of a (inter)face. However, when moving along an interface, it is possible that the FaceInfo::elem
side of the interface is sometimes the subdomain1
side and sometimes the subdomain2
side. So making use of the subdomain
parameters, we provide a protected method called elemIsOne()
that returns a boolean indicating whether the FaceInfo::elem
side of the interface corresponds to the subdomain1
side of the interface. This allows the developer to write code like the following:
FVFooInterface::FVFooInterface(const InputParameters & params)
: FVInterfaceKernel(params),
_coeff1_elem(getADMaterialProperty<Real>("coeff1")),
_coeff2_elem(getADMaterialProperty<Real>("coeff2")),
_coeff1_neighbor(getNeighborADMaterialProperty<Real>("coeff1")),
_coeff2_neighbor(getNeighborADMaterialProperty<Real>("coeff2"))
{
}
ADReal
FVFooInterface::computeQpResidual()
{
const auto & coef_elem = elemIsOne() ? _coeff1_elem : _coeff2_elem;
const auto & coef_neighbor = elemIsOne() ? _coeff2_neighbor : _coeff1_neighbor;
/// Code that uses coef_elem and coef_neighbor
}
and have confidence that they have good data in coef_elem
and coef_neighbor
and have clarity about what is happening in their code.
When using an FVInterfaceKernel which connects variables that belong to different nonlinear systems, create two kernels with flipped variable and material property parameters. The reason behind this is that the interface kernel will only contribute to the system which variable1
belongs to. For an example, see:
[Mesh]
[gmg]
type = CartesianMeshGenerator
dim = 1
ix = '50 50'
dx = '1 1'
subdomain_id = '0 1'
[]
[sds]
type = SideSetsBetweenSubdomainsGenerator
input = gmg
new_boundary = 'between'
paired_block = '1'
primary_block = '0'
[]
[]
[Problem]
nl_sys_names = 'u v'
error_on_jacobian_nonzero_reallocation = true
[]
[Variables]
[u]
type = MooseVariableFVReal
solver_sys = 'u'
block = 0
[]
[v]
type = MooseVariableFVReal
solver_sys = 'v'
block = 1
[]
[]
[FVKernels]
[diff_u]
type = FVDiffusion
variable = u
coeff = 3.0
[]
[force_u]
type = FVBodyForce
variable = u
function = 5
[]
[diff_v]
type = FVDiffusion
variable = v
coeff = 1.0
[]
[force_v]
type = FVBodyForce
variable = v
function = 5
[]
[]
[FVInterfaceKernels]
[diff_ik]
type = FVDiffusionInterface
variable1 = u
variable2 = v
boundary = 'between'
coeff1 = 3
coeff2 = 1
subdomain1 = 0
subdomain2 = 1
[]
[diff_ik_v]
type = FVDiffusionInterface
variable1 = v
variable2 = u
boundary = 'between'
coeff1 = 1
coeff2 = 3
subdomain1 = 1
subdomain2 = 0
[]
[]
[FVBCs]
[left_u]
type = FVDirichletBC
variable = u
boundary = left
value = 0
[]
[right_v]
type = FVDirichletBC
variable = v
boundary = right
value = 1
[]
[]
[Executioner]
type = SteadySolve2
solve_type = 'NEWTON'
petsc_options = '-snes_monitor'
petsc_options_iname = '-pc_type -pc_hypre_type'
petsc_options_value = 'hypre boomeramg'
first_nl_sys_to_solve = 'u'
second_nl_sys_to_solve = 'v'
number_of_iterations = 200
nl_abs_tol = 1e-10
[]
[Outputs]
print_nonlinear_residuals = false
print_linear_residuals = false
exodus = true
[]
(moose/test/tests/fviks/diffusion/multisystem.i)