Skip to content

Commit

Permalink
Merge pull request #26486 from maxnezdyur/refac_opt_data
Browse files Browse the repository at this point in the history
Refactor OptimizationData
  • Loading branch information
GiudGiud authored Mar 13, 2024
2 parents 46cd0ed + ef26bb3 commit 6babef3
Show file tree
Hide file tree
Showing 23 changed files with 958 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ The `measurement_` vectors can be filled in using [!param](/Reporters/Optimizati

For cases where more than one variable is being sampled, the contribution of each sampled variable to the measurement value are specified by weights in csv file input using [!param](/Reporters/OptimizationData/file_variable_weights). These weights are then multiplied by each variable in the forward problem by specifying [!param](/Reporters/OptimizationData/variable_weight_names). There must be one [!param](/Reporters/OptimizationData/variable_weight_names) per [!param](/Reporters/OptimizationData/variable) being sampled and their ordering must be the same. A typical use case for this would be to specify [!param](/Reporters/OptimizationData/file_variable_weights) in the main optimization application input file to be read in along with the other parameters normally read from file. Next, these reporter weights would be transferred to the forward and adjoint problem subapps. In the forward subapp, [!param](/Reporters/OptimizationData/file_variable_weights) and [!param](/Reporters/OptimizationData/variable) would both be specified in the `OptimizationData` block and would weight the different variable contributions to the `simulation_values` and `misfit_values`. In the adjoint subapp, the weights are transferred into a reporter that is used to scale the misfit applied by the [ReporterPointSource.md] using [!param](/DiracKernels/ReporterPointSource/weight_name).

If the [!param](/Reporters/OptimizationData/objective_name) is set by the user
`OptimizationData` will create and store the L2 Norm of the misfit
values divided by two. This can be useful for running an inverse optimization problem with the
[GeneralOptimization.md] reporter.

## Example Input File Syntax

`OptimizationData` is typically used in the forward and homogeneous optimization sub-applications to sample the solution for `simulation_values` and calculating `misfit_values`. The measurement data can either be specified directly or (more commonly) transferred from the optimization main application, while the simulation and misfit values are transferred to the main application. It is also typically used in the adjoint/gradient sub-application to hold the misfit values to apply the [ReporterPointSource.md] Dirac kernel.
Expand Down
12 changes: 12 additions & 0 deletions modules/optimization/include/reporters/OptimizationData.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,17 @@ class OptimizationDataTempl : public T
virtual void execute() override;
virtual void finalize() override {}

/**
* Compute misfit vectors from the simulations and measurement values.
*/
void computeMisfit();

/**
* Compute half the sum of the misfit (squared) values
* @return 1/2 of the sum of the misfit values.
*/
Real computeMisfitValue();

protected:
///@{
/// x,y,z,t and value measurement data
Expand All @@ -55,6 +64,9 @@ class OptimizationDataTempl : public T
/// difference between simulation and measurement values at measurement xyzt
std::vector<Real> & _misfit_values;

/// Reporter value that will hold the objective value
Real & _objective_val;

private:
/// parse measurement data from csv file
void readMeasurementsFromFile();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,17 @@ GeneralOptimization::GeneralOptimization(const InputParameters & parameters)
Real
GeneralOptimization::computeObjective()
{
return _objective_val;
Real val = 0;
if (_tikhonov_coeff > 0.0)
{
Real param_norm_sqr = 0;
for (const auto & data : _parameters)
for (const auto & param_val : *data)
param_norm_sqr += param_val * param_val;
// We multiply by 0.5 to maintain backwards compatibility.
val += 0.5 * _tikhonov_coeff * param_norm_sqr;
}
return _objective_val + val;
}

dof_id_type
Expand Down
22 changes: 20 additions & 2 deletions modules/optimization/src/reporters/OptimizationData.C
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ OptimizationDataTempl<T>::validParams()
"ordering of these weight reporter names corresponds to the ordering used in variable.");
params.addParam<std::vector<VariableName>>(
"variable", "Vector of variable names to sample at measurement points.");

