- boundaryWhich face of the domain this boundary condition applies to.
C++ Type:MooseEnum
Controllable:No
Description:Which face of the domain this boundary condition applies to.
- variableThe field this boundary condition applies to.
C++ Type:std::string
Controllable:No
Description:The field this boundary condition applies to.
TensorDirichletBC
Dirichlet boundary condition (u = value) on a non-periodic domain face.
Overview
Imposes "value" on one face of a non-periodic direction. It is TensorRobinBC with and . The value can vary along the face, from "value_function" or "value_buffer" (see the BCs system).
Example Input File Syntax
[TensorComputes<<<{"href": "../../syntax/TensorComputes/index.html"}>>>]
[BCs<<<{"href": "../../syntax/TensorComputes/BCs/index.html"}>>>]
[left]
type = TensorDirichletBC<<<{"description": "Dirichlet boundary condition (u = value) on a non-periodic domain face.", "href": "TensorDirichletBC.html"}>>>
variable<<<{"description": "The field this boundary condition applies to."}>>> = u
boundary<<<{"description": "Which face of the domain this boundary condition applies to."}>>> = left
value<<<{"description": "Prescribed value of the field on this face (u = value)."}>>> = 1
[]
[right]
type = TensorDirichletBC<<<{"description": "Dirichlet boundary condition (u = value) on a non-periodic domain face.", "href": "TensorDirichletBC.html"}>>>
variable<<<{"description": "The field this boundary condition applies to."}>>> = u
boundary<<<{"description": "Which face of the domain this boundary condition applies to."}>>> = right
value<<<{"description": "Prescribed value of the field on this face (u = value)."}>>> = 3
[]
[]
[](test/tests/real_space/dirichlet_linear.i)Input Parameters
- value0Prescribed value of the field on this face (u = value).
Default:0
C++ Type:Real
Unit:(no unit assumed)
Controllable:No
Description:Prescribed value of the field on this face (u = value).
- value_bufferBuffer whose first owned cell layer next to the face holds the field value along the face. The compute that writes it must evaluate it at the face position, not at the cell centres.
C++ Type:std::string
Controllable:No
Description:Buffer whose first owned cell layer next to the face holds the field value along the face. The compute that writes it must evaluate it at the face position, not at the cell centres.
- value_functionFunction giving the field value along the face, evaluated at the face position at the solve time.
C++ Type:FunctionName
Unit:(no unit assumed)
Controllable:No
Description:Function giving the field value along the face, evaluated at the face position at the solve time.
Optional Parameters
- control_tagsAdds user-defined labels for accessing object parameters via control logic.
C++ Type:std::vector<std::string>
Controllable:No
Description:Adds user-defined labels for accessing object parameters via control logic.
- enableTrueSet the enabled status of the MooseObject.
Default:True
C++ Type:bool
Controllable:No
Description:Set the enabled status of the MooseObject.
Advanced Parameters
Input Files
- (test/tests/real_space/robin_steady_state.i)
- (test/tests/real_space/dirichlet_laplacian_check.i)
- (test/tests/real_space/semi_infinite_diffusion.i)
- (test/tests/implicit_fd/bc_mms.i)
- (test/tests/real_space/bc_varying_laplacian.i)
- (test/tests/real_space/thin_slab_diffusion.i)
- (test/tests/implicit_fd/crank_thin_slab.i)
- (test/tests/real_space/neumann_linear.i)
- (test/tests/real_space/dirichlet_2d_corners.i)
- (test/tests/implicit_fd/crank_semi_infinite.i)
- (test/tests/real_space/dirichlet_linear.i)
value
Default:0
C++ Type:Real
Unit:(no unit assumed)
Controllable:No
Description:Prescribed value of the field on this face (u = value).
value_function
C++ Type:FunctionName
Unit:(no unit assumed)
Controllable:No
Description:Function giving the field value along the face, evaluated at the face position at the solve time.
value_buffer
C++ Type:std::string
Controllable:No
Description:Buffer whose first owned cell layer next to the face holds the field value along the face. The compute that writes it must evaluate it at the face position, not at the cell centres.
(test/tests/real_space/dirichlet_linear.i)
[Domain]
dim = 2
nx = 20
ny = 8
parallel_mode = REAL_SPACE
periodic_directions = 'Y'
xmin = 0
xmax = 1
ymin = -1
ymax = 1
[]
[Functions]
[u_ic_func]
type = ParsedFunction
expression = '1 + 2 * x + 0.001 * y'
[]
[]
[TensorComputes]
[Initialize]
[u_ic]
# Not the steady solution and not matching the BCs pointwise (it depends on y);
# diffusion must drive u to the exact steady profile u = 1 + 2*x.
type = MooseFunctionTensor
buffer = u
function = u_ic_func
[]
[]
[BCs]
[left]
type = TensorDirichletBC
variable = u
boundary = left
value = 1
[]
[right]
type = TensorDirichletBC
variable = u
boundary = right
value = 3
[]
[]
[Solve]
[dt]
type = FiniteDifferenceLaplacian
input = u
buffer = dudt
[]
[]
[]
[TensorSolver]
type = RealSpaceForwardEuler
buffer = u
time_derivative = dudt
substeps = 1000
[]
[Postprocessors]
[max_u]
type = TensorExtremeValuePostprocessor
buffer = u
value_type = MAX
execute_on = 'INITIAL TIMESTEP_END'
[]
[min_u]
type = TensorExtremeValuePostprocessor
buffer = u
value_type = MIN
execute_on = 'INITIAL TIMESTEP_END'
[]
[]
[Executioner]
type = Transient
# dx = 0.05, dy = 0.25: explicit CFL limit 1/(2*(1/dx^2 + 1/dy^2)) ~= 1.2e-3,
# above the substep dt/substeps = 1e-3.
dt = 1
num_steps = 4
[]
[Outputs]
[out]
type = CSV
[]
[]
(test/tests/real_space/robin_steady_state.i)
# Verification against an independent analytic solution: the steady 1D elliptic
# Robin-BC benchmark from OpenGeoSys's documentation,
# https://www.opengeosys.org/6.5.7/docs/benchmarks/elliptic/elliptic-robin/
# ("second benchmark": Dirichlet at x=0, Robin at x=1). The governing equation is
# k*Laplacian(h) = 0 on [0,1] with k=1, boundary conditions
# h(0) = g_D, dh/dn|_{x=1} = alpha*(h0 - h(1)),
# and exact linear solution
# h(x) = [alpha*(h0 - g_D)/(1 + alpha)] * x + g_D.
# TensorRobinBC's convention is a*u + b*du/dn = c; the OGS Robin condition
# du/dn = alpha*(h0 - u) rearranges to alpha*u + du/dn = alpha*h0, i.e.
# a = alpha, b = 1, c = alpha*h0.
#
# Uses alpha = +2 rather than OGS's alpha = -2: the ghost coefficient on u0,
# -(a/2 - b/dx)/(a/2 + b/dx), has magnitude > 1 for a < 0, so explicit relaxation to
# the steady state diverges (OGS solves the steady system directly). With alpha = 2,
# h0 = 1.5 and g_D = 1 the exact solution is h(x) = x/3 + 1.
#
# Y is periodic, and the IC matches neither the steady profile nor the BCs.
[Domain]
dim = 2
nx = 20
ny = 8
parallel_mode = REAL_SPACE
periodic_directions = 'Y'
xmin = 0
xmax = 1
ymin = -1
ymax = 1
[]
[Functions]
[u_ic_func]
type = ParsedFunction
expression = '0.5'
[]
[u_exact_func]
type = ParsedFunction
expression = '1 + x / 3'
[]
[]
[TensorComputes]
[Initialize]
[u_ic]
type = MooseFunctionTensor
buffer = u
function = u_ic_func
[]
[]
[BCs]
[left]
type = TensorDirichletBC
variable = u
boundary = left
value = 1
[]
[right]
# alpha*u + du/dn = alpha*h0, with alpha = 2, h0 = 1.5.
type = TensorRobinBC
variable = u
boundary = right
a = 2
b = 1
c = 3
[]
[]
[Solve]
[dt]
type = FiniteDifferenceLaplacian
input = u
buffer = dudt
[]
[u_exact]
type = MooseFunctionTensor
buffer = u_exact
function = u_exact_func
[]
[diff]
type = ParsedCompute
buffer = diff
expression = 'abs(u - u_exact)'
inputs = 'u u_exact'
[]
[]
[]
[TensorSolver]
type = RealSpaceForwardEuler
buffer = u
time_derivative = dudt
substeps = 1000
[]
[Postprocessors]
[max_error]
type = TensorExtremeValuePostprocessor
buffer = diff
value_type = MAX
execute_on = 'TIMESTEP_END'
[]
[]
[Executioner]
type = Transient
# same grid and CFL margin as dirichlet_linear.i
dt = 1
num_steps = 4
[]
[Outputs]
[out]
type = CSV
[]
[]
(test/tests/real_space/dirichlet_laplacian_check.i)
[Domain]
dim = 2
nx = 20
ny = 8
parallel_mode = REAL_SPACE
periodic_directions = 'Y'
xmin = 0
xmax = 1
ymin = -1
ymax = 1
[]
[Functions]
[u_func]
type = ParsedFunction
expression = '1 + 2 * x'
[]
[]
[TensorComputes]
[Initialize]
[u_ic]
# u = 1 + 2*x satisfies the Dirichlet values below exactly, so the discrete
# Laplacian is zero to roundoff everywhere, including the boundary-adjacent cells.
type = MooseFunctionTensor
buffer = u
function = u_func
[]
[]
[BCs]
[left]
type = TensorDirichletBC
variable = u
boundary = left
value = 1
[]
[right]
type = TensorDirichletBC
variable = u
boundary = right
value = 3
[]
[]
[Solve]
[lap_compute]
type = FiniteDifferenceLaplacian
input = u
buffer = lap
[]
[]
[]
[Postprocessors]
[max_lap]
type = TensorExtremeValuePostprocessor
buffer = lap
value_type = MAX
[]
[min_lap]
type = TensorExtremeValuePostprocessor
buffer = lap
value_type = MIN
[]
[]
[Executioner]
type = Transient
num_steps = 1
[]
[Outputs]
[out]
type = CSV
[]
[]
(test/tests/real_space/semi_infinite_diffusion.i)
# Verification against Crank, "The Mathematics of Diffusion" (2nd ed.), Sec. 3.3(i),
# eq. (3.13): a semi-infinite medium (x > 0) with uniform initial concentration C0 = 0
# and constant surface concentration C1 maintained at x = 0 has the exact solution
# C(x, t) = C1 * erfc(x / (2*sqrt(D*t)))
# (special case of (3.13) with C0 = 0, using erfc = 1 - erf).
#
# Pseudo-1D (ny = 1, Y periodic), D = 1. The domain extends 10 diffusion lengths at
# the comparison time t = 1 (erfc(10) ~ 2e-45), so the far Dirichlet u = 0 does not
# measurably affect the solution near x = 0.
[Domain]
dim = 2
nx = 100
ny = 1
parallel_mode = REAL_SPACE
periodic_directions = 'Y'
xmin = 0
xmax = 10
ymin = -0.5
ymax = 0.5
[]
[TensorComputes]
# no [Initialize]: buffers start at zero, the C0 = 0 initial condition
[BCs]
[left]
type = TensorDirichletBC
variable = u
boundary = left
value = 1
[]
[right]
# Far boundary, approximating the semi-infinite medium's x -> infinity
# condition; diffusion has not reached here by the comparison time.
type = TensorDirichletBC
variable = u
boundary = right
value = 0
[]
[]
[Solve]
[dt]
type = FiniteDifferenceLaplacian
input = u
buffer = dudt
factor = 1
[]
[u_exact]
type = ParsedCompute
buffer = u_exact
expression = 'erfc(x / (2 * sqrt(t))) + 0*y'
extra_symbols = true
[]
[diff]
type = ParsedCompute
buffer = diff
expression = 'abs(u - u_exact)'
inputs = 'u u_exact'
[]
[]
[]
[TensorSolver]
type = RealSpaceForwardEuler
buffer = u
time_derivative = dudt
substeps = 250
[]
[Postprocessors]
[max_error]
type = TensorExtremeValuePostprocessor
buffer = diff
value_type = MAX
execute_on = 'TIMESTEP_END'
[]
[]
[Executioner]
type = Transient
dt = 1
num_steps = 1
[]
[Outputs]
[out]
type = CSV
[]
[]
(test/tests/implicit_fd/bc_mms.i)
# Implicit solve of u_t - D Laplacian(u) = f on the unit square with boundary faces, against the
# manufactured solution
#
# u = g + tf t q, g = cos(3 pi x / 2) cos(pi y) + x y, q = x^2 - y^2,
#
# with tf = 0 for the steady problem -D Laplacian(u) = f and tf = 1 for backward Euler.
# q is harmonic, so f = tf q - D Laplacian(g) is independent of time and the backward Euler
# step makes no time error: the error is the spatial one, provided the boundary values are
# taken at the time of the unknown, t + dt (at t it would be of order dt).
#
# Each face has a different condition and value source:
# left (x = 0) Dirichlet u = cos(pi y) - tf t y^2 function
# right (x = 1) Robin ra u + rb du/dx = c function
# or buffer (right_buffer, steady)
# bottom (y = 0) Neumann du/dn = -du/dy = -x buffer
# top (y = 1) Neumann du/dn = du/dy = x - 2 tf t function
# or buffer (top_buffer, values at t)
D = 0.5
n = 32
stencil = 3
tf = 0
ops = 'lap'
num_steps = 1
dt = 0.05
# Robin coefficients on the right face (the 5-point stencil supports ra = 1, rb = 0 only)
ra = 1
rb = 1
[Domain]
dim = 2
nx = ${n}
ny = ${n}
xmax = 1
ymax = 1
parallel_mode = REAL_SPACE
[]
[Functions]
[u_exact]
type = ParsedFunction
expression = 'cos(1.5*pi*x) * cos(pi*y) + x*y + ${tf} * t * (x^2 - y^2)'
[]
[f_func]
type = ParsedFunction
# Laplacian(g) = -13/4 pi^2 cos(3 pi x / 2) cos(pi y)
expression = '${tf} * (x^2 - y^2) + ${D} * 3.25 * pi^2 * cos(1.5*pi*x) * cos(pi*y)'
[]
[right_c]
type = ParsedFunction
# on x = 1: u = y + tf t (1 - y^2), du/dx = 3/2 pi cos(pi y) + y + 2 tf t
expression = '${ra} * (y + ${tf} * t * (1 - y^2)) + ${rb} * (1.5*pi*cos(pi*y) + y + 2 * ${tf} * t)'
[]
[bottom_flux]
type = ParsedFunction
expression = '-x'
[]
[top_flux]
type = ParsedFunction
expression = 'x - 2 * ${tf} * t'
[]
[]
[TensorBuffers]
[u]
[]
[dudt_u]
[]
[lap_u]
[]
[f]
[]
[bottom_flux]
[]
[right_c]
[]
[top_flux]
[]
[exact]
[]
[diff]
[]
[]
[TensorComputes]
[Initialize]
[u_ic]
type = MooseFunctionTensor
buffer = u
function = u_exact
[]
[f_ic]
type = MooseFunctionTensor
buffer = f
function = f_func
[]
# a face value: depends on the tangential coordinate x only
[bottom_flux]
type = MooseFunctionTensor
buffer = bottom_flux
function = bottom_flux
[]
[right_c]
type = MooseFunctionTensor
buffer = right_c
function = right_c
[]
[]
[BCs]
active = 'left right bottom top'
[left]
type = TensorDirichletBC
variable = u
boundary = left
value_function = u_exact
[]
[right]
type = TensorRobinBC
variable = u
boundary = right
a = ${ra}
b = ${rb}
c_function = right_c
[]
# the Robin c from a buffer instead (active = 'left right_buffer bottom top'), steady only
[right_buffer]
type = TensorRobinBC
variable = u
boundary = right
a = ${ra}
b = ${rb}
c_buffer = right_c
[]
[bottom]
type = TensorNeumannBC
variable = u
boundary = bottom
flux_buffer = bottom_flux
[]
[top]
type = TensorNeumannBC
variable = u
boundary = top
flux_function = top_flux
[]
# the top flux from a buffer instead (active = 'left right bottom top_buffer'); a buffer
# value is the one its compute wrote at the start of the substep, at t
[top_buffer]
type = TensorNeumannBC
variable = u
boundary = top
flux_buffer = top_flux
[]
[]
[Solve]
[top_flux]
type = MooseFunctionTensor
buffer = top_flux
function = top_flux
[]
[dudt]
type = TimeDerivativeOperator
buffer = dudt_u
input = u
[]
[lap]
type = FiniteDifferenceLaplacian
buffer = lap_u
input = u
factor = '${fparse -D}'
stencil_width = ${stencil}
[]
[]
[Postprocess]
[exact_compute]
type = MooseFunctionTensor
buffer = exact
function = u_exact
[]
[diff_compute]
type = ParsedCompute
buffer = diff
expression = 'abs(u - exact)'
inputs = 'u exact'
[]
[]
[]
[TensorSolver]
type = ImplicitFDSolver
buffer = u
operators = '${ops}'
source = f
linear_solver = TORCH_PCG
l_tol = 1e-10
[]
[Postprocessors]
[max_error]
type = TensorExtremeValuePostprocessor
buffer = diff
value_type = MAX
[]
[]
[Problem]
type = TensorProblem
[]
[Executioner]
type = Transient
num_steps = ${num_steps}
dt = ${dt}
[]
[Outputs]
csv = true
[]
(test/tests/real_space/bc_varying_laplacian.i)
# Boundary condition values that vary along the face, from functions and buffers.
#
# u = (x + 1) * y is harmonic and linear in the normal direction of every face, so the ghost
# values are exact, and the discrete Laplacian must be zero everywhere, including next to the
# faces. Each face takes its value from a different source.
[Domain]
dim = 2
nx = 20
ny = 10
parallel_mode = REAL_SPACE
xmin = 0
xmax = 1
ymin = 0
ymax = 1
[]
[Functions]
[u_func]
type = ParsedFunction
expression = '(x + 1) * y'
[]
[right_value]
# u on x = 1
type = ParsedFunction
expression = '2 * y'
[]
[top_flux]
# du/dy on y = 1
type = ParsedFunction
expression = 'x + 1'
[]
[bottom_flux]
# -du/dy on y = 0 (outward normal -y)
type = ParsedFunction
expression = '-(x + 1)'
[]
[]
[TensorComputes]
[Initialize]
[u_ic]
type = MooseFunctionTensor
buffer = u
function = u_func
[]
# buffer values are face values: these depend on the tangential coordinate only
[bottom_flux]
type = MooseFunctionTensor
buffer = bottom_flux
function = bottom_flux
[]
[]
[BCs]
[left]
# evaluated at the face position x = 0, where it is y
type = TensorDirichletBC
variable = u
boundary = left
value_function = u_func
[]
[right]
type = TensorDirichletBC
variable = u
boundary = right
value_buffer = right_value
[]
[bottom]
type = TensorNeumannBC
variable = u
boundary = bottom
flux_buffer = bottom_flux
[]
[top]
type = TensorNeumannBC
variable = u
boundary = top
flux_function = top_flux
[]
[]
[Solve]
[lap_compute]
type = FiniteDifferenceLaplacian
input = u
buffer = lap
[]
# listed after the Laplacian, whose ghost fill reads it: the dependency sort runs it first
[right_value]
type = MooseFunctionTensor
buffer = right_value
function = right_value
[]
[]
[]
[Postprocessors]
[max_lap]
type = TensorExtremeValuePostprocessor
buffer = lap
value_type = MAX
[]
[min_lap]
type = TensorExtremeValuePostprocessor
buffer = lap
value_type = MIN
[]
[]
[Executioner]
type = Transient
num_steps = 1
[]
[Outputs]
[out]
type = CSV
[]
[]
(test/tests/real_space/thin_slab_diffusion.i)
# Verification against Crank, "The Mathematics of Diffusion" (2nd ed.), Sec. 2.5,
# eq. (2.15): an instantaneous planar source of concentration C0 confined initially
# to a thin slab -h < x < h, diffusing into an infinite medium, has the exact solution
# C(x, t) = (C0/2) * { erf[(h-x)/(2*sqrt(D*t))] + erf[(h+x)/(2*sqrt(D*t))] }
#
# Pseudo-1D (ny = 1, Y periodic), D = 1, h = 1. The X faces are 10 diffusion lengths
# beyond the slab edge at the comparison time t = 1, so the far-field Dirichlet u = 0
# does not measurably affect the solution near the slab.
[Domain]
dim = 2
# dx = 0.1 puts the slab edges x = +/-1 on cell faces, so the box IC holds exactly
# the slab mass 2*h*C0 (nx = 200 leaves a ~1% deficit that does not refine away)
nx = 220
ny = 1
parallel_mode = REAL_SPACE
periodic_directions = 'Y'
xmin = -11
xmax = 11
ymin = -0.5
ymax = 0.5
[]
[TensorComputes]
[Initialize]
[u_ic]
type = ParsedCompute
buffer = u
# C0 = 1 inside the slab |x| < h = 1, zero outside
expression = 'if(abs(x) < 1, 1, 0) + 0*y'
extra_symbols = true
[]
[]
[BCs]
[left]
type = TensorDirichletBC
variable = u
boundary = left
value = 0
[]
[right]
type = TensorDirichletBC
variable = u
boundary = right
value = 0
[]
[]
[Solve]
[dt]
type = FiniteDifferenceLaplacian
input = u
buffer = dudt
factor = 1
[]
[u_exact]
type = ParsedCompute
buffer = u_exact
expression = '0.5 * (erf((1 - x) / (2 * sqrt(t))) + erf((1 + x) / (2 * sqrt(t)))) + 0*y'
extra_symbols = true
[]
[diff]
type = ParsedCompute
buffer = diff
expression = 'abs(u - u_exact)'
inputs = 'u u_exact'
[]
[]
[]
[TensorSolver]
type = RealSpaceForwardEuler
buffer = u
time_derivative = dudt
# dx = 0.1; explicit-diffusion CFL limit dt_cfl = dx^2/(2*D) = 5e-3,
# requiring >= dt/dt_cfl = 200 substeps for dt = 1; 250 gives a safety margin.
substeps = 250
[]
[Postprocessors]
[max_error]
type = TensorExtremeValuePostprocessor
buffer = diff
value_type = MAX
execute_on = 'TIMESTEP_END'
[]
[]
[Executioner]
type = Transient
dt = 1
num_steps = 1
[]
[Outputs]
[out]
type = CSV
[]
[]
(test/tests/implicit_fd/crank_thin_slab.i)
# Crank, "The Mathematics of Diffusion" (2nd ed.), Sec. 2.5, eq. (2.15), with the implicit
# solver: an instantaneous planar source C0 = 1 confined to the slab -h < x < h, h = 1,
# diffusing into an infinite medium, has the exact solution
# C(x, t) = (C0/2) (erf((h - x) / (2 sqrt(D t))) + erf((h + x) / (2 sqrt(D t)))).
# The same problem as real_space/thin_slab_diffusion.i, which steps it explicitly.
#
# Pseudo-1D (ny = 1, Y periodic), D = 1. The X faces are 10 diffusion lengths beyond the slab
# edge at the comparison time t = 1, so the far Dirichlet u = 0 does not measurably affect the
# solution.
# Backward Euler with substeps of dt / substeps: the error is first order in the substep.
substeps = 100
[Domain]
dim = 2
# dx = 0.1 puts the slab edges x = +/-1 on cell faces, so the box IC holds the slab mass
nx = 220
ny = 1
parallel_mode = REAL_SPACE
periodic_directions = 'Y'
xmin = -11
xmax = 11
ymin = -0.5
ymax = 0.5
[]
[Functions]
[slab]
type = ParsedFunction
expression = 'if(abs(x) < 1, 1, 0)'
[]
[]
[TensorBuffers]
[u]
[]
[dudt_u]
[]
[lap_u]
[]
[u_exact]
[]
[diff]
[]
[]
[TensorComputes]
[Initialize]
[u_ic]
type = MooseFunctionTensor
buffer = u
function = slab
[]
[]
[BCs]
# far boundaries, approximating the infinite medium
[left]
type = TensorDirichletBC
variable = u
boundary = left
value = 0
[]
[right]
type = TensorDirichletBC
variable = u
boundary = right
value = 0
[]
[]
[Solve]
[dudt]
type = TimeDerivativeOperator
buffer = dudt_u
input = u
[]
[lap]
type = FiniteDifferenceLaplacian
buffer = lap_u
input = u
factor = -1
[]
[]
[Postprocess]
[u_exact]
type = ParsedCompute
buffer = u_exact
expression = '0.5 * (erf((1 - x) / (2 * sqrt(t))) + erf((1 + x) / (2 * sqrt(t)))) + 0*y'
extra_symbols = true
[]
[diff]
type = ParsedCompute
buffer = diff
expression = 'abs(u - u_exact)'
inputs = 'u u_exact'
[]
[]
[]
[TensorSolver]
type = ImplicitFDSolver
buffer = u
operators = 'dudt lap'
root_compute = dudt
substeps = ${substeps}
l_tol = 1e-10
[]
[Postprocessors]
[max_error]
type = TensorExtremeValuePostprocessor
buffer = diff
value_type = MAX
[]
[]
[Problem]
type = TensorProblem
[]
[Executioner]
type = Transient
dt = 1
num_steps = 1
[]
[Outputs]
csv = true
[]
(test/tests/real_space/neumann_linear.i)
# Nonzero-flux Neumann boundary condition: steady 1D diffusion with u(0) = 1
# (Dirichlet, left) and du/dn = 2 (Neumann, right) has the exact solution
# u = 1 + 2*x. Y is periodic, and the IC is not the steady profile.
[Domain]
dim = 2
nx = 20
ny = 8
parallel_mode = REAL_SPACE
periodic_directions = 'Y'
xmin = 0
xmax = 1
ymin = -1
ymax = 1
[]
[Functions]
[u_ic_func]
type = ParsedFunction
expression = '0.5'
[]
[u_exact_func]
type = ParsedFunction
expression = '1 + 2 * x'
[]
[]
[TensorComputes]
[Initialize]
[u_ic]
type = MooseFunctionTensor
buffer = u
function = u_ic_func
[]
[]
[BCs]
[left]
type = TensorDirichletBC
variable = u
boundary = left
value = 1
[]
[right]
type = TensorNeumannBC
variable = u
boundary = right
flux = 2
[]
[]
[Solve]
[dt]
type = FiniteDifferenceLaplacian
input = u
buffer = dudt
[]
[u_exact]
type = MooseFunctionTensor
buffer = u_exact
function = u_exact_func
[]
[diff]
type = ParsedCompute
buffer = diff
expression = 'abs(u - u_exact)'
inputs = 'u u_exact'
[]
[]
[]
[TensorSolver]
type = RealSpaceForwardEuler
buffer = u
time_derivative = dudt
substeps = 1000
[]
[Postprocessors]
[max_error]
type = TensorExtremeValuePostprocessor
buffer = diff
value_type = MAX
execute_on = 'TIMESTEP_END'
[]
[]
[Executioner]
type = Transient
# same grid and CFL margin as dirichlet_linear.i; the Neumann face makes the slowest
# mode decay more slowly, so max_error needs 15 steps to plateau
dt = 1
num_steps = 15
[]
[Outputs]
[out]
type = CSV
[]
[]
(test/tests/real_space/dirichlet_2d_corners.i)
# Non-periodic on both axes (Dirichlet left/right, zero-flux Neumann bottom/top),
# so the ghost fill reaches the four domain corners. exchangeGhostLayers() fills one
# axis at a time, so a corner ghost depends on the fill order.
#
# u = 1 + 2*x is uniform on every face, so it satisfies all four BCs exactly, and the
# discrete Laplacian must be zero everywhere, including the corner-adjacent cells.
[Domain]
dim = 2
nx = 20
ny = 10
parallel_mode = REAL_SPACE
xmin = 0
xmax = 1
ymin = 0
ymax = 1
[]
[Functions]
[u_func]
type = ParsedFunction
expression = '1 + 2 * x'
[]
[]
[TensorComputes]
[Initialize]
[u_ic]
# the steady profile implied by the four BCs below
type = MooseFunctionTensor
buffer = u
function = u_func
[]
[]
[BCs]
[left]
type = TensorDirichletBC
variable = u
boundary = left
value = 1
[]
[right]
type = TensorDirichletBC
variable = u
boundary = right
value = 3
[]
[bottom]
type = TensorNeumannBC
variable = u
boundary = bottom
flux = 0
[]
[top]
type = TensorNeumannBC
variable = u
boundary = top
flux = 0
[]
[]
[Solve]
[lap_compute]
type = FiniteDifferenceLaplacian
input = u
buffer = lap
[]
[]
[]
[Postprocessors]
[max_lap]
type = TensorExtremeValuePostprocessor
buffer = lap
value_type = MAX
[]
[min_lap]
type = TensorExtremeValuePostprocessor
buffer = lap
value_type = MIN
[]
[]
[Executioner]
type = Transient
num_steps = 1
[]
[Outputs]
[out]
type = CSV
[]
[]
(test/tests/implicit_fd/crank_semi_infinite.i)
# Crank, "The Mathematics of Diffusion" (2nd ed.), Sec. 3.3(i), eq. (3.13), with the implicit
# solver: a semi-infinite medium (x > 0) with zero initial concentration and constant surface
# concentration C1 = 1 at x = 0 has the exact solution
# C(x, t) = erfc(x / (2 sqrt(D t))).
# The same problem as real_space/semi_infinite_diffusion.i, which steps it explicitly.
#
# Pseudo-1D (ny = 1, Y periodic), D = 1. The domain extends 10 diffusion lengths at the
# comparison time t = 1, so the far Dirichlet u = 0 does not measurably affect the solution.
# Backward Euler with substeps of dt / substeps: the error is first order in the substep.
substeps = 100
[Domain]
dim = 2
nx = 100
ny = 1
parallel_mode = REAL_SPACE
periodic_directions = 'Y'
xmin = 0
xmax = 10
ymin = -0.5
ymax = 0.5
[]
[TensorBuffers]
[u]
[]
[dudt_u]
[]
[lap_u]
[]
[u_exact]
[]
[diff]
[]
[]
[TensorComputes]
# no [Initialize]: buffers start at zero, the C0 = 0 initial condition
[BCs]
[left]
type = TensorDirichletBC
variable = u
boundary = left
value = 1
[]
[right]
# far boundary, approximating the semi-infinite medium's x -> infinity condition
type = TensorDirichletBC
variable = u
boundary = right
value = 0
[]
[]
[Solve]
[dudt]
type = TimeDerivativeOperator
buffer = dudt_u
input = u
[]
[lap]
type = FiniteDifferenceLaplacian
buffer = lap_u
input = u
factor = -1
[]
[]
[Postprocess]
[u_exact]
type = ParsedCompute
buffer = u_exact
expression = 'erfc(x / (2 * sqrt(t))) + 0*y'
extra_symbols = true
[]
[diff]
type = ParsedCompute
buffer = diff
expression = 'abs(u - u_exact)'
inputs = 'u u_exact'
[]
[]
[]
[TensorSolver]
type = ImplicitFDSolver
buffer = u
operators = 'dudt lap'
root_compute = dudt
substeps = ${substeps}
l_tol = 1e-10
[]
[Postprocessors]
[max_error]
type = TensorExtremeValuePostprocessor
buffer = diff
value_type = MAX
[]
[]
[Problem]
type = TensorProblem
[]
[Executioner]
type = Transient
dt = 1
num_steps = 1
[]
[Outputs]
csv = true
[]
(test/tests/real_space/dirichlet_linear.i)
[Domain]
dim = 2
nx = 20
ny = 8
parallel_mode = REAL_SPACE
periodic_directions = 'Y'
xmin = 0
xmax = 1
ymin = -1
ymax = 1
[]
[Functions]
[u_ic_func]
type = ParsedFunction
expression = '1 + 2 * x + 0.001 * y'
[]
[]
[TensorComputes]
[Initialize]
[u_ic]
# Not the steady solution and not matching the BCs pointwise (it depends on y);
# diffusion must drive u to the exact steady profile u = 1 + 2*x.
type = MooseFunctionTensor
buffer = u
function = u_ic_func
[]
[]
[BCs]
[left]
type = TensorDirichletBC
variable = u
boundary = left
value = 1
[]
[right]
type = TensorDirichletBC
variable = u
boundary = right
value = 3
[]
[]
[Solve]
[dt]
type = FiniteDifferenceLaplacian
input = u
buffer = dudt
[]
[]
[]
[TensorSolver]
type = RealSpaceForwardEuler
buffer = u
time_derivative = dudt
substeps = 1000
[]
[Postprocessors]
[max_u]
type = TensorExtremeValuePostprocessor
buffer = u
value_type = MAX
execute_on = 'INITIAL TIMESTEP_END'
[]
[min_u]
type = TensorExtremeValuePostprocessor
buffer = u
value_type = MIN
execute_on = 'INITIAL TIMESTEP_END'
[]
[]
[Executioner]
type = Transient
# dx = 0.05, dy = 0.25: explicit CFL limit 1/(2*(1/dx^2 + 1/dy^2)) ~= 1.2e-3,
# above the substep dt/substeps = 1e-3.
dt = 1
num_steps = 4
[]
[Outputs]
[out]
type = CSV
[]
[]