KratosOptimizationApplication 10.4.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. KratosMultiphysics/.libs/KratosOptimizationApplication.so +0 -0
  2. KratosMultiphysics/.libs/libKratosOptimizationCore.dylib +0 -0
  3. KratosMultiphysics/OptimizationApplication/__init__.py +19 -0
  4. KratosMultiphysics/OptimizationApplication/algorithms/NLOPT_algorithms.py +255 -0
  5. KratosMultiphysics/OptimizationApplication/algorithms/SciPy_algorithms.py +154 -0
  6. KratosMultiphysics/OptimizationApplication/algorithms/__init__.py +0 -0
  7. KratosMultiphysics/OptimizationApplication/algorithms/algorithm.py +78 -0
  8. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_adam.py +68 -0
  9. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_base.py +393 -0
  10. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_gradient_projection.py +355 -0
  11. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_momentum_relaxed_gradient_projection.py +70 -0
  12. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_nesterov_accelarated_gradient.py +60 -0
  13. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_relaxed_gradient_projection.py +263 -0
  14. KratosMultiphysics/OptimizationApplication/algorithms/algorithm_steepest_descent.py +205 -0
  15. KratosMultiphysics/OptimizationApplication/algorithms/standardized_NLOPT_constraint.py +194 -0
  16. KratosMultiphysics/OptimizationApplication/algorithms/standardized_NLOPT_objective.py +191 -0
  17. KratosMultiphysics/OptimizationApplication/algorithms/standardized_SciPy_constraint.py +123 -0
  18. KratosMultiphysics/OptimizationApplication/algorithms/standardized_SciPy_objective.py +148 -0
  19. KratosMultiphysics/OptimizationApplication/algorithms/standardized_constraint.py +180 -0
  20. KratosMultiphysics/OptimizationApplication/algorithms/standardized_objective.py +133 -0
  21. KratosMultiphysics/OptimizationApplication/algorithms/standardized_rgp_constraint.py +268 -0
  22. KratosMultiphysics/OptimizationApplication/analyses_controller.py +75 -0
  23. KratosMultiphysics/OptimizationApplication/controls/control.py +123 -0
  24. KratosMultiphysics/OptimizationApplication/controls/external_response_function_control.py +149 -0
  25. KratosMultiphysics/OptimizationApplication/controls/master_control.py +198 -0
  26. KratosMultiphysics/OptimizationApplication/controls/material/material_properties_control.py +115 -0
  27. KratosMultiphysics/OptimizationApplication/controls/material/simp_control.py +229 -0
  28. KratosMultiphysics/OptimizationApplication/controls/shape/vertex_morphing_shape_control.py +289 -0
  29. KratosMultiphysics/OptimizationApplication/controls/thickness/shell_thickness_control.py +180 -0
  30. KratosMultiphysics/OptimizationApplication/controls_controller.py +205 -0
  31. KratosMultiphysics/OptimizationApplication/convergence_criteria/avg_abs_improvement_conv_criterion.py +98 -0
  32. KratosMultiphysics/OptimizationApplication/convergence_criteria/combined_conv_criterion.py +87 -0
  33. KratosMultiphysics/OptimizationApplication/convergence_criteria/constraint_conv_criterion.py +68 -0
  34. KratosMultiphysics/OptimizationApplication/convergence_criteria/convergence_criterion.py +26 -0
  35. KratosMultiphysics/OptimizationApplication/convergence_criteria/l2_conv_criterion.py +77 -0
  36. KratosMultiphysics/OptimizationApplication/convergence_criteria/magnitude_reduction_conv_criterion.py +85 -0
  37. KratosMultiphysics/OptimizationApplication/convergence_criteria/max_iter_conv_criterion.py +48 -0
  38. KratosMultiphysics/OptimizationApplication/convergence_criteria/patience_conv_criterion.py +116 -0
  39. KratosMultiphysics/OptimizationApplication/convergence_criteria/target_value_conv_criterion.py +64 -0
  40. KratosMultiphysics/OptimizationApplication/execution_policies/execution_policy.py +46 -0
  41. KratosMultiphysics/OptimizationApplication/execution_policies/execution_policy_decorator.py +67 -0
  42. KratosMultiphysics/OptimizationApplication/execution_policies/independent_analysis_execution_policy.py +78 -0
  43. KratosMultiphysics/OptimizationApplication/execution_policies/kratos_analysis_execution_policy.py +137 -0
  44. KratosMultiphysics/OptimizationApplication/execution_policies/stepping_analysis_execution_policy.py +88 -0
  45. KratosMultiphysics/OptimizationApplication/filtering/explicit_filter.py +124 -0
  46. KratosMultiphysics/OptimizationApplication/filtering/filter.py +188 -0
  47. KratosMultiphysics/OptimizationApplication/filtering/filter_utils.py +55 -0
  48. KratosMultiphysics/OptimizationApplication/filtering/helmholtz_analysis.py +139 -0
  49. KratosMultiphysics/OptimizationApplication/filtering/helmholtz_scalar_solver.py +39 -0
  50. KratosMultiphysics/OptimizationApplication/filtering/helmholtz_shape_solver.py +67 -0
  51. KratosMultiphysics/OptimizationApplication/filtering/helmholtz_solver_base.py +275 -0
  52. KratosMultiphysics/OptimizationApplication/filtering/helmholtz_vector_solver.py +39 -0
  53. KratosMultiphysics/OptimizationApplication/filtering/implicit_filter.py +192 -0
  54. KratosMultiphysics/OptimizationApplication/filtering/python_solvers_wrapper_implicit_filters.py +56 -0
  55. KratosMultiphysics/OptimizationApplication/model_part_controllers/connectivity_preserving_model_part_controller.py +72 -0
  56. KratosMultiphysics/OptimizationApplication/model_part_controllers/external_response_function_model_part_controller.py +110 -0
  57. KratosMultiphysics/OptimizationApplication/model_part_controllers/mdpa_model_part_controller.py +44 -0
  58. KratosMultiphysics/OptimizationApplication/model_part_controllers/model_part_controller.py +19 -0
  59. KratosMultiphysics/OptimizationApplication/model_parts_controller.py +92 -0
  60. KratosMultiphysics/OptimizationApplication/optimization_analysis.py +146 -0
  61. KratosMultiphysics/OptimizationApplication/optimizations_controller.py +223 -0
  62. KratosMultiphysics/OptimizationApplication/optimizer.py +61 -0
  63. KratosMultiphysics/OptimizationApplication/processes/optimization_problem_ascii_output_process.py +212 -0
  64. KratosMultiphysics/OptimizationApplication/processes/optimization_problem_field_output_process.py +122 -0
  65. KratosMultiphysics/OptimizationApplication/processes/optimization_problem_graph_output_process.py +184 -0
  66. KratosMultiphysics/OptimizationApplication/processes/optimization_problem_hdf5_output_process.py +84 -0
  67. KratosMultiphysics/OptimizationApplication/processes/optimization_problem_vtu_output_process.py +94 -0
  68. KratosMultiphysics/OptimizationApplication/processes/spatial_statistics_computation_process.py +81 -0
  69. KratosMultiphysics/OptimizationApplication/responses/__init__.py +0 -0
  70. KratosMultiphysics/OptimizationApplication/responses/additive_manufacturing_responses.py +410 -0
  71. KratosMultiphysics/OptimizationApplication/responses/analysis_based_response_function_factory.py +14 -0
  72. KratosMultiphysics/OptimizationApplication/responses/analysis_free_response_function_factory.py +14 -0
  73. KratosMultiphysics/OptimizationApplication/responses/base_response.py +66 -0
  74. KratosMultiphysics/OptimizationApplication/responses/binary_operator_response_function.py +103 -0
  75. KratosMultiphysics/OptimizationApplication/responses/combined_response_function.py +127 -0
  76. KratosMultiphysics/OptimizationApplication/responses/discrete_value_residual_response_function.py +131 -0
  77. KratosMultiphysics/OptimizationApplication/responses/evaluation_response_function.py +68 -0
  78. KratosMultiphysics/OptimizationApplication/responses/external_response_function.py +87 -0
  79. KratosMultiphysics/OptimizationApplication/responses/geometric_centroid_deviation_response_function.py +97 -0
  80. KratosMultiphysics/OptimizationApplication/responses/linear_strain_energy_response_function.py +72 -0
  81. KratosMultiphysics/OptimizationApplication/responses/literal_value_response_function.py +33 -0
  82. KratosMultiphysics/OptimizationApplication/responses/log_response_function.py +47 -0
  83. KratosMultiphysics/OptimizationApplication/responses/mass_response_function.py +71 -0
  84. KratosMultiphysics/OptimizationApplication/responses/response_function.py +126 -0
  85. KratosMultiphysics/OptimizationApplication/responses/response_routine.py +158 -0
  86. KratosMultiphysics/OptimizationApplication/responses/structural_responses.py +335 -0
  87. KratosMultiphysics/OptimizationApplication/responses_controller.py +390 -0
  88. KratosMultiphysics/OptimizationApplication/utilities/buffered_dict.py +399 -0
  89. KratosMultiphysics/OptimizationApplication/utilities/component_data_view.py +74 -0
  90. KratosMultiphysics/OptimizationApplication/utilities/helper_utilities.py +40 -0
  91. KratosMultiphysics/OptimizationApplication/utilities/logger_utilities.py +222 -0
  92. KratosMultiphysics/OptimizationApplication/utilities/model_part_utilities.py +117 -0
  93. KratosMultiphysics/OptimizationApplication/utilities/opt_line_search.py +173 -0
  94. KratosMultiphysics/OptimizationApplication/utilities/opt_projection.py +191 -0
  95. KratosMultiphysics/OptimizationApplication/utilities/optimization_problem.py +237 -0
  96. KratosMultiphysics/OptimizationApplication/utilities/optimization_problem_utilities.py +237 -0
  97. KratosMultiphysics/OptimizationApplication/utilities/response_utilities.py +249 -0
  98. KratosMultiphysics/OptimizationApplication/utilities/timer.py +45 -0
  99. KratosMultiphysics/OptimizationApplication/utilities/union_utilities.py +6 -0
  100. kratosoptimizationapplication-10.4.4.dist-info/METADATA +25 -0
  101. kratosoptimizationapplication-10.4.4.dist-info/RECORD +106 -0
  102. kratosoptimizationapplication-10.4.4.dist-info/WHEEL +6 -0
  103. kratosoptimizationapplication.dylibs/libKratosCore.dylib +4 -0
  104. kratosoptimizationapplication.dylibs/libgcc_s.1.1.dylib +0 -0
  105. kratosoptimizationapplication.dylibs/libgomp.1.dylib +0 -0
  106. kratosoptimizationapplication.dylibs/libstdc++.6.dylib +0 -0