params.addParam<ReporterValueName>("objective_name",
"Name of reporter value defining the objective.");
params.addParamNamesToGroup("measurement_points measurement_values measurement_times",
"Input Measurement Data");
params.addParamNamesToGroup("measurement_file file_xcoord file_ycoord file_zcoord file_time "
Expand All @@ -74,7 +75,12 @@ OptimizationDataTempl<T>::OptimizationDataTempl(const InputParameters & paramete
_simulation_values(this->template declareValueByName<std::vector<Real>>(
"simulation_values", REPORTER_MODE_REPLICATED)),
_misfit_values(this->template declareValueByName<std::vector<Real>>("misfit_values",
REPORTER_MODE_REPLICATED))
REPORTER_MODE_REPLICATED)),
_objective_val(this->isParamSetByUser("objective_name")
? this->template declareValueByName<Real>(
this->template getParam<ReporterValueName>("objective_name"),
REPORTER_MODE_REPLICATED)
: this->template declareUnusedValue<Real>())
{
// read in data
if (this->isParamValid("measurement_file") && this->isParamValid("measurement_points"))
Expand Down Expand Up @@ -129,6 +135,7 @@ void
OptimizationDataTempl<T>::execute()
{
computeMisfit();
_objective_val = computeMisfitValue();
}

template <typename T>
Expand Down Expand Up @@ -315,5 +322,16 @@ OptimizationDataTempl<T>::errorCheckDataSize()
").");
}

template <typename T>
Real
OptimizationDataTempl<T>::computeMisfitValue()
{
Real val = 0.0;
for (auto & misfit : _misfit_values)
val += misfit * misfit;

return val * 0.5;
}

template class OptimizationDataTempl<GeneralReporter>;
template class OptimizationDataTempl<OptimizationReporterBase>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
[Mesh]
type = GeneratedMesh
dim = 2
nx = 10
ny = 10
xmax = 1
ymax = 1.4
[]

[Variables]
[adjoint]
[]
[]

[Problem]
extra_tag_vectors = 'ref'
[]
[AuxVariables]
[residual_src]
[]
[]
[AuxKernels]
[residual_src]
type = TagVectorAux
vector_tag = 'ref'
v = 'adjoint'
variable = 'residual_src'
[]
[]

[Variables]
[adjoint]
[]
[]

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

#-----every adjoint problem should have these two
[DiracKernels]
[pt]
type = ReporterPointSource
variable = adjoint
x_coord_name = misfit/measurement_xcoord
y_coord_name = misfit/measurement_ycoord
z_coord_name = misfit/measurement_zcoord
value_name = misfit/misfit_values
extra_vector_tags = 'ref'
[]
[]

[Reporters]
[misfit]
type = OptimizationData
measurement_points = ${measurement_points}
measurement_values = ${measurement_values}
[]
[]

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

[Materials]
[steel]
type = GenericConstantMaterial
prop_names = thermal_conductivity
prop_values = 5
[]
[]

[Executioner]
type = Steady
solve_type = NEWTON
nl_abs_tol = 1e-6
nl_rel_tol = 1e-8
petsc_options_iname = '-pc_type'
petsc_options_value = 'lu'
[]

[VectorPostprocessors]
[gradient]
type = PointValueSampler
points = '0.2 0.2 0
0.7 0.56 0
0.4 1 0'
variable = adjoint
sort_by = id
[]
[]

[Outputs]
console = false
exodus = false
file_base = 'adjoint'
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
[Mesh]
[gmg]
type = GeneratedMeshGenerator
dim = 2
nx = 10
ny = 10
xmax = 1
ymax = 1.4
[]
[]

[Variables]
[temperature]
[]
[]

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

[DiracKernels]
[pt]
type = ReporterPointSource
variable = temperature
x_coord_name = 'point_source/x'
y_coord_name = 'point_source/y'
z_coord_name = 'point_source/z'
value_name = 'point_source/value'
[]
[]

[BCs]
[left]
type = DirichletBC
variable = temperature
boundary = left
value = 300
[]
[right]
type = DirichletBC
variable = temperature
boundary = right
value = 300
[]
[bottom]
type = DirichletBC
variable = temperature
boundary = bottom
value = 300
[]
[top]
type = DirichletBC
variable = temperature
boundary = top
value = 300
[]
[]

[Materials]
[steel]
type = GenericConstantMaterial
prop_names = thermal_conductivity
prop_values = 5
[]
[]

[Executioner]
type = Steady
solve_type = NEWTON
nl_abs_tol = 1e-6
nl_rel_tol = 1e-8
petsc_options_iname = '-pc_type'
petsc_options_value = 'lu'
[]

[VectorPostprocessors]
[point_source]
type = ConstantVectorPostprocessor
vector_names = 'x y z value'
value = '0.2 0.7 0.4;
0.2 0.56 1;
0 0 0;
-1000 120 500'
execute_on = LINEAR
[]
[vertical]
type = LineValueSampler
variable = 'temperature'
start_point = '0.5 0 0'
end_point = '0.5 1.4 0'
num_points = 21
sort_by = y
[]
[]

[Reporters]
[measure_data]
type = OptimizationData
variable = temperature
objective_name = misfit_norm
measurement_points = ${measurement_points}
measurement_values = ${measurement_values}
[]
[]

[Outputs]
console = false
file_base = 'forward'
[]
Loading

0 comments on commit 6babef3

Please sign in to comment.