KratosShapeOptimizationApplication 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 (69) hide show
  1. KratosMultiphysics/.libs/KratosShapeOptimizationApplication.so +0 -0
  2. KratosMultiphysics/.libs/libKratosShapeOptimizationCore.dylib +0 -0
  3. KratosMultiphysics/ShapeOptimizationApplication/TemplateMainKratosShapeOptimization.py +31 -0
  4. KratosMultiphysics/ShapeOptimizationApplication/__init__.py +19 -0
  5. KratosMultiphysics/ShapeOptimizationApplication/algorithms/__init__.py +0 -0
  6. KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_base.py +31 -0
  7. KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_bead_optimization.py +412 -0
  8. KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_factory.py +62 -0
  9. KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_gradient_projection.py +317 -0
  10. KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_penalized_projection.py +225 -0
  11. KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_relaxed_gradient_projection.py +580 -0
  12. KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_shape_fraction_optimization.py +622 -0
  13. KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_steepest_descent.py +255 -0
  14. KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_trust_region.py +657 -0
  15. KratosMultiphysics/ShapeOptimizationApplication/analyzers/__init__.py +0 -0
  16. KratosMultiphysics/ShapeOptimizationApplication/analyzers/analyzer_base.py +30 -0
  17. KratosMultiphysics/ShapeOptimizationApplication/analyzers/analyzer_empty.py +21 -0
  18. KratosMultiphysics/ShapeOptimizationApplication/analyzers/analyzer_factory.py +310 -0
  19. KratosMultiphysics/ShapeOptimizationApplication/analyzers/analyzer_internal.py +155 -0
  20. KratosMultiphysics/ShapeOptimizationApplication/communicator_factory.py +259 -0
  21. KratosMultiphysics/ShapeOptimizationApplication/custom_ios/__init__.py +0 -0
  22. KratosMultiphysics/ShapeOptimizationApplication/custom_ios/wrl_io.py +82 -0
  23. KratosMultiphysics/ShapeOptimizationApplication/custom_ios/wrl_reader.py +119 -0
  24. KratosMultiphysics/ShapeOptimizationApplication/loggers/__init__.py +0 -0
  25. KratosMultiphysics/ShapeOptimizationApplication/loggers/data_logger_factory.py +199 -0
  26. KratosMultiphysics/ShapeOptimizationApplication/loggers/design_logger_base.py +28 -0
  27. KratosMultiphysics/ShapeOptimizationApplication/loggers/design_logger_gid.py +112 -0
  28. KratosMultiphysics/ShapeOptimizationApplication/loggers/design_logger_unv.py +73 -0
  29. KratosMultiphysics/ShapeOptimizationApplication/loggers/design_logger_vtk.py +96 -0
  30. KratosMultiphysics/ShapeOptimizationApplication/loggers/sensitivity_heatmap_logger.py +91 -0
  31. KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_base.py +128 -0
  32. KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_bead_optimization.py +79 -0
  33. KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_gradient_projection.py +80 -0
  34. KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_penalized_projection.py +79 -0
  35. KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_relaxed_gradient_projection.py +108 -0
  36. KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_shape_fraction_optimization.py +92 -0
  37. KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_steepest_descent.py +64 -0
  38. KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_trust_region.py +100 -0
  39. KratosMultiphysics/ShapeOptimizationApplication/mapper_factory.py +100 -0
  40. KratosMultiphysics/ShapeOptimizationApplication/mapping/__init__.py +0 -0
  41. KratosMultiphysics/ShapeOptimizationApplication/mapping/in_plane_vertex_morphing_mapper.py +140 -0
  42. KratosMultiphysics/ShapeOptimizationApplication/mapping/sliding_vertex_morphing_mapper.py +378 -0
  43. KratosMultiphysics/ShapeOptimizationApplication/mesh_controllers/__init__.py +0 -0
  44. KratosMultiphysics/ShapeOptimizationApplication/mesh_controllers/mesh_controller_base.py +22 -0
  45. KratosMultiphysics/ShapeOptimizationApplication/mesh_controllers/mesh_controller_basic_updating.py +35 -0
  46. KratosMultiphysics/ShapeOptimizationApplication/mesh_controllers/mesh_controller_with_solver.py +237 -0
  47. KratosMultiphysics/ShapeOptimizationApplication/model_part_controller_factory.py +197 -0
  48. KratosMultiphysics/ShapeOptimizationApplication/optimizer_factory.py +235 -0
  49. KratosMultiphysics/ShapeOptimizationApplication/response_functions/__init__.py +0 -0
  50. KratosMultiphysics/ShapeOptimizationApplication/response_functions/airfoil_2d_responses.py +189 -0
  51. KratosMultiphysics/ShapeOptimizationApplication/response_functions/face_angle.py +140 -0
  52. KratosMultiphysics/ShapeOptimizationApplication/response_functions/mesh_based_packaging.py +70 -0
  53. KratosMultiphysics/ShapeOptimizationApplication/response_functions/packaging_response_base.py +156 -0
  54. KratosMultiphysics/ShapeOptimizationApplication/response_functions/plane_based_packaging.py +61 -0
  55. KratosMultiphysics/ShapeOptimizationApplication/response_functions/response_function_factory.py +40 -0
  56. KratosMultiphysics/ShapeOptimizationApplication/response_functions/surface_normal_shape_change.py +125 -0
  57. KratosMultiphysics/ShapeOptimizationApplication/response_functions/total_volume.py +56 -0
  58. KratosMultiphysics/ShapeOptimizationApplication/utilities/__init__.py +0 -0
  59. KratosMultiphysics/ShapeOptimizationApplication/utilities/custom_math.py +443 -0
  60. KratosMultiphysics/ShapeOptimizationApplication/utilities/custom_sensitivity_heatmap.py +235 -0
  61. KratosMultiphysics/ShapeOptimizationApplication/utilities/custom_timer.py +47 -0
  62. KratosMultiphysics/ShapeOptimizationApplication/utilities/custom_variable_utilities.py +54 -0
  63. kratosshapeoptimizationapplication-10.4.4.dist-info/METADATA +31 -0
  64. kratosshapeoptimizationapplication-10.4.4.dist-info/RECORD +69 -0
  65. kratosshapeoptimizationapplication-10.4.4.dist-info/WHEEL +6 -0
  66. kratosshapeoptimizationapplication.dylibs/libKratosCore.dylib +4 -0
  67. kratosshapeoptimizationapplication.dylibs/libgcc_s.1.1.dylib +0 -0
  68. kratosshapeoptimizationapplication.dylibs/libgomp.1.dylib +0 -0
  69. kratosshapeoptimizationapplication.dylibs/libstdc++.6.dylib +0 -0
