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.
- KratosMultiphysics/.libs/KratosShapeOptimizationApplication.so +0 -0
- KratosMultiphysics/.libs/libKratosShapeOptimizationCore.dylib +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/TemplateMainKratosShapeOptimization.py +31 -0
- KratosMultiphysics/ShapeOptimizationApplication/__init__.py +19 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_base.py +31 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_bead_optimization.py +412 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_factory.py +62 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_gradient_projection.py +317 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_penalized_projection.py +225 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_relaxed_gradient_projection.py +580 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_shape_fraction_optimization.py +622 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_steepest_descent.py +255 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_trust_region.py +657 -0
- KratosMultiphysics/ShapeOptimizationApplication/analyzers/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/analyzers/analyzer_base.py +30 -0
- KratosMultiphysics/ShapeOptimizationApplication/analyzers/analyzer_empty.py +21 -0
- KratosMultiphysics/ShapeOptimizationApplication/analyzers/analyzer_factory.py +310 -0
- KratosMultiphysics/ShapeOptimizationApplication/analyzers/analyzer_internal.py +155 -0
- KratosMultiphysics/ShapeOptimizationApplication/communicator_factory.py +259 -0
- KratosMultiphysics/ShapeOptimizationApplication/custom_ios/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/custom_ios/wrl_io.py +82 -0
- KratosMultiphysics/ShapeOptimizationApplication/custom_ios/wrl_reader.py +119 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/data_logger_factory.py +199 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/design_logger_base.py +28 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/design_logger_gid.py +112 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/design_logger_unv.py +73 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/design_logger_vtk.py +96 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/sensitivity_heatmap_logger.py +91 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_base.py +128 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_bead_optimization.py +79 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_gradient_projection.py +80 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_penalized_projection.py +79 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_relaxed_gradient_projection.py +108 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_shape_fraction_optimization.py +92 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_steepest_descent.py +64 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_trust_region.py +100 -0
- KratosMultiphysics/ShapeOptimizationApplication/mapper_factory.py +100 -0
- KratosMultiphysics/ShapeOptimizationApplication/mapping/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/mapping/in_plane_vertex_morphing_mapper.py +140 -0
- KratosMultiphysics/ShapeOptimizationApplication/mapping/sliding_vertex_morphing_mapper.py +378 -0
- KratosMultiphysics/ShapeOptimizationApplication/mesh_controllers/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/mesh_controllers/mesh_controller_base.py +22 -0
- KratosMultiphysics/ShapeOptimizationApplication/mesh_controllers/mesh_controller_basic_updating.py +35 -0
- KratosMultiphysics/ShapeOptimizationApplication/mesh_controllers/mesh_controller_with_solver.py +237 -0
- KratosMultiphysics/ShapeOptimizationApplication/model_part_controller_factory.py +197 -0
- KratosMultiphysics/ShapeOptimizationApplication/optimizer_factory.py +235 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/airfoil_2d_responses.py +189 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/face_angle.py +140 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/mesh_based_packaging.py +70 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/packaging_response_base.py +156 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/plane_based_packaging.py +61 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/response_function_factory.py +40 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/surface_normal_shape_change.py +125 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/total_volume.py +56 -0
- KratosMultiphysics/ShapeOptimizationApplication/utilities/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/utilities/custom_math.py +443 -0
- KratosMultiphysics/ShapeOptimizationApplication/utilities/custom_sensitivity_heatmap.py +235 -0
- KratosMultiphysics/ShapeOptimizationApplication/utilities/custom_timer.py +47 -0
- KratosMultiphysics/ShapeOptimizationApplication/utilities/custom_variable_utilities.py +54 -0
- kratosshapeoptimizationapplication-10.4.4.dist-info/METADATA +31 -0
- kratosshapeoptimizationapplication-10.4.4.dist-info/RECORD +69 -0
- kratosshapeoptimizationapplication-10.4.4.dist-info/WHEEL +6 -0
- kratosshapeoptimizationapplication.dylibs/libKratosCore.dylib +4 -0
- kratosshapeoptimizationapplication.dylibs/libgcc_s.1.1.dylib +0 -0
- kratosshapeoptimizationapplication.dylibs/libgomp.1.dylib +0 -0
- 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
|