2D MBB Beam with a Convolution Filter and Adaptive Mesh Refinement

In this example we will go over the SIMP approach to topology optimization using adaptive mesh refinement. Only new material not covered in the previous example will be covered here 2D Topology Optimization with Radial Average Filter, 2D Topology Optimization with PDE Filter and Boundary Penalty.

The main addition for this example is showing an effective indicator for adaptive mesh refinement, which is the mat_den_nodal variable below.. In the AuxVariables block there is a new variable.

Listing 1: Nodal material density variable definitions

[AuxVariables<<<{"href": "../../../../syntax/AuxVariables/index.html"}>>>]
  [mat_den_nodal]
    family<<<{"description": "Specifies the family of FE shape functions to use for this variable"}>>> = L2_LAGRANGE
    order<<<{"description": "Specifies the order of the FE shape function to use for this variable (additional orders not listed are allowed)"}>>> = FIRST
    initial_condition<<<{"description": "Specifies a constant initial condition for this variable"}>>> = ${vol_frac}
    [AuxKernel]
      type = SelfAux
      execute_on = TIMESTEP_END
      variable = mat_den_nodal
      v = mat_den
    []
  []
[]
(modules/combined/examples/optimization/2d_mbb_pde_amr.i)

The mat_den_nodal variable works better than using the mat_den variable for the indicator. Using the ValueJumpIndicator on the mat_den_nodal variable and refining the mesh where the indicator is greater than a small threshold (0.1), will result in a mesh that is refined in the areas where the material is not 0 or 1. This helps to create a "sharp" interface between the void and the solid elements, without having to refine the entire mesh.

Listing 2: MBB Adaptivity block

[Adaptivity<<<{"href": "../../../../syntax/Adaptivity/index.html"}>>>]
  max_h_level<<<{"description": "Maximum number of times a single element can be refined. If 0 then infinite."}>>> = 2
  recompute_markers_during_cycles<<<{"description": "Recompute markers during adaptivity cycles"}>>> = true
  interval<<<{"description": "The number of time steps betweeen each adaptivity phase"}>>> = 1
  cycles_per_step<<<{"description": "The number of adaptive steps to use when on each timestep during a Transient simulation."}>>> = 1
  marker<<<{"description": "The name of the Marker to use to actually adapt the mesh."}>>> = density_marker
  [Indicators<<<{"href": "../../../../syntax/Adaptivity/Indicators/index.html"}>>>]
    [density_jump]
      type = ValueJumpIndicator<<<{"description": "Compute the jump of the solution across element bondaries.", "href": "../../../../source/indicators/ValueJumpIndicator.html"}>>>
      variable<<<{"description": "The name of the variable that this side indicator applies to"}>>> = mat_den_nodal
    []
  []
  [Markers<<<{"href": "../../../../syntax/Adaptivity/Markers/index.html"}>>>]
    [density_marker]
      type = ErrorToleranceMarker<<<{"description": "Coarsen or refine elements based on an absolute tolerance allowed from the supplied indicator.", "href": "../../../../source/markers/ErrorToleranceMarker.html"}>>>
      indicator<<<{"description": "The name of the Indicator that this Marker uses."}>>> = density_jump
      coarsen<<<{"description": "Elements with error less than this will be coarsened."}>>> = 0.1
      refine<<<{"description": "Elements with error more than this will be refined."}>>> = 0.1
    []
  []
[]
(modules/combined/examples/optimization/2d_mbb_pde_amr.i)