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,47 @@
|
|
|
1
|
+
from math import log
|
|
2
|
+
import KratosMultiphysics as Kratos
|
|
3
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import ResponseFunction
|
|
4
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import SupportedSensitivityFieldVariableTypes
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.utilities.response_utilities import EvaluateValue
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.utilities.response_utilities import EvaluateGradient
|
|
8
|
+
|
|
9
|
+
class LogResponseFunction(ResponseFunction):
|
|
10
|
+
def __init__(self, response_function: ResponseFunction, optimization_problem: OptimizationProblem):
|
|
11
|
+
super().__init__(f"log({response_function.GetName()})")
|
|
12
|
+
self.response_function = response_function
|
|
13
|
+
self.optimization_problem = optimization_problem
|
|
14
|
+
|
|
15
|
+
def GetImplementedPhysicalKratosVariables(self) -> 'list[SupportedSensitivityFieldVariableTypes]':
|
|
16
|
+
return self.response_function.GetImplementedPhysicalKratosVariables()
|
|
17
|
+
|
|
18
|
+
def Initialize(self) -> None:
|
|
19
|
+
self.response_function.Initialize()
|
|
20
|
+
|
|
21
|
+
def Check(self) -> None:
|
|
22
|
+
self.response_function.Check()
|
|
23
|
+
|
|
24
|
+
def Finalize(self) -> None:
|
|
25
|
+
self.response_function.Finalize()
|
|
26
|
+
|
|
27
|
+
def GetInfluencingModelPart(self) -> Kratos.ModelPart:
|
|
28
|
+
return self.response_function.GetInfluencingModelPart()
|
|
29
|
+
|
|
30
|
+
def CalculateValue(self) -> float:
|
|
31
|
+
return log(EvaluateValue(self.response_function, self.optimization_problem))
|
|
32
|
+
|
|
33
|
+
def CalculateGradient(self, physical_variable_gradient_map: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]') -> None:
|
|
34
|
+
v = EvaluateValue(self.response_function, self.optimization_problem)
|
|
35
|
+
|
|
36
|
+
resp_gradients = {var: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(cta) for var, cta in physical_variable_gradient_map.items()}
|
|
37
|
+
EvaluateGradient(self.response_function, resp_gradients, self.optimization_problem)
|
|
38
|
+
|
|
39
|
+
for variable, cta in physical_variable_gradient_map.items():
|
|
40
|
+
cta.data = resp_gradients[variable].data / v
|
|
41
|
+
Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor(cta, perform_collect_data_recursively=False, perform_store_data_recursively=False, copy=False).StoreData()
|
|
42
|
+
|
|
43
|
+
def GetChildResponses(self) -> 'list[ResponseFunction]':
|
|
44
|
+
return [self.response_function]
|
|
45
|
+
|
|
46
|
+
def __str__(self) -> str:
|
|
47
|
+
return f"Response [type = {self.__class__.__name__}, name = {self.GetName()}]"
|
|
@@ -0,0 +1,71 @@
|
|
|
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.responses.response_function import SupportedSensitivityFieldVariableTypes
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.utilities.model_part_utilities import ModelPartOperation
|
|
8
|
+
|
|
9
|
+
def Factory(model: Kratos.Model, parameters: Kratos.Parameters, _) -> ResponseFunction:
|
|
10
|
+
if not parameters.Has("name"):
|
|
11
|
+
raise RuntimeError(f"MassResponseFunction instantiation requires a \"name\" in parameters [ parameters = {parameters}].")
|
|
12
|
+
if not parameters.Has("settings"):
|
|
13
|
+
raise RuntimeError(f"MassResponseFunction instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
|
|
14
|
+
|
|
15
|
+
return MassResponseFunction(parameters["name"].GetString(), model, parameters["settings"])
|
|
16
|
+
|
|
17
|
+
class MassResponseFunction(ResponseFunction):
|
|
18
|
+
def __init__(self, name: str, model: Kratos.Model, parameters: Kratos.Parameters):
|
|
19
|
+
super().__init__(name)
|
|
20
|
+
|
|
21
|
+
default_settings = Kratos.Parameters("""{
|
|
22
|
+
"evaluated_model_part_names" : [
|
|
23
|
+
"PLEASE_PROVIDE_A_MODEL_PART_NAME"
|
|
24
|
+
],
|
|
25
|
+
"perturbation_size": 1e-6
|
|
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 MassResponseFunction. [ 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
|
+
self.perturbation_size = parameters["perturbation_size"].GetDouble()
|
|
38
|
+
|
|
39
|
+
def GetImplementedPhysicalKratosVariables(self) -> 'list[SupportedSensitivityFieldVariableTypes]':
|
|
40
|
+
return [KratosOA.SHAPE, Kratos.DENSITY, Kratos.THICKNESS, KratosOA.CROSS_AREA]
|
|
41
|
+
|
|
42
|
+
def Initialize(self) -> None:
|
|
43
|
+
self.model_part = self.model_part_operation.GetModelPart()
|
|
44
|
+
|
|
45
|
+
def Check(self) -> None:
|
|
46
|
+
if self.model_part is None:
|
|
47
|
+
raise RuntimeError("Please call MassResponseFunction::Initialize first.")
|
|
48
|
+
KratosOA.ResponseUtils.MassResponseUtils.Check(self.model_part)
|
|
49
|
+
|
|
50
|
+
def Finalize(self) -> None:
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
def GetInfluencingModelPart(self) -> Kratos.ModelPart:
|
|
54
|
+
if self.model_part is None:
|
|
55
|
+
raise RuntimeError("Please call MassResponseFunction::Initialize first.")
|
|
56
|
+
return self.model_part
|
|
57
|
+
|
|
58
|
+
def CalculateValue(self) -> float:
|
|
59
|
+
return KratosOA.ResponseUtils.MassResponseUtils.CalculateValue(self.model_part)
|
|
60
|
+
|
|
61
|
+
def CalculateGradient(self, physical_variable_gradient_map: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]') -> None:
|
|
62
|
+
# calculate the gradients
|
|
63
|
+
for physical_variable, cta in physical_variable_gradient_map.items():
|
|
64
|
+
KratosOA.ResponseUtils.MassResponseUtils.CalculateGradient(
|
|
65
|
+
physical_variable,
|
|
66
|
+
self.model_part,
|
|
67
|
+
cta,
|
|
68
|
+
self.perturbation_size)
|
|
69
|
+
|
|
70
|
+
def __str__(self) -> str:
|
|
71
|
+
return f"Response [type = {self.__class__.__name__}, name = {self.GetName()}, model part name = {self.model_part.FullName()}]"
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Union
|
|
3
|
+
import KratosMultiphysics as Kratos
|
|
4
|
+
import KratosMultiphysics.OptimizationApplication as KratosOA
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.utilities.union_utilities import SupportedSensitivityFieldVariableTypes
|
|
6
|
+
|
|
7
|
+
class ResponseFunction(ABC):
|
|
8
|
+
"""Base response function.
|
|
9
|
+
|
|
10
|
+
This response function is the base response function. This is assumed to have following responsibilities.
|
|
11
|
+
1. CalculateValue for a new design. (@see CalculateValue)
|
|
12
|
+
2. CalculateSensitivity for a new design (@see CalculateSensitivity)
|
|
13
|
+
|
|
14
|
+
This response should only work on one model part. Hence, if multiple model parts required then,
|
|
15
|
+
a single model part should be created using Kratos.ModelPartOperationUtilities.
|
|
16
|
+
"""
|
|
17
|
+
def __init__(self, response_name: str) -> None:
|
|
18
|
+
self.__name = response_name
|
|
19
|
+
|
|
20
|
+
def GetName(self) -> str:
|
|
21
|
+
return self.__name
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def Initialize(self) -> None:
|
|
25
|
+
"""Initializes the response.
|
|
26
|
+
|
|
27
|
+
This method initializes the response. This is only called once in the whole optimization process.
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
@abstractmethod
|
|
33
|
+
def Check(self) -> None:
|
|
34
|
+
"""Checks the response.
|
|
35
|
+
|
|
36
|
+
This method checks the response. This is only called once in the whole optimization process.
|
|
37
|
+
|
|
38
|
+
"""
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def Finalize(self) -> None:
|
|
43
|
+
"""Finalizes the response.
|
|
44
|
+
|
|
45
|
+
This method finalizes the response. This is only called once in the whole optimization process.
|
|
46
|
+
|
|
47
|
+
"""
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
@abstractmethod
|
|
51
|
+
def GetImplementedPhysicalKratosVariables(self) -> 'list[SupportedSensitivityFieldVariableTypes]':
|
|
52
|
+
"""Returns all the dependent physical kratos variables of the response.
|
|
53
|
+
|
|
54
|
+
This method should return all the dependent physical variables of the response to make sure
|
|
55
|
+
that sensitivities w.r.t. those variables are requested from the response. If sensitivities
|
|
56
|
+
w.r.t. other variables are required from this response, they are ASSUMED TO BE ZERO.
|
|
57
|
+
|
|
58
|
+
Please return all the dependent physical variables, even though the gradient computation is not yet
|
|
59
|
+
implemented for some to avoid future bugs.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
list[SupportedSensitivityFieldVariableTypes]: All dependent physical variables of the response.
|
|
63
|
+
"""
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def CalculateValue(self) -> float:
|
|
68
|
+
"""Calculates the response value.
|
|
69
|
+
|
|
70
|
+
This method should always calculate the response value assuming the domain has changed.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
float: Calculated response value.
|
|
74
|
+
"""
|
|
75
|
+
pass
|
|
76
|
+
|
|
77
|
+
@abstractmethod
|
|
78
|
+
def CalculateGradient(self, physical_variable_gradient_map: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]') -> None:
|
|
79
|
+
"""Calculate gradient w.r.t. given physical variables.
|
|
80
|
+
|
|
81
|
+
This method should always calculate the sensitivities w.r.t. requested physical variables on the given @ref Kratos::TensorAdaptor
|
|
82
|
+
in the @ref Kratos::CombinedTensorAdaptor. An error should be thrown if sensitivitiy computation w.r.t. one or more given physical variables
|
|
83
|
+
are not implemented.
|
|
84
|
+
|
|
85
|
+
This method should always calculate the sensitivities assuming the domain has changed.
|
|
86
|
+
|
|
87
|
+
physical_variable_gradient_map is a map of physical variables, and their domains. The domains are represented by a @ref Kratos::CombinedTensorAdaptor
|
|
88
|
+
which contains list of empty @ref Kratos::TensorAdaptor. Each empty Kratos::TensorAdaptor contains details of the model part's nodes/conditions/element/properties
|
|
89
|
+
container for which the sensitivities w.r.t. physical variable requested.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
physical_variable_gradient_map (dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]): Output containing calculated sensitivities w.r.t. requested physical variables.
|
|
93
|
+
"""
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
@abstractmethod
|
|
97
|
+
def GetInfluencingModelPart(self) -> Kratos.ModelPart:
|
|
98
|
+
"""Returns the model part which influences the computation of the response value.
|
|
99
|
+
|
|
100
|
+
Following two cases are considered:
|
|
101
|
+
1. Responses without adjoint system solve: The value of the response can only be influenced by
|
|
102
|
+
changing the quantities in the evaluated model part (evaluated model part is the one which the
|
|
103
|
+
response value is computed.) Therefore, in this case, this method should return the
|
|
104
|
+
evaluated model part.
|
|
105
|
+
2. Responses with adjoint system solve: The value of the response can be influenced by
|
|
106
|
+
changing quantities in the adjoint/primal model part (Evaluated model part needs to have
|
|
107
|
+
intersection with the adjoint/primal model part). Therefore, in this case, this method should return the
|
|
108
|
+
adjoint analysis model part.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Kratos.ModelPart: Response function model part which influences the response value.
|
|
112
|
+
"""
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
def GetChildResponses(self) -> 'list[ResponseFunction]':
|
|
116
|
+
"""Returns the list of child responses.
|
|
117
|
+
|
|
118
|
+
This method returns list of child responses. If the current response is a leaf response,
|
|
119
|
+
then it will return empty list.
|
|
120
|
+
|
|
121
|
+
Needs to be implemented in non-leaf response functions.
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
list[ResponseFunction]: List of child responses.
|
|
125
|
+
"""
|
|
126
|
+
return []
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import KratosMultiphysics as Kratos
|
|
2
|
+
import KratosMultiphysics.OptimizationApplication as KratosOA
|
|
3
|
+
from KratosMultiphysics.OptimizationApplication.controls.control import Control
|
|
4
|
+
from KratosMultiphysics.OptimizationApplication.responses.response_function import ResponseFunction
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.controls.master_control import MasterControl
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.utilities.union_utilities import SupportedSensitivityFieldVariableTypes
|
|
7
|
+
import math, numpy
|
|
8
|
+
|
|
9
|
+
class ResponseRoutine:
|
|
10
|
+
"""A class which adds optimization-specific utilities to simplify routines
|
|
11
|
+
and synchronization between the control field from algorithms and analysis models.
|
|
12
|
+
"""
|
|
13
|
+
def __init__(self, master_control: MasterControl, response: ResponseFunction) -> None:
|
|
14
|
+
# set the master control
|
|
15
|
+
self.__master_control = master_control
|
|
16
|
+
|
|
17
|
+
# set the response
|
|
18
|
+
self.__response = response
|
|
19
|
+
self.__response_value = None
|
|
20
|
+
self.__contributing_controls_list: 'list[Control]' = []
|
|
21
|
+
self.__required_physical_gradients: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]' = {}
|
|
22
|
+
|
|
23
|
+
def GetMasterControl(self) -> MasterControl:
|
|
24
|
+
return self.__master_control
|
|
25
|
+
|
|
26
|
+
def Initialize(self):
|
|
27
|
+
"""Initializes the response routine.
|
|
28
|
+
|
|
29
|
+
Raises:
|
|
30
|
+
RuntimeError: If control domain and response domain does not have any intersection.
|
|
31
|
+
"""
|
|
32
|
+
# create the required physical control fields to compute gradients
|
|
33
|
+
self.__response.Initialize()
|
|
34
|
+
self.__required_physical_gradients = self.__master_control.GetPhysicalKratosVariableMap()
|
|
35
|
+
|
|
36
|
+
# now check which are the dependent physical space variables for the response, if not then remove
|
|
37
|
+
# that variable
|
|
38
|
+
list_of_independent_variables = []
|
|
39
|
+
for required_physical_variable in self.__required_physical_gradients.keys():
|
|
40
|
+
if required_physical_variable not in self.__response.GetImplementedPhysicalKratosVariables():
|
|
41
|
+
list_of_independent_variables.append(required_physical_variable)
|
|
42
|
+
|
|
43
|
+
# now remove this independent combined tensor adaptor from the require combined tensor adaptors map.
|
|
44
|
+
for independent_variable in list_of_independent_variables:
|
|
45
|
+
del self.__required_physical_gradients[independent_variable]
|
|
46
|
+
|
|
47
|
+
for control in self.__master_control.GetListOfControls():
|
|
48
|
+
# check whether control has keys given by required gradients
|
|
49
|
+
if set(control.GetPhysicalKratosVariables()).intersection(self.__required_physical_gradients.keys()):
|
|
50
|
+
self.__contributing_controls_list.append(control)
|
|
51
|
+
|
|
52
|
+
if not self.__contributing_controls_list:
|
|
53
|
+
raise RuntimeError(f"The controls does not have any influence over the response {self.GetResponseName()}.")
|
|
54
|
+
|
|
55
|
+
self.my_current_control_field = self.__master_control.GetEmptyField()
|
|
56
|
+
|
|
57
|
+
def Check(self):
|
|
58
|
+
self.__response.Check()
|
|
59
|
+
|
|
60
|
+
def Finalize(self):
|
|
61
|
+
self.__response.Finalize()
|
|
62
|
+
|
|
63
|
+
def GetResponseName(self):
|
|
64
|
+
return self.__response.GetName()
|
|
65
|
+
|
|
66
|
+
def GetReponse(self) -> ResponseFunction:
|
|
67
|
+
return self.__response
|
|
68
|
+
|
|
69
|
+
def CalculateValue(self, control_field: Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor) -> float:
|
|
70
|
+
"""Calculates the value of the response.
|
|
71
|
+
|
|
72
|
+
This method updates the design with the provided control field. If a control field is updated
|
|
73
|
+
which affects the this response value, then a new value is computed. Otherwise, the previous
|
|
74
|
+
value is returned.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
control_field (Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor): Control field of the new design.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
float: Response value.
|
|
81
|
+
"""
|
|
82
|
+
# update using the master control and get updated states.
|
|
83
|
+
self.__master_control.Update(control_field)
|
|
84
|
+
compute_response_value_flag = False
|
|
85
|
+
|
|
86
|
+
if self.__response_value is None:
|
|
87
|
+
self.my_current_control_field = Kratos.TensorAdaptors.DoubleTensorAdaptor(control_field)
|
|
88
|
+
|
|
89
|
+
if not math.isclose(numpy.linalg.norm(self.my_current_control_field.data, ord=numpy.inf), 0.0, abs_tol=1e-16):
|
|
90
|
+
rel_diff = (self.my_current_control_field.data - control_field.data) / numpy.linalg.norm(self.my_current_control_field.data, ord=numpy.inf)
|
|
91
|
+
else:
|
|
92
|
+
rel_diff = (self.my_current_control_field.data - control_field.data)
|
|
93
|
+
|
|
94
|
+
norm = numpy.linalg.norm(rel_diff, ord=numpy.inf)
|
|
95
|
+
|
|
96
|
+
if not math.isclose(norm, 0.0, abs_tol=1e-16):
|
|
97
|
+
compute_response_value_flag = True
|
|
98
|
+
|
|
99
|
+
compute_response_value_flag = compute_response_value_flag or self.__response_value is None
|
|
100
|
+
# TODO: In the case of having two analysis with the same mesh (model parts) for two different
|
|
101
|
+
# responses, we need to flag all the anayses which are affected by the control update_state
|
|
102
|
+
# from the first call, otherwise the second call will not update anything, hence no execution
|
|
103
|
+
# policies will be executed.
|
|
104
|
+
|
|
105
|
+
# Example: Drag 1 with 10m/s, Drag 2 with 20 m/s using the same mesh and model parts with two
|
|
106
|
+
# different analyses.
|
|
107
|
+
# now set the response value in response data container
|
|
108
|
+
# if len(modified_model_parts) > 0:
|
|
109
|
+
# # if there are any modified model parts, then this changes state of is_executed to false
|
|
110
|
+
# # in the execution policies which has some intersection with the modified model parts.
|
|
111
|
+
# ChangeExecutionPolicyStates(modified_model_parts, False, self.__optimization_problem)
|
|
112
|
+
|
|
113
|
+
if compute_response_value_flag:
|
|
114
|
+
self.__response_value = self.__response.CalculateValue()
|
|
115
|
+
Kratos.Logger.PrintInfo(f"Response value is calculated for {self.GetResponseName()}.")
|
|
116
|
+
else:
|
|
117
|
+
Kratos.Logger.PrintInfo(f"The control field is not updated, hence the response value is not computed for {self.GetResponseName()}.")
|
|
118
|
+
|
|
119
|
+
# Update current control field state
|
|
120
|
+
self.my_current_control_field.data[:] = control_field.data
|
|
121
|
+
|
|
122
|
+
return self.__response_value
|
|
123
|
+
|
|
124
|
+
def CalculateGradient(self) -> Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor:
|
|
125
|
+
"""Returns CombinedTensorAdaptor containing all the control space gradients for all control variable types (fields).
|
|
126
|
+
|
|
127
|
+
Notes:
|
|
128
|
+
1. It expects that the CalculateValue is called.
|
|
129
|
+
2. The gradients are computed with respect to updates from master control.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor: Returns mapped gradients combined tensor adaptor.
|
|
133
|
+
"""
|
|
134
|
+
# fills the proper physical gradients from the response
|
|
135
|
+
self.__response.CalculateGradient(self.__required_physical_gradients)
|
|
136
|
+
|
|
137
|
+
# calculate and return the control space gradients from respective controls
|
|
138
|
+
self.__mapped_gradients = self.__master_control.MapGradient(self.__required_physical_gradients)
|
|
139
|
+
return self.__mapped_gradients
|
|
140
|
+
|
|
141
|
+
def GetMappedGradients(self):
|
|
142
|
+
return self.__mapped_gradients
|
|
143
|
+
|
|
144
|
+
def GetRequiredPhysicalGradients(self) -> 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]':
|
|
145
|
+
"""Returns required physical gradients by this response
|
|
146
|
+
|
|
147
|
+
This method returns required physical gradients. The tensor adaptors may or not be empty field
|
|
148
|
+
depending on CalculateGradient is called or not.
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleCombinedTensorAdaptor]: Required physical gradients.
|
|
152
|
+
"""
|
|
153
|
+
return self.__required_physical_gradients
|
|
154
|
+
|
|
155
|
+
def GetName(self):
|
|
156
|
+
return self.GetReponse().GetName()
|
|
157
|
+
|
|
158
|
+
|