Thermomechanical SIMP Optimization with Multi-Apps

In this example, we setup two different physics problems defined in the same domain. The first model is a mechanical small deformation problem with two loads using symmetric boundary conditions. Such a model yields the typical SIMP "bridge-like" structure. The problem is set up regularly with the mechanical compliance sensitivity computed and adequately filtered.

Listing 1: MBB User objects in structural subapp

[UserObjects]
  [rad_avg]
    type = RadialAverage
    radius = 1.2
    weights = linear
    prop_name = sensitivity
    execute_on = TIMESTEP_END
    force_preaux = true
  []
  [calc_sense]
    type = SensitivityFilter
    density_sensitivity = Dc
    design_density = mat_den
    filter_UO = rad_avg
    execute_on = TIMESTEP_END
    force_postaux = true
  []
[]
(modules/combined/examples/optimization/thermomechanical/structural_sub.i)

The second model is a thermal, heat conduction problem with one heat generation boundary (on the left) with the rest of boundaries defined as insulating material; i.e. zero Neumann boundary condition on temperature. Such a model often generates a dendritic structure to maximize the reduction in the temperature gradients. In a way analogous to the structural problem, the thermal compliance sensitivities are generated and filtered in the subapp:

Listing 2: MBB User objects in thermal subapp

[UserObjects]
  [rad_avg]
    type = RadialAverage
    radius = 0.1
    weights = linear
    prop_name = sensitivity
    execute_on = TIMESTEP_END
    force_preaux = true
  []
  [rad_avg_cost]
    type = RadialAverage
    radius = 0.1
    weights = linear
    prop_name = cost_sensitivity
    execute_on = TIMESTEP_END
    force_preaux = true
  []
  [rad_avg_thermal]
    type = RadialAverage
    radius = 0.1
    weights = linear
    prop_name = thermal_sensitivity
    execute_on = TIMESTEP_END
    force_preaux = true
  []
  # Provides Dc
  [calc_sense]
    type = SensitivityFilter
    density_sensitivity = Dc
    design_density = mat_den
    filter_UO = rad_avg
    execute_on = TIMESTEP_END
    force_postaux = true
  []
  # Provides Cc
  [calc_sense_cost]
    type = SensitivityFilter
    density_sensitivity = Cc
    design_density = mat_den
    filter_UO = rad_avg_cost
    execute_on = TIMESTEP_END
    force_postaux = true
  []
  # Provides Tc
  [calc_sense_thermal]
    type = SensitivityFilter
    density_sensitivity = Tc
    design_density = mat_den
    filter_UO = rad_avg_thermal
    execute_on = TIMESTEP_END
    force_postaux = true
  []
[]
(modules/combined/examples/optimization/thermomechanical/thermal_sub.i)

Finally, the main app obtain the sensitivities from the subapps and sends the computed pseudo-densities to the subapps. This process tends to reduce the objective function of both problems. The extent to which the one particular subapp drives the optimization process depends on the weights used to obtain a total or overall sensitivity, which is used in the density update process.

Listing 3: MBB Density update in main app

[UserObjects]
  # We do filtering in the subapps
  [update]
    type = DensityUpdate
    density_sensitivity = total_sensitivity
    design_density = mat_den
    volume_fraction = ${vol_frac}
    execute_on = MULTIAPP_FIXED_POINT_BEGIN
  []
[]
(modules/combined/examples/optimization/thermomechanical/thermomechanical_main.i)

The result of the optimization, which heavily depends on the many simulation and optimization parameters, is shown in what follows: