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,191 @@
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.helper_utilities import CallOnAll
10
+ from KratosMultiphysics.OptimizationApplication.utilities.response_utilities import EvaluateResponseExpression
11
+ from KratosMultiphysics.kratos_utilities import IssueDeprecationWarning
12
+ import numpy
13
+ import datetime
14
+
15
+ class StandardizedNLOPTObjective(ResponseRoutine):
16
+ """Standardized objective response function
17
+
18
+ This class transformed a user-given optimization problem into the standard format.
19
+ Supported objective types:
20
+ "minimization",
21
+ "maximization"
22
+
23
+ """
24
+ def __init__(self, parameters: Kratos.Parameters, master_control: MasterControl, optimization_problem: OptimizationProblem, required_buffer_size: int = 2):
25
+ # backward compatibility
26
+ if parameters.Has("response_name"):
27
+ IssueDeprecationWarning(self.__class__.__name__, "\"response_name\" is deprecated. Please use \"response_expression\".")
28
+ parameters.AddString("response_expression", parameters["response_name"].GetString())
29
+ parameters.RemoveValue("response_name")
30
+
31
+ default_parameters = Kratos.Parameters("""{
32
+ "response_expression": "",
33
+ "type" : "",
34
+ "scaling" : 1.0
35
+ }""")
36
+ parameters.ValidateAndAssignDefaults(default_parameters)
37
+
38
+ response = EvaluateResponseExpression(parameters["response_expression"].GetString(), optimization_problem)
39
+
40
+ super().__init__(master_control, response)
41
+
42
+ if required_buffer_size < 2:
43
+ raise RuntimeError(f"Standardized objective requires 2 as minimum buffer size. [ response name = {self.GetReponse().GetName()} ]")
44
+
45
+ component_data_view = ComponentDataView(response, optimization_problem)
46
+ component_data_view.SetDataBuffer(required_buffer_size)
47
+
48
+ self.__optimization_problem = optimization_problem
49
+ self.__buffered_data = component_data_view.GetBufferedData()
50
+ self.__unbuffered_data = component_data_view.GetUnBufferedData()
51
+
52
+ scaling = parameters["scaling"].GetDouble()
53
+ if scaling < 0.0:
54
+ raise RuntimeError(f"Scaling should be always positive [ given scale = {scaling}]")
55
+
56
+ self.__objective_type = parameters["type"].GetString()
57
+ if self.__objective_type == "minimization":
58
+ self.__scaling = scaling
59
+ elif self.__objective_type == "maximization":
60
+ self.__scaling = -scaling
61
+ else:
62
+ raise RuntimeError(f"Requesting unsupported type {self.__objective_type} for objective response function. Supported types are: \n\tminimization\n\tmaximization")
63
+
64
+ def GetInitialValue(self) -> float:
65
+ if self.__unbuffered_data.HasValue("initial_value"):
66
+ return self.__unbuffered_data["initial_value"] * self.__scaling
67
+ else:
68
+ raise RuntimeError(f"Response value for {self.GetReponse().GetName()} is not calculated yet.")
69
+
70
+ def CalculateStandardizedValueAndGradients(self, control_field: numpy.ndarray, gradient_field: numpy.ndarray, save_value: bool = True) -> float:
71
+ if self.UpdateMasterControlAndLogFields(control_field) or self.__optimization_problem.GetStep()==0:
72
+ with TimeLogger(f"CalculateStandardizedValueAndGradients {self.GetReponse().GetName()} value", None, "Finished"):
73
+
74
+ response_value = self.GetReponse().CalculateValue()
75
+
76
+ if not self.__unbuffered_data.HasValue("initial_value"):
77
+ self.__unbuffered_data["initial_value"] = response_value
78
+
79
+ if self.__buffered_data.HasValue("value"): del self.__buffered_data["value"]
80
+ self.__buffered_data["value"] = response_value
81
+
82
+ # log values
83
+ if save_value:
84
+ self.LogValues()
85
+
86
+ # print the info
87
+ DictLogger("Objective info",self.GetInfo())
88
+
89
+ # compute standardization factor
90
+ self.standardization_factor = self.__scaling
91
+ if abs(self.__unbuffered_data["initial_value"])>1e-15:
92
+ self.standardization_factor /= abs(self.__unbuffered_data["initial_value"])
93
+ self.standardized_response_value = self.standardization_factor * response_value
94
+
95
+ # compute gradients
96
+ if gradient_field.size > 0:
97
+ self.gradient_combined_tensor_adaptor = self.CalculateGradient()
98
+ # save gradients
99
+ if save_value:
100
+ self.LogGradientFields()
101
+
102
+ if gradient_field.size > 0:
103
+ gradient_field[:] = self.standardization_factor * self.gradient_combined_tensor_adaptor.data.reshape(-1)
104
+
105
+ return self.standardized_response_value
106
+
107
+ def GetValue(self, step_index: int = 0) -> float:
108
+ return self.__buffered_data.GetValue("value", step_index)
109
+
110
+ def GetStandardizedValue(self, step_index: int = 0) -> float:
111
+ return self.GetValue(step_index) * self.__scaling
112
+
113
+ def GetRelativeChange(self) -> float:
114
+ if self.__optimization_problem.GetStep() > 0:
115
+ return self.GetStandardizedValue() / self.GetStandardizedValue(1) - 1.0 if abs(self.GetStandardizedValue(1)) > 1e-12 else self.GetStandardizedValue()
116
+ else:
117
+ return 0.0
118
+
119
+ def GetAbsoluteChange(self) -> float:
120
+ if self.__optimization_problem.GetStep() > 0:
121
+ return self.GetStandardizedValue() / self.GetInitialValue() - 1.0 if abs(self.GetInitialValue()) > 1e-12 else self.GetStandardizedValue()
122
+ else:
123
+ return 0.0
124
+
125
+ def GetInfo(self) -> dict:
126
+ info = {
127
+ "name": self.GetReponse().GetName(),
128
+ "type": self.__objective_type,
129
+ "value": self.GetValue(),
130
+ "abs_change [%]": self.GetAbsoluteChange() * 100.0,
131
+ "rel_change [%]": self.GetRelativeChange() * 100.0
132
+ }
133
+ return info
134
+
135
+ def LogValues(self) -> None:
136
+ values_info = self.GetInfo()
137
+ if self.__buffered_data.HasValue("rel_change [%]"): del self.__buffered_data["rel_change [%]"]
138
+ self.__buffered_data["rel_change [%]"] = values_info["rel_change [%]"]
139
+ if self.__buffered_data.HasValue("abs_change [%]"): del self.__buffered_data["abs_change [%]"]
140
+ self.__buffered_data["abs_change [%]"] = values_info["abs_change [%]"]
141
+
142
+ def LogGradientFields(self) -> None:
143
+ # save the physical gradients for post processing in unbuffered data container.
144
+ for physical_var, physical_gradient in self.GetRequiredPhysicalGradients().items():
145
+ variable_name = f"d{self.GetReponse().GetName()}_d{physical_var.Name()}"
146
+ for physical_gradient_ta in physical_gradient.GetTensorAdaptors():
147
+ if self.__unbuffered_data.HasValue(variable_name): del self.__unbuffered_data[variable_name]
148
+ # cloning is a cheap operation, it only moves underlying pointers
149
+ # does not create additional memory.
150
+ self.__unbuffered_data[variable_name] = physical_gradient_ta.Clone()
151
+
152
+ # save the filtered gradients for post processing in unbuffered data container.
153
+ for gradient_ta, control in zip(self.gradient_combined_tensor_adaptor.GetTensorAdaptors(), self.GetMasterControl().GetListOfControls()):
154
+ variable_name = f"d{self.GetReponse().GetName()}_d{control.GetName()}"
155
+ if self.__unbuffered_data.HasValue(variable_name): del self.__unbuffered_data[variable_name]
156
+ # cloning is a cheap operation, it only moves underlying pointers
157
+ # does not create additional memory.
158
+ self.__unbuffered_data[variable_name] = gradient_ta.Clone()
159
+
160
+ def LogOptimizationStep(self) -> None:
161
+ now = datetime.datetime.now()
162
+ now_str = now.strftime("%Y-%m-%d %H:%M:%S")
163
+ iteration_text = f" EoF Iteration {self.__optimization_problem.GetStep()}"
164
+ iteration_output = f"{'#'} {iteration_text} [Time: {now_str}] {'#'}"
165
+ divided_line = len(iteration_output) * '#'
166
+ to_print = f"{divided_line}\n{iteration_output}\n{divided_line}\n"
167
+ Kratos.Logger.PrintInfo(to_print)
168
+
169
+ def UpdateMasterControlAndLogFields(self, new_control_field: numpy.ndarray) -> bool:
170
+ master_control_updated = False
171
+ master_control = self.GetMasterControl()
172
+ control_change_norm = numpy.linalg.norm(master_control.GetControlField().Evaluate().reshape(-1)-new_control_field)
173
+ if control_change_norm > 1e-15:
174
+ # first out put the fields and update step
175
+ CallOnAll(self.__optimization_problem.GetListOfProcesses("output_processes"), Kratos.OutputProcess.PrintOutput)
176
+ self.LogOptimizationStep()
177
+ self.__optimization_problem.AdvanceStep()
178
+ # convert numpy array to tensor adaptor
179
+ new_control_field_cta = master_control.GetEmptyField()
180
+ number_of_entities = []
181
+ shapes = []
182
+ for control in master_control.GetListOfControls():
183
+ number_of_entities.append(len(control.GetControlField().GetContainer()))
184
+ shapes.append(control.GetControlField().GetItemShape())
185
+
186
+ new_control_field_cta.data[:] = new_control_field
187
+ Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(new_control_field_cta, perform_store_data_recursively=False, copy=False).StoreData()
188
+ # now update the master control
189
+ master_control.Update(new_control_field_cta)
190
+ master_control_updated = True
191
+ return master_control_updated
@@ -0,0 +1,123 @@
1
+ import KratosMultiphysics as Kratos
2
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
3
+ from KratosMultiphysics.OptimizationApplication.responses.response_routine import ResponseRoutine
4
+ from KratosMultiphysics.OptimizationApplication.controls.master_control import MasterControl
5
+ from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
6
+ from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import DictLogger
7
+ from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import TimeLogger
8
+ from KratosMultiphysics.OptimizationApplication.utilities.response_utilities import EvaluateResponseExpression
9
+ from KratosMultiphysics.kratos_utilities import IssueDeprecationWarning
10
+ import numpy as np
11
+
12
+ class StandardizedSciPyConstraint(ResponseRoutine):
13
+ """Standardized SciPy constraint response function
14
+
15
+ This class creates instances to create constraint routine that SciPy is required to handle constraints.
16
+
17
+
18
+ """
19
+
20
+ def __init__(self, parameters: Kratos.Parameters, master_control: MasterControl, optimization_problem: OptimizationProblem, required_buffer_size: int = 2):
21
+ # backward compatibility
22
+ if parameters.Has("response_name"):
23
+ IssueDeprecationWarning(self.__class__.__name__, "\"response_name\" is deprecated. Please use \"response_expression\".")
24
+ parameters.AddString("response_expression", parameters["response_name"].GetString())
25
+ parameters.RemoveValue("response_name")
26
+
27
+ default_parameters = Kratos.Parameters("""{
28
+ "response_expression" : "",
29
+ "upper_boundary" : 1e16,
30
+ "lower_boundary" :-1e16
31
+ }""")
32
+
33
+ parameters.ValidateAndAssignDefaults(default_parameters)
34
+
35
+ response = EvaluateResponseExpression(parameters["response_expression"].GetString(), optimization_problem)
36
+
37
+ super().__init__(master_control, response)
38
+
39
+ if required_buffer_size < 2:
40
+ raise RuntimeError(f"Standardized objective requires 2 as minimum buffer size. [ response name = {self.GetResponseName()} ]")
41
+
42
+ component_data_view = ComponentDataView(response, optimization_problem)
43
+ component_data_view.SetDataBuffer(required_buffer_size)
44
+
45
+ self.__optimization_problem = optimization_problem
46
+ self.__buffered_data = component_data_view.GetBufferedData()
47
+ self.__unbuffered_data = component_data_view.GetUnBufferedData()
48
+
49
+ self.upper_bound = parameters["upper_boundary"].GetDouble()
50
+ self.lower_bound = parameters["lower_boundary"].GetDouble()
51
+
52
+ def CalculateStandardizedValue(self, x:np.array, save_data: bool = True) -> float:
53
+ control_field = self.GetMasterControl().GetEmptyField()
54
+ control_field.data[:] = x
55
+ Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(control_field, perform_store_data_recursively=False, copy=False).StoreData()
56
+
57
+ with TimeLogger(f"StandardizedObjective::Calculate {self.GetResponseName()} value", None, "Finished"):
58
+ response_value = self.CalculateValue(control_field)
59
+ standardized_response_value = response_value
60
+
61
+ if not self.__unbuffered_data.HasValue("initial_value"):
62
+ self.__unbuffered_data["initial_value"] = response_value
63
+
64
+ if save_data:
65
+ if self.__buffered_data.HasValue("value"): del self.__buffered_data["value"]
66
+ self.__buffered_data["value"] = response_value
67
+
68
+ DictLogger("Constraint info",self.GetInfo())
69
+
70
+ return standardized_response_value
71
+
72
+ def GetValue(self, step_index: int = 0) -> float:
73
+ return self.__buffered_data.GetValue("value", step_index)
74
+
75
+ def GetStandardizedValue(self, step_index: int = 0) -> float:
76
+ return self.GetValue(step_index)
77
+
78
+ def CalculateStandardizedGradient(self, x:np.array, save_field: bool = True) -> np.array:
79
+
80
+ self.CalculateStandardizedValue(x, False) # Compute new primal if x has changed. Does nothing if x the same.
81
+
82
+ with TimeLogger(f"StandardizedObjective::Calculate {self.GetResponseName()} gradients", None, "Finished"):
83
+ gradient_combined_tensor_adaptor = self.CalculateGradient()
84
+ if save_field:
85
+ # save the physical gradients for post processing in unbuffered data container.
86
+ for physical_var, physical_gradient in self.GetRequiredPhysicalGradients().items():
87
+ for physical_gradient_ta in physical_gradient.GetTensorAdaptors():
88
+ variable_name = f"d{self.GetResponseName()}_d{physical_var.Name()}"
89
+ if self.__unbuffered_data.HasValue(variable_name): del self.__unbuffered_data[variable_name]
90
+ # cloning is a cheap operation, it only moves underlying pointers
91
+ # does not create additional memory.
92
+ self.__unbuffered_data[variable_name] = physical_gradient_ta.Clone()
93
+
94
+ # save the filtered gradients for post processing in unbuffered data container.
95
+ for gradient_ta, control in zip(gradient_combined_tensor_adaptor.GetTensorAdaptors(), self.GetMasterControl().GetListOfControls()):
96
+ variable_name = f"d{self.GetResponseName()}_d{control.GetName()}"
97
+ if self.__unbuffered_data.HasValue(variable_name): del self.__unbuffered_data[variable_name]
98
+ # cloning is a cheap operation, it only moves underlying pointers
99
+ # does not create additional memory.
100
+ self.__unbuffered_data[variable_name] = gradient_ta.Clone()
101
+
102
+ return gradient_combined_tensor_adaptor.data.reshape(-1)
103
+
104
+ def GetValue(self, step_index: int = 0) -> float:
105
+ return self.__buffered_data.GetValue("value", step_index)
106
+
107
+ def GetStandardizedValue(self, step_index: int = 0) -> float:
108
+ return self.GetValue(step_index) - self.GetStandardizedReferenceValue()
109
+
110
+ def GetUpperBound(self):
111
+ return self.upper_bound
112
+
113
+ def GetLowerBound(self):
114
+ return self.lower_bound
115
+
116
+ def GetInfo(self) -> dict:
117
+ info = {
118
+ "name": self.GetResponseName(),
119
+ "value": self.GetValue(),
120
+ "upper_bound": self.upper_bound,
121
+ "lower_bound": self.lower_bound
122
+ }
123
+ return info
@@ -0,0 +1,148 @@
1
+ import KratosMultiphysics as Kratos
2
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
3
+ from KratosMultiphysics.OptimizationApplication.controls.master_control import MasterControl
4
+ from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
5
+ from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import DictLogger
6
+ from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import TimeLogger
7
+ from KratosMultiphysics.OptimizationApplication.utilities.response_utilities import EvaluateResponseExpression
8
+ from KratosMultiphysics.kratos_utilities import IssueDeprecationWarning
9
+ from KratosMultiphysics.OptimizationApplication.responses.response_routine import ResponseRoutine
10
+
11
+ import numpy as np
12
+
13
+ class StandardizedSciPyObjective(ResponseRoutine):
14
+ """Standardized SciPy objective response routine.
15
+
16
+ This class transformed a user-given optimization problem into the standard format.
17
+ Supported objective types:
18
+ "minimization",
19
+ "maximization"
20
+
21
+ """
22
+
23
+ def __init__(self, parameters: Kratos.Parameters, master_control: MasterControl, optimization_problem: OptimizationProblem, required_buffer_size: int = 2):
24
+ # backward compatibility
25
+ if parameters.Has("response_name"):
26
+ IssueDeprecationWarning(self.__class__.__name__, "\"response_name\" is deprecated. Please use \"response_expression\".")
27
+ parameters.AddString("response_expression", parameters["response_name"].GetString())
28
+ parameters.RemoveValue("response_name")
29
+
30
+ default_parameters = Kratos.Parameters("""{
31
+ "response_expression": "",
32
+ "type" : "",
33
+ "scaling" : 1.0
34
+ }""")
35
+ parameters.ValidateAndAssignDefaults(default_parameters)
36
+
37
+ response = EvaluateResponseExpression(parameters["response_expression"].GetString(), optimization_problem)
38
+
39
+ super().__init__(master_control, response)
40
+
41
+ if required_buffer_size < 2:
42
+ raise RuntimeError(f"Standardized objective requires 2 as minimum buffer size. [ response name = {self.GetResponseName()} ]")
43
+
44
+ component_data_view = ComponentDataView(response, optimization_problem)
45
+ component_data_view.SetDataBuffer(required_buffer_size)
46
+
47
+ self.__optimization_problem = optimization_problem
48
+ self.__buffered_data = component_data_view.GetBufferedData()
49
+ self.__unbuffered_data = component_data_view.GetUnBufferedData()
50
+
51
+ self.computed = False
52
+
53
+ scaling = parameters["scaling"].GetDouble()
54
+ if scaling < 0.0:
55
+ raise RuntimeError(f"Scaling should be always positive [ given scale = {scaling}]")
56
+
57
+ self.__objective_type = parameters["type"].GetString()
58
+ if self.__objective_type == "minimization":
59
+ self.__scaling = scaling
60
+ elif self.__objective_type == "maximization":
61
+ self.__scaling = -scaling
62
+ else:
63
+ raise RuntimeError(f"Requesting unsupported type {self.__objective_type} for objective response function. Supported types are: \n\tminimization\n\tmaximization")
64
+
65
+ def GetInitialValue(self) -> float:
66
+ if self.__unbuffered_data.HasValue("initial_value"):
67
+ return self.__unbuffered_data["initial_value"] * self.__scaling
68
+ else:
69
+ raise RuntimeError(f"Response value for {self.GetResponseName()} is not calculated yet.")
70
+
71
+ def CalculateStandardizedValue(self, x:np.array, save_data: bool = True) -> float:
72
+
73
+ control_field = self.GetMasterControl().GetEmptyField()
74
+ control_field.data[:] = x
75
+ Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(control_field, perform_store_data_recursively=False, copy=False).StoreData()
76
+
77
+ with TimeLogger(f"StandardizedObjective::Calculate {self.GetResponseName()} value", None, "Finished"):
78
+ response_value = self.CalculateValue(control_field)
79
+ standardized_response_value = response_value * self.__scaling
80
+
81
+ if not self.__unbuffered_data.HasValue("initial_value"):
82
+ self.__unbuffered_data["initial_value"] = response_value
83
+
84
+ if save_data:
85
+
86
+ if self.__buffered_data.HasValue("value"): del self.__buffered_data["value"]
87
+ self.__buffered_data["value"] = response_value
88
+ self.computed = True
89
+
90
+ DictLogger("Objective info",self.GetInfo())
91
+
92
+ return standardized_response_value
93
+
94
+ def GetValue(self, step_index: int = 0) -> float:
95
+ return self.__buffered_data.GetValue("value", step_index)
96
+
97
+ def GetStandardizedValue(self, step_index: int = 0) -> float:
98
+ return self.GetValue(step_index) * self.__scaling
99
+
100
+ def CalculateStandardizedGradient(self, x:np.array, save_field: bool = True) -> np.array:
101
+
102
+ self.CalculateStandardizedValue(x, False) # Compute new primal if x has changed. Does nothing if x the same
103
+
104
+ with TimeLogger(f"StandardizedObjective::Calculate {self.GetResponseName()} gradients", None, "Finished"):
105
+ gradient_combined_tensor_adaptor = self.CalculateGradient()
106
+ if save_field:
107
+ # save the physical gradients for post processing in unbuffered data container.
108
+ for physical_var, physical_gradient in self.GetRequiredPhysicalGradients().items():
109
+ for physical_gradient_ta in physical_gradient.GetTensorAdaptors():
110
+ variable_name = f"d{self.GetResponseName()}_d{physical_var.Name()}"
111
+ if self.__unbuffered_data.HasValue(variable_name): del self.__unbuffered_data[variable_name]
112
+ # cloning is a cheap operation, it only moves underlying pointers
113
+ # does not create additional memory.
114
+ self.__unbuffered_data[variable_name] = physical_gradient_ta.Clone()
115
+
116
+ # save the filtered gradients for post processing in unbuffered data container.
117
+ for gradient_ta, control in zip(gradient_combined_tensor_adaptor.GetTensorAdaptors(), self.GetMasterControl().GetListOfControls()):
118
+ variable_name = f"d{self.GetResponseName()}_d{control.GetName()}"
119
+ if self.__unbuffered_data.HasValue(variable_name): del self.__unbuffered_data[variable_name]
120
+ # cloning is a cheap operation, it only moves underlying pointers
121
+ # does not create additional memory.
122
+ self.__unbuffered_data[variable_name] = gradient_ta.Clone()
123
+
124
+ return gradient_combined_tensor_adaptor.data.reshape(-1) * self.__scaling
125
+
126
+ def GetRelativeChange(self) -> float:
127
+ if self.__optimization_problem.GetStep() > 0:
128
+ return self.GetStandardizedValue() / self.GetStandardizedValue(1) - 1.0 if abs(self.GetStandardizedValue(1)) > 1e-12 else self.GetStandardizedValue()
129
+ else:
130
+ return 0.0
131
+
132
+ def GetAbsoluteChange(self) -> float:
133
+ return self.GetValue() - self.GetInitialValue()
134
+
135
+ def GetInfo(self) -> dict:
136
+ info = {
137
+ "name": self.GetResponseName(),
138
+ "type": self.__objective_type,
139
+ "value": self.GetValue(),
140
+ "std_value": self.GetStandardizedValue(),
141
+ "abs_change": self.GetAbsoluteChange(),
142
+ "rel_change [%]": self.GetRelativeChange() * 100.0
143
+ }
144
+ init_value = self.GetInitialValue()
145
+ if init_value:
146
+ info["abs_change [%]"] = self.GetAbsoluteChange()/init_value * 100
147
+
148
+ return info
@@ -0,0 +1,180 @@
1
+ import KratosMultiphysics as Kratos
2
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
3
+ from KratosMultiphysics.OptimizationApplication.responses.response_routine import ResponseRoutine
4
+ from KratosMultiphysics.OptimizationApplication.controls.master_control import MasterControl
5
+ from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
6
+ from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import DictLogger
7
+ from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import TimeLogger
8
+ from KratosMultiphysics.OptimizationApplication.utilities.response_utilities import EvaluateResponseExpression
9
+ from KratosMultiphysics.kratos_utilities import IssueDeprecationWarning
10
+
11
+ class StandardizedConstraint(ResponseRoutine):
12
+ """Standardized constraint response function
13
+
14
+ This class creates instances to standardize any response function for the specified type of the constraint.
15
+ Supported constraint types:
16
+ "=",
17
+ "<",
18
+ "<=,
19
+ ">",
20
+ ">="
21
+
22
+ The reference value for the constraint either can be the "initial_value" or a specified value.
23
+
24
+ """
25
+ def __init__(self, parameters: Kratos.Parameters, master_control: MasterControl, optimization_problem: OptimizationProblem, required_buffer_size: int = 2):
26
+ # backward compatibility
27
+ if parameters.Has("response_name"):
28
+ IssueDeprecationWarning(self.__class__.__name__, "\"response_name\" is deprecated. Please use \"response_expression\".")
29
+ parameters.AddString("response_expression", parameters["response_name"].GetString())
30
+ parameters.RemoveValue("response_name")
31
+
32
+ default_parameters = Kratos.Parameters("""{
33
+ "response_expression" : "",
34
+ "type" : "",
35
+ "scaling" : 1.0,
36
+ "violation_scaling" : 1.0,
37
+ "scaled_ref_value" : "initial_value"
38
+ }""")
39
+
40
+ if parameters.Has("scaled_ref_value") and parameters["scaled_ref_value"].IsDouble():
41
+ default_parameters["scaled_ref_value"].SetDouble(0.0)
42
+
43
+ parameters.ValidateAndAssignDefaults(default_parameters)
44
+
45
+ response = EvaluateResponseExpression(parameters["response_expression"].GetString(), optimization_problem)
46
+
47
+ super().__init__(master_control, response)
48
+
49
+ if required_buffer_size < 2:
50
+ raise RuntimeError(f"Standardized objective requires 2 as minimum buffer size. [ response name = {self.GetResponseName()} ]")
51
+
52
+ component_data_view = ComponentDataView(response, optimization_problem)
53
+ component_data_view.SetDataBuffer(required_buffer_size)
54
+
55
+ self.__optimization_problem = optimization_problem
56
+ self.__buffered_data = component_data_view.GetBufferedData()
57
+ self.__unbuffered_data = component_data_view.GetUnBufferedData()
58
+
59
+ scaling = parameters["scaling"].GetDouble()
60
+ if scaling < 0.0:
61
+ raise RuntimeError(f"Scaling should be always positive [ given scale = {scaling}]")
62
+
63
+ if parameters["scaled_ref_value"].IsDouble():
64
+ self.__ref_type = "specified_value"
65
+ self.__reference_value = parameters["scaled_ref_value"].GetDouble()
66
+ elif parameters["scaled_ref_value"].IsString() and parameters["scaled_ref_value"].GetString() == "initial_value":
67
+ self.__ref_type = "initial_value"
68
+ self.__reference_value = None
69
+ else:
70
+ raise RuntimeError(f"Provided \"reference_type\" = {self.__ref_type} is not supported for constraint response functions. Followings are supported options: \n\tinitial_value\n\tfloat value")
71
+
72
+ self.__violation_scaling = parameters["violation_scaling"].GetDouble()
73
+ self.__constraint_type = parameters["type"].GetString()
74
+ if self.__constraint_type in ["<=", "="]:
75
+ self.__scaling = scaling
76
+ elif self.__constraint_type in [">="]:
77
+ self.__scaling = -scaling
78
+ if not self.__reference_value is None: self.__reference_value *= -1
79
+ else:
80
+ 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<\n\t>=\n\t>")
81
+
82
+ def IsEqualityType(self) -> str:
83
+ return self.__constraint_type == "="
84
+
85
+ def GetStandardizedReferenceValue(self) -> float:
86
+ if self.__reference_value is not None:
87
+ return self.__reference_value
88
+ else:
89
+ if self.__unbuffered_data.HasValue("initial_value"):
90
+ return self.__unbuffered_data["initial_value"] * self.__scaling
91
+ else:
92
+ raise RuntimeError(f"Response value for {self.GetResponseName()} is not calculated yet.")
93
+
94
+ def CalculateStandardizedValue(self, control_field: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor, save_value: bool = True) -> float:
95
+ with TimeLogger(f"StandardizedConstraint::Calculate {self.GetResponseName()} value", None, "Finished"):
96
+ response_value = self.CalculateValue(control_field)
97
+ standardized_response_value = response_value * self.__scaling
98
+
99
+ if not self.__unbuffered_data.HasValue("initial_value"):
100
+ self.__unbuffered_data["initial_value"] = response_value
101
+
102
+ standardized_response_value -= self.GetStandardizedReferenceValue()
103
+
104
+ if save_value:
105
+ if self.__buffered_data.HasValue("value"): del self.__buffered_data["value"]
106
+ if self.__buffered_data.HasValue("std_value"): del self.__buffered_data["std_value"]
107
+ self.__buffered_data["value"] = response_value
108
+ self.__buffered_data["std_value"] = standardized_response_value
109
+
110
+ DictLogger("Constraint info",self.GetInfo())
111
+
112
+ return standardized_response_value
113
+
114
+ def IsActive(self):
115
+ return self.GetStandardizedValue() > 0.0
116
+
117
+ def CalculateStandardizedGradient(self, save_field: bool = True) -> Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor:
118
+
119
+ with TimeLogger(f"StandardizedConstraint::Calculate {self.GetResponseName()} gradients", None, "Finished"):
120
+ gradient_cta = self.CalculateGradient()
121
+ if save_field:
122
+ # save the physical gradients for post processing in unbuffered data container.
123
+ for physical_var, physical_gradient in self.GetRequiredPhysicalGradients().items():
124
+ variable_name = f"d{self.GetResponseName()}_d{physical_var.Name()}"
125
+ if self.__unbuffered_data.HasValue(variable_name): del self.__unbuffered_data[variable_name]
126
+ # cloning is a cheap operation, it only moves underlying pointers
127
+ # does not create additional memory.
128
+ self.__unbuffered_data[variable_name] = Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(physical_gradient)
129
+
130
+ # save the filtered gradients for post processing in unbuffered data container.
131
+ for gradient_ta, control in zip(gradient_cta.GetTensorAdaptors(), self.GetMasterControl().GetListOfControls()):
132
+ variable_name = f"d{self.GetResponseName()}_d{control.GetName()}"
133
+ if self.__unbuffered_data.HasValue(variable_name): del self.__unbuffered_data[variable_name]
134
+ # cloning is a cheap operation, it only moves underlying pointers
135
+ # does not create additional memory.
136
+ self.__unbuffered_data[variable_name] = Kratos.TensorAdaptors.DoubleTensorAdaptor(gradient_ta)
137
+
138
+ gradient_cta.data[:] *= self.__scaling
139
+ Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(gradient_cta, perform_store_data_recursively=False, copy=False).StoreData()
140
+ return gradient_cta
141
+
142
+ def GetValue(self, step_index: int = 0) -> float:
143
+ return self.__buffered_data.GetValue("value", step_index)
144
+
145
+ def GetStandardizedValue(self, step_index: int = 0) -> float:
146
+ return self.GetValue(step_index) * self.__scaling - self.GetStandardizedReferenceValue()
147
+
148
+ def GetScaledViolationValue(self, step_index: int = 0) -> float:
149
+ value = self.GetStandardizedValue(step_index)
150
+ return max(0.0, value * self.__violation_scaling)
151
+
152
+ def GetAbsoluteViolation(self, step_index: int = 0) -> float:
153
+ is_violated = self.IsEqualityType() or self.GetStandardizedValue(step_index) >= 0.0
154
+ return self.GetStandardizedValue(step_index) * is_violated
155
+
156
+ def GetRelativeViolation(self, step_index: int = 0) -> float:
157
+ return self.GetAbsoluteViolation(step_index) / self.GetStandardizedReferenceValue() if abs(self.GetStandardizedReferenceValue()) > 1e-12 else self.GetAbsoluteViolation(step_index)
158
+
159
+ def GetRelativeChange(self) -> float:
160
+ if self.__optimization_problem.GetStep() > 1:
161
+ return self.GetStandardizedValue() / self.GetStandardizedValue(1) - 1.0 if abs(self.GetStandardizedValue(1)) > 1e-12 else self.GetStandardizedValue()
162
+ else:
163
+ return 0.0
164
+
165
+ def GetAbsoluteChange(self) -> float:
166
+ return self.GetStandardizedValue() / self.GetStandardizedReferenceValue() - 1.0 if abs(self.GetStandardizedReferenceValue()) > 1e-12 else self.GetStandardizedValue()
167
+
168
+ def GetInfo(self) -> dict:
169
+ info = {
170
+ "name": self.GetResponseName(),
171
+ "value": self.GetValue(),
172
+ "scaled_value": self.GetValue() * abs(self.__scaling),
173
+ "type": self.__constraint_type,
174
+ "ref_value": self.GetStandardizedReferenceValue(),
175
+ "abs_change": self.GetAbsoluteChange(),
176
+ "rel_change [%]": self.GetRelativeChange() * 100.0,
177
+ "abs_violation [%]": self.GetAbsoluteViolation() * 100,
178
+ "rel_violation [%]": self.GetRelativeViolation() * 100.0
179
+ }
180
+ return info