Material Inversion Example: Constant Thermal Conductivity

Background

The MOOSE optimization module provides a flexible framework for solving inverse optimization problems in MOOSE. This page is part of a set of examples for different types of inverse optimization problems.

Example: Constant Thermal Conductivity

In this example, material properties are the design parameters, described in this section on the theory page. This is a nonlinear optimization problem where the design parameters show up in the derivative of the PDE, see Inverse Optimization, Eq. (33). Getting a nonlinear optimization problem to converge is dependent on the initial guess and bounds for the design parameters. Even convergence doesn't guarantee a correct solution. All of this makes material inversion problems more difficult to solve than the linear optimization problems for force inversion.

Main-App Optimization Executioner

The main input file containing the optimization reporter, executioner and transfers is shown in Listing 1. The gradient of the PDE given by Inverse Optimization, Eq. (33) requires the temperature field from the forward problem to be available in the adjoint problem. This requires the forward problem temperature field be transferred to the adjoint problem. The adjoint problem also needs to be executed with the same material properties used in the forward problem, see the toAdjointParameter transfer in Listing 1.

Listing 1:

[Optimization]
[]

[Mesh]
  type = GeneratedMesh
  dim = 2
  nx = 10
  ny = 10
  xmax = 2
  ymax = 2
[]

[OptimizationReporter]
  type = OptimizationReporter
  parameter_names = 'p1'
  num_values = '1'
  initial_condition = '7'
  lower_bounds = '0'
  upper_bounds = '10'
  measurement_points = '0.2 0.2 0
            0.8 0.6 0
            0.2 1.4 0
            0.8 1.8 0'
  measurement_values = '226 254 214 146'
[]

[Executioner]
  type = Optimize
  tao_solver = taoblmvm
  petsc_options_iname = '-tao_gatol'
  petsc_options_value = '0.0001'
  verbose = true
[]

[MultiApps]
  [forward]
    type = FullSolveMultiApp
    input_files = forward.i
    execute_on = "FORWARD"
    clone_parent_mesh = true
  []
  [adjoint]
    type = FullSolveMultiApp
    input_files = adjoint.i
    execute_on = "ADJOINT"
    clone_parent_mesh = true
  []
[]

[Transfers]
  [toForward]
    type = MultiAppReporterTransfer
    to_multi_app = forward
    from_reporters = 'OptimizationReporter/measurement_xcoord
                      OptimizationReporter/measurement_ycoord
                      OptimizationReporter/measurement_zcoord
                      OptimizationReporter/measurement_time
                      OptimizationReporter/measurement_values
                      OptimizationReporter/p1'
    to_reporters = 'measure_data/measurement_xcoord
                    measure_data/measurement_ycoord
                    measure_data/measurement_zcoord
                    measure_data/measurement_time
                    measure_data/measurement_values
                    params/p1'
  []
  [fromForward_mesh]
    type = MultiAppCopyTransfer
    from_multi_app = forward
    to_multi_app = adjoint
    source_variable = 'temperature'
    variable = 'temperature_forward'
  []
  [fromForward]
    type = MultiAppReporterTransfer
    from_multi_app = forward
    from_reporters = 'measure_data/simulation_values'
    to_reporters = 'OptimizationReporter/simulation_values'
  []

  [toAdjoint]
    type = MultiAppReporterTransfer
    to_multi_app = adjoint
    from_reporters = 'OptimizationReporter/measurement_xcoord
                      OptimizationReporter/measurement_ycoord
                      OptimizationReporter/measurement_zcoord
                      OptimizationReporter/measurement_time
                      OptimizationReporter/misfit_values
                      OptimizationReporter/p1'
    to_reporters = 'misfit/measurement_xcoord
                    misfit/measurement_ycoord
                    misfit/measurement_zcoord
                    misfit/measurement_time
                    misfit/misfit_values
                    params/p1'
  []
  [fromAdjoint]
    type = MultiAppReporterTransfer
    from_multi_app = adjoint
    from_reporters = 'adjoint_grad/inner_product'
    to_reporters = 'OptimizationReporter/grad_p1'
  []
[]

[Outputs]
  csv = true
[]
(modules/optimization/test/tests/optimizationreporter/material/main.i)

Forward Problem Sub-App

The forward input file containing the solution to the PDE of interest is shown in Listing 2. The optimization executioner is controlling the thermal_conductivity prop_name in the thermal Material block.

Listing 2:

[Mesh]
[]

[Variables]
  [temperature]
  []
[]

