Constant Velocity Circle
One of the simplest problems for demonstrating the level set equation is to apply a constant velocity field to an initial field, in this case a circle in two dimensions. The following example assumes that you have a compiled and working level set module executable and is based on the content in the moose/modules/level_set/circle
directory.
Create Input File
This example begins by defining a minimal input file for solving the level set equation. The input file that is used initially is (modules/level_set/examples/circle/circle_16.i).
Mesh
First, the Mesh must be defined, which for this simple problem is a rectangular two-dimensional domain ranging from 0 to 1 in the x and y directions.
[Mesh<<<{"href": "../../syntax/Mesh/index.html"}>>>]
type = GeneratedMesh
dim = 2
xmin = 0
xmax = 1
ymin = 0
ymax = 1
nx = 16
ny = 16
[]
(modules/level_set/examples/circle/circle_16.i)Variables
The unknown that will be solved is defined ("phi") as well as the auxiliary variables that will define the velocity input to the level set equation. Notice that when the velocity variables are defined (vel_x
and vel_y
) each is defined an initial condition of 3. For this problem the velocity will remain constant, the value of which is defined by the initial condition.
[Variables<<<{"href": "../../syntax/Variables/index.html"}>>>]
[./phi]
[../]
[]
[AuxVariables<<<{"href": "../../syntax/AuxVariables/index.html"}>>>]
[./velocity]
family<<<{"description": "Specifies the family of FE shape functions to use for this variable"}>>> = LAGRANGE_VEC
[../]
[]
(modules/level_set/examples/circle/circle_16.i)Initial Condition
The initial condition for the auxiliary variables was defined via a short-cut syntax in the previous section; however, the "phi" variable must also be initialized. This will be accomplished by using the LevelSetOlssonBubble function that is a part of the level set module. In this case, a circle with a radius of 0.15 is defined at the midpoint of the domain.
[ICs<<<{"href": "../../syntax/ICs/index.html"}>>>]
[./phi_ic]
type = FunctionIC<<<{"description": "An initial condition that uses a normal function of x, y, z to produce values (and optionally gradients) for a field variable.", "href": "../../source/ics/FunctionIC.html"}>>>
function<<<{"description": "The initial condition function."}>>> = phi_exact
variable<<<{"description": "The variable this initial condition is supposed to provide values for."}>>> = phi
[../]
[./vel_ic]
type = VectorFunctionIC<<<{"description": "Sets component values for a vector field variable based on a vector function.", "href": "../../source/ics/VectorFunctionIC.html"}>>>
variable<<<{"description": "The variable this initial condition is supposed to provide values for."}>>> = velocity
function<<<{"description": "The initial condition vector function. This cannot be supplied with the component parameters."}>>> = velocity_func
[]
[]
[Functions<<<{"href": "../../syntax/Functions/index.html"}>>>]
[./phi_exact]
type = LevelSetOlssonBubble<<<{"description": "Implementation of 'bubble' ranging from 0 to 1.", "href": "../../source/functions/LevelSetOlssonBubble.html"}>>>
epsilon<<<{"description": "The interface thickness."}>>> = 0.05
center<<<{"description": "The center of the bubble."}>>> = '0.5 0.5 0'
radius<<<{"description": "The radius of the bubble."}>>> = 0.15
[../]
[./velocity_func]
type = ParsedVectorFunction<<<{"description": "Returns a vector function based on string descriptions for each component.", "href": "../../source/functions/MooseParsedVectorFunction.html"}>>>
expression_x<<<{"description": "x-component of function."}>>> = '3'
expression_y<<<{"description": "y-component of function."}>>> = '3'
[../]
[]
(modules/level_set/examples/circle/circle_16.i)Boundary Conditions
This problem assigns periodic boundary conditions for the "phi" in the x an y directions, which is easily accomplished within MOOSE.
[BCs<<<{"href": "../../syntax/BCs/index.html"}>>>]
[./Periodic<<<{"href": "../../syntax/BCs/Periodic/index.html"}>>>]
[./all]
variable<<<{"description": "Variable for the periodic boundary condition"}>>> = phi
auto_direction<<<{"description": "If using a generated mesh, you can specify just the dimension(s) you want to mark as periodic"}>>> = 'x y'
[../]
[../]
[]
(modules/level_set/examples/circle/circle_16.i)Kernels
The level set equation (see Theory) may be defined in MOOSE using two Kernel objects: TimeDerivative and LevelSetAdvection.
Notice, that the LevelSetAdvection requires that the unknown to be solved for ("phi") to be assigned in the "variable" parameters as well as the two velocity variables in the "velocity_x" and "velocity_y" parameters.
[Kernels<<<{"href": "../../syntax/Kernels/index.html"}>>>]
[./time]
type = TimeDerivative<<<{"description": "The time derivative operator with the weak form of $(\\psi_i, \\frac{\\partial u_h}{\\partial t})$.", "href": "../../source/kernels/TimeDerivative.html"}>>>
variable<<<{"description": "The name of the variable that this residual object operates on"}>>> = phi
[../]
[./advection]
type = LevelSetAdvection<<<{"description": "Implements the level set advection equation: $\\vec{v}\\cdot\\nabla u = 0$, where the weak form is $(\\psi_i, \\vec{v}\\cdot\\nabla u) = 0$.", "href": "../../source/kernels/LevelSetAdvection.html"}>>>
velocity<<<{"description": "Velocity vector variable."}>>> = velocity
variable<<<{"description": "The name of the variable that this residual object operates on"}>>> = phi
[../]
[]
(modules/level_set/examples/circle/circle_16.i)Postprocessors
In this example a single Postprocessors is defined. The LevelSetCFLCondition is used to define the minimum timestep that should be used when executing the solve of this equation, as discussed in the following section.
[Postprocessors<<<{"href": "../../syntax/Postprocessors/index.html"}>>>]
[./cfl]
type = LevelSetCFLCondition<<<{"description": "Compute the minimum timestep from the Courant-Friedrichs-Lewy (CFL) condition for the level-set equation.", "href": "../../source/postprocessors/LevelSetCFLCondition.html"}>>>
velocity<<<{"description": "Velocity vector variable."}>>> = velocity
execute_on<<<{"description": "The list of flag(s) indicating when this object should be executed. For a description of each flag, see https://mooseframework.inl.gov/source/interfaces/SetupInterface.html."}>>> = 'initial'
[../]
[]
(modules/level_set/examples/circle/circle_16.i)Execution
This example is a transient problem, hence the Transient execution is used. The other important aspect to illustrate in the Executioner block is the use of the PostprocessorDT time stepper, which allows for the LevelSetCFLCondition postprocessor to govern the timestepping for this problem.
[Executioner<<<{"href": "../../syntax/Executioner/index.html"}>>>]
type = Transient
solve_type = PJFNK
start_time = 0
end_time = 1
scheme = crank-nicolson
petsc_options_iname = '-pc_type -sub_pc_type'
petsc_options_value = 'asm ilu'
[./TimeStepper<<<{"href": "../../syntax/Executioner/TimeStepper/index.html"}>>>]
type = PostprocessorDT
postprocessor = cfl
scale = 0.8
[../]
[]
(modules/level_set/examples/circle/circle_16.i)Output
Finally, the Outputs defines a single types of output. The exodus output contains the mesh and field data for the simulation.
[Outputs<<<{"href": "../../syntax/Outputs/index.html"}>>>]
csv<<<{"description": "Output the scalar variable and postprocessors to a *.csv file using the default CSV output."}>>> = true
exodus<<<{"description": "Output the results using the default settings for Exodus output."}>>> = true
[]
(modules/level_set/examples/circle/circle_16.i)Results
Figure 1: Results of executing (modules/level_set/examples/circle/circle_16.i) showing the "phi" field variable and the 0.5 contour initially (black) and as the solution progresses (green).
Figure 1 show the results of the simulation defined by executing the (modules/level_set/examples/circle/circle_16.i) input file, which can be done using the following commands.
cd ~/projects/moose/modules/level_set/examples/circle
../../level_set-opt -i circle_16.i
Given the constant velocity of 3 in the input file for the x and y directions the initial circle translates at a 45 degree angle and performs three complete transects of the domain, more or less cycles could be achieved by altering the end time in the Executioner block.
Ideally, the circle would maintain it shape throughout the simulation since it is simply being advected by a constant velocity. This is not the case in the results shown in Figure 1, which clearly shows the initial circle being deformed during the simulation.
One method to improve the solution is to increase the number of finite elements in the mesh, which can be done from the command line:
../../level_set-opt -i circle_16.i Mesh/uniform_refine=2
This will cause two uniform refinements of the mesh. Doing this increases the problem size dramatically due to the increased number of elements and for this problem it also causes the time step to decrease because the timestep is a function of the element size (see LevelSetCFLCondition). For this simple example, the increased number of timesteps and the increased problem size are noticeable but do not cause an intractable increase of run time.
Figure 2: Results of executing (modules/level_set/examples/circle/circle_16.i), with two uniform refinement levels, showing the "phi" field variable and the 0.5 contour initially (black) and as the solution progresses (green).
Figure 2 shows the results from running (modules/level_set/examples/circle/circle_16.i) with two uniform refinements applied, the improvement in the solution is drastic and for this simple example may be adequate.