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)