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.