[Kernels]
  [heat_conduction]
    type = MatDiffusion
    variable = temperature
    diffusivity = thermal_conductivity
  []
  [heat_source]
    type = BodyForce
    value = 1000
    variable = temperature
  []
[]

[BCs]
  [left]
    type = NeumannBC
    variable = temperature
    boundary = left
    value = 0
  []
  [right]
    type = NeumannBC
    variable = temperature
    boundary = right
    value = 0
  []
  [bottom]
    type = DirichletBC
    variable = temperature
    boundary = bottom
    value = 200
  []
  [top]
    type = DirichletBC
    variable = temperature
    boundary = top
    value = 100
  []
[]

[Functions]
  [thermo_conduct]
    type = ParsedOptimizationFunction
    expression = 'alpha'
    param_symbol_names = 'alpha'
    param_vector_name = 'params/p1'
  []
[]

[Materials]
  [steel]
    type = GenericFunctionMaterial
    prop_names = 'thermal_conductivity'
    prop_values = 'thermo_conduct'
  []
[]

[Executioner]
  type = Steady
  solve_type = NEWTON
  nl_abs_tol = 1e-8
  nl_rel_tol = 1e-8
  petsc_options_iname = '-ksp_type -pc_type -pc_factor_mat_solver_package'
  petsc_options_value = 'preonly lu       superlu_dist'
[]

[Reporters]
  [measure_data]
    type = OptimizationData
    variable = temperature
  []
  [params]
    type = ConstantReporter
    real_vector_names = 'p1'
    real_vector_values = '0' # Dummy value
  []
[]

[Outputs]
  console = false
  file_base = 'forward'
[]
(modules/optimization/test/tests/optimizationreporter/material/forward.i)

Adjoint Problem Sub-App

The adjoint input file shown in Listing 3 computes the adjoint of the forward PDE. The adjoint problem uses ConstantReporter and ParsedOptimizationFunction objects to allow the main app to transfer the material property used in the forward problem to the adjoint problem. The temperature field computed in the forward problem was transferred back to the main app and is finally transferred from the main app into the adjoint problem using a MultiAppCopyTransfer. The gradient given by Inverse Optimization, Eq. (33) is computed by the ElementOptimizationDiffusionCoefFunctionInnerProduct vector-postprocessor.

Listing 3:

[Mesh]
[]

[Variables]
  [adjointVar]
  []
[]

[Kernels]
  [heat_conduction]
    type = MatDiffusion
    variable = adjointVar
    diffusivity = thermal_conductivity
  []
[]

[DiracKernels]
  [pt]
    type = ReporterPointSource
    variable = adjointVar
    x_coord_name = misfit/measurement_xcoord
    y_coord_name = misfit/measurement_ycoord
    z_coord_name = misfit/measurement_zcoord
    value_name = misfit/misfit_values
  []
[]

[Reporters]
  [misfit]
    type = OptimizationData
  []
  [params]
    type = ConstantReporter
    real_vector_names = 'p1'
    real_vector_values = '0' # Dummy value
  []
[]

[AuxVariables]
  [temperature_forward]
  []
[]

[BCs]
  [left]
    type = NeumannBC
    variable = adjointVar
    boundary = left
    value = 0
  []
  [right]
    type = NeumannBC
    variable = adjointVar
    boundary = right
    value = 0
  []
  [bottom]
    type = DirichletBC
    variable = adjointVar
    boundary = bottom
    value = 0
  []
  [top]
    type = DirichletBC
    variable = adjointVar
    boundary = top
    value = 0
  []
[]

[Functions]
  [thermo_conduct]
    type = ParsedOptimizationFunction
    expression = 'alpha'
    param_symbol_names = 'alpha'
    param_vector_name = 'params/p1'
  []
[]

[Materials]
  [thermalProp]
    type = GenericFunctionMaterial
    prop_names = 'thermal_conductivity'
    prop_values = 'thermo_conduct'
  []
[]

[Executioner]
  type = Steady
  solve_type = PJFNK
  nl_abs_tol = 1e-8
  nl_rel_tol = 1e-8
  petsc_options_iname = '-ksp_type -pc_type -pc_factor_mat_solver_package'
  petsc_options_value = 'preonly lu       superlu_dist'
[]

[VectorPostprocessors]
  [adjoint_grad]
    type = ElementOptimizationDiffusionCoefFunctionInnerProduct
    variable = adjointVar
    forward_variable = temperature_forward
    function = thermo_conduct
  []
[]

[Outputs]
  console = false
  file_base = 'adjoint'
[]
(modules/optimization/test/tests/optimizationreporter/material/adjoint.i)