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,191 @@
|
|
|
1
|
+
# Temporal fix until to avoid list[type] related errors until we move to 3.9 and above.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Optional
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
|
|
7
|
+
import KratosMultiphysics as Kratos
|
|
8
|
+
import KratosMultiphysics.OptimizationApplication as KratosOA
|
|
9
|
+
from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
|
|
10
|
+
|
|
11
|
+
class DesignVariableProjection(ABC):
|
|
12
|
+
"""Design variable projection methods to convert given x space values to given y space values
|
|
13
|
+
|
|
14
|
+
This is the interface class which can be used to implement design variable projection classes
|
|
15
|
+
which project forward and backward given x space values to y space.
|
|
16
|
+
|
|
17
|
+
The projection spaces should be scalar spaces.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
@abstractmethod
|
|
21
|
+
def SetProjectionSpaces(self, x_space_values: 'list[float]', y_space_values: 'list[float]') -> None:
|
|
22
|
+
"""Space values in x space and y space
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
x_space_values (list[float]): List of values to be used in x space
|
|
26
|
+
y_space_values (list[float]): List of values to be used in y space
|
|
27
|
+
"""
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def ProjectForward(self, x_values: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
32
|
+
"""Project x space values to y space
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
x_values (Kratos.TensorAdaptors.DoubleTensorAdaptor): x space values.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Kratos.TensorAdaptors.DoubleTensorAdaptor: y space values.
|
|
39
|
+
"""
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
@abstractmethod
|
|
43
|
+
def ProjectBackward(self, y_values: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
44
|
+
"""Project y space values to x space values
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
y_values (Kratos.TensorAdaptors.DoubleTensorAdaptor): y space values.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Kratos.TensorAdaptors.DoubleTensorAdaptor: x space values.
|
|
51
|
+
"""
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
@abstractmethod
|
|
55
|
+
def ForwardProjectionGradient(self, x_values: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
56
|
+
"""Computes the forward projected y space values' gradient w.r.t x space.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
x_values (Kratos.TensorAdaptors.DoubleTensorAdaptor): x space values.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Kratos.TensorAdaptors.DoubleTensorAdaptor: gradient of the y space values w.r.t. x space.
|
|
63
|
+
"""
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def Update(self) -> None:
|
|
68
|
+
"""Updates the projection method
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
class IdentityDesignVariableProjection(DesignVariableProjection):
|
|
72
|
+
def __init__(self, parameters: Kratos.Parameters, _):
|
|
73
|
+
default_settings = Kratos.Parameters("""{
|
|
74
|
+
"type" : "identity_projection"
|
|
75
|
+
}""")
|
|
76
|
+
parameters.ValidateAndAssignDefaults(default_settings)
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
def SetProjectionSpaces(self, _: 'list[float]', __: 'list[float]') -> None:
|
|
80
|
+
# not using any of the spaces provided.
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
def ProjectForward(self, x_values: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
84
|
+
# returns the x_values since x and y are the same for IdentityProjection
|
|
85
|
+
return Kratos.TensorAdaptors.DoubleTensorAdaptor(x_values)
|
|
86
|
+
|
|
87
|
+
def ProjectBackward(self, y_values: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
88
|
+
# return the y_values since x and y are the same for Identity projection
|
|
89
|
+
return Kratos.TensorAdaptors.DoubleTensorAdaptor(y_values)
|
|
90
|
+
|
|
91
|
+
def ForwardProjectionGradient(self, x_values: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
92
|
+
result = Kratos.TensorAdaptors.DoubleTensorAdaptor(x_values)
|
|
93
|
+
# x = y, hence the gradients are 1.0
|
|
94
|
+
result.data[:] = 1.0
|
|
95
|
+
return result
|
|
96
|
+
|
|
97
|
+
def Update(self) -> None:
|
|
98
|
+
pass
|
|
99
|
+
|
|
100
|
+
class SigmoidalDesignVariableProjection(DesignVariableProjection):
|
|
101
|
+
def __init__(self, parameters: Kratos.Parameters, _):
|
|
102
|
+
default_parameters = Kratos.Parameters("""{
|
|
103
|
+
"type" : "sigmoidal_projection",
|
|
104
|
+
"beta_value" : 5,
|
|
105
|
+
"penalty_factor": 1
|
|
106
|
+
}""")
|
|
107
|
+
|
|
108
|
+
parameters.ValidateAndAssignDefaults(default_parameters)
|
|
109
|
+
self.beta = parameters["beta_value"].GetDouble()
|
|
110
|
+
self.penalty_factor = parameters["penalty_factor"].GetInt()
|
|
111
|
+
|
|
112
|
+
self.x_space_values: 'Optional[list[float]]' = None
|
|
113
|
+
self.y_space_values: 'Optional[list[float]]' = None
|
|
114
|
+
|
|
115
|
+
def SetProjectionSpaces(self, x_space_values: 'list[float]', y_space_values: 'list[float]') -> None:
|
|
116
|
+
self.x_space_values = x_space_values
|
|
117
|
+
self.y_space_values = y_space_values
|
|
118
|
+
|
|
119
|
+
def ProjectForward(self, x_values: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
120
|
+
return KratosOA.ControlUtils.SigmoidalProjectionUtils.ProjectForward(x_values, self.x_space_values, self.y_space_values, self.beta, self.penalty_factor)
|
|
121
|
+
|
|
122
|
+
def ProjectBackward(self, y_values: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
123
|
+
return KratosOA.ControlUtils.SigmoidalProjectionUtils.ProjectBackward(y_values, self.x_space_values, self.y_space_values, self.beta, self.penalty_factor)
|
|
124
|
+
|
|
125
|
+
def ForwardProjectionGradient(self, x_values: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
126
|
+
return KratosOA.ControlUtils.SigmoidalProjectionUtils.CalculateForwardProjectionGradient(x_values, self.x_space_values, self.y_space_values, self.beta, self.penalty_factor)
|
|
127
|
+
|
|
128
|
+
def Update(self) -> None:
|
|
129
|
+
pass
|
|
130
|
+
|
|
131
|
+
class AdaptiveSigmoidalDesignVariableProjection(DesignVariableProjection):
|
|
132
|
+
def __init__(self, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
|
|
133
|
+
default_parameters = Kratos.Parameters("""{
|
|
134
|
+
"type" : "adaptive_sigmoidal_projection",
|
|
135
|
+
"initial_value" : 5,
|
|
136
|
+
"max_value" : 30,
|
|
137
|
+
"increase_fac" : 1.05,
|
|
138
|
+
"update_period" : 50,
|
|
139
|
+
"penalty_factor": 1
|
|
140
|
+
}""")
|
|
141
|
+
|
|
142
|
+
parameters.ValidateAndAssignDefaults(default_parameters)
|
|
143
|
+
self.beta = parameters["initial_value"].GetDouble()
|
|
144
|
+
self.max_beta = parameters["max_value"].GetDouble()
|
|
145
|
+
self.increase_fac = parameters["increase_fac"].GetDouble()
|
|
146
|
+
self.update_period = parameters["update_period"].GetInt()
|
|
147
|
+
self.penalty_factor = parameters["penalty_factor"].GetInt()
|
|
148
|
+
self.beta_computed_step = 1
|
|
149
|
+
|
|
150
|
+
self.x_space_values: 'Optional[list[float]]' = None
|
|
151
|
+
self.y_space_values: 'Optional[list[float]]' = None
|
|
152
|
+
|
|
153
|
+
self.optimization_problem = optimization_problem
|
|
154
|
+
|
|
155
|
+
def SetProjectionSpaces(self, x_space_values: 'list[float]', y_space_values: 'list[float]') -> None:
|
|
156
|
+
self.x_space_values = x_space_values
|
|
157
|
+
self.y_space_values = y_space_values
|
|
158
|
+
|
|
159
|
+
def ProjectForward(self, x_values: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
160
|
+
return KratosOA.ControlUtils.SigmoidalProjectionUtils.ProjectForward(x_values, self.x_space_values, self.y_space_values, self.beta, self.penalty_factor)
|
|
161
|
+
|
|
162
|
+
def ProjectBackward(self, y_values: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
163
|
+
return KratosOA.ControlUtils.SigmoidalProjectionUtils.ProjectBackward(y_values, self.x_space_values, self.y_space_values, self.beta, self.penalty_factor)
|
|
164
|
+
|
|
165
|
+
def ForwardProjectionGradient(self, x_values: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
166
|
+
return KratosOA.ControlUtils.SigmoidalProjectionUtils.CalculateForwardProjectionGradient(x_values, self.x_space_values, self.y_space_values, self.beta, self.penalty_factor)
|
|
167
|
+
|
|
168
|
+
def Update(self) -> None:
|
|
169
|
+
step = self.optimization_problem.GetStep()
|
|
170
|
+
if step % self.update_period == 0 and self.beta_computed_step != step:
|
|
171
|
+
self.beta_computed_step = step
|
|
172
|
+
self.beta = min(self.beta * self.increase_fac, self.max_beta)
|
|
173
|
+
Kratos.Logger.PrintInfo(self.__class__.__name__, f"Increased beta to {self.beta}.")
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def CreateProjection(parameters: Kratos.Parameters, optimization_problem: OptimizationProblem) -> DesignVariableProjection:
|
|
177
|
+
if not parameters.Has("type"):
|
|
178
|
+
raise RuntimeError("DesignVariableProjection \"type\" is not present in following parameters:\n" + str(parameters))
|
|
179
|
+
|
|
180
|
+
projection_type = parameters["type"].GetString()
|
|
181
|
+
|
|
182
|
+
projection_types_map: 'dict[str, type[DesignVariableProjection]]' = {
|
|
183
|
+
"identity_projection" : IdentityDesignVariableProjection,
|
|
184
|
+
"sigmoidal_projection" : SigmoidalDesignVariableProjection,
|
|
185
|
+
"adaptive_sigmoidal_projection": AdaptiveSigmoidalDesignVariableProjection
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if projection_type in projection_types_map.keys():
|
|
189
|
+
return projection_types_map[projection_type](parameters, optimization_problem)
|
|
190
|
+
else:
|
|
191
|
+
raise RuntimeError(f"Unsupported projected type = \"{projection_type}\" requested. Followings are supported:\n\t" + "\n\t".join(list(projection_types_map.keys())))
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import Any, Union
|
|
3
|
+
|
|
4
|
+
import KratosMultiphysics as Kratos
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.utilities.buffered_dict import BufferedDict
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.execution_policies.execution_policy import ExecutionPolicy
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.controls.master_control import MasterControl
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import ResponseFunction
|
|
9
|
+
from KratosMultiphysics.OptimizationApplication.controls.control import Control
|
|
10
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_routine import ResponseRoutine
|
|
11
|
+
|
|
12
|
+
class OptimizationProblem:
|
|
13
|
+
"""This is the main data holder for optimization problems
|
|
14
|
+
|
|
15
|
+
This class holds one private @ref BufferedDict container
|
|
16
|
+
which is used to hold components of the optimization problem being solved,
|
|
17
|
+
and the problem data generated while solving the optimization problem.
|
|
18
|
+
|
|
19
|
+
"""
|
|
20
|
+
def __init__(self, echo_level: int = 0) -> None:
|
|
21
|
+
"""Creates an instance of Optimization info
|
|
22
|
+
|
|
23
|
+
Creates an instance of optimization info with most basic structure
|
|
24
|
+
for the BufferedDict container and components container.
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
self.__echo_level = echo_level
|
|
28
|
+
|
|
29
|
+
# create the optimization components data container with basic types
|
|
30
|
+
self.__components: 'dict[Any, dict[str, Any]]' = {
|
|
31
|
+
ResponseFunction: {},
|
|
32
|
+
ExecutionPolicy: {},
|
|
33
|
+
Control: {},
|
|
34
|
+
MasterControl:{},
|
|
35
|
+
ResponseRoutine:{}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# now set the processes dict with different categories of processes
|
|
39
|
+
# such as initialization, output processes
|
|
40
|
+
self.__proceses: 'dict[str, list[Kratos.Process]]' = {}
|
|
41
|
+
|
|
42
|
+
# create the unbufferd optimization problem data container
|
|
43
|
+
self.__problem_data = BufferedDict(1)
|
|
44
|
+
|
|
45
|
+
# initialize the step
|
|
46
|
+
self.__problem_data["step"] = 0
|
|
47
|
+
|
|
48
|
+
def GetComponentType(self, component: Union[ExecutionPolicy, ResponseFunction, Control, MasterControl, ResponseRoutine]) -> Any:
|
|
49
|
+
for k in self.__components.keys():
|
|
50
|
+
if isinstance(component, k):
|
|
51
|
+
return k
|
|
52
|
+
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
def GetComponentName(self, component: Union[ExecutionPolicy, ResponseFunction, Control, MasterControl, ResponseRoutine]) -> str:
|
|
56
|
+
component_type = self.GetComponentType(component)
|
|
57
|
+
if not component_type is None:
|
|
58
|
+
components = self.__components[component_type]
|
|
59
|
+
else:
|
|
60
|
+
raise RuntimeError(f"Unsupported component type {component} provided.")
|
|
61
|
+
|
|
62
|
+
for comp_name, current_component in components.items():
|
|
63
|
+
if component == current_component:
|
|
64
|
+
return comp_name
|
|
65
|
+
|
|
66
|
+
raise RuntimeError(f"The given {component} not found in components of type {component_type}.")
|
|
67
|
+
|
|
68
|
+
def AddComponent(self, component: Union[ExecutionPolicy, ResponseFunction, Control, MasterControl, ResponseRoutine]) -> None:
|
|
69
|
+
for k, v in self.__components.items():
|
|
70
|
+
if isinstance(component, k):
|
|
71
|
+
added_component_type = k.__name__
|
|
72
|
+
v[component.GetName()] = component
|
|
73
|
+
break
|
|
74
|
+
|
|
75
|
+
if added_component_type is None:
|
|
76
|
+
raise RuntimeError(f"The given component is of not supported types. Supported types:\n\tKratos.Process\n\t" + "\n\t".join([k.__name__ for k in self.__components.keys()]))
|
|
77
|
+
else:
|
|
78
|
+
if self.__echo_level > 0:
|
|
79
|
+
Kratos.Logger.PrintInfo(self.__class__.__name__, f"Added \"{component.GetName()}\" to \"{added_component_type}\".")
|
|
80
|
+
|
|
81
|
+
def GetResponse(self, name: str) -> ResponseFunction:
|
|
82
|
+
return self.GetComponent(name, ResponseFunction)
|
|
83
|
+
|
|
84
|
+
def GetListOfResponses(self) -> 'list[ResponseFunction]':
|
|
85
|
+
return self.__components[ResponseFunction].values()
|
|
86
|
+
|
|
87
|
+
def HasResponse(self, name_or_response: 'Union[str, ResponseFunction]') -> bool:
|
|
88
|
+
if isinstance(name_or_response, str):
|
|
89
|
+
return name_or_response in [response_function.GetName() for response_function in self.GetListOfResponses()]
|
|
90
|
+
elif isinstance(name_or_response, ResponseFunction):
|
|
91
|
+
return name_or_response in self.GetListOfResponses()
|
|
92
|
+
else:
|
|
93
|
+
raise RuntimeError(f"Unsupported type provided for name_or_response. Only allowed to have string or ResponseFunction types.")
|
|
94
|
+
|
|
95
|
+
def RemoveResponse(self, name: str) -> None:
|
|
96
|
+
self.RemoveComponent(name, ResponseFunction)
|
|
97
|
+
|
|
98
|
+
def GetExecutionPolicy(self, name: str) -> ExecutionPolicy:
|
|
99
|
+
return self.GetComponent(name, ExecutionPolicy)
|
|
100
|
+
|
|
101
|
+
def GetListOfExecutionPolicies(self) -> 'list[ExecutionPolicy]':
|
|
102
|
+
return self.__components[ExecutionPolicy].values()
|
|
103
|
+
|
|
104
|
+
def HasExecutionPolicy(self, name_or_execution_policy: 'Union[str, ExecutionPolicy]') -> bool:
|
|
105
|
+
if isinstance(name_or_execution_policy, str):
|
|
106
|
+
return name_or_execution_policy in [execution_policy.GetName() for execution_policy in self.GetListOfExecutionPolicies()]
|
|
107
|
+
elif isinstance(name_or_execution_policy, ExecutionPolicy):
|
|
108
|
+
return name_or_execution_policy in self.GetListOfExecutionPolicies()
|
|
109
|
+
else:
|
|
110
|
+
raise RuntimeError(f"Unsupported type provided for name_or_execution_policy. Only allowed to have string or ExecutionPolicy types.")
|
|
111
|
+
|
|
112
|
+
def RemoveExecutionPolicy(self, name: str) -> None:
|
|
113
|
+
self.RemoveComponent(name, ExecutionPolicy)
|
|
114
|
+
|
|
115
|
+
def GetControl(self, name: str) -> Control:
|
|
116
|
+
return self.GetComponent(name, Control)
|
|
117
|
+
|
|
118
|
+
def GetListOfControls(self) -> 'list[Control]':
|
|
119
|
+
return self.__components[Control].values()
|
|
120
|
+
|
|
121
|
+
def HasControl(self, name_or_control: 'Union[str, Control]') -> bool:
|
|
122
|
+
if isinstance(name_or_control, str):
|
|
123
|
+
return name_or_control in [control.GetName() for control in self.GetListOfControls()]
|
|
124
|
+
elif isinstance(name_or_control, Control):
|
|
125
|
+
return name_or_control in self.GetListOfControls()
|
|
126
|
+
else:
|
|
127
|
+
raise RuntimeError(f"Unsupported type provided for name_or_control. Only allowed to have string or Control types.")
|
|
128
|
+
|
|
129
|
+
def RemoveControl(self, name: str) -> None:
|
|
130
|
+
self.RemoveComponent(name, Control)
|
|
131
|
+
|
|
132
|
+
def AddProcessType(self, process_type: str) -> None:
|
|
133
|
+
self.__proceses[process_type] = []
|
|
134
|
+
|
|
135
|
+
def GetResponseRoutine(self, name: str) -> ResponseRoutine:
|
|
136
|
+
return self.GetComponent(name, ResponseRoutine)
|
|
137
|
+
|
|
138
|
+
def GetListOfResponseRoutines(self) -> 'list[ResponseRoutine]':
|
|
139
|
+
return self.__components[ResponseRoutine].values()
|
|
140
|
+
|
|
141
|
+
def HasResponseRoutine(self, name_or_response_routine: 'Union[str, ResponseRoutine]') -> bool:
|
|
142
|
+
if isinstance(name_or_response_routine, str):
|
|
143
|
+
return name_or_response_routine in [response_routine.GetName() for response_routine in self.GetListOfResponseRoutines()]
|
|
144
|
+
elif isinstance(name_or_response_routine, ResponseRoutine):
|
|
145
|
+
return name_or_response_routine in self.GetListOfResponseRoutines()
|
|
146
|
+
else:
|
|
147
|
+
raise RuntimeError(f"Unsupported type provided for name_or_control. Only allowed to have string or Control types.")
|
|
148
|
+
|
|
149
|
+
def RemoveResponseRoutine(self, name: str) -> None:
|
|
150
|
+
self.RemoveComponent(name, ResponseRoutine)
|
|
151
|
+
|
|
152
|
+
def GetMasterControl(self, name: str) -> MasterControl:
|
|
153
|
+
return self.GetComponent(name, MasterControl)
|
|
154
|
+
|
|
155
|
+
def GetListOfMasterControls(self) -> 'list[MasterControl]':
|
|
156
|
+
return self.__components[MasterControl].values()
|
|
157
|
+
|
|
158
|
+
def HasMasterControl(self, name_or_master_control: 'Union[str, MasterControl]') -> bool:
|
|
159
|
+
if isinstance(name_or_master_control, str):
|
|
160
|
+
return name_or_master_control in [master_control.GetName() for master_control in self.GetListOfMasterControls()]
|
|
161
|
+
elif isinstance(name_or_master_control, MasterControl):
|
|
162
|
+
return name_or_master_control in self.GetListOfMasterControls()
|
|
163
|
+
else:
|
|
164
|
+
raise RuntimeError(f"Unsupported type provided for name_or_control. Only allowed to have string or Control types.")
|
|
165
|
+
|
|
166
|
+
def RemoveMasterControl(self, name: str) -> None:
|
|
167
|
+
self.RemoveComponent(name, MasterControl)
|
|
168
|
+
|
|
169
|
+
def AddProcess(self, process_type: str, process: Kratos.Process) -> None:
|
|
170
|
+
if process_type not in self.__proceses.keys():
|
|
171
|
+
self.__proceses[process_type]: 'list[Kratos.Process]' = []
|
|
172
|
+
|
|
173
|
+
if not isinstance(process, Kratos.Process):
|
|
174
|
+
raise RuntimeError(f"The provided process is not of type Kratos.Process. [ process = {process}]")
|
|
175
|
+
|
|
176
|
+
if self.__echo_level > 0:
|
|
177
|
+
Kratos.Logger.PrintInfo(self.__class__.__name__, f"Added \"{process.__class__.__name__}\" to \"{process_type}\".")
|
|
178
|
+
self.__proceses[process_type].append(process)
|
|
179
|
+
|
|
180
|
+
def GetAvailableProcessTypes(self) -> 'list[str]':
|
|
181
|
+
return self.__proceses.keys()
|
|
182
|
+
|
|
183
|
+
def GetListOfProcesses(self, process_type: str) -> 'list[Kratos.Process]':
|
|
184
|
+
if process_type not in self.__proceses.keys():
|
|
185
|
+
raise RuntimeError(f"The process type = \"{process_type}\" not found. Followings are available process types:\n\t" + "\n\t".join([k for k in self.__proceses.keys()]))
|
|
186
|
+
|
|
187
|
+
return self.__proceses[process_type]
|
|
188
|
+
|
|
189
|
+
def GetStep(self) -> int:
|
|
190
|
+
"""Gets the current step of the optimization info
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
int: Current step of the optimization info.
|
|
194
|
+
"""
|
|
195
|
+
return self.__problem_data["step"]
|
|
196
|
+
|
|
197
|
+
def AdvanceStep(self) -> None:
|
|
198
|
+
"""Advances the problem data by one step.
|
|
199
|
+
|
|
200
|
+
This method advances problem data by one step and
|
|
201
|
+
clears all the data in the advanced step.
|
|
202
|
+
|
|
203
|
+
"""
|
|
204
|
+
current_step = self.__problem_data["step"]
|
|
205
|
+
self.__problem_data.AdvanceStep()
|
|
206
|
+
self.__problem_data["step"] = current_step + 1
|
|
207
|
+
|
|
208
|
+
def GetProblemDataContainer(self) -> BufferedDict:
|
|
209
|
+
"""Gets the global problem data container.
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
BufferedDict: Global problem data container.
|
|
213
|
+
"""
|
|
214
|
+
return self.__problem_data
|
|
215
|
+
|
|
216
|
+
def GetComponentContainer(self) -> 'dict[Any, dict[str, Any]]':
|
|
217
|
+
return self.__components
|
|
218
|
+
|
|
219
|
+
def GetComponent(self, name: str, component_type: Any) -> Any:
|
|
220
|
+
if component_type not in self.__components.keys():
|
|
221
|
+
raise RuntimeError(f"Unsupported component type requested from GetComponent. [ requested component type = \"{component_type}\" ]. Followings are supported component types:\n\t" + "\n\t".join([component_type.__name__ for component_type in list(self.__components.keys())]))
|
|
222
|
+
|
|
223
|
+
components = self.__components[component_type]
|
|
224
|
+
if name in components.keys():
|
|
225
|
+
return components[name]
|
|
226
|
+
else:
|
|
227
|
+
raise RuntimeError(f"No {component_type.__name__} with name = \"{name}\" exists. Followings are the available {component_type.__name__}:\n" + "\n\t".join(components.keys()))
|
|
228
|
+
|
|
229
|
+
def RemoveComponent(self, name: str, component_type: Any) -> None:
|
|
230
|
+
if component_type not in self.__components.keys():
|
|
231
|
+
raise RuntimeError(f"Unsupported component type requested from RemoveComponent. [ requested component type = \"{str(component_type)}\" ]. Followings are supported component types:\n\t" + "\n\t".join([component_type.__name__ for component_type in list(self.__components.keys())]))
|
|
232
|
+
|
|
233
|
+
components = self.__components[component_type]
|
|
234
|
+
if name in components.keys():
|
|
235
|
+
del components[name]
|
|
236
|
+
else:
|
|
237
|
+
raise RuntimeError(f"No {component_type.__name__} with name = \"{name}\" exists. Followings are the available {component_type.__name__}:\n" + "\n\t".join(components.keys()))
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
from importlib import import_module
|
|
2
|
+
from typing import Any, Union
|
|
3
|
+
|
|
4
|
+
import KratosMultiphysics as Kratos
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_routine import ResponseRoutine
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import ResponseFunction
|
|
9
|
+
from KratosMultiphysics.OptimizationApplication.controls.control import Control
|
|
10
|
+
from KratosMultiphysics.OptimizationApplication.execution_policies.execution_policy import ExecutionPolicy
|
|
11
|
+
|
|
12
|
+
def OptimizationComponentFactory(model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
|
|
13
|
+
if not parameters.Has("type"):
|
|
14
|
+
raise RuntimeError(f"Components created from OptimizationComponentFactory require the \"type\" [ provided parameters = {parameters}].")
|
|
15
|
+
|
|
16
|
+
python_type = parameters["type"].GetString()
|
|
17
|
+
|
|
18
|
+
if not parameters.Has("module") or parameters["module"].GetString() == "":
|
|
19
|
+
# in the case python type comes without a module
|
|
20
|
+
# as in the case python_type is in the sys path or the current working directory.
|
|
21
|
+
full_module_name = python_type
|
|
22
|
+
else:
|
|
23
|
+
# in the case python type comes with a module.
|
|
24
|
+
module = parameters["module"].GetString()
|
|
25
|
+
full_module_name = f"{module}.{python_type}"
|
|
26
|
+
|
|
27
|
+
module = import_module(full_module_name)
|
|
28
|
+
if not hasattr(module, "Factory"):
|
|
29
|
+
raise RuntimeError(f"Python module {full_module_name} does not have a Factory method.")
|
|
30
|
+
|
|
31
|
+
return getattr(module, "Factory")(model, parameters, optimization_problem)
|
|
32
|
+
|
|
33
|
+
def GetAllComponentFullNamesWithData(optimization_problem: OptimizationProblem) -> 'list[str]':
|
|
34
|
+
data_container = optimization_problem.GetProblemDataContainer()
|
|
35
|
+
|
|
36
|
+
list_of_components_full_names_with_data: 'list[str]' = []
|
|
37
|
+
for component_type_str, components_dict in data_container.GetSubItems().items():
|
|
38
|
+
if component_type_str != "object":
|
|
39
|
+
component_type_str = Kratos.StringUtilities.ConvertCamelCaseToSnakeCase(component_type_str) + "."
|
|
40
|
+
else:
|
|
41
|
+
component_type_str = ""
|
|
42
|
+
for component_name in components_dict.GetSubItems().keys():
|
|
43
|
+
list_of_components_full_names_with_data.append(f"{component_type_str}{component_name}")
|
|
44
|
+
|
|
45
|
+
return list_of_components_full_names_with_data
|
|
46
|
+
|
|
47
|
+
def GetComponentHavingDataByFullName(component_full_name: str, optimization_problem: OptimizationProblem) -> Any:
|
|
48
|
+
data_container = optimization_problem.GetProblemDataContainer()
|
|
49
|
+
|
|
50
|
+
name_data = component_full_name.split(".")
|
|
51
|
+
|
|
52
|
+
if len(name_data) == 1:
|
|
53
|
+
if data_container.HasValue("object") and data_container["object"].HasValue(component_full_name):
|
|
54
|
+
return component_full_name
|
|
55
|
+
else:
|
|
56
|
+
component_type_str = Kratos.StringUtilities.ConvertSnakeCaseToCamelCase(name_data[0])
|
|
57
|
+
component_name = name_data[1]
|
|
58
|
+
|
|
59
|
+
for component_type in optimization_problem.GetComponentContainer().keys():
|
|
60
|
+
if component_type.__name__ == component_type_str:
|
|
61
|
+
return optimization_problem.GetComponent(component_name, component_type)
|
|
62
|
+
|
|
63
|
+
msg = ""
|
|
64
|
+
for component_type, dict_of_components in optimization_problem.GetComponentContainer().items():
|
|
65
|
+
for sub_item_name in dict_of_components.keys():
|
|
66
|
+
msg += "\n\t" + Kratos.StringUtilities.ConvertCamelCaseToSnakeCase(component_type.__name__) + f".{sub_item_name}"
|
|
67
|
+
if data_container.HasValue("object"):
|
|
68
|
+
for sub_item_name in data_container["object"].GetSubItems().keys():
|
|
69
|
+
msg += "\n\t" + sub_item_name
|
|
70
|
+
|
|
71
|
+
raise RuntimeError(f"\"{component_full_name}\" full component name is not found in the optimization problem. Followings are supported component with full names:" + msg)
|
|
72
|
+
|
|
73
|
+
def GetComponentValueByFullName(component_data_view: ComponentDataView, value_name: str, step_index = 0) -> Any:
|
|
74
|
+
value_info = value_name.split(":")
|
|
75
|
+
if len(value_info) != 2 or value_info[1] not in ["historical", "non_historical"]:
|
|
76
|
+
raise RuntimeError(f"The value_name should contain the name of the value and either it is located at buffered data or un buffered data. Ex: \"objective_Value:historical\" for buffered container or \"reference_value:non_historical\" for unbuffered container [ value_name = \"{value_name}\" ].")
|
|
77
|
+
|
|
78
|
+
if value_info[1] == "historical":
|
|
79
|
+
data = component_data_view.GetBufferedData()
|
|
80
|
+
elif value_info[1] == "non_historical":
|
|
81
|
+
data = component_data_view.GetUnBufferedData()
|
|
82
|
+
|
|
83
|
+
if not data.HasValue(value_info[0], step_index):
|
|
84
|
+
raise RuntimeError(f"The value = \"{value_info[0]}\" is not found in the component = \"{component_data_view.GetComponentName()}\" [ value_name = \"{value_name}\", step_index = {step_index}, data = {data}, component_data_view = {component_data_view}")
|
|
85
|
+
|
|
86
|
+
return data.GetValue(value_info[0], step_index)
|
|
87
|
+
|
|
88
|
+
def SetComponentValueByFullName(component_data_view: ComponentDataView, value_name: str, value: Any, step_index = 0, overwrite = False) -> None:
|
|
89
|
+
value_info = value_name.split(":")
|
|
90
|
+
if len(value_info) != 2 or value_info[1] not in ["historical", "non_historical"]:
|
|
91
|
+
raise RuntimeError(f"The value_name should contain the name of the value and either it is located at buffered data or un buffered data. Ex: \"objective_Value:historical\" for buffered container or \"reference_value:non_historical\" for unbuffered container [ value_name = \"{value_name}\" ].")
|
|
92
|
+
|
|
93
|
+
if value_info[1] == "historical":
|
|
94
|
+
data = component_data_view.GetBufferedData()
|
|
95
|
+
elif value_info[1] == "non_historical":
|
|
96
|
+
data = component_data_view.GetUnBufferedData()
|
|
97
|
+
|
|
98
|
+
data.SetValue(value_info[0], value, step_index, overwrite)
|
|
99
|
+
|
|
100
|
+
def OutputGradientFields(response: ResponseRoutine, optimization_problem: OptimizationProblem, is_gradients_computed: bool) -> None:
|
|
101
|
+
unbuffered_data = ComponentDataView(response.GetReponse(), optimization_problem).GetUnBufferedData()
|
|
102
|
+
if is_gradients_computed:
|
|
103
|
+
# save the physical gradients for post processing in unbuffered data container.
|
|
104
|
+
for physical_var, physical_gradient in response.GetRequiredPhysicalGradients().items():
|
|
105
|
+
variable_name = f"d{response.GetResponseName()}_d{physical_var.Name()}"
|
|
106
|
+
for physical_gradient_ta in physical_gradient.GetTensorAdaptors():
|
|
107
|
+
unbuffered_data.SetValue(variable_name, Kratos.TensorAdaptors.DoubleTensorAdaptor(physical_gradient_ta), overwrite=True)
|
|
108
|
+
|
|
109
|
+
# save the filtered gradients for post processing in unbuffered data container.
|
|
110
|
+
for gradient_container_ta, control in zip(response.GetMappedGradients().GetTensorAdaptors(), response.GetMasterControl().GetListOfControls()):
|
|
111
|
+
variable_name = f"d{response.GetResponseName()}_d{control.GetName()}"
|
|
112
|
+
unbuffered_data.SetValue(variable_name, Kratos.TensorAdaptors.DoubleTensorAdaptor(gradient_container_ta), overwrite=True)
|
|
113
|
+
else:
|
|
114
|
+
# save the physical gradients for post processing in unbuffered data container.
|
|
115
|
+
for physical_var, physical_gradient in response.GetRequiredPhysicalGradients().items():
|
|
116
|
+
variable_name = f"d{response.GetResponseName()}_d{physical_var.Name()}"
|
|
117
|
+
for physical_gradient_ta in physical_gradient.GetTensorAdaptors():
|
|
118
|
+
temp_ta = Kratos.TensorAdaptors.DoubleTensorAdaptor(physical_gradient_ta)
|
|
119
|
+
temp_ta.data[:] = 0.0
|
|
120
|
+
unbuffered_data.SetValue(variable_name, temp_ta, overwrite=True)
|
|
121
|
+
|
|
122
|
+
# save the filtered gradients for post processing in unbuffered data container.
|
|
123
|
+
for control in response.GetMasterControl().GetListOfControls():
|
|
124
|
+
variable_name = f"d{response.GetResponseName()}_d{control.GetName()}"
|
|
125
|
+
unbuffered_data.SetValue(variable_name, control.GetEmptyField(), overwrite=True)
|
|
126
|
+
|
|
127
|
+
class TensorAdaptorData:
|
|
128
|
+
def __init__(self, tensor_adaptor_path: str, tensor_adaptor: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> None:
|
|
129
|
+
self.tensor_adaptor_path = tensor_adaptor_path
|
|
130
|
+
self.container = tensor_adaptor.GetContainer()
|
|
131
|
+
|
|
132
|
+
def GetTensorAdaptorName(self) -> str:
|
|
133
|
+
return self.tensor_adaptor_path[self.tensor_adaptor_path.rfind("/")+1:]
|
|
134
|
+
|
|
135
|
+
def GetTensorAdaptorPath(self) -> str:
|
|
136
|
+
return self.tensor_adaptor_path
|
|
137
|
+
|
|
138
|
+
def GetContainer(self):
|
|
139
|
+
return self.container
|
|
140
|
+
|
|
141
|
+
def GetTensorAdaptor(self, optimization_problem: OptimizationProblem) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
142
|
+
data = optimization_problem.GetProblemDataContainer()[self.tensor_adaptor_path]
|
|
143
|
+
|
|
144
|
+
if not isinstance(data, Kratos.TensorAdaptors.DoubleTensorAdaptor):
|
|
145
|
+
raise RuntimeError(f"The data type at \"{self.tensor_adaptor_path}\" changed from {Kratos.TensorAdaptors.DoubleTensorAdaptor.__name__} to {type(data).__class__.__name__}. Found data = {data}")
|
|
146
|
+
if not data.HasContainer():
|
|
147
|
+
raise RuntimeError(f"The data at \"{self.tensor_adaptor_path}\" does not represent a {Kratos.TensorAdaptors.DoubleTensorAdaptor.__name__} with a container. Found data = {data}")
|
|
148
|
+
if data.GetContainer() != self.container:
|
|
149
|
+
raise RuntimeError(f"The container at \"{self.tensor_adaptor_path}\" mismatch with the original container. Found data = {data}")
|
|
150
|
+
|
|
151
|
+
return data
|
|
152
|
+
|
|
153
|
+
class CombinedTensorAdaptorData(TensorAdaptorData):
|
|
154
|
+
def __init__(self, combined_tensor_adaptor_path: str, combined_tensor_adaptor: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor, tensor_adaptor_index: int) -> None:
|
|
155
|
+
super().__init__(combined_tensor_adaptor_path, combined_tensor_adaptor.GetTensorAdaptors()[tensor_adaptor_index])
|
|
156
|
+
self.tensor_adaptor_index = tensor_adaptor_index
|
|
157
|
+
|
|
158
|
+
def GetTensorAdaptor(self, optimization_problem: OptimizationProblem) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
159
|
+
data = optimization_problem.GetProblemDataContainer()[self.tensor_adaptor_path]
|
|
160
|
+
|
|
161
|
+
if not isinstance(data, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor):
|
|
162
|
+
raise RuntimeError(f"The data type at \"{self.tensor_adaptor_path}\" changed from {Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor.__name__} to {type(data).__class__.__name__}. Found data = {data}")
|
|
163
|
+
if not data.GetTensorAdaptors()[self.tensor_adaptor_index].HasContainer():
|
|
164
|
+
raise RuntimeError(f"The tensor adaptor at \"{self.tensor_adaptor_path}\" with index = {self.tensor_adaptor_index} does not represent a {Kratos.TensorAdaptors.DoubleTensorAdaptor.__name__} with a container. Found data = {data}")
|
|
165
|
+
if data.GetTensorAdaptors()[self.tensor_adaptor_index].GetContainer() != self.container:
|
|
166
|
+
raise RuntimeError(f"The container from tensor adaptor \"{self.tensor_adaptor_path}\" with index = {self.tensor_adaptor_index} mismatch with the original container. Found data = {data}")
|
|
167
|
+
|
|
168
|
+
return data.GetTensorAdaptors()[self.tensor_adaptor_index]
|
|
169
|
+
|
|
170
|
+
class TensorAdaptorDataManager:
|
|
171
|
+
def __init__(self, optimization_problem: OptimizationProblem):
|
|
172
|
+
self.optimization_problem = optimization_problem
|
|
173
|
+
self.list_of_component_names = ["all"]
|
|
174
|
+
self.list_of_tensor_adaptor_hdf5_outputs = []
|
|
175
|
+
self.create_method = None
|
|
176
|
+
|
|
177
|
+
def InitializeHDF5Output(self) -> None:
|
|
178
|
+
# get all the component names at the first writing point
|
|
179
|
+
if len(self.list_of_component_names) == 1 and self.list_of_component_names[0] == "all":
|
|
180
|
+
self.list_of_component_names = GetAllComponentFullNamesWithData(self.optimization_problem)
|
|
181
|
+
|
|
182
|
+
list_of_components: 'list[Union[str, ResponseFunction, Control, ExecutionPolicy]]' = []
|
|
183
|
+
for component_name in self.list_of_component_names:
|
|
184
|
+
list_of_components.append(GetComponentHavingDataByFullName(component_name, self.optimization_problem))
|
|
185
|
+
|
|
186
|
+
global_values_map = self.optimization_problem.GetProblemDataContainer().GetMap()
|
|
187
|
+
for global_k, global_v in global_values_map.items():
|
|
188
|
+
# first check whether this is part of requested list of components
|
|
189
|
+
found_valid_component = False
|
|
190
|
+
for component in list_of_components:
|
|
191
|
+
component_data = ComponentDataView(component, self.optimization_problem)
|
|
192
|
+
if global_k.startswith(component_data.GetDataPath()):
|
|
193
|
+
found_valid_component = True
|
|
194
|
+
break
|
|
195
|
+
|
|
196
|
+
# if a valid component is found, add the tensor adaptor
|
|
197
|
+
if found_valid_component:
|
|
198
|
+
if isinstance(global_v, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor):
|
|
199
|
+
for i, _ in enumerate(global_v.GetTensorAdaptors()):
|
|
200
|
+
self._AddContainerTensorAdaptor(CombinedTensorAdaptorData(global_k, global_v, i))
|
|
201
|
+
elif isinstance(global_v, Kratos.TensorAdaptors.DoubleTensorAdaptor) or \
|
|
202
|
+
isinstance(global_v, Kratos.TensorAdaptors.IntTensorAdaptor) or \
|
|
203
|
+
isinstance(global_v, Kratos.TensorAdaptors.BoolTensorAdaptor):
|
|
204
|
+
self._AddContainerTensorAdaptor(TensorAdaptorData(global_k, global_v))
|
|
205
|
+
|
|
206
|
+
def _AddContainerTensorAdaptor(self, tensor_adaptor_data: TensorAdaptorData):
|
|
207
|
+
found_vtu_output = False
|
|
208
|
+
for tensor_adaptor_hdf5_output in self.list_of_tensor_adaptor_hdf5_outputs:
|
|
209
|
+
if tensor_adaptor_hdf5_output.AddTensorAdaptorData(tensor_adaptor_data):
|
|
210
|
+
found_vtu_output = True
|
|
211
|
+
break
|
|
212
|
+
|
|
213
|
+
if not found_vtu_output:
|
|
214
|
+
tensor_adaptor_hdf5_output = self.create_method(self.__GetRootModelPart(tensor_adaptor_data.GetContainer()), self.optimization_problem)
|
|
215
|
+
tensor_adaptor_hdf5_output.AddTensorAdaptorData(tensor_adaptor_data)
|
|
216
|
+
self.list_of_tensor_adaptor_hdf5_outputs.append(tensor_adaptor_hdf5_output)
|
|
217
|
+
if self.echo_level > 0:
|
|
218
|
+
Kratos.Logger.PrintInfo(self.__class__.__name__, f"Created tensor adaptor hdf5 output for {tensor_adaptor_hdf5_output.model_part.FullName()}.")
|
|
219
|
+
|
|
220
|
+
def __GetRootModelPart(self, container) -> Kratos.ModelPart:
|
|
221
|
+
def get_model_part(container, model_part: Kratos.ModelPart):
|
|
222
|
+
if container in [model_part.Nodes, model_part.Conditions, model_part.Elements]:
|
|
223
|
+
return model_part.GetRootModelPart()
|
|
224
|
+
|
|
225
|
+
for sub_model_part_name in model_part.GetSubModelPartNames():
|
|
226
|
+
root_model_part = get_model_part(container, model_part.GetSubModelPart(sub_model_part_name))
|
|
227
|
+
if root_model_part is not None:
|
|
228
|
+
return root_model_part
|
|
229
|
+
|
|
230
|
+
return None
|
|
231
|
+
|
|
232
|
+
for model_part_name in self.model.GetModelPartNames():
|
|
233
|
+
root_model_part = get_model_part(container, self.model[model_part_name])
|
|
234
|
+
if root_model_part is not None:
|
|
235
|
+
return root_model_part
|
|
236
|
+
|
|
237
|
+
raise RuntimeError(f"No model part contains the provided container.")
|