@@ -0,0 +1,26 @@
1
+ import abc
2
+ import typing
3
+
4
+ class ConvergenceCriterion(abc.ABC):
5
+ """Initializes the convergence criteria
6
+ """
7
+ @abc.abstractmethod
8
+ def Initialize(self) -> None:
9
+ pass
10
+
11
+ """This method returns whether the convergence criteria detected the optimization
12
+ has converged.
13
+ """
14
+ @abc.abstractmethod
15
+ def IsConverged(self) -> bool:
16
+ pass
17
+
18
+ """Finalizes the convergence criteria """
19
+ @abc.abstractmethod
20
+ def Finalize(self) -> None:
21
+ pass
22
+
23
+ """Returns a list[(str, Any)] with information about the current convergence."""
24
+ @abc.abstractmethod
25
+ def GetInfo(self) -> 'list[tuple[str, typing.Union[int, float, str]]]':
26
+ pass
@@ -0,0 +1,77 @@
1
+ import typing, numpy
2
+ import KratosMultiphysics as Kratos
3
+ import KratosMultiphysics.OptimizationApplication as KratosOA
4
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
5
+ from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
6
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem_utilities import GetComponentHavingDataByFullName
7
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem_utilities import GetComponentValueByFullName
8
+ from KratosMultiphysics.OptimizationApplication.convergence_criteria.convergence_criterion import ConvergenceCriterion
9
+ from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import time_decorator
10
+
11
+ def Factory(_: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem) -> ConvergenceCriterion:
12
+ if not parameters.Has("settings"):
13
+ raise RuntimeError(f"L2ConvCriterion instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
14
+ return L2ConvCriterion(parameters["settings"], optimization_problem)
15
+
16
+ class L2ConvCriterion(ConvergenceCriterion):
17
+ """
18
+ L2ConvCriterion is a convergence criterion based on the L2 norm of a specified field in an optimization problem.
19
+
20
+ This class checks whether the L2 norm of a given field (e.g., search direction) falls below a specified tolerance,
21
+ indicating convergence. The field can be either historical or non-historical, and the criterion is configurable
22
+ via parameters.
23
+ """
24
+ @classmethod
25
+ def GetDefaultParameters(cls):
26
+ return Kratos.Parameters("""{
27
+ "component_name": "algorithm",
28
+ "field_name" : "search_direction:historical",
29
+ "tolerance" : 1e-9
30
+ }""")
31
+
32
+ def __init__(self, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
33
+ parameters.ValidateAndAssignDefaults(self.GetDefaultParameters())
34
+
35
+ self.__component_name = parameters["component_name"].GetString()
36
+ self.__field_name = parameters["field_name"].GetString()
37
+ self.__tolerance = parameters["tolerance"].GetDouble()
38
+ self.__optimization_problem = optimization_problem
39
+ self.__component_data_view: 'typing.Optional[ComponentDataView]' = None
40
+
41
+ if self.__field_name.find(":") == -1:
42
+ # not found where the data location. So the default for field names
43
+ # will be unbuffered (i.e. non_historical). So appending it
44
+ self.__field_name += ":non_historical"
45
+
46
+ if self.__tolerance < 0.0:
47
+ raise RuntimeError(f"Tolerance should be non-negative [ tolerance = {self.__tolerance} ].")
48
+
49
+ def Initialize(self):
50
+ component = GetComponentHavingDataByFullName(self.__component_name, self.__optimization_problem)
51
+ self.__component_data_view = ComponentDataView(component, self.__optimization_problem)
52
+
53
+ @time_decorator()
54
+ def IsConverged(self) -> bool:
55
+ field: Kratos.TensorAdaptors.DoubleTensorAdaptor = GetComponentValueByFullName(self.__component_data_view, self.__field_name)
56
+
57
+ if not hasattr(field, "data"):
58
+ raise RuntimeError(f"The value represented by {self.__field_name} is not a field.")
59
+
60
+ self.__norm = numpy.linalg.norm(field.data)
61
+ self.__conv = self.__norm <= self.__tolerance
62
+ self.__component_data_view.GetBufferedData().SetValue(self.__field_name.split(':')[0] + "_l2_norm", self.__norm)
63
+ return self.__conv
64
+
65
+ def Finalize(self):
66
+ pass
67
+
68
+ def GetInfo(self) -> 'list[tuple[str, typing.Union[int, float, str]]]':
69
+ info = [
70
+ ('type' , 'l2_conv_criterion'),
71
+ ('l2_norm' , self.__norm),
72
+ ('tolerance' , self.__tolerance),
73
+ ('component_name', self.__component_name),
74
+ ('field_name' , self.__field_name),
75
+ ('status' , str("converged" if self.__conv else "not converged"))
76
+ ]
77
+ return info
@@ -0,0 +1,85 @@
1
+ import typing
2
+ import KratosMultiphysics as Kratos
3
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
4
+ from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
5
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem_utilities import GetComponentHavingDataByFullName
6
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem_utilities import GetComponentValueByFullName
7
+ from KratosMultiphysics.OptimizationApplication.convergence_criteria.convergence_criterion import ConvergenceCriterion
8
+ from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import time_decorator
9
+
10
+ def Factory(_: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem) -> ConvergenceCriterion:
11
+ if not parameters.Has("settings"):
12
+ raise RuntimeError(f"MagnitudeReductionConvCriterion instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
13
+ return MagnitudeReductionConvCriterion(parameters["settings"], optimization_problem)
14
+
15
+ class MagnitudeReductionConvCriterion(ConvergenceCriterion):
16
+ """
17
+ Convergence criterion based on the reduction of a magnitude (e.g., objective value) during optimization.
18
+
19
+ This criterion checks whether the current value of a specified component has been reduced below a target value,
20
+ which is computed as a scaling factor of the initial value or a specified machine precision, whichever is greater.
21
+
22
+ Raises:
23
+ RuntimeError: If the target scaling factor is not greater than zero or machine precision is negative.
24
+ """
25
+ @classmethod
26
+ def GetDefaultParameters(cls):
27
+ return Kratos.Parameters("""{
28
+ "component_name" : "algorithm",
29
+ "value_name" : "std_obj_value",
30
+ "target_scaling_factor": 1e-3,
31
+ "machine_precision" : 1e-16
32
+ }""")
33
+
34
+ def __init__(self, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
35
+ parameters.ValidateAndAssignDefaults(self.GetDefaultParameters())
36
+
37
+ self.__component_name = parameters["component_name"].GetString()
38
+ self.__value_name = parameters["value_name"].GetString()
39
+ self.__target_scaling_factor = parameters["target_scaling_factor"].GetDouble()
40
+ self.__machine_precision = parameters["machine_precision"].GetDouble()
41
+ self.__optimization_problem = optimization_problem
42
+ self.__component_data_view: 'typing.Optional[ComponentDataView]' = None
43
+
44
+ if self.__value_name.find(":") == -1:
45
+ # not found where the data location. So the default for value names
46
+ # will be buffered (i.e. historical). So appending it
47
+ self.__value_name += ":historical"
48
+
49
+ if self.__target_scaling_factor <= 0.0:
50
+ raise RuntimeError(f"The target scaling factor should be greater than zero [ target_scaling_factor = {self.__target_scaling_factor} ].")
51
+
52
+ if self.__machine_precision < 0.0:
53
+ raise RuntimeError(f"The machine precision should be non-negative [ machine_precision = {self.__machine_precision} ].")
54
+
55
+ def Initialize(self):
56
+ component = GetComponentHavingDataByFullName(self.__component_name, self.__optimization_problem)
57
+ self.__component_data_view = ComponentDataView(component, self.__optimization_problem)
58
+
59
+ @time_decorator()
60
+ def IsConverged(self) -> bool:
61
+ iter = self.__optimization_problem.GetStep()
62
+ self.__current_value = GetComponentValueByFullName(self.__component_data_view, self.__value_name)
63
+
64
+ if iter == 0:
65
+ self.__target_value = max(self.__current_value * self.__target_scaling_factor, self.__machine_precision)
66
+ self.__component_data_view.GetUnBufferedData().SetValue(f"{self.__value_name.split(':')[0]}_conv_target", self.__target_value)
67
+ self.__conv = False
68
+ else:
69
+ self.__conv = self.__current_value <= self.__target_value
70
+
71
+ return self.__conv
72
+
73
+ def Finalize(self):
74
+ pass
75
+
76
+ def GetInfo(self) -> 'list[tuple[str, typing.Union[int, float, str]]]':
77
+ info = [
78
+ ('type' , 'magnitude_reduction_conv_criterion'),
79
+ ('value' , self.__current_value),
80
+ ('target_value' , self.__target_value),
81
+ ('component_name', self.__component_name),
82
+ ('value_name' , self.__value_name),
83
+ ('status' , str("converged" if self.__conv else "not converged"))
84
+ ]
85
+ return info
@@ -0,0 +1,48 @@
1
+ import typing
2
+ import KratosMultiphysics as Kratos
3
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
4
+ from KratosMultiphysics.OptimizationApplication.convergence_criteria.convergence_criterion import ConvergenceCriterion
5
+ from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import time_decorator
6
+
7
+ def Factory(_: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem) -> ConvergenceCriterion:
8
+ if not parameters.Has("settings"):
9
+ raise RuntimeError(f"MaxIterConvCriterion instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
10
+ return MaxIterConvCriterion(parameters["settings"], optimization_problem)
11
+
12
+ class MaxIterConvCriterion(ConvergenceCriterion):
13
+ """
14
+ MaxIterConvCriterion is a convergence criterion for optimization problems based on the maximum number of iterations.
15
+ """
16
+ @classmethod
17
+ def GetDefaultParameters(cls):
18
+ return Kratos.Parameters("""{
19
+ "max_iter": 0
20
+ }""")
21
+
22
+ def __init__(self, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
23
+ parameters.ValidateAndAssignDefaults(self.GetDefaultParameters())
24
+
25
+ self.__max_iter = parameters["max_iter"].GetInt()
26
+ self.__optimization_problem = optimization_problem
27
+
28
+ if self.__max_iter < 0:
29
+ raise RuntimeError(f"The number of max iterations cannot negative.")
30
+
31
+ def Initialize(self):
32
+ pass
33
+
34
+ @time_decorator()
35
+ def IsConverged(self) -> bool:
36
+ self.__conv = (self.__optimization_problem.GetStep() >= self.__max_iter)
37
+ return self.__conv
38
+
39
+ def Finalize(self):
40
+ pass
41
+
42
+ def GetInfo(self) -> 'list[tuple[str, typing.Union[int, float, str]]]':
43
+ info = [
44
+ ("type" , "max_iter_conv_criterion"),
45
+ ("iter" , f"{self.__optimization_problem.GetStep()} of {self.__max_iter}"),
46
+ ("status", str("converged" if self.__conv else "not converged"))
47
+ ]
48
+ return info
@@ -0,0 +1,116 @@
1
+ import typing
2
+ import numpy
3
+ import KratosMultiphysics as Kratos
4
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
5
+ from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
6
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem_utilities import GetComponentHavingDataByFullName
7
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem_utilities import GetComponentValueByFullName
8
+ from KratosMultiphysics.OptimizationApplication.convergence_criteria.convergence_criterion import ConvergenceCriterion
9
+ from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import time_decorator
10
+
11
+ def Factory(_: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem) -> ConvergenceCriterion:
12
+ if not parameters.Has("settings"):
13
+ raise RuntimeError(f"PatienceConvCriterion instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
14
+ return PatienceConvCriterion(parameters["settings"], optimization_problem)
15
+
16
+ class PatienceConvCriterion(ConvergenceCriterion):
17
+ """
18
+ Convergence criterion based on the 'patience' concept, commonly used in optimization and machine learning.
19
+
20
+ This criterion monitors the improvement of a specified value (e.g., objective function) over iterations.
21
+ Convergence is declared if no significant improvement (greater than a specified tolerance) is observed
22
+ for a consecutive number of iterations (patience_itr), after a minimum number of iterations (minimum_itr)
23
+ have been performed.
24
+
25
+ Raises:
26
+ RuntimeError: If tolerance is negative, minimum_itr is not positive, patience_itr is not greater than minimum_itr,
27
+ or the monitored value is not a float or int.
28
+ """
29
+ @classmethod
30
+ def GetDefaultParameters(cls):
31
+ return Kratos.Parameters("""{
32
+ "component_name": "algorithm",
33
+ "value_name" : "std_obj_value",
34
+ "minimum_itr" : 100,
35
+ "patience_itr" : 50,
36
+ "tolerance" : 1e-6
37
+ }""")
38
+
39
+ def __init__(self, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
40
+ parameters.ValidateAndAssignDefaults(self.GetDefaultParameters())
41
+
42
+ self.__component_name = parameters["component_name"].GetString()
43
+ self.__value_name = parameters["value_name"].GetString()
44
+ self.__tolerance = parameters["tolerance"].GetDouble()
45
+ self.__patience_itr = parameters["patience_itr"].GetInt()
46
+ self.__minimum_itr = parameters["minimum_itr"].GetInt()
47
+ self.__optimization_problem = optimization_problem
48
+ self.__component_data_view: 'typing.Optional[ComponentDataView]' = None
49
+
50
+ if self.__value_name.find(":") == -1:
51
+ # not found where the data location. So the default for value names
52
+ # will be buffered (i.e. historical). So appending it
53
+ self.__value_name += ":historical"
54
+
55
+ if self.__tolerance < 0.0:
56
+ raise RuntimeError(f"Tolerance should be non-negative [ tolerance = {self.__tolerance} ].")
57
+
58
+ if self.__minimum_itr <= 0:
59
+ raise RuntimeError(f"The minimum number of iterations needs to be greater than 0 [ minimum_itr = {self.__minimum_itr} ].")
60
+
61
+ if self.__patience_itr >= self.__minimum_itr:
62
+ raise RuntimeError(f"The number of patience iterations needs to be greater than minimum number of iterations [ patience_itr = {self.__patience_itr}, minimum_itr = {self.__minimum_itr} ].")
63
+
64
+ self.__best_value: 'typing.Optional[float]' = None
65
+ self.__patience_step = 0
66
+
67
+ def Initialize(self):
68
+ component = GetComponentHavingDataByFullName(self.__component_name, self.__optimization_problem)
69
+ self.__component_data_view = ComponentDataView(component, self.__optimization_problem)
70
+
71
+ @time_decorator()
72
+ def IsConverged(self) -> bool:
73
+ step = self.__optimization_problem.GetStep()
74
+ value = GetComponentValueByFullName(self.__component_data_view, self.__value_name)
75
+
76
+ if not isinstance(value, float) and not isinstance(value, int):
77
+ raise RuntimeError(f"The value represented by {self.__value_name} is not a floating or int value.")
78
+
79
+ if self.__best_value is None:
80
+ self.__init_value = value
81
+ self.__best_value = value
82
+
83
+ if step >= self.__minimum_itr:
84
+ if self.__best_value > value + self.__tolerance * self.__init_value:
85
+ self.__best_value = value
86
+ self.__patience_step = 0
87
+ else:
88
+ self.__patience_step += 1
89
+
90
+ # say it is converged if you cannot find a better solution within the number of
91
+ # patience iterations. That means, there were no improvement for patience iterations.
92
+ self.__conv = self.__patience_step >= self.__patience_itr
93
+ else:
94
+ self.__conv = False
95
+
96
+ self.__component_data_view.GetBufferedData().SetValue(f"{self.__value_name.split(':')[0]}_pat_itr_{self.__patience_itr}_best_value", self.__best_value)
97
+ self.__component_data_view.GetBufferedData().SetValue(f"{self.__value_name.split(':')[0]}_pat_itr_{self.__patience_itr}_patience_step", self.__patience_step)
98
+
99
+ return self.__conv
100
+
101
+ def Finalize(self):
102
+ pass
103
+
104
+ def GetInfo(self) -> 'list[tuple[str, typing.Union[int, float, str]]]':
105
+ info = [
106
+ ('type' , 'patience_conv_criterion'),
107
+ ('best_value' , self.__best_value),
108
+ ('patience_step' , self.__patience_step),
109
+ ('patience_itr' , self.__patience_itr),
110
+ ('minimum_itr' , self.__minimum_itr),
111
+ ('tolerance' , self.__tolerance),
112
+ ('component_name', self.__component_name),
113
+ ('value_name' , self.__value_name),
114
+ ('status' , str("converged" if self.__conv else "not converged"))
115
+ ]
116
+ return info
@@ -0,0 +1,64 @@
1
+ import typing
2
+ import KratosMultiphysics as Kratos
3
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
4
+ from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
5
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem_utilities import GetComponentHavingDataByFullName
6
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem_utilities import GetComponentValueByFullName
7
+ from KratosMultiphysics.OptimizationApplication.convergence_criteria.convergence_criterion import ConvergenceCriterion
8
+ from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import time_decorator
9
+
10
+ def Factory(_: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem) -> ConvergenceCriterion:
11
+ if not parameters.Has("settings"):
12
+ raise RuntimeError(f"TargetValueConvCriterion instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
13
+ return TargetValueConvCriterion(parameters["settings"], optimization_problem)
14
+
15
+ class TargetValueConvCriterion(ConvergenceCriterion):
16
+ """
17
+ TargetValueConvCriterion is a convergence criterion for optimization problems that checks
18
+ whether a specified value associated with a component has reached a target threshold.
19
+ """
20
+ @classmethod
21
+ def GetDefaultParameters(cls):
22
+ return Kratos.Parameters("""{
23
+ "component_name": "algorithm",
24
+ "value_name" : "std_obj_value",
25
+ "target_value" : 1e-9
26
+ }""")
27
+
28
+ def __init__(self, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
29
+ parameters.ValidateAndAssignDefaults(self.GetDefaultParameters())
30
+
31
+ self.__component_name = parameters["component_name"].GetString()
32
+ self.__value_name = parameters["value_name"].GetString()
33
+ self.__target_value = parameters["target_value"].GetDouble()
34
+ self.__optimization_problem = optimization_problem
35
+ self.__component_data_view: 'typing.Optional[ComponentDataView]' = None
36
+
37
+ if self.__value_name.find(":") == -1:
38
+ # not found where the data location. So the default for value names
39
+ # will be buffered (i.e. historical). So appending it
40
+ self.__value_name += ":historical"
41
+
42
+ def Initialize(self):
43
+ component = GetComponentHavingDataByFullName(self.__component_name, self.__optimization_problem)
44
+ self.__component_data_view = ComponentDataView(component, self.__optimization_problem)
45
+
46
+ @time_decorator()
47
+ def IsConverged(self) -> bool:
48
+ self.__current_value = GetComponentValueByFullName(self.__component_data_view, self.__value_name)
49
+ self.__conv = self.__current_value <= self.__target_value
50
+ return self.__conv
51
+
52
+ def Finalize(self):
53
+ pass
54
+
55
+ def GetInfo(self) -> 'list[tuple[str, typing.Union[int, float, str]]]':
56
+ info = [
57
+ ('type' , 'target_value_conv_criteria'),
58
+ ('value' , self.__current_value),
59
+ ('target_value' , self.__target_value),
60
+ ('component_name', self.__component_name),
61
+ ('value_name' , self.__value_name),
62
+ ('status' , str("converged" if self.__conv else "not converged"))
63
+ ]
64
+ return info
@@ -0,0 +1,46 @@
1
+ from abc import ABC, abstractmethod
2
+ import KratosMultiphysics as Kratos
3
+
4
+ class ExecutionPolicy(ABC):
5
+ """Base class for execution policy
6
+
7
+ This represents the base class for the execution policy which
8
+ can be used to execute primal analysis to obtain response function
9
+ values and their gradients.
10
+
11
+ """
12
+ def __init__(self, execution_policy_name: str) -> None:
13
+ self.__name = execution_policy_name
14
+
15
+ def GetName(self) -> str:
16
+ return self.__name
17
+
18
+ @abstractmethod
19
+ def Initialize(self) -> None:
20
+ pass
21
+
22
+ @abstractmethod
23
+ def Check(self) -> None:
24
+ pass
25
+
26
+ @abstractmethod
27
+ def Finalize(self) -> None:
28
+ pass
29
+
30
+ @abstractmethod
31
+ def GetAnalysisModelPart(self) -> Kratos.ModelPart:
32
+ """Returns the analysis model part.
33
+
34
+ Each execution policy will be using a domain to compute the primal model part.
35
+ This method should return that domain as a Kratos::ModelPart.
36
+
37
+ Returns:
38
+ Kratos.ModelPart: Domain used to compute the primal solution.
39
+ """
40
+ pass
41
+
42
+ @abstractmethod
43
+ def Execute(self) -> None:
44
+ """Solves the associated primal problem.
45
+ """
46
+ pass
@@ -0,0 +1,67 @@
1
+ import KratosMultiphysics as Kratos
2
+ from KratosMultiphysics.model_parameters_factory import KratosModelParametersFactory
3
+ from KratosMultiphysics.OptimizationApplication.execution_policies.execution_policy import ExecutionPolicy
4
+ from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import FileLogger
5
+ from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import TimeLogger
6
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem_utilities import OptimizationComponentFactory
7
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
8
+ from KratosMultiphysics.OptimizationApplication.utilities.helper_utilities import CallOnAll
9
+
10
+ class ExecutionPolicyDecorator(ExecutionPolicy):
11
+ def __init__(self, model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
12
+ default_parameters = Kratos.Parameters("""{
13
+ "name" : "",
14
+ "type" : "please_provide_python_module_name",
15
+ "module" : "KratosMultiphysics.OptimizationApplication.execution_policies",
16
+ "pre_operations" : [],
17
+ "post_operations": [],
18
+ "log_in_file" : false,
19
+ "log_file_name" : "",
20
+ "settings" : {}
21
+ }""")
22
+ parameters.ValidateAndAssignDefaults(default_parameters)
23
+
24
+ super().__init__(parameters["name"].GetString())
25
+
26
+ self.__log_file_name = parameters["log_file_name"].GetString()
27
+ self.__log_in_file = parameters["log_in_file"].GetBool()
28
+
29
+ if self.__log_in_file and self.__log_file_name == "":
30
+ raise RuntimeError("Logger file name is empty for execution policy. Please provide \"log_file_name\" or make \"log_in_file\" to false.")
31
+
32
+ factory = KratosModelParametersFactory(model)
33
+
34
+ # create operations
35
+ self.__list_of_pre_operations: 'list[Kratos.Operation]' = factory.ConstructListOfItems(parameters["pre_operations"])
36
+ self.__list_of_post_operations: 'list[Kratos.Operation]' = factory.ConstructListOfItems(parameters["post_operations"])
37
+
38
+ # create execution policy
39
+ self.__execution_policy: ExecutionPolicy = OptimizationComponentFactory(model, parameters, optimization_problem)
40
+
41
+ def GetExecutionPolicy(self):
42
+ return self.__execution_policy
43
+
44
+ def GetAnalysisModelPart(self) -> Kratos.ModelPart:
45
+ return self.__execution_policy.GetAnalysisModelPart()
46
+
47
+ def Initialize(self):
48
+ self.__execution_policy.Initialize()
49
+
50
+ def Check(self):
51
+ self.__execution_policy.Check()
52
+
53
+ def Finalize(self):
54
+ self.__execution_policy.Finalize()
55
+
56
+ def Execute(self):
57
+ with TimeLogger(f"ExecutionPolicyDecorator::Executing {self.GetName()}", None, "Finished"):
58
+ if self.__log_in_file:
59
+ with FileLogger(self.__log_file_name):
60
+ self.__ExecuteWithoutFileLogger()
61
+ else:
62
+ self.__ExecuteWithoutFileLogger()
63
+
64
+ def __ExecuteWithoutFileLogger(self):
65
+ CallOnAll(self.__list_of_pre_operations, Kratos.Operation.Execute)
66
+ self.__execution_policy.Execute()
67
+ CallOnAll(self.__list_of_post_operations, Kratos.Operation.Execute)
@@ -0,0 +1,78 @@
1
+ from typing import Union
2
+ from importlib import import_module
3
+
4
+ import KratosMultiphysics as Kratos
5
+ from KratosMultiphysics.analysis_stage import AnalysisStage
6
+ from KratosMultiphysics.project import Project
7
+ from KratosMultiphysics.orchestrators.orchestrator import Orchestrator
8
+ from KratosMultiphysics.OptimizationApplication.execution_policies.execution_policy import ExecutionPolicy
9
+ from KratosMultiphysics.OptimizationApplication.utilities.helper_utilities import GetClassModuleFromKratos
10
+
11
+ def Factory(model: Kratos.Model, parameters: Kratos.Parameters, _) -> ExecutionPolicy:
12
+ if not parameters.Has("name"):
13
+ raise RuntimeError(f"IndependentAnalysisExecutionPolicy instantiation requires a \"name\" in parameters [ parameters = {parameters}].")
14
+ if not parameters.Has("settings"):
15
+ raise RuntimeError(f"IndependentAnalysisExecutionPolicy instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
16
+
17
+ return IndependentAnalysisExecutionPolicy(parameters["name"].GetString(), model, parameters["settings"])
18
+
19
+ class IndependentAnalysisExecutionPolicy(ExecutionPolicy):
20
+ def __init__(self, name: str, model: Kratos.Model, parameters: Kratos.Parameters):
21
+ super().__init__(name)
22
+
23
+ self.model = model
24
+
25
+ default_settings = Kratos.Parameters("""{
26
+ "analysis_module" : "KratosMultiphysics",
27
+ "analysis_type" : "",
28
+ "analysis_model_part_name": "",
29
+ "analysis_settings" : {}
30
+ }""")
31
+
32
+ parameters.ValidateAndAssignDefaults(default_settings)
33
+
34
+ self.analysis_module = parameters["analysis_module"].GetString()
35
+ self.analysis_type = parameters["analysis_type"].GetString()
36
+ self.analysis_settings = parameters["analysis_settings"]
37
+ self.analysis_model_part_name = parameters["analysis_model_part_name"].GetString()
38
+
39
+ if self.analysis_module == "KratosMultiphysics":
40
+ self.analysis_full_module, self.analysis_type = GetClassModuleFromKratos(self.analysis_type)
41
+ else:
42
+ self.analysis_full_module = f"{self.analysis_module}.{Kratos.StringUtilities.ConvertCamelCaseToSnakeCase(self.analysis_type)}"
43
+
44
+
45
+ def Initialize(self) -> None:
46
+ pass
47
+
48
+ def Check(self) -> None:
49
+ pass
50
+
51
+ def Finalize(self) -> None:
52
+ pass
53
+
54
+ def Execute(self):
55
+ analysis_type = getattr(import_module(self.analysis_full_module), self.analysis_type)
56
+ if AnalysisStage in analysis_type.mro():
57
+ # the analysis type is derived from AnalysisStage
58
+ self.current_analysis: AnalysisStage = getattr(import_module(self.analysis_full_module), self.analysis_type)(self.model, self.analysis_settings.Clone())
59
+ elif Orchestrator in analysis_type.mro():
60
+ # the analysis type is derive from the Orchestrator
61
+ project = Project(self.analysis_settings.Clone())
62
+ self.current_analysis: Orchestrator = getattr(import_module(self.analysis_full_module), self.analysis_type)(project)
63
+
64
+ self.current_analysis.Run()
65
+
66
+ def GetAnalysisModelPart(self):
67
+ if self.current_analysis is not None:
68
+ if isinstance(self.current_analysis, AnalysisStage):
69
+ if self.analysis_model_part_name == "" or self.analysis_model_part_name == self.current_analysis._GetSolver().GetComputingModelPart().FullName():
70
+ return self.current_analysis._GetSolver().GetComputingModelPart()
71
+ else:
72
+ raise RuntimeError(f"The specified analysis model part name mismatch [ specified analysis model part name = {self.analysis_model_part_name}, used analysis model part name = {self.current_analysis._GetSolver().GetComputingModelPart().FullName()} ].")
73
+ elif isinstance(self.current_analysis, Orchestrator):
74
+ return self.current_analysis.GetProject().GetModel()[self.analysis_model_part_name]
75
+ else:
76
+ raise RuntimeError(f"Unsupported analysis type = {self.current_analysis}.")
77
+ else:
78
+ raise RuntimeError("The analysis is not run yet.")