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,317 @@
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
+
13
+ # Kratos Core and Apps
14
+ import KratosMultiphysics as KM
15
+ import KratosMultiphysics.ShapeOptimizationApplication as KSO
16
+ from KratosMultiphysics.LinearSolversApplication import dense_linear_solver_factory
17
+
18
+ # Additional imports
19
+ from KratosMultiphysics.ShapeOptimizationApplication.algorithms.algorithm_base import OptimizationAlgorithm
20
+ from KratosMultiphysics.ShapeOptimizationApplication import mapper_factory
21
+ from KratosMultiphysics.ShapeOptimizationApplication.loggers import data_logger_factory
22
+ from KratosMultiphysics.ShapeOptimizationApplication.utilities.custom_timer import Timer
23
+ from KratosMultiphysics.ShapeOptimizationApplication.utilities.custom_variable_utilities import WriteDictionaryDataOnNodalVariable
24
+
25
+ import math
26
+
27
+ # ==============================================================================
28
+ class AlgorithmGradientProjection(OptimizationAlgorithm):
29
+ # --------------------------------------------------------------------------
30
+ def __init__(self, optimization_settings, analyzer, communicator, model_part_controller):
31
+ default_algorithm_settings = KM.Parameters("""
32
+ {
33
+ "name" : "penalized_projection",
34
+ "max_correction_share" : 0.75,
35
+ "max_iterations" : 100,
36
+ "relative_tolerance" : 1e-3,
37
+ "line_search" : {
38
+ "line_search_type" : "manual_stepping",
39
+ "normalize_search_direction" : true,
40
+ "step_size" : 1.0
41
+ }
42
+ }""")
43
+ self.algorithm_settings = optimization_settings["optimization_algorithm"]
44
+ self.algorithm_settings.RecursivelyValidateAndAssignDefaults(default_algorithm_settings)
45
+
46
+ self.optimization_settings = optimization_settings
47
+ self.mapper_settings = optimization_settings["design_variables"]["filter"]
48
+
49
+ self.analyzer = analyzer
50
+ self.communicator = communicator
51
+ self.model_part_controller = model_part_controller
52
+
53
+ self.design_surface = None
54
+ self.mapper = None
55
+ self.data_logger = None
56
+ self.optimization_utilities = None
57
+
58
+ self.objectives = optimization_settings["objectives"]
59
+ self.constraints = optimization_settings["constraints"]
60
+ self.constraint_gradient_variables = {}
61
+ for itr, constraint in enumerate(self.constraints.values()):
62
+ self.constraint_gradient_variables.update({
63
+ constraint["identifier"].GetString() : {
64
+ "gradient": KM.KratosGlobals.GetVariable(f"DC{(itr+1)}DX"),
65
+ "mapped_gradient": KM.KratosGlobals.GetVariable(f"DC{(itr+1)}DX_MAPPED")
66
+ }
67
+ })
68
+ self.max_correction_share = self.algorithm_settings["max_correction_share"].GetDouble()
69
+
70
+ self.step_size = self.algorithm_settings["line_search"]["step_size"].GetDouble()
71
+ self.max_iterations = self.algorithm_settings["max_iterations"].GetInt() + 1
72
+ self.relative_tolerance = self.algorithm_settings["relative_tolerance"].GetDouble()
73
+
74
+ self.optimization_model_part = model_part_controller.GetOptimizationModelPart()
75
+ self.optimization_model_part.AddNodalSolutionStepVariable(KSO.SEARCH_DIRECTION)
76
+ self.optimization_model_part.AddNodalSolutionStepVariable(KSO.CORRECTION)
77
+
78
+ # --------------------------------------------------------------------------
79
+ def CheckApplicability(self):
80
+ if self.objectives.size() > 1:
81
+ raise RuntimeError("Gradient projection algorithm only supports one objective function!")
82
+ if self.constraints.size() == 0:
83
+ raise RuntimeError("Gradient projection algorithm requires definition of at least one constraint!")
84
+
85
+ # --------------------------------------------------------------------------
86
+ def InitializeOptimizationLoop(self):
87
+ self.model_part_controller.Initialize()
88
+
89
+ self.analyzer.InitializeBeforeOptimizationLoop()
90
+
91
+ self.design_surface = self.model_part_controller.GetDesignSurface()
92
+
93
+ self.mapper = mapper_factory.CreateMapper(self.design_surface, self.design_surface, self.mapper_settings)
94
+ self.mapper.Initialize()
95
+ self.model_part_controller.InitializeDamping()
96
+
97
+ self.data_logger = data_logger_factory.CreateDataLogger(self.model_part_controller, self.communicator, self.optimization_settings)
98
+ self.data_logger.InitializeDataLogging()
99
+
100
+ self.optimization_utilities = KSO.OptimizationUtilities
101
+
102
+ # --------------------------------------------------------------------------
103
+ def RunOptimizationLoop(self):
104
+ timer = Timer()
105
+ timer.StartTimer()
106
+
107
+ for self.optimization_iteration in range(1,self.max_iterations):
108
+ KM.Logger.Print("")
109
+ KM.Logger.Print("===============================================================================")
110
+ KM.Logger.PrintInfo("ShapeOpt", timer.GetTimeStamp(), ": Starting optimization iteration ", self.optimization_iteration)
111
+ KM.Logger.Print("===============================================================================\n")
112
+
113
+ timer.StartNewLap()
114
+
115
+ self.__initializeNewShape()
116
+
117
+ self.__analyzeShape()
118
+
119
+ self.__computeShapeUpdate()
120
+
121
+ self.__logCurrentOptimizationStep()
122
+
123
+ KM.Logger.Print("")
124
+ KM.Logger.PrintInfo("ShapeOpt", "Time needed for current optimization step = ", timer.GetLapTime(), "s")
125
+ KM.Logger.PrintInfo("ShapeOpt", "Time needed for total optimization so far = ", timer.GetTotalTime(), "s")
126
+
127
+ if self.__isAlgorithmConverged():
128
+ break
129
+ else:
130
+ self.__determineAbsoluteChanges()
131
+
132
+ # --------------------------------------------------------------------------
133
+ def FinalizeOptimizationLoop(self):
134
+ self.data_logger.FinalizeDataLogging()
135
+ self.analyzer.FinalizeAfterOptimizationLoop()
136
+
137
+ # --------------------------------------------------------------------------
138
+ def __initializeNewShape(self):
139
+ self.model_part_controller.UpdateTimeStep(self.optimization_iteration)
140
+ self.model_part_controller.UpdateMeshAccordingInputVariable(KSO.SHAPE_UPDATE)
141
+ self.model_part_controller.SetReferenceMeshToMesh()
142
+
143
+ # --------------------------------------------------------------------------
144
+ def __analyzeShape(self):
145
+ self.communicator.initializeCommunication()
146
+ self.communicator.requestValueOf(self.objectives[0]["identifier"].GetString())
147
+ self.communicator.requestGradientOf(self.objectives[0]["identifier"].GetString())
148
+
149
+ for constraint in self.constraints.values():
150
+ con_id = constraint["identifier"].GetString()
151
+ self.communicator.requestValueOf(con_id)
152
+ self.communicator.requestGradientOf(con_id)
153
+
154
+ self.analyzer.AnalyzeDesignAndReportToCommunicator(self.optimization_model_part, self.optimization_iteration, self.communicator)
155
+
156
+ # compute normals only if required
157
+ surface_normals_required = self.objectives[0]["project_gradient_on_surface_normals"].GetBool()
158
+ for constraint in self.constraints.values():
159
+ if constraint["project_gradient_on_surface_normals"].GetBool():
160
+ surface_normals_required = True
161
+
162
+ if surface_normals_required:
163
+ self.model_part_controller.ComputeUnitSurfaceNormals()
164
+
165
+ # project and damp objective gradients
166
+ objGradientDict = self.communicator.getStandardizedGradient(self.objectives[0]["identifier"].GetString())
167
+ WriteDictionaryDataOnNodalVariable(objGradientDict, self.optimization_model_part, KSO.DF1DX)
168
+
169
+ if self.objectives[0]["project_gradient_on_surface_normals"].GetBool():
170
+ self.model_part_controller.ProjectNodalVariableOnUnitSurfaceNormals(KSO.DF1DX)
171
+
172
+ self.model_part_controller.DampNodalSensitivityVariableIfSpecified(KSO.DF1DX)
173
+
174
+ # project and damp constraint gradients
175
+ for constraint in self.constraints.values():
176
+ con_id = constraint["identifier"].GetString()
177
+ conGradientDict = self.communicator.getStandardizedGradient(con_id)
178
+ gradient_variable = self.constraint_gradient_variables[con_id]["gradient"]
179
+ WriteDictionaryDataOnNodalVariable(conGradientDict, self.optimization_model_part, gradient_variable)
180
+
181
+ if constraint["project_gradient_on_surface_normals"].GetBool():
182
+ self.model_part_controller.ProjectNodalVariableOnUnitSurfaceNormals(gradient_variable)
183
+
184
+ self.model_part_controller.DampNodalSensitivityVariableIfSpecified(gradient_variable)
185
+
186
+ # --------------------------------------------------------------------------
187
+ def __computeShapeUpdate(self):
188
+ self.mapper.Update()
189
+ self.mapper.InverseMap(KSO.DF1DX, KSO.DF1DX_MAPPED)
190
+
191
+ for constraint in self.constraints.values():
192
+ con_id = constraint["identifier"].GetString()
193
+ gradient_variable = self.constraint_gradient_variables[con_id]["gradient"]
194
+ mapped_gradient_variable = self.constraint_gradient_variables[con_id]["mapped_gradient"]
195
+ self.mapper.InverseMap(gradient_variable, mapped_gradient_variable)
196
+
197
+ self.__computeControlPointUpdate()
198
+
199
+ self.mapper.Map(KSO.CONTROL_POINT_UPDATE, KSO.SHAPE_UPDATE)
200
+ self.model_part_controller.DampNodalUpdateVariableIfSpecified(KSO.SHAPE_UPDATE)
201
+
202
+ # --------------------------------------------------------------------------
203
+ def __computeControlPointUpdate(self):
204
+ """adapted from https://msulaiman.org/onewebmedia/GradProj_2.pdf"""
205
+ g_a, g_a_variables = self.__getActiveConstraints()
206
+
207
+ KM.Logger.PrintInfo("ShapeOpt", "Assemble vector of objective gradient.")
208
+ nabla_f = KM.Vector()
209
+ s = KM.Vector()
210
+ self.optimization_utilities.AssembleVector(self.design_surface, nabla_f, KSO.DF1DX_MAPPED)
211
+
212
+ if len(g_a) == 0:
213
+ KM.Logger.PrintInfo("ShapeOpt", "No constraints active, use negative objective gradient as search direction.")
214
+ s = nabla_f * (-1.0)
215
+ s *= self.step_size / s.norm_inf()
216
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, s, KSO.SEARCH_DIRECTION)
217
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, [0.0]*len(s), KSO.CORRECTION)
218
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, s, KSO.CONTROL_POINT_UPDATE)
219
+ return
220
+
221
+
222
+ KM.Logger.PrintInfo("ShapeOpt", "Assemble matrix of constraint gradient.")
223
+ N = KM.Matrix()
224
+ self.optimization_utilities.AssembleMatrix(self.design_surface, N, g_a_variables)
225
+
226
+ settings = KM.Parameters('{ "solver_type" : "LinearSolversApplication.dense_col_piv_householder_qr" }')
227
+ solver = dense_linear_solver_factory.ConstructSolver(settings)
228
+
229
+ KM.Logger.PrintInfo("ShapeOpt", "Calculate projected search direction and correction.")
230
+ c = KM.Vector()
231
+ self.optimization_utilities.CalculateProjectedSearchDirectionAndCorrection(
232
+ nabla_f,
233
+ N,
234
+ g_a,
235
+ solver,
236
+ s,
237
+ c)
238
+
239
+ if c.norm_inf() != 0.0:
240
+ if c.norm_inf() <= self.max_correction_share * self.step_size:
241
+ delta = self.step_size - c.norm_inf()
242
+ s *= delta/s.norm_inf()
243
+ else:
244
+ KM.Logger.PrintWarning("ShapeOpt", f"Correction is scaled down from {c.norm_inf()} to {self.max_correction_share * self.step_size}.")
245
+ c *= self.max_correction_share * self.step_size / c.norm_inf()
246
+ s *= (1.0 - self.max_correction_share) * self.step_size / s.norm_inf()
247
+ else:
248
+ s *= self.step_size / s.norm_inf()
249
+
250
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, s, KSO.SEARCH_DIRECTION)
251
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, c, KSO.CORRECTION)
252
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, s+c, KSO.CONTROL_POINT_UPDATE)
253
+
254
+ # --------------------------------------------------------------------------
255
+ def __getActiveConstraints(self):
256
+ active_constraint_values = []
257
+ active_constraint_variables = []
258
+
259
+ for constraint in self.constraints.values():
260
+ if self.__isConstraintActive(constraint):
261
+ identifier = constraint["identifier"].GetString()
262
+ constraint_value = self.communicator.getStandardizedValue(identifier)
263
+ active_constraint_values.append(constraint_value)
264
+ active_constraint_variables.append(
265
+ self.constraint_gradient_variables[identifier]["mapped_gradient"])
266
+
267
+ return active_constraint_values, active_constraint_variables
268
+
269
+ # --------------------------------------------------------------------------
270
+ def __isConstraintActive(self, constraint):
271
+ identifier = constraint["identifier"].GetString()
272
+ constraint_value = self.communicator.getStandardizedValue(identifier)
273
+ if constraint["type"].GetString() == "=" or constraint_value >= 0:
274
+ gradient_norm = self.optimization_utilities.ComputeMaxNormOfNodalVariable(
275
+ self.design_surface, self.constraint_gradient_variables[identifier]["mapped_gradient"]
276
+ )
277
+ if math.isclose(gradient_norm, 0.0, abs_tol=1e-16):
278
+ KM.Logger.PrintWarning("ShapeOpt", f"Gradient for constraint {identifier} is 0.0 - will not be considered!")
279
+ return False
280
+ return True
281
+ else:
282
+ return False
283
+
284
+ # --------------------------------------------------------------------------
285
+ def __logCurrentOptimizationStep(self):
286
+ additional_values_to_log = {}
287
+ additional_values_to_log["step_size"] = self.step_size
288
+ additional_values_to_log["inf_norm_s"] = self.optimization_utilities.ComputeMaxNormOfNodalVariable(self.design_surface, KSO.SEARCH_DIRECTION)
289
+ additional_values_to_log["inf_norm_c"] = self.optimization_utilities.ComputeMaxNormOfNodalVariable(self.design_surface, KSO.CORRECTION)
290
+ self.data_logger.LogSensitivityHeatmap(self.optimization_iteration, self.mapper)
291
+ self.data_logger.LogCurrentValues(self.optimization_iteration, additional_values_to_log)
292
+ self.data_logger.LogCurrentDesign(self.optimization_iteration)
293
+
294
+ # --------------------------------------------------------------------------
295
+ def __isAlgorithmConverged(self):
296
+
297
+ if self.optimization_iteration > 1 :
298
+
299
+ # Check if maximum iterations were reached
300
+ if self.optimization_iteration == self.max_iterations:
301
+ KM.Logger.Print("")
302
+ KM.Logger.PrintInfo("ShapeOpt", "Maximal iterations of optimization problem reached!")
303
+ return True
304
+
305
+ # Check for relative tolerance
306
+ relative_change_of_objective_value = self.data_logger.GetValues("rel_change_objective")[self.optimization_iteration]
307
+ if abs(relative_change_of_objective_value) < self.relative_tolerance:
308
+ KM.Logger.Print("")
309
+ KM.Logger.PrintInfo("ShapeOpt", "Optimization problem converged within a relative objective tolerance of ",self.relative_tolerance,"%.")
310
+ return True
311
+
312
+ # --------------------------------------------------------------------------
313
+ def __determineAbsoluteChanges(self):
314
+ self.optimization_utilities.AddFirstVariableToSecondVariable(self.design_surface, KSO.CONTROL_POINT_UPDATE, KSO.CONTROL_POINT_CHANGE)
315
+ self.optimization_utilities.AddFirstVariableToSecondVariable(self.design_surface, KSO.SHAPE_UPDATE, KSO.SHAPE_CHANGE)
316
+
317
+ # ==============================================================================
@@ -0,0 +1,225 @@
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
+
13
+ # Kratos Core and Apps
14
+ import KratosMultiphysics as KM
15
+ import KratosMultiphysics.ShapeOptimizationApplication as KSO
16
+
17
+ # Additional imports
18
+ from KratosMultiphysics.ShapeOptimizationApplication.algorithms.algorithm_base import OptimizationAlgorithm
19
+ from KratosMultiphysics.ShapeOptimizationApplication import mapper_factory
20
+ from KratosMultiphysics.ShapeOptimizationApplication.loggers import data_logger_factory
21
+ from KratosMultiphysics.ShapeOptimizationApplication.utilities.custom_timer import Timer
22
+ from KratosMultiphysics.ShapeOptimizationApplication.utilities.custom_variable_utilities import WriteDictionaryDataOnNodalVariable
23
+
24
+ # ==============================================================================
25
+ class AlgorithmPenalizedProjection(OptimizationAlgorithm):
26
+ # --------------------------------------------------------------------------
27
+ def __init__(self, optimization_settings, analyzer, communicator, model_part_controller):
28
+ default_algorithm_settings = KM.Parameters("""
29
+ {
30
+ "name" : "penalized_projection",
31
+ "correction_scaling" : 1.0,
32
+ "use_adaptive_correction" : true,
33
+ "max_iterations" : 100,
34
+ "relative_tolerance" : 1e-3,
35
+ "line_search" : {
36
+ "line_search_type" : "manual_stepping",
37
+ "normalize_search_direction" : true,
38
+ "step_size" : 1.0
39
+ }
40
+ }""")
41
+ self.algorithm_settings = optimization_settings["optimization_algorithm"]
42
+ self.algorithm_settings.RecursivelyValidateAndAssignDefaults(default_algorithm_settings)
43
+
44
+ self.optimization_settings = optimization_settings
45
+ self.mapper_settings = optimization_settings["design_variables"]["filter"]
46
+
47
+ self.analyzer = analyzer
48
+ self.communicator = communicator
49
+ self.model_part_controller = model_part_controller
50
+
51
+ self.design_surface = None
52
+ self.mapper = None
53
+ self.data_logger = None
54
+ self.optimization_utilities = None
55
+ self.constraint_value = 0.0
56
+ self.correction_scaling = optimization_settings["optimization_algorithm"]["correction_scaling"].GetDouble()
57
+
58
+ self.objectives = optimization_settings["objectives"]
59
+ self.constraints = optimization_settings["constraints"]
60
+
61
+ self.step_size = self.algorithm_settings["line_search"]["step_size"].GetDouble()
62
+ self.max_iterations = self.algorithm_settings["max_iterations"].GetInt() + 1
63
+ self.relative_tolerance = self.algorithm_settings["relative_tolerance"].GetDouble()
64
+
65
+ self.optimization_model_part = model_part_controller.GetOptimizationModelPart()
66
+ self.optimization_model_part.AddNodalSolutionStepVariable(KSO.SEARCH_DIRECTION)
67
+
68
+ # --------------------------------------------------------------------------
69
+ def CheckApplicability(self):
70
+ if self.objectives.size() > 1:
71
+ raise RuntimeError("Penalized projection algorithm only supports one objective function!")
72
+ if self.constraints.size() == 0:
73
+ raise RuntimeError("Penalized projection algorithm requires definition of a constraint!")
74
+ if self.constraints.size() > 1:
75
+ raise RuntimeError("Penalized projection algorithm only supports one constraint!")
76
+
77
+ # --------------------------------------------------------------------------
78
+ def InitializeOptimizationLoop(self):
79
+ self.model_part_controller.Initialize()
80
+
81
+ self.analyzer.InitializeBeforeOptimizationLoop()
82
+
83
+ self.design_surface = self.model_part_controller.GetDesignSurface()
84
+
85
+ self.mapper = mapper_factory.CreateMapper(self.design_surface, self.design_surface, self.mapper_settings)
86
+ self.mapper.Initialize()
87
+ self.model_part_controller.InitializeDamping()
88
+
89
+ self.data_logger = data_logger_factory.CreateDataLogger(self.model_part_controller, self.communicator, self.optimization_settings)
90
+ self.data_logger.InitializeDataLogging()
91
+
92
+ self.optimization_utilities = KSO.OptimizationUtilities
93
+
94
+ # --------------------------------------------------------------------------
95
+ def RunOptimizationLoop(self):
96
+ timer = Timer()
97
+ timer.StartTimer()
98
+
99
+ for self.optimization_iteration in range(1,self.max_iterations):
100
+ KM.Logger.Print("")
101
+ KM.Logger.Print("===============================================================================")
102
+ KM.Logger.PrintInfo("ShapeOpt", timer.GetTimeStamp(), ": Starting optimization iteration ", self.optimization_iteration)
103
+ KM.Logger.Print("===============================================================================\n")
104
+
105
+ timer.StartNewLap()
106
+
107
+ self.__initializeNewShape()
108
+
109
+ self.__analyzeShape()
110
+
111
+ self.__computeShapeUpdate()
112
+
113
+ self.__logCurrentOptimizationStep()
114
+
115
+ KM.Logger.Print("")
116
+ KM.Logger.PrintInfo("ShapeOpt", "Time needed for current optimization step = ", timer.GetLapTime(), "s")
117
+ KM.Logger.PrintInfo("ShapeOpt", "Time needed for total optimization so far = ", timer.GetTotalTime(), "s")
118
+
119
+ if self.__isAlgorithmConverged():
120
+ break
121
+ else:
122
+ self.__determineAbsoluteChanges()
123
+
124
+ # --------------------------------------------------------------------------
125
+ def FinalizeOptimizationLoop(self):
126
+ self.data_logger.FinalizeDataLogging()
127
+ self.analyzer.FinalizeAfterOptimizationLoop()
128
+
129
+ # --------------------------------------------------------------------------
130
+ def __initializeNewShape(self):
131
+ self.model_part_controller.UpdateTimeStep(self.optimization_iteration)
132
+ self.model_part_controller.UpdateMeshAccordingInputVariable(KSO.SHAPE_UPDATE)
133
+ self.model_part_controller.SetReferenceMeshToMesh()
134
+
135
+ # --------------------------------------------------------------------------
136
+ def __analyzeShape(self):
137
+ self.communicator.initializeCommunication()
138
+ self.communicator.requestValueOf(self.objectives[0]["identifier"].GetString())
139
+ self.communicator.requestGradientOf(self.objectives[0]["identifier"].GetString())
140
+ self.communicator.requestValueOf(self.constraints[0]["identifier"].GetString())
141
+ self.communicator.requestGradientOf(self.constraints[0]["identifier"].GetString())
142
+
143
+ self.analyzer.AnalyzeDesignAndReportToCommunicator(self.optimization_model_part, self.optimization_iteration, self.communicator)
144
+
145
+ objGradientDict = self.communicator.getStandardizedGradient(self.objectives[0]["identifier"].GetString())
146
+ conGradientDict = self.communicator.getStandardizedGradient(self.constraints[0]["identifier"].GetString())
147
+
148
+ WriteDictionaryDataOnNodalVariable(objGradientDict, self.optimization_model_part, KSO.DF1DX)
149
+ WriteDictionaryDataOnNodalVariable(conGradientDict, self.optimization_model_part, KSO.DC1DX)
150
+
151
+ if self.objectives[0]["project_gradient_on_surface_normals"].GetBool() or self.constraints[0]["project_gradient_on_surface_normals"].GetBool():
152
+ self.model_part_controller.ComputeUnitSurfaceNormals()
153
+
154
+ if self.objectives[0]["project_gradient_on_surface_normals"].GetBool():
155
+ self.model_part_controller.ProjectNodalVariableOnUnitSurfaceNormals(KSO.DF1DX)
156
+
157
+ if self.constraints[0]["project_gradient_on_surface_normals"].GetBool():
158
+ self.model_part_controller.ProjectNodalVariableOnUnitSurfaceNormals(KSO.DC1DX)
159
+
160
+ self.model_part_controller.DampNodalSensitivityVariableIfSpecified(KSO.DF1DX)
161
+ self.model_part_controller.DampNodalSensitivityVariableIfSpecified(KSO.DC1DX)
162
+
163
+ # --------------------------------------------------------------------------
164
+ def __computeShapeUpdate(self):
165
+ self.mapper.Update()
166
+ self.mapper.InverseMap(KSO.DF1DX, KSO.DF1DX_MAPPED)
167
+ self.mapper.InverseMap(KSO.DC1DX, KSO.DC1DX_MAPPED)
168
+ is_adaptive = self.algorithm_settings["use_adaptive_correction"].GetBool()
169
+
170
+ constraint_value = self.communicator.getStandardizedValue(self.constraints[0]["identifier"].GetString())
171
+ if self.__isConstraintActive(constraint_value):
172
+ self.optimization_utilities.ComputeProjectedSearchDirection(self.design_surface)
173
+ self.correction_scaling = self.optimization_utilities.CorrectProjectedSearchDirection(self.design_surface, self.constraint_value, constraint_value, self.correction_scaling, is_adaptive)
174
+ self.constraint_value = constraint_value
175
+ else:
176
+ self.optimization_utilities.ComputeSearchDirectionSteepestDescent(self.design_surface)
177
+
178
+ normalize = self.algorithm_settings["line_search"]["normalize_search_direction"].GetBool()
179
+ self.optimization_utilities.ComputeControlPointUpdate(self.design_surface, self.step_size, normalize)
180
+
181
+ self.mapper.Map(KSO.CONTROL_POINT_UPDATE, KSO.SHAPE_UPDATE)
182
+ self.model_part_controller.DampNodalUpdateVariableIfSpecified(KSO.SHAPE_UPDATE)
183
+
184
+ # --------------------------------------------------------------------------
185
+ def __isConstraintActive(self, constraintValue):
186
+ if self.constraints[0]["type"].GetString() == "=":
187
+ return True
188
+ elif constraintValue > 0:
189
+ return True
190
+ else:
191
+ return False
192
+
193
+ # --------------------------------------------------------------------------
194
+ def __logCurrentOptimizationStep(self):
195
+ additional_values_to_log = {}
196
+ additional_values_to_log["correction_scaling"] = self.correction_scaling
197
+ additional_values_to_log["step_size"] = self.step_size
198
+ self.data_logger.LogSensitivityHeatmap(self.optimization_iteration, self.mapper)
199
+ self.data_logger.LogCurrentValues(self.optimization_iteration, additional_values_to_log)
200
+ self.data_logger.LogCurrentDesign(self.optimization_iteration)
201
+
202
+ # --------------------------------------------------------------------------
203
+ def __isAlgorithmConverged(self):
204
+
205
+ if self.optimization_iteration > 1 :
206
+
207
+ # Check if maximum iterations were reached
208
+ if self.optimization_iteration == self.max_iterations:
209
+ KM.Logger.Print("")
210
+ KM.Logger.PrintInfo("ShapeOpt", "Maximal iterations of optimization problem reached!")
211
+ return True
212
+
213
+ # Check for relative tolerance
214
+ relative_change_of_objective_value = self.data_logger.GetValues("rel_change_objective")[self.optimization_iteration]
215
+ if abs(relative_change_of_objective_value) < self.relative_tolerance:
216
+ KM.Logger.Print("")
217
+ KM.Logger.PrintInfo("ShapeOpt", "Optimization problem converged within a relative objective tolerance of ",self.relative_tolerance,"%.")
218
+ return True
219
+
220
+ # --------------------------------------------------------------------------
221
+ def __determineAbsoluteChanges(self):
222
+ self.optimization_utilities.AddFirstVariableToSecondVariable(self.design_surface, KSO.CONTROL_POINT_UPDATE, KSO.CONTROL_POINT_CHANGE)
223
+ self.optimization_utilities.AddFirstVariableToSecondVariable(self.design_surface, KSO.SHAPE_UPDATE, KSO.SHAPE_CHANGE)
224
+
225
+ # ==============================================================================