@@ -0,0 +1,30 @@
1
+ # ==============================================================================
2
+ # KratosShapeOptimizationApplication
3
+ #
4
+ # License: BSD License
5
+ # license: ShapeOptimizationApplication/license.txt
6
+ #
7
+ # Main authors: Baumgaertner Daniel, https://github.com/dbaumgaertner
8
+ #
9
+ # ==============================================================================
10
+
11
+
12
+ # ==============================================================================
13
+ class AnalyzerBaseClass:
14
+ # --------------------------------------------------------------------------
15
+ def __init__(self):
16
+ pass
17
+
18
+ # --------------------------------------------------------------------------
19
+ def InitializeBeforeOptimizationLoop(self):
20
+ pass
21
+
22
+ # --------------------------------------------------------------------------
23
+ def AnalyzeDesignAndReportToCommunicator(self, current_design, optimization_iteration, communicator):
24
+ raise RuntimeError("Analyzer base class is called. Please check your implementation of the function >> AnalyzeDesignAndReportToCommunicator << .")
25
+
26
+ # --------------------------------------------------------------------------
27
+ def FinalizeAfterOptimizationLoop(self):
28
+ pass
29
+
30
+ # ==============================================================================
@@ -0,0 +1,21 @@
1
+ # ==============================================================================
2
+ # KratosShapeOptimizationApplication
3
+ #
4
+ # License: BSD License
5
+ # license: ShapeOptimizationApplication/license.txt
6
+ #
7
+ # Main authors: Baumgaertner Daniel, https://github.com/dbaumgaertner
8
+ #
9
+ # ==============================================================================
10
+
11
+
12
+ # Additional imports
13
+ from .analyzer_base import AnalyzerBaseClass
14
+
15
+ # ==============================================================================
16
+ class EmptyAnalyzer( AnalyzerBaseClass ):
17
+ # --------------------------------------------------------------------------
18
+ def AnalyzeDesignAndReportToCommunicator( self, currentDesign, optimizationIteration, communicator ):
19
+ pass
20
+
21
+ # ==============================================================================
@@ -0,0 +1,310 @@
1
+ # ==============================================================================
2
+ # KratosShapeOptimizationApplication
3
+ #
4
+ # License: BSD License
5
+ # license: ShapeOptimizationApplication/license.txt
6
+ #
7
+ # Main authors: Baumgaertner Daniel, https://github.com/dbaumgaertner
8
+ #
9
+ # ==============================================================================
10
+
11
+
12
+ # additional imports
13
+ from KratosMultiphysics.ShapeOptimizationApplication.analyzers.analyzer_internal import KratosInternalAnalyzer
14
+ from KratosMultiphysics.ShapeOptimizationApplication.analyzers.analyzer_empty import EmptyAnalyzer
15
+ from KratosMultiphysics.ShapeOptimizationApplication.analyzers.analyzer_base import AnalyzerBaseClass
16
+ import KratosMultiphysics.kratos_utilities as kratos_utilities
17
+ import csv, math
18
+ import copy
19
+
20
+ # ==============================================================================
21
+ def CreateAnalyzer(optimization_settings, model_part_controller, external_analyzer):
22
+ objectives = optimization_settings["objectives"]
23
+ constraints = optimization_settings["constraints"]
24
+
25
+ internal_objectives = _IdentifyInternalResponsesRecursively(objectives)
26
+ internal_constraints = _IdentifyInternalResponsesRecursively(constraints)
27
+ internal_responses = internal_objectives + internal_constraints
28
+ # internal_responses = [ (response_id_1, kratos_settings_1),
29
+ # (response_id_2, kratos_settings_2),
30
+ # ... ]
31
+
32
+ if len(internal_responses) > 0:
33
+ internal_analyzer = KratosInternalAnalyzer(internal_responses, model_part_controller)
34
+ else:
35
+ internal_analyzer = EmptyAnalyzer()
36
+
37
+ dependency_graph, exist_dependencies = _CreateDependencyGraphRecursively(objectives)
38
+ # dependency_graph = [ (response_id_1, weight_1, [], combination_type),
39
+ # (response_id_2, weight_2, [], combination_type),
40
+ # (response_id_3, [ (response_id_3a, weight_3a, [], combination_type),
41
+ # (response_id_3b, weight_3b, [], combination_type),
42
+ # (response_id_3c, weight_3c, [...]) ], weight_3, combination_type),
43
+ # ... ]
44
+
45
+ if exist_dependencies:
46
+ return AnalyzerWithDependencies(internal_analyzer, model_part_controller, external_analyzer, dependency_graph)
47
+ else:
48
+ return Analyzer(internal_analyzer, model_part_controller, external_analyzer)
49
+
50
+ # ------------------------------------------------------------------------------
51
+ def _IdentifyInternalResponsesRecursively(responses):
52
+ internal_responses = []
53
+
54
+ for itr in range(responses.size()):
55
+ response_i = responses[itr]
56
+
57
+ if response_i.Has("is_combined"):
58
+ if response_i["is_combined"].GetBool():
59
+ internal_responses += _IdentifyInternalResponsesRecursively(response_i["combined_responses"])
60
+
61
+ if response_i["analyzer"].GetString() == "kratos":
62
+ identifier = response_i["identifier"].GetString()
63
+ kratos_settings = response_i["response_settings"]
64
+ internal_responses.append([identifier, kratos_settings])
65
+
66
+ return internal_responses
67
+
68
+ # ------------------------------------------------------------------------------
69
+ def _CreateDependencyGraphRecursively(responses):
70
+ dependency_graph = []
71
+ exist_dependencies = False
72
+
73
+ for itr in range(responses.size()):
74
+ response_i = responses[itr]
75
+ identifier = response_i["identifier"].GetString()
76
+ weight = response_i["weight"].GetDouble()
77
+ combination_type = response_i["combination_type"].GetString()
78
+
79
+ if response_i.Has("is_combined"):
80
+ if response_i["is_combined"].GetBool():
81
+ exist_dependencies = True
82
+ sub_dependency_graph, _ = _CreateDependencyGraphRecursively(response_i["combined_responses"])
83
+ dependency_graph.append((identifier, weight, sub_dependency_graph, combination_type))
84
+ else:
85
+ dependency_graph.append((identifier, weight, [], None))
86
+
87
+ return dependency_graph, exist_dependencies
88
+
89
+ # ==============================================================================
90
+ class Analyzer(AnalyzerBaseClass):
91
+ # --------------------------------------------------------------------------
92
+ def __init__(self, internal_analyzer, model_part_controller, external_analyzer):
93
+ self.model_part_controller = model_part_controller
94
+ self.internal_analyzer = internal_analyzer
95
+ self.external_analyzer = external_analyzer
96
+
97
+ if isinstance(internal_analyzer, EmptyAnalyzer) and isinstance(external_analyzer, EmptyAnalyzer):
98
+ raise RuntimeError("Neither an internal nor an external analyzer is defined!")
99
+
100
+ # --------------------------------------------------------------------------
101
+ def InitializeBeforeOptimizationLoop(self):
102
+ self.internal_analyzer.InitializeBeforeOptimizationLoop()
103
+ self.external_analyzer.InitializeBeforeOptimizationLoop()
104
+
105
+ # --------------------------------------------------------------------------
106
+ def AnalyzeDesignAndReportToCommunicator(self, current_design, unique_iterator, communicator):
107
+ self.internal_analyzer.AnalyzeDesignAndReportToCommunicator(current_design, unique_iterator, communicator)
108
+ self.external_analyzer.AnalyzeDesignAndReportToCommunicator(current_design, unique_iterator, communicator)
109
+
110
+ self.__ResetPossibleShapeModificationsFromAnalysis()
111
+
112
+ # --------------------------------------------------------------------------
113
+ def FinalizeAfterOptimizationLoop(self):
114
+ self.internal_analyzer.FinalizeAfterOptimizationLoop()
115
+ self.external_analyzer.FinalizeAfterOptimizationLoop()
116
+
117
+ # --------------------------------------------------------------------------
118
+ def __ResetPossibleShapeModificationsFromAnalysis( self ):
119
+ self.model_part_controller.SetMeshToReferenceMesh()
120
+ self.model_part_controller.SetDeformationVariablesToZero()
121
+
122
+ # ==============================================================================
123
+ class AnalyzerWithDependencies(Analyzer):
124
+ # --------------------------------------------------------------------------
125
+ def __init__(self, internal_analyzer, model_part_controller, external_analyzer, dependency_graph):
126
+ super().__init__(internal_analyzer, model_part_controller, external_analyzer)
127
+
128
+ self.dependency_graph = dependency_graph
129
+ self.response_combination_filename = "response_combination.csv"
130
+ self.gradient_max_norms = {}
131
+
132
+ # --------------------------------------------------------------------------
133
+ def InitializeBeforeOptimizationLoop(self):
134
+ super().InitializeBeforeOptimizationLoop()
135
+
136
+ self.__InitializeOutputOfResponses()
137
+
138
+ # --------------------------------------------------------------------------
139
+ def AnalyzeDesignAndReportToCommunicator(self, current_design, unique_iterator, communicator):
140
+ self.__RequestResponsesAccordingDependencies(communicator)
141
+
142
+ super().AnalyzeDesignAndReportToCommunicator(current_design, unique_iterator, communicator)
143
+
144
+ self.__CombineResponsesAccordingDependencies(communicator)
145
+ self.__ComputeGradientNorms(communicator)
146
+ self.__WriteResultsOfCombinedResponses(unique_iterator,communicator)
147
+
148
+ # --------------------------------------------------------------------------
149
+ def __InitializeOutputOfResponses(self):
150
+ kratos_utilities.DeleteFileIfExisting(self.response_combination_filename)
151
+
152
+ with open(self.response_combination_filename, 'w') as csvfile:
153
+ writer = csv.writer(csvfile, delimiter=',')
154
+ response_ids = self.__GetIdentifiersRecursively(self.dependency_graph)
155
+
156
+ writer.writerow(["---------------------------------"])
157
+ for itr, identifier in enumerate(response_ids):
158
+ writer.writerow(["f"+str(itr)+": "+identifier])
159
+ writer.writerow(["---------------------------------"])
160
+
161
+ row = []
162
+ row.append("{:>4s}".format("itr"))
163
+ for itr, identifier in enumerate(response_ids):
164
+ row.append("{:>13s}".format("f"+str(itr)+"_value"))
165
+ for itr, identifier in enumerate(response_ids):
166
+ row.append("{:>13s}".format("||df"+str(itr)+"dx_st||"))
167
+ writer.writerow(row)
168
+
169
+ # --------------------------------------------------------------------------
170
+ def __GetIdentifiersRecursively(self, dependencies):
171
+ response_ids = []
172
+
173
+ for response_id, _, dependencies, _ in dependencies:
174
+ response_ids += [response_id]
175
+ if len(dependencies) > 0:
176
+ sub_identifiers = self.__GetIdentifiersRecursively(dependencies)
177
+ response_ids += sub_identifiers
178
+
179
+ return response_ids
180
+
181
+ # --------------------------------------------------------------------------
182
+ def __RequestResponsesAccordingDependencies(self, communicator):
183
+ for response_id, _, dependencies, _ in self.dependency_graph:
184
+ sub_response_ids = self.__GetIdentifiersRecursively(dependencies)
185
+
186
+ if communicator.isRequestingValueOf(response_id):
187
+ for sub_response_id in sub_response_ids:
188
+ communicator.requestValueOf(sub_response_id)
189
+
190
+ if communicator.isRequestingGradientOf(response_id):
191
+ for sub_response_id in sub_response_ids:
192
+ communicator.requestGradientOf(sub_response_id)
193
+
194
+ # --------------------------------------------------------------------------
195
+ def __CombineResponsesAccordingDependencies(self, communicator):
196
+ for response_id, _, dependencies, combination_type in self.dependency_graph:
197
+ if len(dependencies) > 0:
198
+ if communicator.isRequestingValueOf(response_id):
199
+ combined_value = self.__ComputeCombinedValuesRecursively(dependencies, combination_type, communicator)
200
+ communicator.reportValue(response_id, combined_value)
201
+
202
+ for response_id, _, dependencies, _ in self.dependency_graph:
203
+ if len(dependencies) > 0:
204
+ if communicator.isRequestingGradientOf(response_id):
205
+ combined_gradient = self.__ComputeCombinedGradientsRecursively(dependencies, communicator)
206
+ communicator.reportGradient(response_id, combined_gradient)
207
+
208
+ # --------------------------------------------------------------------------
209
+ def __ComputeCombinedValuesRecursively(self, dependencies, combination_type, communicator):
210
+ combined_value = None
211
+ relevant_responses = []
212
+
213
+ for response_id, weight, sub_dependencies, sub_combination_type in dependencies:
214
+ if len(sub_dependencies) > 0:
215
+ value = self.__ComputeCombinedValuesRecursively(sub_dependencies, sub_combination_type, communicator)
216
+ communicator.reportValue(response_id, value)
217
+ else:
218
+ value = communicator.getStandardizedValue(response_id)
219
+
220
+ value = weight*value
221
+
222
+ if combined_value is None:
223
+ combined_value = value
224
+ relevant_responses.append(response_id)
225
+ else:
226
+ if combination_type == "sum":
227
+ combined_value += value
228
+ relevant_responses.append(response_id)
229
+ elif combination_type == "max":
230
+ if value > combined_value:
231
+ relevant_responses = [response_id]
232
+ combined_value = value
233
+ elif combination_type == "min":
234
+ if value < combined_value:
235
+ relevant_responses = [response_id]
236
+ combined_value = value
237
+ else:
238
+ raise NameError("The following combination_type is not supported:" + combination_type)
239
+
240
+ for response_id, _, _, _ in dependencies:
241
+ if response_id not in relevant_responses:
242
+ communicator.updateRequest(response_id, request_value=True, request_gradient=False)
243
+
244
+ return combined_value
245
+
246
+ # --------------------------------------------------------------------------
247
+ def __ComputeCombinedGradientsRecursively(self, dependencies, communicator):
248
+ combined_gradient = {}
249
+
250
+ for response_id, weight, sub_dependencies, _ in dependencies:
251
+ if communicator.isRequestingGradientOf(response_id):
252
+ if len(sub_dependencies) > 0:
253
+ gradient = self.__ComputeCombinedGradientsRecursively(sub_dependencies, communicator)
254
+ communicator.reportGradient(response_id, gradient)
255
+ else:
256
+ gradient = communicator.getStandardizedGradient(response_id)
257
+
258
+ for vector in gradient.values():
259
+ vector[0] *= weight
260
+ vector[1] *= weight
261
+ vector[2] *= weight
262
+
263
+ if not combined_gradient:
264
+ # initialize combined gradient with zeros
265
+ combined_gradient = {key: [0.0, 0.0, 0.0] for key in gradient.keys()}
266
+
267
+ # Perform nodal sum
268
+ for key_a, vector_a in combined_gradient.items():
269
+ vector_b = gradient[key_a]
270
+ vector_a[0] += vector_b[0]
271
+ vector_a[1] += vector_b[1]
272
+ vector_a[2] += vector_b[2]
273
+
274
+ return combined_gradient
275
+
276
+ # --------------------------------------------------------------------------
277
+ def __ComputeGradientNorms(self, communicator):
278
+ response_ids = self.__GetIdentifiersRecursively(self.dependency_graph)
279
+
280
+ for response_id in response_ids:
281
+ if communicator.isRequestingGradientOf(response_id):
282
+ gradient = communicator.getStandardizedGradient(response_id)
283
+
284
+ nodal_norms = [ entry[0]**2 + entry[1]**2 + entry[2]**2 for entry in gradient.values() ]
285
+ max_norm = math.sqrt(max(nodal_norms))
286
+ self.gradient_max_norms[response_id] = max_norm
287
+
288
+ # --------------------------------------------------------------------------
289
+ def __WriteResultsOfCombinedResponses(self, iteration, communicator):
290
+ with open(self.response_combination_filename, 'a') as csvfile:
291
+ writer = csv.writer(csvfile, delimiter=',')
292
+
293
+ identifiers = self.__GetIdentifiersRecursively(self.dependency_graph)
294
+ values = []
295
+ for response_id in identifiers:
296
+ values.append(communicator.getValue(response_id))
297
+
298
+ row = []
299
+ row.append("{:>4d}".format(iteration))
300
+ for identifier, value in zip(identifiers, values):
301
+ row.append(" {:> .5E}".format(value))
302
+ for identifier, value in zip(identifiers, values):
303
+ if communicator.isRequestingGradientOf(identifier):
304
+ row.append(" {:> .5E}".format(self.gradient_max_norms[identifier]))
305
+ else:
306
+ row.append(" -")
307
+
308
+ writer.writerow(row)
309
+
310
+ # ==============================================================================
@@ -0,0 +1,155 @@
1
+ # ==============================================================================
2
+ # KratosShapeOptimizationApplication
3
+ #
4
+ # License: BSD License
5
+ # license: ShapeOptimizationApplication/license.txt
6
+ #
7
+ # Main authors: Baumgaertner Daniel, https://github.com/dbaumgaertner
8
+ # Geiser Armin, https://github.com/armingeiser
9
+ #
10
+ # ==============================================================================
11
+
12
+ import os, pathlib, sys
13
+
14
+ # Kratos Core and Apps
15
+ import KratosMultiphysics as KM
16
+
17
+ # Additional imports
18
+ from KratosMultiphysics.ShapeOptimizationApplication.analyzers.analyzer_base import AnalyzerBaseClass
19
+ from KratosMultiphysics.ShapeOptimizationApplication.response_functions import response_function_factory as sho_response_factory
20
+ try:
21
+ from KratosMultiphysics.StructuralMechanicsApplication import structural_response_function_factory as csm_response_factory
22
+ except ImportError:
23
+ csm_response_factory = None
24
+ try:
25
+ from KratosMultiphysics.ConvectionDiffusionApplication.response_functions import convection_diffusion_response_function_factory as convdiff_response_factory
26
+ except ImportError:
27
+ convdiff_response_factory = None
28
+ try:
29
+ from KratosMultiphysics.CompressiblePotentialFlowApplication import potential_flow_response_function_factory as potential_flow_response_factory
30
+ except ImportError:
31
+ potential_flow_response_factory = None
32
+
33
+ import time as timer
34
+
35
+ class IterationScope:
36
+ def __init__(self, response_id, iteration_number, is_evaluated_in_folder):
37
+ self.is_evaluated_in_folder = is_evaluated_in_folder
38
+ if (self.is_evaluated_in_folder):
39
+ self.currentPath = pathlib.Path.cwd()
40
+ output_path = pathlib.Path("Design_Iterations")
41
+ response_text = "{:}/{:d}".format(response_id, iteration_number)
42
+ self.scope = output_path / response_text
43
+
44
+ def __enter__(self):
45
+ if (self.is_evaluated_in_folder):
46
+ self.scope.mkdir(parents=True, exist_ok=True)
47
+ sys.path.insert(0, str(self.scope.absolute()))
48
+ os.chdir(str(self.scope))
49
+
50
+ def __exit__(self, exc_type, exc_value, traceback):
51
+ if (self.is_evaluated_in_folder):
52
+ os.chdir(self.currentPath)
53
+ sys.path.remove(str(self.scope.absolute()))
54
+
55
+
56
+ # ==============================================================================
57
+ class KratosInternalAnalyzer( AnalyzerBaseClass ):
58
+ # --------------------------------------------------------------------------
59
+ def __init__( self, specified_responses, model_part_controller ):
60
+ self.model_part_controller = model_part_controller
61
+ self.response_functions = self.__CreateResponseFunctions(specified_responses, model_part_controller.GetModel())
62
+
63
+ # --------------------------------------------------------------------------
64
+ def InitializeBeforeOptimizationLoop( self ):
65
+ for response in self.response_functions.values():
66
+ response.Initialize()
67
+
68
+ # --------------------------------------------------------------------------
69
+ def AnalyzeDesignAndReportToCommunicator( self, currentDesign, optimizationIteration, communicator ):
70
+ optimization_model_part = self.model_part_controller.GetOptimizationModelPart()
71
+
72
+ time_before_analysis = optimization_model_part.ProcessInfo.GetValue(KM.TIME)
73
+ step_before_analysis = optimization_model_part.ProcessInfo.GetValue(KM.STEP)
74
+ delta_time_before_analysis = optimization_model_part.ProcessInfo.GetValue(KM.DELTA_TIME)
75
+
76
+ for identifier, response in self.response_functions.items():
77
+
78
+ # Reset step/time iterators such that they match the optimization iteration after calling CalculateValue (which internally calls CloneTimeStep)
79
+ optimization_model_part.ProcessInfo.SetValue(KM.STEP, step_before_analysis-1)
80
+ optimization_model_part.ProcessInfo.SetValue(KM.TIME, time_before_analysis-1)
81
+ optimization_model_part.ProcessInfo.SetValue(KM.DELTA_TIME, 0)
82
+
83
+ # now we scope in to the directory where response operations are done
84
+ with IterationScope(identifier, optimizationIteration, response.IsEvaluatedInFolder()):
85
+ response.UpdateDesign(optimization_model_part, KM.SHAPE_SENSITIVITY)
86
+
87
+ response.InitializeSolutionStep()
88
+
89
+ # response values
90
+ if communicator.isRequestingValueOf(identifier):
91
+ response.CalculateValue()
92
+ communicator.reportValue(identifier, response.GetValue())
93
+
94
+ # response gradients
95
+ if communicator.isRequestingGradientOf(identifier):
96
+ response.CalculateGradient()
97
+ communicator.reportGradient(identifier, response.GetNodalGradient(KM.SHAPE_SENSITIVITY))
98
+
99
+ response.FinalizeSolutionStep()
100
+
101
+ # Clear results or modifications on model part
102
+ optimization_model_part.ProcessInfo.SetValue(KM.STEP, step_before_analysis)
103
+ optimization_model_part.ProcessInfo.SetValue(KM.TIME, time_before_analysis)
104
+ optimization_model_part.ProcessInfo.SetValue(KM.DELTA_TIME, delta_time_before_analysis)
105
+
106
+ self.model_part_controller.SetMeshToReferenceMesh()
107
+ self.model_part_controller.SetDeformationVariablesToZero()
108
+
109
+ # --------------------------------------------------------------------------
110
+ def FinalizeAfterOptimizationLoop( self ):
111
+ for response in self.response_functions.values():
112
+ response.Finalize()
113
+
114
+ # --------------------------------------------------------------------------
115
+ @staticmethod
116
+ def __CreateResponseFunctions( specified_responses, model ):
117
+ response_functions = {}
118
+
119
+ sho_response_functions = [
120
+ "plane_based_packaging",
121
+ "mesh_based_packaging",
122
+ "surface_normal_shape_change",
123
+ "face_angle",
124
+ "airfoil_angle_of_attack",
125
+ "airfoil_chord_length",
126
+ "airfoil_perimeter"
127
+ ]
128
+ csm_response_functions = ["strain_energy", "mass", "eigenfrequency", "adjoint_local_stress", "adjoint_max_stress", "adjoint_nodal_displacement", "adjoint_linear_strain_energy", "adjoint_nodal_reaction"]
129
+ cps_response_functions = ["adjoint_lift_potential_jump", "stochastic_adjoint_lift_potential_jump"]
130
+ convdiff_response_functions = ["point_temperature"]
131
+
132
+ for (response_id, response_settings) in specified_responses:
133
+ if response_id in response_functions.keys():
134
+ raise NameError("There are multiple response functions with the following identifier: " + response_id)
135
+
136
+ response_type = response_settings["response_type"].GetString()
137
+
138
+ if response_type in csm_response_functions:
139
+ if csm_response_factory is None:
140
+ raise RuntimeError("ShapeOpt: {} response function requires StructuralMechanicsApplication.".format(response_type))
141
+ response_functions[response_id] = csm_response_factory.CreateResponseFunction(response_id, response_settings, model)
142
+ elif response_type in convdiff_response_functions:
143
+ if convdiff_response_factory is None:
144
+ raise RuntimeError("ShapeOpt: {} response function requires ConvectionDiffusionApplication.".format(response_type))
145
+ response_functions[response_id] = convdiff_response_factory.CreateResponseFunction(response_id, response_settings, model)
146
+ elif response_type in cps_response_functions:
147
+ if potential_flow_response_factory is None:
148
+ raise RuntimeError("ShapeOpt: {} response function requires CompressiblePotentialFlowApplication.".format(response_type))
149
+ response_functions[response_id] = potential_flow_response_factory.CreateResponseFunction(response_id, response_settings, model)
150
+ elif response_type in sho_response_functions:
151
+ response_functions[response_id] = sho_response_factory.CreateResponseFunction(response_id, response_settings, model)
152
+ else:
153
+ raise NameError("The response function '{}' of type '{}' is not available.".format(response_id, response_type))
154
+
155
+ return response_functions