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
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
import KratosMultiphysics as Kratos
|
|
4
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import ResponseFunction
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.utilities.union_utilities import SupportedSensitivityFieldVariableTypes
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.utilities.model_part_utilities import ModelPartOperation
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
|
|
9
|
+
|
|
10
|
+
def Factory(model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem) -> ResponseFunction:
|
|
11
|
+
if not parameters.Has("name"):
|
|
12
|
+
raise RuntimeError(f"CombinedResponseFunction instantiation requires a \"name\" in parameters [ parameters = {parameters}].")
|
|
13
|
+
if not parameters.Has("settings"):
|
|
14
|
+
raise RuntimeError(f"CombinedResponseFunction instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
|
|
15
|
+
|
|
16
|
+
return CombinedResponseFunction(parameters["name"].GetString(), model, parameters["settings"], optimization_problem)
|
|
17
|
+
|
|
18
|
+
class CombinedResponseFunction(ResponseFunction):
|
|
19
|
+
"""Response function to combine multiple response functions.
|
|
20
|
+
|
|
21
|
+
This response function can combine multiple response functions to a single response function.
|
|
22
|
+
Following methods are used to combine the response values:
|
|
23
|
+
1. weighted sum - Weighted summation of responses list is used as the combined response function value.
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
def __init__(self, name: str, model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
|
|
27
|
+
super().__init__(name)
|
|
28
|
+
|
|
29
|
+
default_settings = Kratos.Parameters("""{
|
|
30
|
+
"combining_method" : "sum",
|
|
31
|
+
"combining_responses": [
|
|
32
|
+
{
|
|
33
|
+
"response_name" : "",
|
|
34
|
+
"response_weight": 0.0
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}""")
|
|
38
|
+
parameters.ValidateAndAssignDefaults(default_settings)
|
|
39
|
+
self.combining_method = parameters["combining_method"].GetString()
|
|
40
|
+
|
|
41
|
+
self.model = model
|
|
42
|
+
self.model_part: Optional[Kratos.ModelPart] = None
|
|
43
|
+
self.optimization_problem = optimization_problem
|
|
44
|
+
|
|
45
|
+
self.list_of_responses: 'list[tuple[ResponseFunction, float]]' = []
|
|
46
|
+
for response_params in parameters["combining_responses"].values():
|
|
47
|
+
response_params.ValidateAndAssignDefaults(default_settings["combining_responses"].values()[0])
|
|
48
|
+
response_name = response_params["response_name"].GetString()
|
|
49
|
+
|
|
50
|
+
if response_name not in [response.GetName() for response in optimization_problem.GetListOfResponses()]:
|
|
51
|
+
raise RuntimeError(f"\"{response_name}\" not found in the optimization problem. Please check whether this response is defined before the \"{self.GetName()}\".")
|
|
52
|
+
|
|
53
|
+
self.list_of_responses.append(
|
|
54
|
+
(
|
|
55
|
+
self.optimization_problem.GetResponse(response_name),
|
|
56
|
+
response_params["response_weight"].GetDouble()
|
|
57
|
+
))
|
|
58
|
+
|
|
59
|
+
if len(self.list_of_responses) == 0:
|
|
60
|
+
raise RuntimeError(f"Combined response \"{self.GetName()}\" does not have any responses to combine.")
|
|
61
|
+
|
|
62
|
+
def GetImplementedPhysicalKratosVariables(self) -> 'list[SupportedSensitivityFieldVariableTypes]':
|
|
63
|
+
variables_list: 'list[SupportedSensitivityFieldVariableTypes]' = []
|
|
64
|
+
for response, _ in self.list_of_responses:
|
|
65
|
+
variables_list.extend(response.GetImplementedPhysicalKratosVariables())
|
|
66
|
+
return list(set(variables_list))
|
|
67
|
+
|
|
68
|
+
def GetInfluencingModelPart(self) -> Kratos.ModelPart:
|
|
69
|
+
influencing_model_part_names = [response.GetInfluencingModelPart().FullName() for response, _ in self.list_of_responses]
|
|
70
|
+
model_part_operation = ModelPartOperation(self.model, ModelPartOperation.OperationType.UNION, f"response_{self.GetName()}", influencing_model_part_names, False)
|
|
71
|
+
self.model_part = model_part_operation.GetModelPart()
|
|
72
|
+
return self.model_part
|
|
73
|
+
|
|
74
|
+
def Initialize(self) -> None:
|
|
75
|
+
for response, _ in self.list_of_responses:
|
|
76
|
+
response.Initialize()
|
|
77
|
+
|
|
78
|
+
component_data_view = ComponentDataView(self, self.optimization_problem)
|
|
79
|
+
component_data_view.SetDataBuffer(1)
|
|
80
|
+
self.buffered_data = component_data_view.GetBufferedData()
|
|
81
|
+
self.unbuffered_data = component_data_view.GetUnBufferedData()
|
|
82
|
+
|
|
83
|
+
def Check(self) -> None:
|
|
84
|
+
for response, _ in self.list_of_responses:
|
|
85
|
+
response.Check()
|
|
86
|
+
|
|
87
|
+
def Finalize(self) -> None:
|
|
88
|
+
for response, _ in self.list_of_responses:
|
|
89
|
+
response.Finalize()
|
|
90
|
+
|
|
91
|
+
def CalculateValue(self) -> float:
|
|
92
|
+
if self.combining_method == "sum":
|
|
93
|
+
value = 0.0
|
|
94
|
+
for response, weight in self.list_of_responses:
|
|
95
|
+
response_value = response.CalculateValue()
|
|
96
|
+
value += response_value * weight
|
|
97
|
+
self.buffered_data.SetValue(f"{response.GetName()}", response_value, overwrite=True)
|
|
98
|
+
else:
|
|
99
|
+
raise RuntimeError(f"Unsupported combining_method = \"{self.combining_method}\". Followings are supported:\n\tsum")
|
|
100
|
+
return value
|
|
101
|
+
|
|
102
|
+
def CalculateGradient(self, physical_variable_gradient_map: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]') -> None:
|
|
103
|
+
# make everything zeros
|
|
104
|
+
for _, combined_tensor_adaptor in physical_variable_gradient_map.items():
|
|
105
|
+
combined_tensor_adaptor.data[:] = 0.0
|
|
106
|
+
Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(combined_tensor_adaptor, perform_store_data_recursively=False, copy=False).StoreData()
|
|
107
|
+
|
|
108
|
+
for response_function, weight in self.list_of_responses:
|
|
109
|
+
# get the map for the response function
|
|
110
|
+
sub_physical_variable_combined_tensor_adaptor: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]' = {}
|
|
111
|
+
for physical_variable, combined_tensor_adaptor in physical_variable_gradient_map.items():
|
|
112
|
+
if physical_variable in response_function.GetImplementedPhysicalKratosVariables():
|
|
113
|
+
sub_physical_variable_combined_tensor_adaptor[physical_variable] = combined_tensor_adaptor.Clone()
|
|
114
|
+
|
|
115
|
+
# calculate the gradients
|
|
116
|
+
response_function.CalculateGradient(sub_physical_variable_combined_tensor_adaptor)
|
|
117
|
+
|
|
118
|
+
# now aggregate the gradients
|
|
119
|
+
for physical_variable, local_combined_tensor_adaptor in sub_physical_variable_combined_tensor_adaptor.items():
|
|
120
|
+
self.unbuffered_data.SetValue(f"d{response_function.GetName()}_d{physical_variable.Name()}", local_combined_tensor_adaptor.Clone(), overwrite=True)
|
|
121
|
+
if self.combining_method == "sum":
|
|
122
|
+
physical_variable_gradient_map[physical_variable].data[:] += local_combined_tensor_adaptor.data[:] * weight
|
|
123
|
+
else:
|
|
124
|
+
raise RuntimeError(f"Unsupported combining_method = \"{self.combining_method}\". Followings are supported:\n\tsum")
|
|
125
|
+
|
|
126
|
+
for _, combined_tensor_adaptor in physical_variable_gradient_map.items():
|
|
127
|
+
Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(combined_tensor_adaptor, perform_store_data_recursively=False, copy=False).StoreData()
|
KratosMultiphysics/OptimizationApplication/responses/discrete_value_residual_response_function.py
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import numpy
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
import KratosMultiphysics as Kratos
|
|
5
|
+
import KratosMultiphysics.OptimizationApplication as KratosOA
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import ResponseFunction
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.utilities.union_utilities import SupportedSensitivityFieldVariableTypes
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.utilities.model_part_utilities import ModelPartOperation
|
|
9
|
+
|
|
10
|
+
def Factory(model: Kratos.Model, parameters: Kratos.Parameters, _) -> ResponseFunction:
|
|
11
|
+
if not parameters.Has("name"):
|
|
12
|
+
raise RuntimeError(f"DiscreteValueResidualResponseFunction instantiation requires a \"name\" in parameters [ parameters = {parameters}].")
|
|
13
|
+
if not parameters.Has("settings"):
|
|
14
|
+
raise RuntimeError(f"DiscreteValueResidualResponseFunction instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
|
|
15
|
+
|
|
16
|
+
return DiscreteValueResidualResponseFunction(parameters["name"].GetString(), model, parameters["settings"])
|
|
17
|
+
|
|
18
|
+
class DiscreteValueResidualResponseFunction(ResponseFunction):
|
|
19
|
+
def __init__(self, name: str, model: Kratos.Model, parameters: Kratos.Parameters):
|
|
20
|
+
super().__init__(name)
|
|
21
|
+
|
|
22
|
+
default_settings = Kratos.Parameters("""{
|
|
23
|
+
"evaluated_model_part_names" : [
|
|
24
|
+
"PLEASE_PROVIDE_A_MODEL_PART_NAME"
|
|
25
|
+
],
|
|
26
|
+
"container_type" : "node_historical",
|
|
27
|
+
"variable_name" : "",
|
|
28
|
+
"residual_type" : "exact",
|
|
29
|
+
"list_of_discrete_values": [0.0]
|
|
30
|
+
}""")
|
|
31
|
+
parameters.ValidateAndAssignDefaults(default_settings)
|
|
32
|
+
|
|
33
|
+
self.model = model
|
|
34
|
+
self.variable: SupportedSensitivityFieldVariableTypes = Kratos.KratosGlobals.GetVariable(parameters["variable_name"].GetString())
|
|
35
|
+
if not isinstance(self.variable, Kratos.DoubleVariable):
|
|
36
|
+
raise RuntimeError(f"Only supports double variables. Provided variable is \"{self.variable.Name()}\".")
|
|
37
|
+
|
|
38
|
+
self.list_of_discrete_values = parameters["list_of_discrete_values"].GetVector()
|
|
39
|
+
|
|
40
|
+
self.residual_type = parameters["residual_type"].GetString()
|
|
41
|
+
if self.residual_type not in ["exact", "logarithm"]:
|
|
42
|
+
raise RuntimeError(f"Unsupported residual_type = \"{self.residual_type}\" requested. Followings are supported:\n\texact\n\tlogarithm")
|
|
43
|
+
|
|
44
|
+
container_type = parameters["container_type"].GetString()
|
|
45
|
+
if container_type == "node_historical":
|
|
46
|
+
self.ta_getter = lambda model_part: Kratos.TensorAdaptors.HistoricalVariableTensorAdaptor(model_part.Nodes, self.variable)
|
|
47
|
+
elif container_type == "node_non_historical":
|
|
48
|
+
self.ta_getter = lambda model_part : Kratos.TensorAdaptors.VariableTensorAdaptor(model_part.Nodes, self.variable)
|
|
49
|
+
elif container_type == "condition":
|
|
50
|
+
self.ta_getter = lambda model_part : Kratos.TensorAdaptors.VariableTensorAdaptor(model_part.Conditions, self.variable)
|
|
51
|
+
elif container_type == "condition_properties":
|
|
52
|
+
self.ta_getter = lambda model_part : KratosOA.TensorAdaptors.PropertiesVariableTensorAdaptor(model_part.Conditions, self.variable)
|
|
53
|
+
elif container_type == "element":
|
|
54
|
+
self.ta_getter = lambda model_part : Kratos.TensorAdaptors.VariableTensorAdaptor(model_part.Elements, self.variable)
|
|
55
|
+
elif container_type == "element_properties":
|
|
56
|
+
self.ta_getter = lambda model_part : KratosOA.TensorAdaptors.PropertiesVariableTensorAdaptor(model_part.Elements, self.variable)
|
|
57
|
+
else:
|
|
58
|
+
raise RuntimeError(f"Unsupported container_type = \"{container_type}\" requested. Followings are supported:\n\tnode_historical\n\tnode_non_historical\n\tcondition\n\tcondition_properties\n\telement\n\telement_properties")
|
|
59
|
+
|
|
60
|
+
evaluated_model_part_names = parameters["evaluated_model_part_names"].GetStringArray()
|
|
61
|
+
if len(evaluated_model_part_names) == 0:
|
|
62
|
+
raise RuntimeError(f"No model parts were provided for DiscreteValueResidualResponseFunction. [ response name = \"{self.GetName()}\"]")
|
|
63
|
+
|
|
64
|
+
self.model_part_operation = ModelPartOperation(self.model, ModelPartOperation.OperationType.UNION, f"response_{self.GetName()}", evaluated_model_part_names, False)
|
|
65
|
+
self.model_part: Optional[Kratos.ModelPart] = None
|
|
66
|
+
|
|
67
|
+
def GetImplementedPhysicalKratosVariables(self) -> 'list[SupportedSensitivityFieldVariableTypes]':
|
|
68
|
+
return [self.variable]
|
|
69
|
+
|
|
70
|
+
def GetInfluencingModelPart(self) -> Kratos.ModelPart:
|
|
71
|
+
if self.model_part is None:
|
|
72
|
+
raise RuntimeError("Please call DiscreteValueResidualResponseFunction::Initialize first.")
|
|
73
|
+
return self.model_part
|
|
74
|
+
|
|
75
|
+
def Initialize(self) -> None:
|
|
76
|
+
self.model_part = self.model_part_operation.GetModelPart()
|
|
77
|
+
|
|
78
|
+
def Check(self) -> None:
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
def Finalize(self) -> None:
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
def CalculateValue(self) -> float:
|
|
85
|
+
ta = self.ta_getter(self.model_part)
|
|
86
|
+
ta.CollectData()
|
|
87
|
+
|
|
88
|
+
resultant = Kratos.TensorAdaptors.DoubleTensorAdaptor(ta)
|
|
89
|
+
|
|
90
|
+
if self.residual_type == "exact":
|
|
91
|
+
resultant.data[:] = 1.0
|
|
92
|
+
elif self.residual_type == "logarithm":
|
|
93
|
+
resultant.data[:] = 0.0
|
|
94
|
+
|
|
95
|
+
for value in self.list_of_discrete_values:
|
|
96
|
+
if self.residual_type == "exact":
|
|
97
|
+
resultant.data[:] *= (ta.data[:] - value) ** 2
|
|
98
|
+
elif self.residual_type == "logarithm":
|
|
99
|
+
resultant.data[:] += numpy.log((ta.data[:] - value) ** 2)
|
|
100
|
+
|
|
101
|
+
return numpy.sum(resultant.data)
|
|
102
|
+
|
|
103
|
+
def CalculateGradient(self, physical_variable_gradient_map: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]') -> None:
|
|
104
|
+
values = self.ta_getter(self.model_part)
|
|
105
|
+
values.CollectData()
|
|
106
|
+
|
|
107
|
+
# calculate the gradients
|
|
108
|
+
for physical_variable, cta in physical_variable_gradient_map.items():
|
|
109
|
+
if physical_variable == self.variable:
|
|
110
|
+
|
|
111
|
+
# initialize the current tensor adaptor
|
|
112
|
+
for ta in cta.GetTensorAdaptors():
|
|
113
|
+
ta.data[:] = 0.0
|
|
114
|
+
|
|
115
|
+
for ta in cta.GetTensorAdaptors():
|
|
116
|
+
for i, value_i in enumerate(self.list_of_discrete_values):
|
|
117
|
+
if self.residual_type == "exact":
|
|
118
|
+
partial_gradient_ta = Kratos.TensorAdaptors.DoubleTensorAdaptor(ta)
|
|
119
|
+
partial_gradient_ta.data[:] = 1.0
|
|
120
|
+
for j, value_j in enumerate(self.list_of_discrete_values):
|
|
121
|
+
if i == j:
|
|
122
|
+
partial_gradient_ta.data *= (values.data[:] - value_j) * 2.0
|
|
123
|
+
else:
|
|
124
|
+
partial_gradient_ta.data *= (values.data[:] - value_j) ** 2
|
|
125
|
+
ta.data[:] += partial_gradient_ta.data
|
|
126
|
+
elif self.residual_type == "logarithm":
|
|
127
|
+
ta.data[:] += (((values.data - value_i) ** (-2)) * (values.data - value_i) * 2.0)
|
|
128
|
+
|
|
129
|
+
Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(cta, perform_collect_data_recursively=False, copy=False).CollectData()
|
|
130
|
+
else:
|
|
131
|
+
raise RuntimeError(f"Unsupported sensitivity w.r.t. {physical_variable.Name()} requested. Followings are supported sensitivity variables:\n\t{self.variable.Name()}")
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import KratosMultiphysics as Kratos
|
|
2
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import ResponseFunction
|
|
3
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import SupportedSensitivityFieldVariableTypes
|
|
4
|
+
from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.utilities.buffered_dict import BufferedDict
|
|
7
|
+
|
|
8
|
+
class EvaluationResponseFunction(ResponseFunction):
|
|
9
|
+
def __init__(self, response_function: ResponseFunction, optimization_problem: OptimizationProblem):
|
|
10
|
+
super().__init__(f"Eval_{response_function.GetName()}")
|
|
11
|
+
self.response_function = response_function
|
|
12
|
+
self.optimization_problem = optimization_problem
|
|
13
|
+
|
|
14
|
+
def GetImplementedPhysicalKratosVariables(self) -> 'list[SupportedSensitivityFieldVariableTypes]':
|
|
15
|
+
return self.response_function.GetImplementedPhysicalKratosVariables()
|
|
16
|
+
|
|
17
|
+
def Initialize(self) -> None:
|
|
18
|
+
self.response_function.Initialize()
|
|
19
|
+
if not ComponentDataView("evaluated_responses", self.optimization_problem).HasDataBuffer():
|
|
20
|
+
ComponentDataView("evaluated_responses", self.optimization_problem).SetDataBuffer(1)
|
|
21
|
+
|
|
22
|
+
def Check(self) -> None:
|
|
23
|
+
self.response_function.Check()
|
|
24
|
+
|
|
25
|
+
def Finalize(self) -> None:
|
|
26
|
+
self.response_function.Finalize()
|
|
27
|
+
|
|
28
|
+
def GetInfluencingModelPart(self) -> Kratos.ModelPart:
|
|
29
|
+
return self.response_function.GetInfluencingModelPart()
|
|
30
|
+
|
|
31
|
+
def CalculateValue(self) -> float:
|
|
32
|
+
# this response is used at the top most level of the evaluated chained responses.
|
|
33
|
+
# so this creates a new data container under the optimization problem to avoid
|
|
34
|
+
# having to compute the same response value twice.
|
|
35
|
+
|
|
36
|
+
buffered_data = ComponentDataView("evaluated_responses", self.optimization_problem).GetBufferedData()
|
|
37
|
+
|
|
38
|
+
# reset data of the evaluation
|
|
39
|
+
self.__ResetEvaluationData(self, buffered_data, "values")
|
|
40
|
+
|
|
41
|
+
# now calculate
|
|
42
|
+
return self.response_function.CalculateValue()
|
|
43
|
+
|
|
44
|
+
def CalculateGradient(self, physical_variable_gradient_map: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]') -> None:
|
|
45
|
+
# this response is used at the top most level of the evaluated chained responses.
|
|
46
|
+
# so this creates a new data container under the optimization problem to avoid
|
|
47
|
+
# having to compute the same response gradient twice.
|
|
48
|
+
|
|
49
|
+
unbuffered_data = ComponentDataView("evaluated_responses", self.optimization_problem).GetUnBufferedData()
|
|
50
|
+
|
|
51
|
+
# reset data of the evaluation
|
|
52
|
+
self.__ResetEvaluationData(self, unbuffered_data, "gradients")
|
|
53
|
+
|
|
54
|
+
return self.response_function.CalculateGradient(physical_variable_gradient_map)
|
|
55
|
+
|
|
56
|
+
def GetChildResponses(self) -> 'list[ResponseFunction]':
|
|
57
|
+
return [self.response_function]
|
|
58
|
+
|
|
59
|
+
def __str__(self) -> str:
|
|
60
|
+
return f"Response [type = {self.__class__.__name__}, name = {self.GetName()}]"
|
|
61
|
+
|
|
62
|
+
@staticmethod
|
|
63
|
+
def __ResetEvaluationData(response_function: ResponseFunction, data: BufferedDict, prefix: str) -> None:
|
|
64
|
+
if data.HasValue(f"{prefix}/{response_function.GetName()}"):
|
|
65
|
+
del data[f"{prefix}/{response_function.GetName()}"]
|
|
66
|
+
for child_response in response_function.GetChildResponses():
|
|
67
|
+
# now reset the children
|
|
68
|
+
EvaluationResponseFunction.__ResetEvaluationData(child_response, data, prefix)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import numpy
|
|
2
|
+
from typing import Optional
|
|
3
|
+
import KratosMultiphysics as Kratos
|
|
4
|
+
import KratosMultiphysics.OptimizationApplication as KratosOA
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import ResponseFunction
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.utilities.model_part_utilities import ModelPartOperation
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.utilities.union_utilities import SupportedSensitivityFieldVariableTypes
|
|
9
|
+
|
|
10
|
+
def Factory(model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem) -> ResponseFunction:
|
|
11
|
+
if not parameters.Has("name"):
|
|
12
|
+
raise RuntimeError(f"ExternalResponseFunction instantiation requires a \"name\" in parameters [ parameters = {parameters}].")
|
|
13
|
+
if not parameters.Has("settings"):
|
|
14
|
+
raise RuntimeError(f"ExternalResponseFunction instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
|
|
15
|
+
|
|
16
|
+
return ExternalResponseFunction(parameters["name"].GetString(), model, parameters["settings"], optimization_problem)
|
|
17
|
+
|
|
18
|
+
class ExternalResponseFunction(ResponseFunction):
|
|
19
|
+
def __init__(self, response_name: str, model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem) -> None:
|
|
20
|
+
super().__init__(response_name)
|
|
21
|
+
|
|
22
|
+
default_parameters = Kratos.Parameters("""{
|
|
23
|
+
"evaluated_model_part_names": []
|
|
24
|
+
}""")
|
|
25
|
+
parameters.ValidateAndAssignDefaults(default_parameters)
|
|
26
|
+
|
|
27
|
+
self.model = model
|
|
28
|
+
self.optimization_problem = optimization_problem
|
|
29
|
+
|
|
30
|
+
evaluated_model_part_names = parameters["evaluated_model_part_names"].GetStringArray()
|
|
31
|
+
if len(evaluated_model_part_names) == 0:
|
|
32
|
+
raise RuntimeError(f"No model parts were provided for MassResponseFunction. [ response name = \"{self.GetName()}\"]")
|
|
33
|
+
self.model_part_operation = ModelPartOperation(self.model, ModelPartOperation.OperationType.UNION, f"response_{self.GetName()}", evaluated_model_part_names, False)
|
|
34
|
+
self.model_part: Optional[Kratos.ModelPart] = None
|
|
35
|
+
|
|
36
|
+
def Initialize(self) -> None:
|
|
37
|
+
self.model_part = self.model_part_operation.GetModelPart()
|
|
38
|
+
|
|
39
|
+
def Check(self) -> None:
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
def Finalize(self) -> None:
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
def GetImplementedPhysicalKratosVariables(self) -> 'list[SupportedSensitivityFieldVariableTypes]':
|
|
46
|
+
return [KratosOA.CUSTOM_DESIGN_VARIABLE]
|
|
47
|
+
|
|
48
|
+
def GetInfluencingModelPart(self) -> Kratos.ModelPart:
|
|
49
|
+
return self.model_part
|
|
50
|
+
|
|
51
|
+
def _GetDesignVariableValues(self) -> 'dict[str, numpy.ndarray]':
|
|
52
|
+
# get the values from the model part nodal non-historical container
|
|
53
|
+
result: 'dict[str, numpy.ndarray]' = {}
|
|
54
|
+
for mp_name in self.model_part_operation.list_of_operation_model_part_full_names:
|
|
55
|
+
ta = Kratos.TensorAdaptors.VariableTensorAdaptor(self.model[mp_name].Nodes, KratosOA.CUSTOM_DESIGN_VARIABLE)
|
|
56
|
+
ta.CollectData()
|
|
57
|
+
result[mp_name] = ta.data
|
|
58
|
+
|
|
59
|
+
return result
|
|
60
|
+
|
|
61
|
+
def _UpdateGradientsFromNumpy(self, numpy_values_map: 'dict[str, numpy.ndarray]', physical_variable_gradient_map: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]') -> None:
|
|
62
|
+
for i, mp_name in enumerate(self.model_part_operation.list_of_operation_model_part_full_names):
|
|
63
|
+
# assign the sensitivities to the physical_variable_gradient_map
|
|
64
|
+
physical_variable_gradient_map[KratosOA.CUSTOM_DESIGN_VARIABLE].GetTensorAdaptors()[i].data[:] = numpy_values_map[mp_name]
|
|
65
|
+
Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(physical_variable_gradient_map[KratosOA.CUSTOM_DESIGN_VARIABLE], perform_collect_data_recursively=False, copy=False).CollectData()
|
|
66
|
+
|
|
67
|
+
def CalculateValue(self) -> float:
|
|
68
|
+
numpy_values = self._GetDesignVariableValues()[self.model_part_operation.list_of_operation_model_part_full_names[0]]
|
|
69
|
+
|
|
70
|
+
# do the update of the model here with the new values.
|
|
71
|
+
# there after compute the new response value.
|
|
72
|
+
|
|
73
|
+
return float((numpy_values[0]-2) ** 2 + (numpy_values[1]-3) ** 2 + (numpy_values[2]-4) ** 2 + (numpy_values[3]-5))**2
|
|
74
|
+
|
|
75
|
+
def CalculateGradient(self, physical_variable_gradient_map: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]') -> None:
|
|
76
|
+
numpy_values = self._GetDesignVariableValues()[self.model_part_operation.list_of_operation_model_part_full_names[0]]
|
|
77
|
+
|
|
78
|
+
# compute the gradients
|
|
79
|
+
df_dx0 = 2 * (numpy_values[0]-2)
|
|
80
|
+
df_dx1 = 2 * (numpy_values[1]-3)
|
|
81
|
+
df_dx2 = 2 * (numpy_values[2]-4)
|
|
82
|
+
df_dx3 = 2 * (numpy_values[3]-5)
|
|
83
|
+
|
|
84
|
+
# create the numpy array of sensitivities
|
|
85
|
+
numpy_exp_map = {self.model_part_operation.list_of_operation_model_part_full_names[0]: numpy.array([df_dx0, df_dx1, df_dx2, df_dx3])}
|
|
86
|
+
|
|
87
|
+
self._UpdateGradientsFromNumpy(numpy_exp_map, physical_variable_gradient_map)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
import KratosMultiphysics as Kratos
|
|
4
|
+
import KratosMultiphysics.OptimizationApplication as KratosOA
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import ResponseFunction
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.utilities.union_utilities import SupportedSensitivityFieldVariableTypes
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.utilities.model_part_utilities import ModelPartOperation
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.utilities.model_part_utilities import ModelPartUtilities
|
|
9
|
+
|
|
10
|
+
def Factory(model: Kratos.Model, parameters: Kratos.Parameters, _) -> ResponseFunction:
|
|
11
|
+
if not parameters.Has("name"):
|
|
12
|
+
raise RuntimeError(f"GeometricCentroidDeviationResponseFunction instantiation requires a \"name\" in parameters [ parameters = {parameters}].")
|
|
13
|
+
if not parameters.Has("settings"):
|
|
14
|
+
raise RuntimeError(f"GeometricCentroidDeviationResponseFunction instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
|
|
15
|
+
|
|
16
|
+
return GeometricCentroidDeviationResponseFunction(parameters["name"].GetString(), model, parameters["settings"])
|
|
17
|
+
|
|
18
|
+
class GeometricCentroidDeviationResponseFunction(ResponseFunction):
|
|
19
|
+
def __init__(self, name: str, model: Kratos.Model, parameters: Kratos.Parameters):
|
|
20
|
+
super().__init__(name)
|
|
21
|
+
|
|
22
|
+
default_settings = Kratos.Parameters("""{
|
|
23
|
+
"evaluated_model_part_names" : [
|
|
24
|
+
"PLEASE_PROVIDE_A_MODEL_PART_NAME"
|
|
25
|
+
]
|
|
26
|
+
}""")
|
|
27
|
+
parameters.ValidateAndAssignDefaults(default_settings)
|
|
28
|
+
|
|
29
|
+
self.model = model
|
|
30
|
+
|
|
31
|
+
evaluated_model_part_names = parameters["evaluated_model_part_names"].GetStringArray()
|
|
32
|
+
if len(evaluated_model_part_names) == 0:
|
|
33
|
+
raise RuntimeError(f"No model parts were provided for GeometricCentroidDeviationResponseFunction. [ response name = \"{self.GetName()}\"]")
|
|
34
|
+
|
|
35
|
+
self.model_part_operation = ModelPartOperation(self.model, ModelPartOperation.OperationType.UNION, f"response_{self.GetName()}", evaluated_model_part_names, False)
|
|
36
|
+
self.model_part: Optional[Kratos.ModelPart] = None
|
|
37
|
+
|
|
38
|
+
def GetImplementedPhysicalKratosVariables(self) -> 'list[SupportedSensitivityFieldVariableTypes]':
|
|
39
|
+
return [KratosOA.SHAPE]
|
|
40
|
+
|
|
41
|
+
def GetInfluencingModelPart(self) -> Kratos.ModelPart:
|
|
42
|
+
if self.model_part is None:
|
|
43
|
+
raise RuntimeError("Please call GeometricCentroidDeviationResponseFunction::Initialize first.")
|
|
44
|
+
return self.model_part
|
|
45
|
+
|
|
46
|
+
def Initialize(self) -> None:
|
|
47
|
+
self.model_part = self.model_part_operation.GetModelPart()
|
|
48
|
+
|
|
49
|
+
self.model_part_center = Kratos.Array3(0.0)
|
|
50
|
+
number_of_nodes = self.model_part.GetCommunicator().GlobalNumberOfNodes()
|
|
51
|
+
|
|
52
|
+
if number_of_nodes == 0:
|
|
53
|
+
raise RuntimeError(f"The provided model part {self.model_part.FullName()} does not contain any nodes.")
|
|
54
|
+
|
|
55
|
+
for node in self.model_part.Nodes:
|
|
56
|
+
self.model_part_center[0] += node.X
|
|
57
|
+
self.model_part_center[1] += node.Y
|
|
58
|
+
self.model_part_center[2] += node.Z
|
|
59
|
+
|
|
60
|
+
self.model_part_center = self.model_part.GetCommunicator().GetDataCommunicator().SumAll(self.model_part_center)
|
|
61
|
+
self.model_part_center /= number_of_nodes
|
|
62
|
+
|
|
63
|
+
def Check(self) -> None:
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
def Finalize(self) -> None:
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
def CalculateValue(self) -> float:
|
|
70
|
+
average_location = Kratos.Array3(0.0)
|
|
71
|
+
for node in self.model_part.Nodes:
|
|
72
|
+
average_location[0] += node.X
|
|
73
|
+
average_location[1] += node.Y
|
|
74
|
+
average_location[2] += node.Z
|
|
75
|
+
|
|
76
|
+
average_location = self.model_part.GetCommunicator().GetDataCommunicator().SumAll(average_location)
|
|
77
|
+
|
|
78
|
+
number_of_nodes = self.model_part.GetCommunicator().GlobalNumberOfNodes()
|
|
79
|
+
self.value_array = (average_location / number_of_nodes - self.model_part_center)
|
|
80
|
+
return self.value_array[0] ** 2 + self.value_array[1] ** 2 + self.value_array[2] ** 2
|
|
81
|
+
|
|
82
|
+
def CalculateGradient(self, physical_variable_gradient_map: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]') -> None:
|
|
83
|
+
number_of_nodes = self.model_part.GetCommunicator().GlobalNumberOfNodes()
|
|
84
|
+
|
|
85
|
+
# calculate the gradients
|
|
86
|
+
for physical_variable, sensitivity_ta in physical_variable_gradient_map.items():
|
|
87
|
+
if physical_variable == KratosOA.SHAPE:
|
|
88
|
+
Kratos.VariableUtils().SetNonHistoricalVariableToZero(Kratos.SHAPE_SENSITIVITY, self.model_part.Nodes)
|
|
89
|
+
Kratos.VariableUtils().SetNonHistoricalVariable(Kratos.SHAPE_SENSITIVITY, 2.0 * self.value_array / number_of_nodes, self.model_part.Nodes)
|
|
90
|
+
for sub_sensitivity_ta in sensitivity_ta.GetTensorAdaptors():
|
|
91
|
+
if isinstance(sub_sensitivity_ta.GetContainer(), Kratos.NodesArray):
|
|
92
|
+
Kratos.TensorAdaptors.VariableTensorAdaptor(sub_sensitivity_ta, Kratos.SHAPE_SENSITIVITY, copy=False).CollectData()
|
|
93
|
+
else:
|
|
94
|
+
raise RuntimeError(f"Requesting sensitivity w.r.t. SHAPE for a non nodal tensor adaptor. [ Requested container tensor adaptor = {sub_sensitivity_ta} ].")
|
|
95
|
+
sensitivity_ta.CollectData()
|
|
96
|
+
else:
|
|
97
|
+
raise RuntimeError(f"Unsupported sensitivity w.r.t. {physical_variable.Name()} requested. Followings are supported sensitivity variables:\n\tSHAPE")
|
KratosMultiphysics/OptimizationApplication/responses/linear_strain_energy_response_function.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
import KratosMultiphysics as Kratos
|
|
4
|
+
import KratosMultiphysics.OptimizationApplication as KratosOA
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.execution_policies.execution_policy_decorator import ExecutionPolicyDecorator
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import ResponseFunction
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import SupportedSensitivityFieldVariableTypes
|
|
9
|
+
from KratosMultiphysics.OptimizationApplication.utilities.model_part_utilities import ModelPartOperation
|
|
10
|
+
|
|
11
|
+
def Factory(model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem) -> ResponseFunction:
|
|
12
|
+
if not parameters.Has("name"):
|
|
13
|
+
raise RuntimeError(f"LinearStrainEnergyResponseFunction instantiation requires a \"name\" in parameters [ parameters = {parameters}].")
|
|
14
|
+
if not parameters.Has("settings"):
|
|
15
|
+
raise RuntimeError(f"LinearStrainEnergyResponseFunction instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
|
|
16
|
+
|
|
17
|
+
return LinearStrainEnergyResponseFunction(parameters["name"].GetString(), model, parameters["settings"], optimization_problem)
|
|
18
|
+
|
|
19
|
+
class LinearStrainEnergyResponseFunction(ResponseFunction):
|
|
20
|
+
def __init__(self, name: str, model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
|
|
21
|
+
super().__init__(name)
|
|
22
|
+
|
|
23
|
+
default_settings = Kratos.Parameters("""{
|
|
24
|
+
"primal_analysis_name" : "",
|
|
25
|
+
"perturbation_size" : 1e-8,
|
|
26
|
+
"evaluated_model_part_names" : [
|
|
27
|
+
"PLEASE_PROVIDE_A_MODEL_PART_NAME"
|
|
28
|
+
]
|
|
29
|
+
}""")
|
|
30
|
+
parameters.ValidateAndAssignDefaults(default_settings)
|
|
31
|
+
|
|
32
|
+
self.perturbation_size = parameters["perturbation_size"].GetDouble()
|
|
33
|
+
self.model = model
|
|
34
|
+
self.primal_analysis_execution_policy_decorator: ExecutionPolicyDecorator = optimization_problem.GetExecutionPolicy(parameters["primal_analysis_name"].GetString())
|
|
35
|
+
|
|
36
|
+
evaluated_model_part_names = parameters["evaluated_model_part_names"].GetStringArray()
|
|
37
|
+
if len(evaluated_model_part_names) == 0:
|
|
38
|
+
raise RuntimeError(f"No model parts were provided for LinearStrainEnergyResponseFunction. [ response name = \"{self.GetName()}\"]")
|
|
39
|
+
|
|
40
|
+
self.model_part_operation = ModelPartOperation(self.model, ModelPartOperation.OperationType.UNION, f"response_{self.GetName()}", evaluated_model_part_names, False)
|
|
41
|
+
self.model_part: Optional[Kratos.ModelPart] = None
|
|
42
|
+
|
|
43
|
+
def GetImplementedPhysicalKratosVariables(self) -> 'list[SupportedSensitivityFieldVariableTypes]':
|
|
44
|
+
return [KratosOA.SHAPE, Kratos.YOUNG_MODULUS, Kratos.THICKNESS, Kratos.POISSON_RATIO]
|
|
45
|
+
|
|
46
|
+
def Initialize(self) -> None:
|
|
47
|
+
self.model_part = self.model_part_operation.GetModelPart()
|
|
48
|
+
|
|
49
|
+
def Check(self) -> None:
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
def Finalize(self) -> None:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
def GetInfluencingModelPart(self) -> Kratos.ModelPart:
|
|
56
|
+
return self.primal_analysis_execution_policy_decorator.GetAnalysisModelPart()
|
|
57
|
+
|
|
58
|
+
def CalculateValue(self) -> float:
|
|
59
|
+
self.primal_analysis_execution_policy_decorator.Execute()
|
|
60
|
+
return KratosOA.ResponseUtils.LinearStrainEnergyResponseUtils.CalculateValue(self.model_part)
|
|
61
|
+
|
|
62
|
+
def CalculateGradient(self, physical_variable_gradient_map: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]') -> None:
|
|
63
|
+
# calculate the gradients
|
|
64
|
+
for physical_variable, cta in physical_variable_gradient_map.items():
|
|
65
|
+
KratosOA.ResponseUtils.LinearStrainEnergyResponseUtils.CalculateGradient(
|
|
66
|
+
physical_variable,
|
|
67
|
+
self.GetInfluencingModelPart(),
|
|
68
|
+
cta,
|
|
69
|
+
self.perturbation_size)
|
|
70
|
+
|
|
71
|
+
def __str__(self) -> str:
|
|
72
|
+
return f"Response [type = {self.__class__.__name__}, name = {self.GetName()}, model part name = {self.model_part.FullName()}]"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import KratosMultiphysics as Kratos
|
|
2
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import ResponseFunction
|
|
3
|
+
from KratosMultiphysics.OptimizationApplication.utilities.union_utilities import SupportedSensitivityFieldVariableTypes
|
|
4
|
+
|
|
5
|
+
class LiteralValueResponseFunction(ResponseFunction):
|
|
6
|
+
def __init__(self, value: float):
|
|
7
|
+
super().__init__(str(value))
|
|
8
|
+
|
|
9
|
+
self.value = value
|
|
10
|
+
|
|
11
|
+
def GetImplementedPhysicalKratosVariables(self) -> 'list[SupportedSensitivityFieldVariableTypes]':
|
|
12
|
+
return []
|
|
13
|
+
|
|
14
|
+
def Initialize(self) -> None:
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
def Check(self) -> None:
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
def Finalize(self) -> None:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
def GetInfluencingModelPart(self) -> Kratos.ModelPart:
|
|
24
|
+
raise RuntimeError(f"The literal value response function does not have an influencing model part.")
|
|
25
|
+
|
|
26
|
+
def CalculateValue(self) -> float:
|
|
27
|
+
return self.value
|
|
28
|
+
|
|
29
|
+
def CalculateGradient(self, _: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]') -> None:
|
|
30
|
+
raise RuntimeError(f"The literal value response function does not depend on any variable, hence no gradients.")
|
|
31
|
+
|
|
32
|
+
def __str__(self) -> str:
|
|
33
|
+
return f"Response [type = {self.__class__.__name__}, name = {self.GetName()}]"
|