KratosOptimizationApplication 10.4.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- KratosMultiphysics/.libs/KratosOptimizationApplication.so +0 -0
- KratosMultiphysics/.libs/libKratosOptimizationCore.dylib +0 -0
- KratosMultiphysics/OptimizationApplication/__init__.py +19 -0
- KratosMultiphysics/OptimizationApplication/algorithms/NLOPT_algorithms.py +255 -0
- KratosMultiphysics/OptimizationApplication/algorithms/SciPy_algorithms.py +154 -0
- KratosMultiphysics/OptimizationApplication/algorithms/__init__.py +0 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm.py +78 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_adam.py +68 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_base.py +393 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_gradient_projection.py +355 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_momentum_relaxed_gradient_projection.py +70 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_nesterov_accelarated_gradient.py +60 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_relaxed_gradient_projection.py +263 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_steepest_descent.py +205 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_NLOPT_constraint.py +194 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_NLOPT_objective.py +191 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_SciPy_constraint.py +123 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_SciPy_objective.py +148 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_constraint.py +180 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_objective.py +133 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_rgp_constraint.py +268 -0
- KratosMultiphysics/OptimizationApplication/analyses_controller.py +75 -0
- KratosMultiphysics/OptimizationApplication/controls/control.py +123 -0
- KratosMultiphysics/OptimizationApplication/controls/external_response_function_control.py +149 -0
- KratosMultiphysics/OptimizationApplication/controls/master_control.py +198 -0
- KratosMultiphysics/OptimizationApplication/controls/material/material_properties_control.py +115 -0
- KratosMultiphysics/OptimizationApplication/controls/material/simp_control.py +229 -0
- KratosMultiphysics/OptimizationApplication/controls/shape/vertex_morphing_shape_control.py +289 -0
- KratosMultiphysics/OptimizationApplication/controls/thickness/shell_thickness_control.py +180 -0
- KratosMultiphysics/OptimizationApplication/controls_controller.py +205 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/avg_abs_improvement_conv_criterion.py +98 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/combined_conv_criterion.py +87 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/constraint_conv_criterion.py +68 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/convergence_criterion.py +26 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/l2_conv_criterion.py +77 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/magnitude_reduction_conv_criterion.py +85 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/max_iter_conv_criterion.py +48 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/patience_conv_criterion.py +116 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/target_value_conv_criterion.py +64 -0
- KratosMultiphysics/OptimizationApplication/execution_policies/execution_policy.py +46 -0
- KratosMultiphysics/OptimizationApplication/execution_policies/execution_policy_decorator.py +67 -0
- KratosMultiphysics/OptimizationApplication/execution_policies/independent_analysis_execution_policy.py +78 -0
- KratosMultiphysics/OptimizationApplication/execution_policies/kratos_analysis_execution_policy.py +137 -0
- KratosMultiphysics/OptimizationApplication/execution_policies/stepping_analysis_execution_policy.py +88 -0
- KratosMultiphysics/OptimizationApplication/filtering/explicit_filter.py +124 -0
- KratosMultiphysics/OptimizationApplication/filtering/filter.py +188 -0
- KratosMultiphysics/OptimizationApplication/filtering/filter_utils.py +55 -0
- KratosMultiphysics/OptimizationApplication/filtering/helmholtz_analysis.py +139 -0
- KratosMultiphysics/OptimizationApplication/filtering/helmholtz_scalar_solver.py +39 -0
- KratosMultiphysics/OptimizationApplication/filtering/helmholtz_shape_solver.py +67 -0
- KratosMultiphysics/OptimizationApplication/filtering/helmholtz_solver_base.py +275 -0
- KratosMultiphysics/OptimizationApplication/filtering/helmholtz_vector_solver.py +39 -0
- KratosMultiphysics/OptimizationApplication/filtering/implicit_filter.py +192 -0
- KratosMultiphysics/OptimizationApplication/filtering/python_solvers_wrapper_implicit_filters.py +56 -0
- KratosMultiphysics/OptimizationApplication/model_part_controllers/connectivity_preserving_model_part_controller.py +72 -0
- KratosMultiphysics/OptimizationApplication/model_part_controllers/external_response_function_model_part_controller.py +110 -0
- KratosMultiphysics/OptimizationApplication/model_part_controllers/mdpa_model_part_controller.py +44 -0
- KratosMultiphysics/OptimizationApplication/model_part_controllers/model_part_controller.py +19 -0
- KratosMultiphysics/OptimizationApplication/model_parts_controller.py +92 -0
- KratosMultiphysics/OptimizationApplication/optimization_analysis.py +146 -0
- KratosMultiphysics/OptimizationApplication/optimizations_controller.py +223 -0
- KratosMultiphysics/OptimizationApplication/optimizer.py +61 -0
- KratosMultiphysics/OptimizationApplication/processes/optimization_problem_ascii_output_process.py +212 -0
- KratosMultiphysics/OptimizationApplication/processes/optimization_problem_field_output_process.py +122 -0
- KratosMultiphysics/OptimizationApplication/processes/optimization_problem_graph_output_process.py +184 -0
- KratosMultiphysics/OptimizationApplication/processes/optimization_problem_hdf5_output_process.py +84 -0
- KratosMultiphysics/OptimizationApplication/processes/optimization_problem_vtu_output_process.py +94 -0
- KratosMultiphysics/OptimizationApplication/processes/spatial_statistics_computation_process.py +81 -0
- KratosMultiphysics/OptimizationApplication/responses/__init__.py +0 -0
- KratosMultiphysics/OptimizationApplication/responses/additive_manufacturing_responses.py +410 -0
- KratosMultiphysics/OptimizationApplication/responses/analysis_based_response_function_factory.py +14 -0
- KratosMultiphysics/OptimizationApplication/responses/analysis_free_response_function_factory.py +14 -0
- KratosMultiphysics/OptimizationApplication/responses/base_response.py +66 -0
- KratosMultiphysics/OptimizationApplication/responses/binary_operator_response_function.py +103 -0
- KratosMultiphysics/OptimizationApplication/responses/combined_response_function.py +127 -0
- KratosMultiphysics/OptimizationApplication/responses/discrete_value_residual_response_function.py +131 -0
- KratosMultiphysics/OptimizationApplication/responses/evaluation_response_function.py +68 -0
- KratosMultiphysics/OptimizationApplication/responses/external_response_function.py +87 -0
- KratosMultiphysics/OptimizationApplication/responses/geometric_centroid_deviation_response_function.py +97 -0
- KratosMultiphysics/OptimizationApplication/responses/linear_strain_energy_response_function.py +72 -0
- KratosMultiphysics/OptimizationApplication/responses/literal_value_response_function.py +33 -0
- KratosMultiphysics/OptimizationApplication/responses/log_response_function.py +47 -0
- KratosMultiphysics/OptimizationApplication/responses/mass_response_function.py +71 -0
- KratosMultiphysics/OptimizationApplication/responses/response_function.py +126 -0
- KratosMultiphysics/OptimizationApplication/responses/response_routine.py +158 -0
- KratosMultiphysics/OptimizationApplication/responses/structural_responses.py +335 -0
- KratosMultiphysics/OptimizationApplication/responses_controller.py +390 -0
- KratosMultiphysics/OptimizationApplication/utilities/buffered_dict.py +399 -0
- KratosMultiphysics/OptimizationApplication/utilities/component_data_view.py +74 -0
- KratosMultiphysics/OptimizationApplication/utilities/helper_utilities.py +40 -0
- KratosMultiphysics/OptimizationApplication/utilities/logger_utilities.py +222 -0
- KratosMultiphysics/OptimizationApplication/utilities/model_part_utilities.py +117 -0
- KratosMultiphysics/OptimizationApplication/utilities/opt_line_search.py +173 -0
- KratosMultiphysics/OptimizationApplication/utilities/opt_projection.py +191 -0
- KratosMultiphysics/OptimizationApplication/utilities/optimization_problem.py +237 -0
- KratosMultiphysics/OptimizationApplication/utilities/optimization_problem_utilities.py +237 -0
- KratosMultiphysics/OptimizationApplication/utilities/response_utilities.py +249 -0
- KratosMultiphysics/OptimizationApplication/utilities/timer.py +45 -0
- KratosMultiphysics/OptimizationApplication/utilities/union_utilities.py +6 -0
- kratosoptimizationapplication-10.4.4.dist-info/METADATA +25 -0
- kratosoptimizationapplication-10.4.4.dist-info/RECORD +106 -0
- kratosoptimizationapplication-10.4.4.dist-info/WHEEL +6 -0
- kratosoptimizationapplication.dylibs/libKratosCore.dylib +4 -0
- kratosoptimizationapplication.dylibs/libgcc_s.1.1.dylib +0 -0
- kratosoptimizationapplication.dylibs/libgomp.1.dylib +0 -0
- kratosoptimizationapplication.dylibs/libstdc++.6.dylib +0 -0
KratosMultiphysics/OptimizationApplication/algorithms/algorithm_relaxed_gradient_projection.py
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import numpy
|
|
2
|
+
import KratosMultiphysics as Kratos
|
|
3
|
+
from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
|
|
4
|
+
from KratosMultiphysics.OptimizationApplication.algorithms.standardized_objective import StandardizedObjective
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.controls.master_control import MasterControl
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.algorithms.algorithm_gradient_projection import AlgorithmGradientProjection
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.utilities.opt_line_search import CreateLineSearch
|
|
9
|
+
from KratosMultiphysics.OptimizationApplication.algorithms.standardized_rgp_constraint import StandardizedRGPConstraint
|
|
10
|
+
from KratosMultiphysics.LinearSolversApplication.dense_linear_solver_factory import ConstructSolver
|
|
11
|
+
from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import time_decorator
|
|
12
|
+
from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import OptimizationAlgorithmTimeLogger
|
|
13
|
+
from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import ListLogger
|
|
14
|
+
import math
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def Factory(model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
|
|
18
|
+
return AlgorithmRelaxedGradientProjection(model, parameters, optimization_problem)
|
|
19
|
+
|
|
20
|
+
class AlgorithmRelaxedGradientProjection(AlgorithmGradientProjection):
|
|
21
|
+
"""
|
|
22
|
+
Relaxed Gradient Projection algorithm to solve constrained optimization problems. Implemnetation is based on:
|
|
23
|
+
Antonau, I., Hojjat, M. & Bletzinger, KU. Relaxed gradient projection algorithm for constrained node-based shape optimization. Struct Multidisc Optim 63, 1633–1651 (2021). https://doi.org/10.1007/s00158-020-02821-y
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def GetDefaultParameters(cls):
|
|
28
|
+
return Kratos.Parameters("""{
|
|
29
|
+
"module" : "KratosMultiphysics.OptimizationApplication.algorithms",
|
|
30
|
+
"type" : "PLEASE_PROVIDE_AN_ALGORITHM_CLASS_NAME",
|
|
31
|
+
"objective" : {},
|
|
32
|
+
"constraints" : [],
|
|
33
|
+
"controls" : [],
|
|
34
|
+
"echo_level" : 0,
|
|
35
|
+
"settings" : {
|
|
36
|
+
"echo_level" : 0,
|
|
37
|
+
"line_search" : {},
|
|
38
|
+
"conv_settings" : {},
|
|
39
|
+
"linear_solver_settings" : {},
|
|
40
|
+
"history_size" : 20,
|
|
41
|
+
"max_inner_iter" : 20,
|
|
42
|
+
"buffer_coeff_update_factor" : 0.1
|
|
43
|
+
}
|
|
44
|
+
}""")
|
|
45
|
+
|
|
46
|
+
def __init__(self, model:Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
|
|
47
|
+
self.model = model
|
|
48
|
+
self.parameters = parameters
|
|
49
|
+
self._optimization_problem = optimization_problem
|
|
50
|
+
parameters.ValidateAndAssignDefaults(self.GetDefaultParameters())
|
|
51
|
+
|
|
52
|
+
self.master_control = MasterControl() # Need to fill it with controls
|
|
53
|
+
self._optimization_problem.AddComponent(self.master_control)
|
|
54
|
+
|
|
55
|
+
for control_name in parameters["controls"].GetStringArray():
|
|
56
|
+
control = optimization_problem.GetControl(control_name)
|
|
57
|
+
self.master_control.AddControl(control)
|
|
58
|
+
|
|
59
|
+
settings = parameters["settings"]
|
|
60
|
+
settings.ValidateAndAssignDefaults(self.GetDefaultParameters()["settings"])
|
|
61
|
+
|
|
62
|
+
self.history_size = settings["history_size"].GetInt()
|
|
63
|
+
|
|
64
|
+
self.echo_level = settings["echo_level"].GetInt()
|
|
65
|
+
|
|
66
|
+
ComponentDataView("algorithm", self._optimization_problem).SetDataBuffer(self.GetMinimumBufferSize())
|
|
67
|
+
|
|
68
|
+
# self.__convergence_criteria = CreateConvergenceCriteria(settings["conv_settings"], self._optimization_problem)
|
|
69
|
+
self.__line_search_method = CreateLineSearch(settings["line_search"], self._optimization_problem)
|
|
70
|
+
|
|
71
|
+
self._objective = StandardizedObjective(parameters["objective"], self.master_control, self._optimization_problem)
|
|
72
|
+
self._optimization_problem.AddComponent(self._objective)
|
|
73
|
+
self._constraints_list: 'list[StandardizedRGPConstraint]' = []
|
|
74
|
+
for constraint_param in parameters["constraints"].values():
|
|
75
|
+
constraint = StandardizedRGPConstraint(constraint_param, self.master_control, self._optimization_problem, self.GetMinimumBufferSize())
|
|
76
|
+
self._optimization_problem.AddComponent(constraint)
|
|
77
|
+
self._constraints_list.append(constraint)
|
|
78
|
+
self._control_field = None
|
|
79
|
+
self._obj_val = None
|
|
80
|
+
|
|
81
|
+
self._convergence_criteria = self._CreateConvergenceCriteria(settings["conv_settings"])
|
|
82
|
+
|
|
83
|
+
default_linear_solver_settings = Kratos.Parameters("""{
|
|
84
|
+
"solver_type": "LinearSolversApplication.dense_col_piv_householder_qr"
|
|
85
|
+
}""")
|
|
86
|
+
settings["linear_solver_settings"].ValidateAndAssignDefaults(default_linear_solver_settings)
|
|
87
|
+
self.linear_solver = ConstructSolver(settings["linear_solver_settings"])
|
|
88
|
+
self.max_inner_iter = settings["max_inner_iter"].GetInt()
|
|
89
|
+
self.buffer_coeff_update_factor = settings["buffer_coeff_update_factor"].GetDouble()
|
|
90
|
+
|
|
91
|
+
def GetMinimumBufferSize(self) -> int:
|
|
92
|
+
return self.history_size
|
|
93
|
+
|
|
94
|
+
@time_decorator()
|
|
95
|
+
def ComputeSearchDirection(self, obj_grad: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor, constr_grad: 'list[Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]', w_r: Kratos.Vector, w_c: Kratos.Vector) -> Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor:
|
|
96
|
+
active_constraints_list = self.GetActiveConstraintsList()
|
|
97
|
+
number_of_active_constraints = len(active_constraints_list)
|
|
98
|
+
|
|
99
|
+
search_direction = Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(obj_grad, perform_collect_data_recursively=False, perform_store_data_recursively=False)
|
|
100
|
+
correction = Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(search_direction)
|
|
101
|
+
projected_direction = Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(search_direction)
|
|
102
|
+
|
|
103
|
+
if not number_of_active_constraints:
|
|
104
|
+
search_direction.data[:] = obj_grad.data * -1.0
|
|
105
|
+
correction.data[:] = 0.0
|
|
106
|
+
projected_direction.data[:] = 0.0
|
|
107
|
+
else:
|
|
108
|
+
# scaling obj gradients
|
|
109
|
+
obj_norm = numpy.linalg.norm(obj_grad.data.ravel(), ord=numpy.inf)
|
|
110
|
+
scaled_obj_grad = Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(obj_grad, perform_collect_data_recursively=False, perform_store_data_recursively=False)
|
|
111
|
+
if not math.isclose(obj_norm, 0.0, abs_tol=1e-16):
|
|
112
|
+
scaled_obj_grad.data[:] /= obj_norm
|
|
113
|
+
scaled_obj_grad.StoreData()
|
|
114
|
+
|
|
115
|
+
scaled_constr_grad: 'list[Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]' = []
|
|
116
|
+
lagrangian_multiplier = Kratos.Vector(number_of_active_constraints)
|
|
117
|
+
for i in range(number_of_active_constraints):
|
|
118
|
+
# scaling constraints grad
|
|
119
|
+
norm = numpy.linalg.norm(constr_grad[i].data.ravel(), ord=numpy.inf)
|
|
120
|
+
ta = Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(constr_grad[i], perform_collect_data_recursively=False, perform_store_data_recursively=False)
|
|
121
|
+
scaled_constr_grad.append(ta)
|
|
122
|
+
if not math.isclose(norm, 0.0, abs_tol=1e-16):
|
|
123
|
+
ta.data[:] /= norm
|
|
124
|
+
ta.StoreData()
|
|
125
|
+
|
|
126
|
+
# compute the projected search direction and correction
|
|
127
|
+
ntn = Kratos.Matrix(number_of_active_constraints, number_of_active_constraints)
|
|
128
|
+
for i in range(number_of_active_constraints):
|
|
129
|
+
for j in range(i, number_of_active_constraints):
|
|
130
|
+
ntn[i, j] = numpy.dot(scaled_constr_grad[i].data.ravel(), scaled_constr_grad[j].data.ravel())
|
|
131
|
+
ntn[j, i] = ntn[i, j]
|
|
132
|
+
|
|
133
|
+
# get the inverse of ntn
|
|
134
|
+
ntn_inverse = Kratos.Matrix(number_of_active_constraints, number_of_active_constraints)
|
|
135
|
+
|
|
136
|
+
# create the identity matrix
|
|
137
|
+
identity_matrix = Kratos.Matrix(number_of_active_constraints, number_of_active_constraints, 0.0)
|
|
138
|
+
for i in range(number_of_active_constraints):
|
|
139
|
+
identity_matrix[i, i] = 1.0
|
|
140
|
+
|
|
141
|
+
# solve for inverse of ntn
|
|
142
|
+
self.linear_solver.Solve(ntn, ntn_inverse, identity_matrix)
|
|
143
|
+
|
|
144
|
+
lagrangian_multiplier = ntn_inverse * self._CollectiveListCollectiveProduct(scaled_constr_grad, scaled_obj_grad)
|
|
145
|
+
for i in range(number_of_active_constraints):
|
|
146
|
+
if lagrangian_multiplier[i] > 0.0:
|
|
147
|
+
lagrangian_multiplier[i] = 0.0
|
|
148
|
+
else:
|
|
149
|
+
lagrangian_multiplier[i] *= w_r[i]
|
|
150
|
+
projected_direction.data[:] = - (scaled_obj_grad.data - self._CollectiveListVectorProduct(scaled_constr_grad, lagrangian_multiplier).data)
|
|
151
|
+
correction.data[:] = - self._CollectiveListVectorProduct(scaled_constr_grad, w_c).data
|
|
152
|
+
search_direction.data[:] = projected_direction.data + correction.data
|
|
153
|
+
self.algorithm_data.GetBufferedData().SetValue("search_direction", search_direction, overwrite=True)
|
|
154
|
+
self.algorithm_data.GetBufferedData().SetValue("correction", correction, overwrite=True)
|
|
155
|
+
self.algorithm_data.GetBufferedData().SetValue("projected_direction", projected_direction, overwrite=True)
|
|
156
|
+
|
|
157
|
+
def ComputeBufferCoefficients(self):
|
|
158
|
+
active_constraints_list = self.GetActiveConstraintsList()
|
|
159
|
+
number_of_active_constraints = len(active_constraints_list)
|
|
160
|
+
if number_of_active_constraints == 0:
|
|
161
|
+
return Kratos.Vector(), Kratos.Vector()
|
|
162
|
+
else:
|
|
163
|
+
w_r = Kratos.Vector(number_of_active_constraints)
|
|
164
|
+
w_c = Kratos.Vector(number_of_active_constraints)
|
|
165
|
+
for i, active_constraint in enumerate(active_constraints_list):
|
|
166
|
+
w = active_constraint.ComputeW()
|
|
167
|
+
w_r[i] = active_constraint.Compute_W_relax(w)
|
|
168
|
+
w_c[i] = active_constraint.Compute_W_correction(w)
|
|
169
|
+
print(f"RGP Constraint {active_constraint.GetResponseName()}:: w_r = {w_r[i]}, w_c = {w_c[i]}")
|
|
170
|
+
return w_r, w_c
|
|
171
|
+
|
|
172
|
+
@time_decorator()
|
|
173
|
+
def ComputeControlUpdate(self, alpha: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor) -> Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor:
|
|
174
|
+
search_direction: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor = self.algorithm_data.GetBufferedData()["search_direction"]
|
|
175
|
+
update = Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(search_direction, perform_collect_data_recursively=False, perform_store_data_recursively=False)
|
|
176
|
+
update.data[:] = search_direction.data * alpha.data
|
|
177
|
+
update.StoreData()
|
|
178
|
+
self.algorithm_data.GetBufferedData().SetValue("control_field_update", update, overwrite=True)
|
|
179
|
+
return update
|
|
180
|
+
|
|
181
|
+
def CheckLinearizedConstraints(self, active_constr_grad: 'list[Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]', update: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor, w_r, w_c) -> bool:
|
|
182
|
+
all_feasible = True
|
|
183
|
+
active_constraints_list = self.GetActiveConstraintsList()
|
|
184
|
+
for i, constraint in enumerate(active_constraints_list):
|
|
185
|
+
predicted_value = constraint.GetStandardizedValue() + numpy.dot(active_constr_grad[i].data.ravel(), update.data.ravel())
|
|
186
|
+
print(f"RGP Constraint {constraint.GetResponseName()}:: predicted g_i {predicted_value}")
|
|
187
|
+
if not constraint.IsSatisfied(predicted_value):
|
|
188
|
+
all_feasible = False
|
|
189
|
+
w = constraint.ComputeW()
|
|
190
|
+
w += self.buffer_coeff_update_factor
|
|
191
|
+
w_r[i] = constraint.Compute_W_relax(w)
|
|
192
|
+
w_c[i] = constraint.Compute_W_correction(w)
|
|
193
|
+
print(f"RGP Constraint {constraint.GetResponseName()}:: Corrected w_r = {w_r[i]}, w_c = {w_c[i]}")
|
|
194
|
+
else:
|
|
195
|
+
print(f"RGP Constraint {constraint.GetResponseName()}:: no correction for w_r, w_c ")
|
|
196
|
+
return all_feasible
|
|
197
|
+
|
|
198
|
+
def GetActiveConstraintsList(self):
|
|
199
|
+
return [constraint for constraint in self._constraints_list if constraint.IsActive()]
|
|
200
|
+
|
|
201
|
+
def GetConstraintsList(self):
|
|
202
|
+
return self._constraints_list
|
|
203
|
+
|
|
204
|
+
@time_decorator()
|
|
205
|
+
def Solve(self):
|
|
206
|
+
while not self.converged:
|
|
207
|
+
with OptimizationAlgorithmTimeLogger("Gradient Projection",self._optimization_problem.GetStep()):
|
|
208
|
+
self._InitializeIteration()
|
|
209
|
+
|
|
210
|
+
self._obj_val = self._objective.CalculateStandardizedValue(self._control_field)
|
|
211
|
+
obj_info = self._objective.GetInfo()
|
|
212
|
+
self.algorithm_data.GetBufferedData()["std_obj_value"] = obj_info["std_value"]
|
|
213
|
+
self.algorithm_data.GetBufferedData()["rel_change[%]"] = obj_info["rel_change [%]"]
|
|
214
|
+
if "abs_change [%]" in obj_info:
|
|
215
|
+
self.algorithm_data.GetBufferedData()["abs_change[%]"] = obj_info["abs_change [%]"]
|
|
216
|
+
|
|
217
|
+
obj_grad = self._objective.CalculateStandardizedGradient()
|
|
218
|
+
|
|
219
|
+
self.__constr_value = []
|
|
220
|
+
active_constr_grad = []
|
|
221
|
+
for constraint in self._constraints_list:
|
|
222
|
+
value = constraint.CalculateStandardizedValue(self._control_field)
|
|
223
|
+
constraint.UpdateBufferSize()
|
|
224
|
+
self.__constr_value.append(value)
|
|
225
|
+
constr_name = constraint.GetResponseName()
|
|
226
|
+
self.algorithm_data.GetBufferedData()[f"std_constr_{constr_name}_value"] = value
|
|
227
|
+
msg = "active" if constraint.IsActive() else "non-active"
|
|
228
|
+
print(f"RGP Constraint {constraint.GetResponseName()} is {msg}")
|
|
229
|
+
if constraint.IsActive():
|
|
230
|
+
active_constr_grad.append(constraint.CalculateStandardizedGradient())
|
|
231
|
+
|
|
232
|
+
w_r, w_c = self.ComputeBufferCoefficients()
|
|
233
|
+
|
|
234
|
+
inner_iter = 0
|
|
235
|
+
while inner_iter < self.max_inner_iter:
|
|
236
|
+
|
|
237
|
+
print(f"\n inner_iter :: {inner_iter}")
|
|
238
|
+
|
|
239
|
+
self.ComputeSearchDirection(obj_grad, active_constr_grad, w_r, w_c)
|
|
240
|
+
|
|
241
|
+
alpha = self.__line_search_method.ComputeStep()
|
|
242
|
+
|
|
243
|
+
update = self.ComputeControlUpdate(alpha)
|
|
244
|
+
|
|
245
|
+
if self.CheckLinearizedConstraints(active_constr_grad, update, w_r, w_c):
|
|
246
|
+
break
|
|
247
|
+
|
|
248
|
+
inner_iter += 1
|
|
249
|
+
|
|
250
|
+
self._FinalizeIteration()
|
|
251
|
+
|
|
252
|
+
self.converged = self._convergence_criteria.IsConverged()
|
|
253
|
+
|
|
254
|
+
self.Output()
|
|
255
|
+
|
|
256
|
+
self.UpdateControl()
|
|
257
|
+
|
|
258
|
+
ListLogger("Convergence info", self._convergence_criteria.GetInfo())
|
|
259
|
+
|
|
260
|
+
if not self.converged:
|
|
261
|
+
self._optimization_problem.AdvanceStep()
|
|
262
|
+
|
|
263
|
+
return self.converged
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import KratosMultiphysics as Kratos
|
|
2
|
+
from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
|
|
3
|
+
from KratosMultiphysics.OptimizationApplication.algorithms.standardized_objective import StandardizedObjective
|
|
4
|
+
from KratosMultiphysics.OptimizationApplication.controls.master_control import MasterControl
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.algorithms.algorithm import Algorithm
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.utilities.opt_line_search import CreateLineSearch
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import time_decorator
|
|
9
|
+
from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import OptimizationAlgorithmTimeLogger
|
|
10
|
+
from KratosMultiphysics.OptimizationApplication.convergence_criteria.convergence_criterion import ConvergenceCriterion
|
|
11
|
+
from KratosMultiphysics.OptimizationApplication.convergence_criteria.combined_conv_criterion import CombinedConvCriterion
|
|
12
|
+
from KratosMultiphysics.OptimizationApplication.convergence_criteria.max_iter_conv_criterion import MaxIterConvCriterion
|
|
13
|
+
from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem_utilities import OptimizationComponentFactory
|
|
14
|
+
from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import ListLogger
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def Factory(model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
|
|
18
|
+
return AlgorithmSteepestDescent(model, parameters, optimization_problem)
|
|
19
|
+
|
|
20
|
+
class AlgorithmSteepestDescent(Algorithm):
|
|
21
|
+
"""
|
|
22
|
+
A classical steepest descent algorithm to solve unconstrained optimization problems.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def GetDefaultParameters(cls):
|
|
27
|
+
return Kratos.Parameters("""{
|
|
28
|
+
"module" : "KratosMultiphysics.OptimizationApplication.algorithms",
|
|
29
|
+
"type" : "PLEASE_PROVIDE_AN_ALGORITHM_CLASS_NAME",
|
|
30
|
+
"objective" : {},
|
|
31
|
+
"controls" : [],
|
|
32
|
+
"echo_level" : 0,
|
|
33
|
+
"settings" : {
|
|
34
|
+
"echo_level" : 0,
|
|
35
|
+
"line_search" : {},
|
|
36
|
+
"conv_settings" : {}
|
|
37
|
+
}
|
|
38
|
+
}""")
|
|
39
|
+
|
|
40
|
+
def __init__(self, model:Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
|
|
41
|
+
self.model = model
|
|
42
|
+
self.parameters = parameters
|
|
43
|
+
self._optimization_problem = optimization_problem
|
|
44
|
+
|
|
45
|
+
parameters.ValidateAndAssignDefaults(self.GetDefaultParameters())
|
|
46
|
+
|
|
47
|
+
self.master_control = MasterControl() # Need to fill it with controls
|
|
48
|
+
self._optimization_problem.AddComponent(self.master_control)
|
|
49
|
+
|
|
50
|
+
for control_name in parameters["controls"].GetStringArray():
|
|
51
|
+
control = optimization_problem.GetControl(control_name)
|
|
52
|
+
self.master_control.AddControl(control)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
settings = parameters["settings"]
|
|
56
|
+
settings.ValidateAndAssignDefaults(self.GetDefaultParameters()["settings"])
|
|
57
|
+
|
|
58
|
+
self.echo_level = settings["echo_level"].GetInt()
|
|
59
|
+
|
|
60
|
+
ComponentDataView("algorithm", self._optimization_problem).SetDataBuffer(self.GetMinimumBufferSize())
|
|
61
|
+
|
|
62
|
+
self._convergence_criteria = self.__CreateConvergenceCriteria(settings["conv_settings"])
|
|
63
|
+
self.__line_search_method = CreateLineSearch(settings["line_search"], self._optimization_problem)
|
|
64
|
+
|
|
65
|
+
self.__objective = StandardizedObjective(parameters["objective"], self.master_control, self._optimization_problem)
|
|
66
|
+
self._optimization_problem.AddComponent(self.__objective)
|
|
67
|
+
self.__control_field = None
|
|
68
|
+
self.__obj_val = None
|
|
69
|
+
|
|
70
|
+
def GetMinimumBufferSize(self) -> int:
|
|
71
|
+
return 2
|
|
72
|
+
|
|
73
|
+
def Check(self) -> None:
|
|
74
|
+
self.master_control.Check()
|
|
75
|
+
self.__objective.Check()
|
|
76
|
+
|
|
77
|
+
@time_decorator()
|
|
78
|
+
def Initialize(self) -> None:
|
|
79
|
+
self.converged = False
|
|
80
|
+
self.__obj_val = None
|
|
81
|
+
self.master_control.Initialize()
|
|
82
|
+
self.__objective.Initialize()
|
|
83
|
+
self.__control_field = self.master_control.GetControlField()
|
|
84
|
+
self.algorithm_data = ComponentDataView("algorithm", self._optimization_problem)
|
|
85
|
+
self._convergence_criteria.Initialize()
|
|
86
|
+
|
|
87
|
+
def Finalize(self) -> None:
|
|
88
|
+
self.master_control.Finalize()
|
|
89
|
+
self.__objective.Finalize()
|
|
90
|
+
self._convergence_criteria.Finalize()
|
|
91
|
+
|
|
92
|
+
@time_decorator()
|
|
93
|
+
def ComputeSearchDirection(self, obj_grad: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor) -> Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor:
|
|
94
|
+
search_direction: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor = obj_grad.Clone()
|
|
95
|
+
search_direction.data[:] *= -1.0
|
|
96
|
+
Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(search_direction, perform_store_data_recursively=False, copy=False).StoreData()
|
|
97
|
+
self.algorithm_data.GetBufferedData()["search_direction"] = search_direction
|
|
98
|
+
return search_direction
|
|
99
|
+
|
|
100
|
+
@time_decorator()
|
|
101
|
+
def ComputeControlUpdate(self, alpha: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor) -> None:
|
|
102
|
+
update: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor = self.algorithm_data.GetBufferedData()["search_direction"].Clone()
|
|
103
|
+
update.data[:] *= alpha.data[:]
|
|
104
|
+
Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(update, perform_store_data_recursively=False, copy=False).StoreData()
|
|
105
|
+
self.algorithm_data.GetBufferedData()["control_field_update"] = update
|
|
106
|
+
|
|
107
|
+
@time_decorator()
|
|
108
|
+
def UpdateControl(self) -> Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor:
|
|
109
|
+
update: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor = self.algorithm_data.GetBufferedData()["control_field_update"]
|
|
110
|
+
self.__control_field.data[:] += update.data
|
|
111
|
+
Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(self.__control_field, perform_store_data_recursively=False, copy=False).StoreData()
|
|
112
|
+
|
|
113
|
+
@time_decorator()
|
|
114
|
+
def Output(self) -> None:
|
|
115
|
+
self.algorithm_data.GetBufferedData()["control_field"] = Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(self.__control_field)
|
|
116
|
+
for process in self._optimization_problem.GetListOfProcesses("output_processes"):
|
|
117
|
+
if process.IsOutputStep():
|
|
118
|
+
process.PrintOutput()
|
|
119
|
+
|
|
120
|
+
def GetCurrentObjValue(self) -> float:
|
|
121
|
+
return self.__obj_val
|
|
122
|
+
|
|
123
|
+
def GetCurrentControlField(self) -> Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor:
|
|
124
|
+
return self.__control_field
|
|
125
|
+
|
|
126
|
+
@time_decorator()
|
|
127
|
+
def Solve(self) -> bool:
|
|
128
|
+
while not self.converged:
|
|
129
|
+
with OptimizationAlgorithmTimeLogger("AlgorithmSteepestDescent",self._optimization_problem.GetStep()):
|
|
130
|
+
self._InitializeIteration()
|
|
131
|
+
|
|
132
|
+
self.__obj_val = self.__objective.CalculateStandardizedValue(self.__control_field)
|
|
133
|
+
obj_info = self.__objective.GetInfo()
|
|
134
|
+
self.algorithm_data.GetBufferedData()["std_obj_value"] = obj_info["std_value"]
|
|
135
|
+
self.algorithm_data.GetBufferedData()["rel_obj[%]"] = obj_info["rel_change [%]"]
|
|
136
|
+
if "abs_change [%]" in obj_info:
|
|
137
|
+
self.algorithm_data.GetBufferedData()["abs_obj[%]"] = obj_info["abs_change [%]"]
|
|
138
|
+
|
|
139
|
+
obj_grad = self.__objective.CalculateStandardizedGradient()
|
|
140
|
+
|
|
141
|
+
self.ComputeSearchDirection(obj_grad)
|
|
142
|
+
|
|
143
|
+
alpha = self.__line_search_method.ComputeStep()
|
|
144
|
+
|
|
145
|
+
self.ComputeControlUpdate(alpha)
|
|
146
|
+
|
|
147
|
+
self._FinalizeIteration()
|
|
148
|
+
|
|
149
|
+
self.converged = self._convergence_criteria.IsConverged()
|
|
150
|
+
|
|
151
|
+
self.Output()
|
|
152
|
+
|
|
153
|
+
self.UpdateControl()
|
|
154
|
+
|
|
155
|
+
ListLogger("Convergence info", self._convergence_criteria.GetInfo())
|
|
156
|
+
|
|
157
|
+
if not self.converged:
|
|
158
|
+
self._optimization_problem.AdvanceStep()
|
|
159
|
+
|
|
160
|
+
return self.converged
|
|
161
|
+
|
|
162
|
+
def GetOptimizedObjectiveValue(self) -> float:
|
|
163
|
+
if self.converged:
|
|
164
|
+
return self.__obj_val
|
|
165
|
+
else:
|
|
166
|
+
raise RuntimeError("Optimization problem hasn't been solved.")
|
|
167
|
+
|
|
168
|
+
def __CreateConvergenceCriteria(self, settings: Kratos.Parameters) -> ConvergenceCriterion:
|
|
169
|
+
default_settings = Kratos.Parameters("""{
|
|
170
|
+
"max_iter": 0,
|
|
171
|
+
"type" : "",
|
|
172
|
+
"module" : "KratosMultiphysics.OptimizationApplication.convergence_criteria",
|
|
173
|
+
"settings": {}
|
|
174
|
+
}""")
|
|
175
|
+
settings.AddMissingParameters(default_settings)
|
|
176
|
+
|
|
177
|
+
max_iter_params = Kratos.Parameters("""{
|
|
178
|
+
"max_iter": """ + str(settings["max_iter"].GetInt()) + """
|
|
179
|
+
}""")
|
|
180
|
+
max_iter_conv_criteria = MaxIterConvCriterion(max_iter_params, self._optimization_problem)
|
|
181
|
+
if settings["type"].GetString() == "":
|
|
182
|
+
return max_iter_conv_criteria
|
|
183
|
+
else:
|
|
184
|
+
# create the additional convergence criterions given by the user
|
|
185
|
+
additional_conv_params = Kratos.Parameters("""{
|
|
186
|
+
"type" : "",
|
|
187
|
+
"module" : "",
|
|
188
|
+
"settings": {}
|
|
189
|
+
}""")
|
|
190
|
+
additional_conv_params["type"].SetString(settings["type"].GetString())
|
|
191
|
+
additional_conv_params["module"].SetString(settings["module"].GetString())
|
|
192
|
+
additional_conv_params["settings"] = settings["settings"]
|
|
193
|
+
additional_conv: ConvergenceCriterion = OptimizationComponentFactory(self.model, additional_conv_params, self._optimization_problem)
|
|
194
|
+
|
|
195
|
+
# now create the combined one and return the combined one
|
|
196
|
+
combined_params = Kratos.Parameters("""{
|
|
197
|
+
"operator": "or"
|
|
198
|
+
}""")
|
|
199
|
+
combined_conv_criteria = CombinedConvCriterion(self.model, combined_params, self._optimization_problem)
|
|
200
|
+
combined_conv_criteria.Add(max_iter_conv_criteria) # add the max iter conv criteria
|
|
201
|
+
combined_conv_criteria.Add(additional_conv) # add the additional conv criteria
|
|
202
|
+
return combined_conv_criteria
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import KratosMultiphysics as Kratos
|
|
2
|
+
import KratosMultiphysics.OptimizationApplication as KratosOA
|
|
3
|
+
from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
|
|
4
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_routine import ResponseRoutine
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.controls.master_control import MasterControl
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import DictLogger
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import TimeLogger
|
|
9
|
+
from KratosMultiphysics.OptimizationApplication.utilities.response_utilities import EvaluateResponseExpression
|
|
10
|
+
from KratosMultiphysics.kratos_utilities import IssueDeprecationWarning
|
|
11
|
+
import numpy
|
|
12
|
+
import sys
|
|
13
|
+
|
|
14
|
+
class StandardizedNLOPTConstraint(ResponseRoutine):
|
|
15
|
+
"""Standardized constraint response function
|
|
16
|
+
|
|
17
|
+
This class creates instances to standardize any response function for the specified type of the constraint.
|
|
18
|
+
Supported constraint types:
|
|
19
|
+
"=",
|
|
20
|
+
"<",
|
|
21
|
+
">"
|
|
22
|
+
|
|
23
|
+
The reference value for the constraint either can be the "initial_value" or a specified value.
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
def __init__(self, parameters: Kratos.Parameters, master_control: MasterControl, optimization_problem: OptimizationProblem, required_buffer_size: int = 2):
|
|
27
|
+
# backward compatibility
|
|
28
|
+
if parameters.Has("response_name"):
|
|
29
|
+
IssueDeprecationWarning(self.__class__.__name__, "\"response_name\" is deprecated. Please use \"response_expression\".")
|
|
30
|
+
parameters.AddString("response_expression", parameters["response_name"].GetString())
|
|
31
|
+
parameters.RemoveValue("response_name")
|
|
32
|
+
|
|
33
|
+
default_parameters = Kratos.Parameters("""{
|
|
34
|
+
"response_expression": "",
|
|
35
|
+
"type" : "",
|
|
36
|
+
"ref_value" : "initial_value"
|
|
37
|
+
}""")
|
|
38
|
+
|
|
39
|
+
response_name = str(parameters["response_name"].GetString())
|
|
40
|
+
if not parameters.Has("ref_value"):
|
|
41
|
+
raise RuntimeError(f"Constraint for response {response_name} requires reference value specified in ref_value")
|
|
42
|
+
|
|
43
|
+
if parameters.Has("ref_value") and parameters["ref_value"].IsDouble():
|
|
44
|
+
default_parameters["ref_value"].SetDouble(0.0)
|
|
45
|
+
|
|
46
|
+
parameters.ValidateAndAssignDefaults(default_parameters)
|
|
47
|
+
|
|
48
|
+
response = EvaluateResponseExpression(parameters["response_expression"].GetString(), optimization_problem)
|
|
49
|
+
|
|
50
|
+
super().__init__(master_control, response)
|
|
51
|
+
|
|
52
|
+
if required_buffer_size < 2:
|
|
53
|
+
raise RuntimeError(f"Standardized constraint requires 2 as minimum buffer size. [ response name = {self.GetReponse().GetName()} ]")
|
|
54
|
+
|
|
55
|
+
component_data_view = ComponentDataView(response, optimization_problem)
|
|
56
|
+
component_data_view.SetDataBuffer(required_buffer_size)
|
|
57
|
+
|
|
58
|
+
self.__optimization_problem = optimization_problem
|
|
59
|
+
self.__buffered_data = component_data_view.GetBufferedData()
|
|
60
|
+
self.__unbuffered_data = component_data_view.GetUnBufferedData()
|
|
61
|
+
|
|
62
|
+
if parameters["ref_value"].IsDouble():
|
|
63
|
+
self.__reference_value = parameters["ref_value"].GetDouble()
|
|
64
|
+
elif parameters["ref_value"].IsString() and parameters["ref_value"].GetString() == "initial_value":
|
|
65
|
+
self.__reference_value = None
|
|
66
|
+
else:
|
|
67
|
+
raise RuntimeError("Provided \"reference_type\" is not supported for constraint response functions. Followings are supported options: \n\tinitial_value\n\tfloat value")
|
|
68
|
+
|
|
69
|
+
self.__constraint_type = parameters["type"].GetString()
|
|
70
|
+
if self.__constraint_type in ["=", "<"]:
|
|
71
|
+
self.__scaling = 1.0
|
|
72
|
+
elif self.__constraint_type in [">"]:
|
|
73
|
+
self.__scaling = -1.0
|
|
74
|
+
if not self.__reference_value is None: self.__reference_value *= -1
|
|
75
|
+
else:
|
|
76
|
+
raise RuntimeError(f"Provided \"type\" = {self.__constraint_type} is not supported in constraint response functions. Followings are supported options: \n\t=\n\t<\n\t>")
|
|
77
|
+
|
|
78
|
+
self.__zero_threshold = sys.float_info.epsilon
|
|
79
|
+
|
|
80
|
+
def IsEqualityType(self) -> str:
|
|
81
|
+
return self.__constraint_type == "="
|
|
82
|
+
|
|
83
|
+
def GetReferenceValue(self) -> float:
|
|
84
|
+
if self.__reference_value is not None:
|
|
85
|
+
return self.__reference_value
|
|
86
|
+
else:
|
|
87
|
+
if self.__unbuffered_data.HasValue("initial_value"):
|
|
88
|
+
self.__reference_value = self.__unbuffered_data["initial_value"]
|
|
89
|
+
return self.__reference_value
|
|
90
|
+
else:
|
|
91
|
+
raise RuntimeError(f"Response value for {self.GetReponse().GetName()} is not calculated yet.")
|
|
92
|
+
|
|
93
|
+
def CalculateStandardizedValueAndGradients(self, control_field: numpy.ndarray, gradient_field: numpy.ndarray, save_value: bool = True) -> float:
|
|
94
|
+
|
|
95
|
+
with TimeLogger(f"StandardizedNLOPTConstraint::Calculate {self.GetReponse().GetName()} value", None, "Finished"):
|
|
96
|
+
|
|
97
|
+
# first update the master control
|
|
98
|
+
self.UpdateMasterControl(control_field)
|
|
99
|
+
|
|
100
|
+
# compute the value
|
|
101
|
+
response_value = self.GetReponse().CalculateValue()
|
|
102
|
+
|
|
103
|
+
if not self.__unbuffered_data.HasValue("initial_value"):
|
|
104
|
+
self.__unbuffered_data["initial_value"] = response_value
|
|
105
|
+
|
|
106
|
+
if self.__buffered_data.HasValue("value"): del self.__buffered_data["value"]
|
|
107
|
+
self.__buffered_data["value"] = response_value
|
|
108
|
+
|
|
109
|
+
# log values
|
|
110
|
+
if save_value:
|
|
111
|
+
self.LogValues()
|
|
112
|
+
|
|
113
|
+
# print the info
|
|
114
|
+
DictLogger("Constraint info",self.GetInfo())
|
|
115
|
+
|
|
116
|
+
if gradient_field.size > 0:
|
|
117
|
+
gradient_combined_tensor_adaptor = self.CalculateGradient()
|
|
118
|
+
gradient_field[:] = gradient_combined_tensor_adaptor.data.reshape(-1) * self.GetStandardizationFactor()
|
|
119
|
+
|
|
120
|
+
if save_value:
|
|
121
|
+
self.LogGradientFields(gradient_combined_tensor_adaptor)
|
|
122
|
+
|
|
123
|
+
return self.GetStandardizedValue()
|
|
124
|
+
|
|
125
|
+
def GetValue(self, step_index: int = 0) -> float:
|
|
126
|
+
return self.__buffered_data.GetValue("value", step_index)
|
|
127
|
+
|
|
128
|
+
def GetStandardizationFactor(self):
|
|
129
|
+
ref_value = self.GetReferenceValue()
|
|
130
|
+
standardization_factor = self.__scaling
|
|
131
|
+
if abs(ref_value) > self.__zero_threshold:
|
|
132
|
+
standardization_factor /= abs(ref_value)
|
|
133
|
+
return standardization_factor
|
|
134
|
+
|
|
135
|
+
def GetStandardizedValue(self, step_index: int = 0) -> float:
|
|
136
|
+
ref_value = self.GetReferenceValue()
|
|
137
|
+
standardized_response_value = self.GetValue(step_index) - ref_value
|
|
138
|
+
standardized_response_value *= self.GetStandardizationFactor()
|
|
139
|
+
return standardized_response_value
|
|
140
|
+
|
|
141
|
+
def GetAbsoluteViolation(self, step_index: int = 0) -> float:
|
|
142
|
+
ref_value = self.GetReferenceValue()
|
|
143
|
+
standardized_response_value = self.GetValue(step_index) - ref_value
|
|
144
|
+
standardization_factor = self.__scaling
|
|
145
|
+
if abs(ref_value) > self.__zero_threshold:
|
|
146
|
+
standardization_factor /= abs(ref_value)
|
|
147
|
+
standardization_factor *= 100
|
|
148
|
+
standardized_response_value *= standardization_factor
|
|
149
|
+
return standardized_response_value
|
|
150
|
+
|
|
151
|
+
def GetInfo(self) -> dict:
|
|
152
|
+
info = {
|
|
153
|
+
"name": self.GetReponse().GetName(),
|
|
154
|
+
"value": self.GetValue(),
|
|
155
|
+
"type": self.__constraint_type,
|
|
156
|
+
"ref_value": self.GetReferenceValue(),
|
|
157
|
+
"violation [%]": self.GetAbsoluteViolation()
|
|
158
|
+
}
|
|
159
|
+
return info
|
|
160
|
+
|
|
161
|
+
def LogValues(self) -> None:
|
|
162
|
+
if self.__buffered_data.HasValue("violation [%]"): del self.__buffered_data["violation [%]"]
|
|
163
|
+
self.__buffered_data["violation [%]"] = self.GetAbsoluteViolation()
|
|
164
|
+
|
|
165
|
+
def LogGradientFields(self, gradient_combined_tensor_adaptor: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor) -> None:
|
|
166
|
+
# save the physical gradients for post processing in unbuffered data container.
|
|
167
|
+
for physical_var, physical_gradient in self.GetRequiredPhysicalGradients().items():
|
|
168
|
+
variable_name = f"d{self.GetReponse().GetName()}_d{physical_var.Name()}"
|
|
169
|
+
for physical_gradient_ta in physical_gradient.GetTensorAdaptors():
|
|
170
|
+
if self.__unbuffered_data.HasValue(variable_name): del self.__unbuffered_data[variable_name]
|
|
171
|
+
# cloning is a cheap operation, it only moves underlying pointers
|
|
172
|
+
# does not create additional memory.
|
|
173
|
+
self.__unbuffered_data[variable_name] = physical_gradient_ta.Clone()
|
|
174
|
+
|
|
175
|
+
# save the filtered gradients for post processing in unbuffered data container.
|
|
176
|
+
for gradient_ta, control in zip(gradient_combined_tensor_adaptor.GetTensorAdaptors(), self.GetMasterControl().GetListOfControls()):
|
|
177
|
+
variable_name = f"d{self.GetReponse().GetName()}_d{control.GetName()}"
|
|
178
|
+
if self.__unbuffered_data.HasValue(variable_name): del self.__unbuffered_data[variable_name]
|
|
179
|
+
# cloning is a cheap operation, it only moves underlying pointers
|
|
180
|
+
# does not create additional memory.
|
|
181
|
+
self.__unbuffered_data[variable_name] = gradient_ta.Clone()
|
|
182
|
+
|
|
183
|
+
def UpdateMasterControl(self, new_control_field: numpy.ndarray) -> None:
|
|
184
|
+
master_control = self.GetMasterControl()
|
|
185
|
+
new_control_field_ta = master_control.GetEmptyField()
|
|
186
|
+
number_of_entities = []
|
|
187
|
+
shapes = []
|
|
188
|
+
for control in master_control.GetListOfControls():
|
|
189
|
+
number_of_entities.append(len(control.GetControlField().GetContainer()))
|
|
190
|
+
shapes.append(control.GetControlField().GetItemShape())
|
|
191
|
+
new_control_field_ta.data[:] = new_control_field
|
|
192
|
+
Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(new_control_field_ta, perform_store_data_recursively=False, copy=False).StoreData()
|
|
193
|
+
# now update the master control
|
|
194
|
+
master_control.Update(new_control_field_ta)
|