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,399 @@
1
+ from __future__ import annotations
2
+ from typing import Any
3
+
4
+ class BufferedDict:
5
+ """Buffered dict container with buffered data ability
6
+
7
+ Instances of this can hold (str, Any) data pairs in hierachychal data
8
+ structure where each sub item can have their own buffer sizes. Hence,
9
+ Different sub structures can have their own buffers and can be advanced
10
+ separately or all together.
11
+
12
+ Overwriting of the existing data is not allowed because, this is used
13
+ as a central place to store data from various objects, hence allowing
14
+ overwriting will make difficult to track the changes.
15
+
16
+ Buffer size setting can only be done at the construction time
17
+ of the instance to not to allow re sizing because then it is not
18
+ clear how to handle the connected steps.
19
+
20
+ The buffered data is stored in a cyclic buffer.
21
+ """
22
+ def __init__(self, buffer_size: int = 1, clear_buffer_when_advancing: bool = True):
23
+ """Creates an instance of BufferedDict with specified buffer size
24
+
25
+ This creates an instance of buffered data with given buffer size.
26
+
27
+ Args:
28
+ buffer_size (int, optional): Cyclic buffer size. Defaults to 1.
29
+ clear_buffer_when_advancing (bool): Clears the buffer and sub item buffers when advancing.
30
+ """
31
+ self.__parent = None
32
+ self.__buffer_index = 0
33
+ self.__buffered_data: 'list[dict[str, Any]]' = []
34
+ self.__sub_items: 'dict[str, BufferedDict]' = {}
35
+ self.__clear_buffer_when_advancing = clear_buffer_when_advancing
36
+
37
+ # sets the buffer
38
+ self.__SetBufferSize(buffer_size)
39
+
40
+ def GetBufferSize(self) -> int:
41
+ """Returns the buffer size of current instance of buffered data
42
+
43
+ Returns:
44
+ int: Buffer size of the cyclic buffer
45
+ """
46
+ return len(self.__buffered_data)
47
+
48
+ def AdvanceStep(self, recursive = True) -> None:
49
+ """Advances the buffered data containers
50
+
51
+ Advances to the next index of the buffer in the cyclic buffer
52
+ making the current index accessible as a past value index (step_index = 1)
53
+
54
+ Clears the values in the current step after advancement.
55
+
56
+ Args:
57
+ recursive (bool, optional): Advance step recursively in sub items. Defaults to True.
58
+ """
59
+ # first advance the current instance
60
+ self.__buffer_index = (self.__buffer_index + 1) % self.GetBufferSize()
61
+ if self.__clear_buffer_when_advancing:
62
+ self.__buffered_data[self.__GetBufferIndex(0)] = {}
63
+
64
+ if recursive:
65
+ # now advance the sub items
66
+ for sub_item in self.__sub_items.values():
67
+ sub_item.AdvanceStep(recursive)
68
+
69
+ def HasValue(self, key: str, step_index: int = 0) -> bool:
70
+ """Checks whether key exists in the given step_index
71
+
72
+ The key in here should always be relative to the instance it is called upon.
73
+ Hence, this key can have "/" separations for subitems, then this method
74
+ will navigate through the sub items as well to check whether given key is available.
75
+
76
+ Args:
77
+ key (str): Relative path of the key to be checked for.
78
+ step_index (int, optional): Step index to be looked for. Defaults to 0.
79
+
80
+ Returns:
81
+ bool: True if the key is found in given step index. False otherwise.
82
+ """
83
+ pos = key.find("/")
84
+
85
+ if pos == -1:
86
+ # this is a leaf key, then look for the value
87
+ # first in the value container
88
+ if step_index < self.GetBufferSize() and step_index >= 0:
89
+ if key in self.__buffered_data[self.__GetBufferIndex(step_index)].keys():
90
+ return True
91
+ # now if it was not in the buffered data, then check it in sub items.
92
+ return key in self.__sub_items.keys()
93
+ else:
94
+ # not the leaf key. hence check for the sub items
95
+ current_key = key[:pos]
96
+ if current_key in self.__sub_items.keys():
97
+ # found the subkey. Call HasValue recursively
98
+ return self.__sub_items[current_key].HasValue(key[pos+1:], step_index)
99
+ else:
100
+ # not found the subkey. Hence the given key is not available.
101
+ return False
102
+
103
+ def GetValue(self, key: str, step_index: int = 0) -> Any:
104
+ """Get the value given by the key at the specified step_index.
105
+
106
+ This method retrieves the value given by the key at the specified step_index.
107
+ The key must be the relative path w.r.t. current instance of the BufferedDict.
108
+ It can include "/" separators to get a value which is in sub items. In this case,
109
+ it will be retrieved by recursive calls.
110
+
111
+ Args:
112
+ key (str): Relative path to the value.
113
+ step_index (int, optional): Step index the value should be retrieved. Defaults to 0.
114
+
115
+ Raises:
116
+ RuntimeError: If the given key is not found.
117
+ RuntimeError: If parent keys are not found.
118
+
119
+ Returns:
120
+ Any: Value stored at the key for the specified step_index.
121
+ """
122
+ pos = key.find("/")
123
+
124
+ if pos == -1:
125
+ # this is a leaf key, then look for the value
126
+ if not self.HasValue(key, step_index):
127
+ raise RuntimeError(f"The key \"{key}\" not found in the buffered data [ step_index = {step_index} ]. BufferedDict:\n{self}")
128
+
129
+ # first in the value container
130
+ if step_index < self.GetBufferSize() and step_index >= 0:
131
+ buffer_data = self.__buffered_data[self.__GetBufferIndex(step_index)]
132
+ if key in buffer_data.keys():
133
+ return buffer_data[key]
134
+
135
+ # now if it was not in the buffered data, then it is in sub items.
136
+ return self.__sub_items[key]
137
+ else:
138
+ current_key = key[:pos]
139
+ if current_key in self.__sub_items.keys():
140
+ return self.__sub_items[current_key].GetValue(key[pos+1:], step_index)
141
+ else:
142
+ raise RuntimeError(f"The key \"{current_key}\" not found in the buffered data which is a parent key for \"{key}\". BufferedDict:\n{self}")
143
+
144
+ def SetValue(self, key: str, value: Any, step_index: int = 0, overwrite: bool = False) -> None:
145
+ """Sets a value for specified key at specified step_index.
146
+
147
+ This method sets the value at the key at the specified step_index.
148
+ The key must be the relative path w.r.t. current instance of the BufferedDict.
149
+ It can include "/" separators to set a value which is in sub items. In this case,
150
+ it will be set by recursive calls.
151
+
152
+ Args:
153
+ key (str): Relative path to the value.
154
+ value (Any): value to be set
155
+ step_index (int, optional): Step index the value should be set. Defaults to 0.
156
+ overwrite (bool): Overwrites if existing key is found with the new value, otherwise creates a key with the value.
157
+
158
+ Raises:
159
+ RuntimeError: If a value is overwritten.
160
+ """
161
+ pos = key.find("/")
162
+ if pos == -1:
163
+ # this is a leaf, then we check the type of the value and add appropriately
164
+ if isinstance(value, dict):
165
+ # if the given value is a dict, then convert the structure
166
+ # to BufferedDict while keeping the sub_item structure.
167
+ sub_item = BufferedDict(self.GetBufferSize(), self.__clear_buffer_when_advancing)
168
+ self.__AddSubItem(key, sub_item)
169
+
170
+ # now iterate through all the sub_keys and values of the dictionary and
171
+ # add them to sub_item
172
+ for sub_key, sub_value in value.items():
173
+ sub_item.SetValue(f"{sub_key}", sub_value, step_index)
174
+ elif isinstance(value, BufferedDict):
175
+ # if the given value is of type BufferedDict, then put it to sub_items.
176
+ self.__AddSubItem(key, value)
177
+ else:
178
+ # if not any of the above, it is a normal value. Then put it to buffer.
179
+ self.__AddBufferedValue(key, value, step_index, overwrite)
180
+ else:
181
+ # if it is not a leaf key. then look for the sub_item, and recursively
182
+ # call the Set method.
183
+ current_key = key[:pos]
184
+ if not current_key in self.__sub_items.keys():
185
+ # no existing key found then create it.
186
+ self.__AddSubItem(current_key, BufferedDict(self.GetBufferSize(), self.__clear_buffer_when_advancing))
187
+
188
+ self.__sub_items[current_key].SetValue(key[pos+1:], value, step_index, overwrite)
189
+
190
+ def RemoveValue(self, key: str, step_index: int = 0) -> None:
191
+ """Remove value at the key in the specified step_index
192
+
193
+ This method removes value at the key specified at the step_index.
194
+ The key must be the relative path w.r.t. current instance of the BufferedDict.
195
+ It can include "/" separators to remove a value which is in sub items. In this case,
196
+ it will be removed by recursive calls.
197
+
198
+ Args:
199
+ key (str): Relative path to the value.
200
+ step_index (int, optional): Step index the value should be removed from. Defaults to 0.
201
+
202
+ Raises:
203
+ RuntimeError: If the given key is not found.
204
+ RuntimeError: If the given parents of the key is not found.
205
+ """
206
+ pos = key.find("/")
207
+ if pos == -1:
208
+ # found a leaf key.
209
+ is_reomved = False
210
+
211
+ if step_index < self.GetBufferSize() and step_index >= 0:
212
+ buffer_data = self.__buffered_data[self.__GetBufferIndex(step_index)]
213
+ # check whether the key is available in the given step_index
214
+ if key in buffer_data.keys():
215
+ is_reomved = True
216
+ del buffer_data[key]
217
+
218
+ if not is_reomved:
219
+ # if it is not removed from the buffered data, then check whether it is available
220
+ # in the sub_items
221
+ if key in self.__sub_items.keys():
222
+ is_reomved = True
223
+ del self.__sub_items[key]
224
+
225
+ if not is_reomved:
226
+ raise RuntimeError(f"\"{key}\" is not found. BufferedDict:\n{self}")
227
+ else:
228
+ # it is not a leaf key
229
+ current_key = key[:pos]
230
+ if current_key in self.__sub_items.keys():
231
+ # call recursively the sub_items remove value
232
+ self.__sub_items[current_key].RemoveValue(key[pos+1:], step_index)
233
+ else:
234
+ raise RuntimeError(f"\"{key}\" is not found. BufferedDict:\n{self}")
235
+
236
+ def GetValueItems(self, step_index: int = 0) -> 'dict[str, Any]':
237
+ return self.__buffered_data[self.__GetBufferIndex(step_index)]
238
+
239
+ def GetSubItems(self) -> 'dict[str, BufferedDict]':
240
+ return self.__sub_items
241
+
242
+ def GetMap(self, step_index: int = 0) -> 'dict[str, Any]':
243
+ """Generates (str, Any) pair map with recursively collecting all items in the BufferedDict
244
+
245
+ This method recursively collects all items in the buffered data and returns a dict
246
+ with (str, Any) pairs. All the sub_items are also added as (str, BufferedDict) pairs.
247
+
248
+ Args:
249
+ step_index (int, optional): Step index the value should be looked at. Defaults to 0.
250
+
251
+ Returns:
252
+ dict[str, Any]: (str, Any) map of all the items.
253
+ """
254
+ key_value_pair_map = {}
255
+ self.__AddKeyValuePairsToMap("", key_value_pair_map, step_index)
256
+ return key_value_pair_map
257
+
258
+ def GetParent(self) -> BufferedDict:
259
+ """Get the parent of the current buffered data
260
+
261
+ Returns:
262
+ BufferedDict: Returns parent of the current instance.
263
+ """
264
+ return self.__parent
265
+
266
+ def GetRoot(self) -> BufferedDict:
267
+ """Get the root parent of the current buffered data
268
+
269
+ Get the root parent of the current buffered data by recursive calls.
270
+
271
+ Returns:
272
+ BufferedDict: Root parent of the current buffered data.
273
+ """
274
+ if self.GetParent() is not None:
275
+ return self.GetParent().GetRoot()
276
+ else:
277
+ return self
278
+
279
+ def PrintData(self, step_index: int = -1, tabbing = "") -> str:
280
+ """Prints containing data in a json like structure.
281
+
282
+ This method prints containing data and sub_item data recursively.
283
+
284
+ If the step_index == -1 then, it prints all the values on all the steps of the buffer
285
+ in current and all the sub_items recursively.
286
+
287
+ If the step_index > 0 then, it will only print values at that specified buffer index for
288
+ current instance as well as all the sub_items.
289
+
290
+ Args:
291
+ step_index (int, optional): Step index to be printed. Defaults to -1.
292
+ tabbing (str, optional): Initial tabbing for json output.. Defaults to "".
293
+
294
+ Returns:
295
+ str: String will all the containing values formatted like json.
296
+ """
297
+ info = self.__Info(step_index, tabbing)
298
+ info = f"{tabbing}{info}"
299
+ return info
300
+
301
+ def __AddKeyValuePairsToMap(self, current_path: str, key_value_pair_map: 'dict[str, Any]', step_index: int) -> None:
302
+ # first add the buffered data
303
+ if step_index >= 0 and step_index < self.GetBufferSize():
304
+ buffer_data = self.__buffered_data[self.__GetBufferIndex(step_index)]
305
+ for k, v in buffer_data.items():
306
+ key_value_pair_map[f"{current_path}{k}"] = v
307
+
308
+ # now add the sub item data recursively
309
+ for k, v in self.__sub_items.items():
310
+ key_value_pair_map[f"{current_path}{k}"] = v
311
+ v.__AddKeyValuePairsToMap(f"{current_path}{k}/", key_value_pair_map, step_index)
312
+
313
+ def __AddBufferedValue(self, key: str, value: Any, step_index: int, overwrite: bool) -> None:
314
+ # first check whether this key exists in the specified step_index
315
+ buffer_data = self.__buffered_data[self.__GetBufferIndex(step_index)]
316
+ if not overwrite and key in buffer_data.keys():
317
+ raise RuntimeError(f"Trying to add a buffer value with key = \"{key}\" when already value exists for the key [ Existing value = {buffer_data[key]}]. BufferedDict:\n{self}")
318
+
319
+ # now check whether a sub item exists
320
+ if key in self.__sub_items.keys():
321
+ raise RuntimeError(f"Trying to add a buffer value with key = \"{key}\" when a subitem exists with the same key. BufferedDict:\n{self}")
322
+
323
+ # now add the buffer value
324
+ buffer_data[key] = value
325
+
326
+ def __AddSubItem(self, key: str, value: BufferedDict) -> None:
327
+ # first check if any of the buffered data has the same key.
328
+ # this is because, sub_items are valid for all step_indices.
329
+ if any([key in buffer_data.keys() for buffer_data in self.__buffered_data]):
330
+ raise RuntimeError(f"Trying to add a new a sub item with key = \"{key}\" when a value with the same key exists in buffered data. BufferedDict:\n{self}")
331
+
332
+ # now check if the item exists in the sub_items
333
+ if key in self.__sub_items.keys():
334
+ raise RuntimeError(f"Trying to add a new sub_item with key = \"{key}\" when already a sub item exists. BufferedDict:\n{self}")
335
+
336
+ # now add the sub_item
337
+ value.__parent = self
338
+ self.__sub_items[key] = value
339
+
340
+ def __SetBufferSize(self, buffer_size: int) -> None:
341
+ self.__buffer_index = 0
342
+ self.__buffered_data.clear()
343
+ for _ in range(buffer_size):
344
+ self.__buffered_data.append({})
345
+
346
+ def __GetBufferIndex(self, step_index: int) -> int:
347
+ if step_index >= self.GetBufferSize() or step_index < 0:
348
+ raise RuntimeError(f"Invalid step index. Allowed step indices are in [0, {self.GetBufferSize()}) [ StepIndex = {step_index} ]. BufferedDict:\n{self}")
349
+
350
+ return (self.__buffer_index - step_index) % self.GetBufferSize()
351
+
352
+ def __Info(self, step_index: int, tabbing: str) -> str:
353
+ info = "{"
354
+
355
+ if step_index == -1:
356
+ for i in range(self.GetBufferSize()):
357
+ info += f"\n{tabbing}\t--- Step = {i:2d} ---"
358
+ for key, value in self.__buffered_data[self.__GetBufferIndex(i)].items():
359
+ info += f"\n{tabbing}\t\"{key}\": {value}"
360
+ else:
361
+ for key, value in self.__buffered_data[self.__GetBufferIndex(step_index)].items():
362
+ info += f"\n{tabbing}\t\"{key}\": {value}"
363
+
364
+ if step_index == -1:
365
+ info += f"\n{tabbing}\t--- Sub items ---"
366
+
367
+ next_tabbing = f"{tabbing}\t"
368
+ for sub_key, sub_value in self.__sub_items.items():
369
+ info += f"\n{tabbing}\t\"{sub_key}\": {sub_value.__Info(step_index, next_tabbing)}"
370
+
371
+ info += f"\n{tabbing}" + "}"
372
+ return info
373
+
374
+ def __getitem__(self, key: str) -> Any:
375
+ if isinstance(key, str):
376
+ return self.GetValue(key)
377
+ elif isinstance(key, tuple) and len(key) == 2:
378
+ return self.GetValue(key[0], key[1])
379
+ else:
380
+ raise RuntimeError(f"The key should be either a string (representing the key path) or (string, int) tuple (representing key path and step index) [ key = {key}].")
381
+
382
+ def __setitem__(self, key: str, value: Any) -> None:
383
+ if isinstance(key, str):
384
+ return self.SetValue(key, value)
385
+ elif isinstance(key, tuple) and len(key) == 2:
386
+ return self.SetValue(key[0], value, key[1])
387
+ else:
388
+ raise RuntimeError(f"The key should be either a string (representing the key path) or (string, int) tuple (representing key path and step index) [ key = {key}].")
389
+
390
+ def __delitem__(self, key: str) -> None:
391
+ if isinstance(key, str):
392
+ return self.RemoveValue(key)
393
+ elif isinstance(key, tuple) and len(key) == 2:
394
+ return self.RemoveValue(key[0], key[1])
395
+ else:
396
+ raise RuntimeError(f"The key should be either a string (representing the key path) or (string, int) tuple (representing key path and step index) [ key = {key}].")
397
+
398
+ def __str__(self) -> str:
399
+ return self.__Info(-1, "")
@@ -0,0 +1,74 @@
1
+ from typing import Any
2
+ from KratosMultiphysics.OptimizationApplication.utilities.buffered_dict import BufferedDict
3
+ from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
4
+
5
+ class ComponentDataView:
6
+ """A viewer to view component's data in optimization problem.
7
+
8
+ Instances of this class create or view provided component's data in
9
+ the OptimizationProblem container. It will view both buffered and
10
+ unbuffered data.
11
+
12
+ The component must be first added to the OptimizationProblem
13
+ to use instances of this class to modify component data.
14
+
15
+ """
16
+ def __init__(self, component: Any, optimization_problem: OptimizationProblem):
17
+ self.__problem_data = optimization_problem.GetProblemDataContainer()
18
+
19
+ if isinstance(component, str):
20
+ self.__component_type = object
21
+ self.__component_name = component
22
+ else:
23
+ self.__component_type = optimization_problem.GetComponentType(component)
24
+ self.__component_name = optimization_problem.GetComponentName(component)
25
+
26
+ self.__data_name = f"{self.__component_type.__name__}/{self.__component_name}"
27
+ self.__buffered_data_name = f"{self.__data_name}/buffered"
28
+ self.__unbuffered_data_name = f"{self.__data_name}/unbuffered"
29
+ self.__component = component
30
+
31
+ # if the component data container not found, then create it.
32
+ if not self.__problem_data.HasValue(self.__data_name):
33
+ self.ResetData()
34
+
35
+ def ResetData(self):
36
+ if self.__problem_data.HasValue(self.__data_name):
37
+ # if exists, delete the current problem data
38
+ del self.__problem_data[self.__data_name]
39
+
40
+ self.__problem_data[self.__data_name] = BufferedDict(1)
41
+ # create the unbuffered data container
42
+ self.__problem_data[self.__unbuffered_data_name] = BufferedDict(1, False)
43
+
44
+ def SetDataBuffer(self, buffer_size: int):
45
+ if not self.__problem_data.HasValue(self.__buffered_data_name):
46
+ self.__problem_data[self.__buffered_data_name] = BufferedDict(buffer_size)
47
+ else:
48
+ buffered_data: BufferedDict = self.__problem_data[self.__buffered_data_name]
49
+ if buffered_data.GetBufferSize() < buffer_size:
50
+ raise RuntimeError(f"The required buffer size is not satisfied with the existing problem data container. [ component data container buffer size = {buffered_data.GetBufferSize()}, required buffer size = {buffer_size}, component = {self.__component_name}, component type = {self.__component_type}")
51
+
52
+ def HasDataBuffer(self) -> bool:
53
+ return self.__problem_data.HasValue(self.__buffered_data_name)
54
+
55
+ def GetComponent(self) -> Any:
56
+ return self.__component
57
+
58
+ def GetBufferedData(self) -> BufferedDict:
59
+ if not self.HasDataBuffer():
60
+ raise RuntimeError(f"Buffered data is not set by calling ComponentData::SetDataBuffer for component of type \"{self.__component_type}\" with component name \"{self.__component_name}\".")
61
+
62
+ return self.__problem_data[self.__buffered_data_name]
63
+
64
+ def GetUnBufferedData(self) -> BufferedDict:
65
+ return self.__problem_data[self.__unbuffered_data_name]
66
+
67
+ def GetDataPath(self) -> str:
68
+ return self.__data_name
69
+
70
+ def GetComponentName(self):
71
+ if isinstance(self.__component, str):
72
+ return self.__component
73
+ else:
74
+ return self.__component.GetName()
@@ -0,0 +1,40 @@
1
+ from pathlib import Path
2
+ from typing import Any
3
+
4
+ import KratosMultiphysics as Kratos
5
+ from KratosMultiphysics.kratos_utilities import GetListOfAvailableApplications
6
+ from KratosMultiphysics.kratos_utilities import GetKratosMultiphysicsPath
7
+
8
+ def GetClassModuleFromKratos(full_class_name: str) -> str:
9
+ sub_module_paths = full_class_name.split(".")
10
+
11
+ if not sub_module_paths:
12
+ raise RuntimeError("Empty class names are not allowed.")
13
+
14
+ relative_sub_module = Kratos.StringUtilities.ConvertCamelCaseToSnakeCase(sub_module_paths[-1])
15
+ if len(sub_module_paths) > 1:
16
+ relative_sub_module = ".".join(sub_module_paths[:-1]) + f".{relative_sub_module}"
17
+
18
+ relative_sub_module_path = relative_sub_module.replace(".", "/")
19
+ kratos_path = GetKratosMultiphysicsPath()
20
+
21
+ # check whether it is in Kratos core
22
+ if Path(f"{kratos_path}/{relative_sub_module_path}.py").is_file():
23
+ return f"KratosMultiphysics.{relative_sub_module}", sub_module_paths[-1]
24
+
25
+ # now check if it is found in any of the compiled applications
26
+ list_of_available_appliacations = GetListOfAvailableApplications()
27
+
28
+ module_application = ""
29
+ for application in list_of_available_appliacations:
30
+ if Path(f"{kratos_path}/{application}/{relative_sub_module_path}.py").is_file():
31
+ module_application = f"KratosMultiphysics.{application}.{relative_sub_module}"
32
+
33
+ if module_application != "":
34
+ return module_application, sub_module_paths[-1]
35
+ else:
36
+ raise RuntimeError(f"{full_class_name} is not found in KratosMultiphysics core or any of the available application directories in Kratos. Available applications:\n\t" + "\n\t".join(list_of_available_appliacations))
37
+
38
+ def CallOnAll(list_of_objects: 'list[Any]', method: Any, *args, **kwargs):
39
+ for obj in list_of_objects:
40
+ getattr(obj, method.__name__)(*args, **kwargs)