- variableThe name of the variable that this residual object operates on
C++ Type:NonlinearVariableName
Unit:(no unit assumed)
Controllable:No
Description:The name of the variable that this residual object operates on
- velocityVelocity vector
C++ Type:std::vector<VariableName>
Unit:(no unit assumed)
Controllable:No
Description:Velocity vector
ConservativeAdvection
Description
The ConservativeAdvection
kernel implements an advection term given for the domain () defined as
where is the advecting velocity and the second term on the left hand side represents the strong forms of other kernels. ConservativeAdvection
does not assume that the velocity is divergence free and instead applies to the test function in the weak variational form after integrating by parts, which results in the following (without numerical stabilization)
where are the test functions and is the finite element solution of the weak formulation. The first term is the volumetric term and the second term is a surface term describing the advective flux out of the volume. ConservativeAdvection
corresponds to the former volumetric term, while the surface term is implemented as a BC in MOOSE (see discussion below regarding OutflowBC
and InflowBC
).
Without numerical stabilization the corresponding Jacobian is given by
Full upwinding
Advective flow is notoriously prone to physically-incorrect overshoots and undershoots, so in many simulations some numerical stabilization is used to reduce or eliminate this spurious behaviour. Full-upwinding Dalen (1979) and Adhikary and Wilkins (2011) is an example of numerical stabilization and this essentially adds numerical diffusion to completely eliminate overshoots and undershoots. Full-upwinding is available in ConservativeAdvection
by setting the upwinding_type
appropriately.
Full upwinding only works for continuous FEM
In DE systems describing more than just advection (e.g., in diffusion-advection problems) full upwinding may be used on the advection alone. In practice, it is reasonably common that these more complicated cases benefit from numerical stabilization on their other terms too, in which case full upwinding could also be used, but this is not mandatory and is not implemented in the ConservativeAdvection
Kernel.
For each element in the mesh, full upwinding is implemented in the following way. For each , the quantity is evaluated. If is positive then mass (or heat, or whatever represents) is flowing out of node , and this is called an "upwind" node. If , the residual for node is set to Here is the value of at the node . Define the total mass flowing from the upwind nodes: Similarly, define Mass is conserved if the residual for the downwind nodes is defined to be
Full upwinding adds more numerical diffusion than most other numerical stabilization techniques such as SUPG and TVD. Another problem is that steady-state can be hard to achieve in nonlinear problems where the velocity is not fixed and changes every nonlinear iteration (this does not occur for ConservativeAdvection
). On the other hand, full upwinding is computationally cheap.
Example Syntax
ConservativeAdvection
can be used in a variety of problems, including advection-diffusion-reaction. The syntax for ConservativeAdvection
is demonstrated in this Kernels
block from a pure advection test case:
[Kernels]
[./udot]
type = TimeDerivative
variable = u
[../]
[./advection]
type = ConservativeAdvection
variable = u
velocity = '1 0 0'
[../]
[]
(moose/test/tests/kernels/conservative_advection/no_upwinding_1D.i)The velocity is supplied as a three component vector with order , , and .
Boundary conditions for pure advection
To form the correct equations, the boundary term needs to be included in the BCs
block of a MOOSE input file ( is the outward normal to the boundary). An OutflowBC
may be used, for instance
[BCs]
[./allow_mass_out]
type = OutflowBC
boundary = right
variable = u
velocity = '1 0 0'
[../]
[]
(moose/test/tests/kernels/conservative_advection/none_in_all_out.i)Physically this subtracts "fluid mass" (or whatever represents) from the boundary.
For adding the OutflowBC
allows "fluid" to flow freely through the boundary. The advective velocity is "blowing fluid" into this boundary, and the OutflowBC
is removing it at the correct rate, because the flux through any area is .
On the other hand, including an OutflowBC
for isn't usually desirable. Adding the OutflowBC
in this case fixes at the boundary to its initial condition. This is because the ConservativeAdvection
Kernel is taking fluid from the boundary to the interior of the model, but at the same time the OutflowBC
is removing : note that , so the OutflowBC
is actually adding fluid at the same rate the ConservativeAdvection
Kernel is removing it. The physical interpretation is that something external to the model is adding fluid at exactly the rate specified by the initial conditions at that boundary.
Instead, for users typically want to specify a particular value for an injected flux. This is achieved by using an InflowBC
. This adds , where (kg.m.s) is the injection rate. For instance
[BCs]
[./u_injection_left]
type = InflowBC
boundary = left
variable = u
velocity = '1 0 0'
inlet_conc = 1
[../]
[]
(moose/test/tests/kernels/conservative_advection/full_upwinding_1D.i)To make impermeable boundaries, either for or , simply use no BC at that boundary. Then for there is no BC to remove fluid from that boundary so the fluid "piles up" there. For the omission of a BC can be thought of setting in an InflowBC
.
Comparison of no upwinding and full upwinding
The tests
# ConservativeAdvection with upwinding_type = None
# Apply a velocity = (1, 0, 0) and see a pulse advect to the right
# Note there are overshoots and undershoots
[Mesh]
type = GeneratedMesh
dim = 1
nx = 10
[]
[Variables]
[./u]
[../]
[]
[BCs]
[./u_injection_left]
type = InflowBC
boundary = left
variable = u
velocity = '1 0 0'
inlet_conc = 1
[../]
[]
[Kernels]
[./udot]
type = TimeDerivative
variable = u
[../]
[./advection]
type = ConservativeAdvection
variable = u
velocity = '1 0 0'
[../]
[]
[Executioner]
type = Transient
solve_type = LINEAR
dt = 0.1
end_time = 1
l_tol = 1E-14
[]
[Outputs]
exodus = true
[]
(moose/test/tests/kernels/conservative_advection/no_upwinding_1D.i)and
# ConservativeAdvection with upwinding_type = full
# Apply a velocity = (1, 0, 0) and see a pulse advect to the right
# Note that the pulse diffuses more than with no upwinding,
# but there are no overshoots and undershoots and that the
# center of the pulse at u=0.5 advects with the correct velocity
[Mesh]
type = GeneratedMesh
dim = 1
nx = 10
[]
[Variables]
[./u]
[../]
[]
[BCs]
[./u_injection_left]
type = InflowBC
boundary = left
variable = u
velocity = '1 0 0'
inlet_conc = 1
[../]
[]
[Kernels]
[./udot]
type = MassLumpedTimeDerivative
variable = u
[../]
[./advection]
type = ConservativeAdvection
variable = u
velocity = '1 0 0'
upwinding_type = full
[../]
[]
[Executioner]
type = Transient
solve_type = LINEAR
dt = 0.1
end_time = 1
l_tol = 1E-14
[]
[Outputs]
exodus = true
[]
(moose/test/tests/kernels/conservative_advection/full_upwinding_1D.i)describe the same physical situation: advection from left to right along a line. A source at the left boundary introduces into the domain at a fixed rate (using an InflowBC
). The right boundary is impermeable (no BC), so when arrives there it starts building up at the boundary. It is clear from the figures below that no upwinding leads to unphysical overshoots and undershoots, while full upwinding results in none of that oscillatory behaviour but instead produces more numerical diffusion.
Input Parameters
- blockThe list of blocks (ids or names) that this object will be applied
C++ Type:std::vector<SubdomainName>
Unit:(no unit assumed)
Controllable:No
Description:The list of blocks (ids or names) that this object will be applied
- displacementsThe displacements
C++ Type:std::vector<VariableName>
Unit:(no unit assumed)
Controllable:No
Description:The displacements
- prop_getter_suffixAn optional suffix parameter that can be appended to any attempt to retrieve/get material properties. The suffix will be prepended with a '_' character.
C++ Type:MaterialPropertyName
Unit:(no unit assumed)
Controllable:No
Description:An optional suffix parameter that can be appended to any attempt to retrieve/get material properties. The suffix will be prepended with a '_' character.
- upwinding_typenoneType of upwinding used. None: Typically results in overshoots and undershoots, but numerical diffusion is minimized. Full: Overshoots and undershoots are avoided, but numerical diffusion is large
Default:none
C++ Type:MooseEnum
Unit:(no unit assumed)
Controllable:No
Description:Type of upwinding used. None: Typically results in overshoots and undershoots, but numerical diffusion is minimized. Full: Overshoots and undershoots are avoided, but numerical diffusion is large
- use_interpolated_stateFalseFor the old and older state use projected material properties interpolated at the quadrature points. To set up projection use the ProjectedStatefulMaterialStorageAction.
Default:False
C++ Type:bool
Unit:(no unit assumed)
Controllable:No
Description:For the old and older state use projected material properties interpolated at the quadrature points. To set up projection use the ProjectedStatefulMaterialStorageAction.
Optional Parameters
- absolute_value_vector_tagsThe tags for the vectors this residual object should fill with the absolute value of the residual contribution
C++ Type:std::vector<TagName>
Unit:(no unit assumed)
Controllable:No
Description:The tags for the vectors this residual object should fill with the absolute value of the residual contribution
- extra_matrix_tagsThe extra tags for the matrices this Kernel should fill
C++ Type:std::vector<TagName>
Unit:(no unit assumed)
Controllable:No
Description:The extra tags for the matrices this Kernel should fill
- extra_vector_tagsThe extra tags for the vectors this Kernel should fill
C++ Type:std::vector<TagName>
Unit:(no unit assumed)
Controllable:No
Description:The extra tags for the vectors this Kernel should fill
- matrix_tagssystemThe tag for the matrices this Kernel should fill
Default:system
C++ Type:MultiMooseEnum
Unit:(no unit assumed)
Controllable:No
Description:The tag for the matrices this Kernel should fill
- vector_tagsnontimeThe tag for the vectors this Kernel should fill
Default:nontime
C++ Type:MultiMooseEnum
Unit:(no unit assumed)
Controllable:No
Description:The tag for the vectors this Kernel should fill
Tagging Parameters
- control_tagsAdds user-defined labels for accessing object parameters via control logic.
C++ Type:std::vector<std::string>
Unit:(no unit assumed)
Controllable:No
Description:Adds user-defined labels for accessing object parameters via control logic.
- diag_save_inThe name of auxiliary variables to save this Kernel's diagonal Jacobian contributions to. Everything about that variable must match everything about this variable (the type, what blocks it's on, etc.)
C++ Type:std::vector<AuxVariableName>
Unit:(no unit assumed)
Controllable:No
Description:The name of auxiliary variables to save this Kernel's diagonal Jacobian contributions to. Everything about that variable must match everything about this variable (the type, what blocks it's on, etc.)
- enableTrueSet the enabled status of the MooseObject.
Default:True
C++ Type:bool
Unit:(no unit assumed)
Controllable:Yes
Description:Set the enabled status of the MooseObject.
- implicitTrueDetermines whether this object is calculated using an implicit or explicit form
Default:True
C++ Type:bool
Unit:(no unit assumed)
Controllable:No
Description:Determines whether this object is calculated using an implicit or explicit form
- save_inThe name of auxiliary variables to save this Kernel's residual contributions to. Everything about that variable must match everything about this variable (the type, what blocks it's on, etc.)
C++ Type:std::vector<AuxVariableName>
Unit:(no unit assumed)
Controllable:No
Description:The name of auxiliary variables to save this Kernel's residual contributions to. Everything about that variable must match everything about this variable (the type, what blocks it's on, etc.)
- seed0The seed for the master random number generator
Default:0
C++ Type:unsigned int
Unit:(no unit assumed)
Controllable:No
Description:The seed for the master random number generator
- use_displaced_meshFalseWhether or not this object should use the displaced mesh for computation. Note that in the case this is true but no displacements are provided in the Mesh block the undisplaced mesh will still be used.
Default:False
C++ Type:bool
Unit:(no unit assumed)
Controllable:No
Description:Whether or not this object should use the displaced mesh for computation. Note that in the case this is true but no displacements are provided in the Mesh block the undisplaced mesh will still be used.
Advanced Parameters
References
- D. Adhikary and A. Wilkins.
Analysis of finite element discretisation schemes for multi-phase Darcy flow.
Defect and Diffusion Forum, 318:33–40, 2011.
doi:10.4028/www.scientific.net/DDF.318.33.[BibTeX]
- V. Dalen.
Simplified Finite-Element Models for Reservoir Flow Problems.
Society of Petroleum Engineers Journal, 19:333–342, 1979.
doi:10.2118/7196-PA.[BibTeX]