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.
Files changed (106) hide show
  1. KratosMultiphysics/.libs/KratosOptimizationApplication.so +0 -0
  2. KratosMultiphysics/.libs/libKratosOptimizationCore.dylib +0 -0
  3. KratosMultiphysics/OptimizationApplication/__init__.py +19 -0
  4. KratosMultiphysics/OptimizationApplication/algorithms/NLOPT_algorithms.py +255 -0
  5. KratosMultiphysics/OptimizationApplication/algorithms/SciPy_algorithms.py +154 -0
  6. KratosMultiphysics/OptimizationApplication/algorithms/__init__.py +0 -0
  7. KratosMultiphysics/OptimizationApplication/algorithms/algorithm.py +78 -0
  8. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_adam.py +68 -0
  9. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_base.py +393 -0
  10. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_gradient_projection.py +355 -0
  11. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_momentum_relaxed_gradient_projection.py +70 -0
  12. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_nesterov_accelarated_gradient.py +60 -0
  13. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_relaxed_gradient_projection.py +263 -0
  14. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_steepest_descent.py +205 -0
  15. KratosMultiphysics/OptimizationApplication/algorithms/standardized_NLOPT_constraint.py +194 -0
  16. KratosMultiphysics/OptimizationApplication/algorithms/standardized_NLOPT_objective.py +191 -0
  17. KratosMultiphysics/OptimizationApplication/algorithms/standardized_SciPy_constraint.py +123 -0
  18. KratosMultiphysics/OptimizationApplication/algorithms/standardized_SciPy_objective.py +148 -0
  19. KratosMultiphysics/OptimizationApplication/algorithms/standardized_constraint.py +180 -0
  20. KratosMultiphysics/OptimizationApplication/algorithms/standardized_objective.py +133 -0
  21. KratosMultiphysics/OptimizationApplication/algorithms/standardized_rgp_constraint.py +268 -0
  22. KratosMultiphysics/OptimizationApplication/analyses_controller.py +75 -0
  23. KratosMultiphysics/OptimizationApplication/controls/control.py +123 -0
  24. KratosMultiphysics/OptimizationApplication/controls/external_response_function_control.py +149 -0
  25. KratosMultiphysics/OptimizationApplication/controls/master_control.py +198 -0
  26. KratosMultiphysics/OptimizationApplication/controls/material/material_properties_control.py +115 -0
  27. KratosMultiphysics/OptimizationApplication/controls/material/simp_control.py +229 -0
  28. KratosMultiphysics/OptimizationApplication/controls/shape/vertex_morphing_shape_control.py +289 -0
  29. KratosMultiphysics/OptimizationApplication/controls/thickness/shell_thickness_control.py +180 -0
  30. KratosMultiphysics/OptimizationApplication/controls_controller.py +205 -0
  31. KratosMultiphysics/OptimizationApplication/convergence_criteria/avg_abs_improvement_conv_criterion.py +98 -0
  32. KratosMultiphysics/OptimizationApplication/convergence_criteria/combined_conv_criterion.py +87 -0
  33. KratosMultiphysics/OptimizationApplication/convergence_criteria/constraint_conv_criterion.py +68 -0
  34. KratosMultiphysics/OptimizationApplication/convergence_criteria/convergence_criterion.py +26 -0
  35. KratosMultiphysics/OptimizationApplication/convergence_criteria/l2_conv_criterion.py +77 -0
  36. KratosMultiphysics/OptimizationApplication/convergence_criteria/magnitude_reduction_conv_criterion.py +85 -0
  37. KratosMultiphysics/OptimizationApplication/convergence_criteria/max_iter_conv_criterion.py +48 -0
  38. KratosMultiphysics/OptimizationApplication/convergence_criteria/patience_conv_criterion.py +116 -0
  39. KratosMultiphysics/OptimizationApplication/convergence_criteria/target_value_conv_criterion.py +64 -0
  40. KratosMultiphysics/OptimizationApplication/execution_policies/execution_policy.py +46 -0
  41. KratosMultiphysics/OptimizationApplication/execution_policies/execution_policy_decorator.py +67 -0
  42. KratosMultiphysics/OptimizationApplication/execution_policies/independent_analysis_execution_policy.py +78 -0
  43. KratosMultiphysics/OptimizationApplication/execution_policies/kratos_analysis_execution_policy.py +137 -0
  44. KratosMultiphysics/OptimizationApplication/execution_policies/stepping_analysis_execution_policy.py +88 -0
  45. KratosMultiphysics/OptimizationApplication/filtering/explicit_filter.py +124 -0
  46. KratosMultiphysics/OptimizationApplication/filtering/filter.py +188 -0
  47. KratosMultiphysics/OptimizationApplication/filtering/filter_utils.py +55 -0
  48. KratosMultiphysics/OptimizationApplication/filtering/helmholtz_analysis.py +139 -0
  49. KratosMultiphysics/OptimizationApplication/filtering/helmholtz_scalar_solver.py +39 -0
  50. KratosMultiphysics/OptimizationApplication/filtering/helmholtz_shape_solver.py +67 -0
  51. KratosMultiphysics/OptimizationApplication/filtering/helmholtz_solver_base.py +275 -0
  52. KratosMultiphysics/OptimizationApplication/filtering/helmholtz_vector_solver.py +39 -0
  53. KratosMultiphysics/OptimizationApplication/filtering/implicit_filter.py +192 -0
  54. KratosMultiphysics/OptimizationApplication/filtering/python_solvers_wrapper_implicit_filters.py +56 -0
  55. KratosMultiphysics/OptimizationApplication/model_part_controllers/connectivity_preserving_model_part_controller.py +72 -0
  56. KratosMultiphysics/OptimizationApplication/model_part_controllers/external_response_function_model_part_controller.py +110 -0
  57. KratosMultiphysics/OptimizationApplication/model_part_controllers/mdpa_model_part_controller.py +44 -0
  58. KratosMultiphysics/OptimizationApplication/model_part_controllers/model_part_controller.py +19 -0
  59. KratosMultiphysics/OptimizationApplication/model_parts_controller.py +92 -0
  60. KratosMultiphysics/OptimizationApplication/optimization_analysis.py +146 -0
  61. KratosMultiphysics/OptimizationApplication/optimizations_controller.py +223 -0
  62. KratosMultiphysics/OptimizationApplication/optimizer.py +61 -0
  63. KratosMultiphysics/OptimizationApplication/processes/optimization_problem_ascii_output_process.py +212 -0
  64. KratosMultiphysics/OptimizationApplication/processes/optimization_problem_field_output_process.py +122 -0
  65. KratosMultiphysics/OptimizationApplication/processes/optimization_problem_graph_output_process.py +184 -0
  66. KratosMultiphysics/OptimizationApplication/processes/optimization_problem_hdf5_output_process.py +84 -0
  67. KratosMultiphysics/OptimizationApplication/processes/optimization_problem_vtu_output_process.py +94 -0
  68. KratosMultiphysics/OptimizationApplication/processes/spatial_statistics_computation_process.py +81 -0
  69. KratosMultiphysics/OptimizationApplication/responses/__init__.py +0 -0
  70. KratosMultiphysics/OptimizationApplication/responses/additive_manufacturing_responses.py +410 -0
  71. KratosMultiphysics/OptimizationApplication/responses/analysis_based_response_function_factory.py +14 -0
  72. KratosMultiphysics/OptimizationApplication/responses/analysis_free_response_function_factory.py +14 -0
  73. KratosMultiphysics/OptimizationApplication/responses/base_response.py +66 -0
  74. KratosMultiphysics/OptimizationApplication/responses/binary_operator_response_function.py +103 -0
  75. KratosMultiphysics/OptimizationApplication/responses/combined_response_function.py +127 -0
  76. KratosMultiphysics/OptimizationApplication/responses/discrete_value_residual_response_function.py +131 -0
  77. KratosMultiphysics/OptimizationApplication/responses/evaluation_response_function.py +68 -0
  78. KratosMultiphysics/OptimizationApplication/responses/external_response_function.py +87 -0
  79. KratosMultiphysics/OptimizationApplication/responses/geometric_centroid_deviation_response_function.py +97 -0
  80. KratosMultiphysics/OptimizationApplication/responses/linear_strain_energy_response_function.py +72 -0
  81. KratosMultiphysics/OptimizationApplication/responses/literal_value_response_function.py +33 -0
  82. KratosMultiphysics/OptimizationApplication/responses/log_response_function.py +47 -0
  83. KratosMultiphysics/OptimizationApplication/responses/mass_response_function.py +71 -0
  84. KratosMultiphysics/OptimizationApplication/responses/response_function.py +126 -0
  85. KratosMultiphysics/OptimizationApplication/responses/response_routine.py +158 -0
  86. KratosMultiphysics/OptimizationApplication/responses/structural_responses.py +335 -0
  87. KratosMultiphysics/OptimizationApplication/responses_controller.py +390 -0
  88. KratosMultiphysics/OptimizationApplication/utilities/buffered_dict.py +399 -0
  89. KratosMultiphysics/OptimizationApplication/utilities/component_data_view.py +74 -0
  90. KratosMultiphysics/OptimizationApplication/utilities/helper_utilities.py +40 -0
  91. KratosMultiphysics/OptimizationApplication/utilities/logger_utilities.py +222 -0
  92. KratosMultiphysics/OptimizationApplication/utilities/model_part_utilities.py +117 -0
  93. KratosMultiphysics/OptimizationApplication/utilities/opt_line_search.py +173 -0
  94. KratosMultiphysics/OptimizationApplication/utilities/opt_projection.py +191 -0
  95. KratosMultiphysics/OptimizationApplication/utilities/optimization_problem.py +237 -0
  96. KratosMultiphysics/OptimizationApplication/utilities/optimization_problem_utilities.py +237 -0
  97. KratosMultiphysics/OptimizationApplication/utilities/response_utilities.py +249 -0
  98. KratosMultiphysics/OptimizationApplication/utilities/timer.py +45 -0
  99. KratosMultiphysics/OptimizationApplication/utilities/union_utilities.py +6 -0
  100. kratosoptimizationapplication-10.4.4.dist-info/METADATA +25 -0
  101. kratosoptimizationapplication-10.4.4.dist-info/RECORD +106 -0
  102. kratosoptimizationapplication-10.4.4.dist-info/WHEEL +6 -0
  103. kratosoptimizationapplication.dylibs/libKratosCore.dylib +4 -0
  104. kratosoptimizationapplication.dylibs/libgcc_s.1.1.dylib +0 -0
  105. kratosoptimizationapplication.dylibs/libgomp.1.dylib +0 -0
  106. kratosoptimizationapplication.dylibs/libstdc++.6.dylib +0 -0
@@ -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)