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,580 @@
1
+ # ==============================================================================
2
+ # KratosShapeOptimizationApplication
3
+ #
4
+ # License: BSD License
5
+ # license: ShapeOptimizationApplication/license.txt
6
+ #
7
+ # Main authors: Ihar Antonau
8
+ #
9
+ # ==============================================================================
10
+
11
+ # Making KratosMultiphysics backward compatible with python 2.6 and 2.7
12
+ from __future__ import print_function, absolute_import, division
13
+
14
+ # Kratos Core and Apps
15
+ import KratosMultiphysics as Kratos
16
+ import KratosMultiphysics.ShapeOptimizationApplication as KSO
17
+ from KratosMultiphysics.LinearSolversApplication import dense_linear_solver_factory
18
+
19
+ # Additional imports
20
+ from .algorithm_base import OptimizationAlgorithm
21
+ from .. import mapper_factory
22
+ from KratosMultiphysics.ShapeOptimizationApplication.loggers import data_logger_factory
23
+ from KratosMultiphysics.ShapeOptimizationApplication.utilities.custom_timer import Timer
24
+ from KratosMultiphysics.ShapeOptimizationApplication.utilities.custom_variable_utilities import WriteDictionaryDataOnNodalVariable
25
+ import numpy as np
26
+
27
+
28
+ # ==============================================================================
29
+ class AlgorithmRelaxedGradientProjection(OptimizationAlgorithm):
30
+ # --------------------------------------------------------------------------
31
+ def __init__(self, optimization_settings, analyzer, communicator, model_part_controller):
32
+ default_algorithm_settings = Kratos.Parameters("""
33
+ {
34
+ "name" : "relaxed_gradient_projection",
35
+ "max_iterations" : 100,
36
+ "max_inner_iter" : 100,
37
+ "relative_tolerance" : 1e-3,
38
+ "line_search" : {
39
+ "line_search_type" : "manual_stepping",
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
+ self.constraint_buffer_variables = {}
62
+ self.constraint_laplace_multipliers = {}
63
+ for itr, constraint in enumerate(self.constraints.values()):
64
+ constraint_id = constraint["identifier"].GetString()
65
+ self.constraint_gradient_variables.update({
66
+ constraint_id : {
67
+ "gradient": Kratos.KratosGlobals.GetVariable("DC"+str(itr+1)+"DX"),
68
+ "mapped_gradient": Kratos.KratosGlobals.GetVariable("DC"+str(itr+1)+"DX_MAPPED")
69
+ }
70
+ })
71
+ self.constraint_buffer_variables.update({
72
+ constraint_id : {
73
+ "buffer_value": 0.0,
74
+ "buffer_value-1": 0.0,
75
+ "buffer_size": 1e-12,
76
+ "buffer_size_factor": 2.0,
77
+ "central_buffer_value": 0.0,
78
+ "lower_buffer_value": - 1e-12,
79
+ "upper_buffer_value": 1e-12,
80
+ "g_i-1": 0.0,
81
+ "g_i-2": 0.0,
82
+ "g_i-3": 0.0,
83
+ "max_constraint_change": 0.0
84
+ }
85
+ })
86
+
87
+
88
+ self.step_size = self.algorithm_settings["line_search"]["step_size"].GetDouble()
89
+ self.line_search_type = self.algorithm_settings["line_search"]["line_search_type"].GetString()
90
+ self.max_iterations = self.algorithm_settings["max_iterations"].GetInt() + 1
91
+ self.relative_tolerance = self.algorithm_settings["relative_tolerance"].GetDouble()
92
+ self.s_norm = 0.0
93
+
94
+ self.max_inner_iter = self.algorithm_settings["max_inner_iter"].GetDouble()
95
+ self.buffer_coeff_update = 2.0 / self.max_inner_iter
96
+
97
+ self.optimization_model_part = model_part_controller.GetOptimizationModelPart()
98
+ self.optimization_model_part.AddNodalSolutionStepVariable(KSO.INV_HESSIAN)
99
+ self.optimization_model_part.AddNodalSolutionStepVariable(KSO.PROJECTION)
100
+ self.optimization_model_part.AddNodalSolutionStepVariable(KSO.CORRECTION)
101
+ self.optimization_model_part.AddNodalSolutionStepVariable(KSO.SEARCH_DIRECTION)
102
+
103
+
104
+ # --------------------------------------------------------------------------
105
+ def CheckApplicability(self):
106
+ if self.objectives.size() > 1:
107
+ raise RuntimeError("Gradient projection algorithm only supports one objective function!")
108
+ if self.constraints.size() == 0:
109
+ raise RuntimeError("Gradient projection algorithm requires definition of at least one constraint!")
110
+
111
+ # --------------------------------------------------------------------------
112
+ def InitializeOptimizationLoop(self):
113
+ self.model_part_controller.Initialize()
114
+
115
+ self.analyzer.InitializeBeforeOptimizationLoop()
116
+
117
+ self.design_surface = self.model_part_controller.GetDesignSurface()
118
+
119
+ self.mapper = mapper_factory.CreateMapper(self.design_surface, self.design_surface, self.mapper_settings)
120
+ self.mapper.Initialize()
121
+ self.model_part_controller.InitializeDamping()
122
+
123
+ self.data_logger = data_logger_factory.CreateDataLogger(self.model_part_controller, self.communicator, self.optimization_settings)
124
+ self.data_logger.InitializeDataLogging()
125
+
126
+ self.optimization_utilities = KSO.OptimizationUtilities
127
+
128
+ # --------------------------------------------------------------------------
129
+ def RunOptimizationLoop(self):
130
+ timer = Timer()
131
+ timer.StartTimer()
132
+
133
+ for self.optimization_iteration in range(1,self.max_iterations):
134
+ Kratos.Logger.Print("")
135
+ Kratos.Logger.Print("===============================================================================")
136
+ Kratos.Logger.PrintInfo("ShapeOpt", timer.GetTimeStamp(), ": Starting optimization iteration ", self.optimization_iteration)
137
+ Kratos.Logger.Print("===============================================================================\n")
138
+
139
+ timer.StartNewLap()
140
+
141
+ self.__initializeNewShape()
142
+
143
+ self.__analyzeShape()
144
+
145
+ self.__computeBufferValue()
146
+
147
+ self.__computeShapeUpdate()
148
+
149
+ self.__logCurrentOptimizationStep()
150
+
151
+ self.__updateBufferZone()
152
+
153
+ Kratos.Logger.Print("")
154
+ Kratos.Logger.PrintInfo("ShapeOpt", "Time needed for current optimization step = ", timer.GetLapTime(), "s")
155
+ Kratos.Logger.PrintInfo("ShapeOpt", "Time needed for total optimization so far = ", timer.GetTotalTime(), "s")
156
+
157
+ if self.__isAlgorithmConverged():
158
+ break
159
+ else:
160
+ self.__determineAbsoluteChanges()
161
+
162
+ # --------------------------------------------------------------------------
163
+ def FinalizeOptimizationLoop(self):
164
+ self.data_logger.FinalizeDataLogging()
165
+ self.analyzer.FinalizeAfterOptimizationLoop()
166
+
167
+ # --------------------------------------------------------------------------
168
+ def __initializeNewShape(self):
169
+ self.model_part_controller.UpdateTimeStep(self.optimization_iteration)
170
+ self.model_part_controller.UpdateMeshAccordingInputVariable(KSO.SHAPE_UPDATE)
171
+ self.model_part_controller.SetReferenceMeshToMesh()
172
+
173
+ # --------------------------------------------------------------------------
174
+ def __analyzeShape(self):
175
+ self.communicator.initializeCommunication()
176
+ self.communicator.requestValueOf(self.objectives[0]["identifier"].GetString())
177
+ self.communicator.requestGradientOf(self.objectives[0]["identifier"].GetString())
178
+
179
+ for constraint in self.constraints.values():
180
+ con_id = constraint["identifier"].GetString()
181
+ self.communicator.requestValueOf(con_id)
182
+ self.communicator.requestGradientOf(con_id)
183
+
184
+ self.analyzer.AnalyzeDesignAndReportToCommunicator(self.optimization_model_part, self.optimization_iteration, self.communicator)
185
+
186
+ # compute normals only if required
187
+ surface_normals_required = self.objectives[0]["project_gradient_on_surface_normals"].GetBool()
188
+ for constraint in self.constraints.values():
189
+ if constraint["project_gradient_on_surface_normals"].GetBool():
190
+ surface_normals_required = True
191
+
192
+ if surface_normals_required:
193
+ self.model_part_controller.ComputeUnitSurfaceNormals()
194
+
195
+ # project and damp objective gradients
196
+ objGradientDict = self.communicator.getStandardizedGradient(self.objectives[0]["identifier"].GetString())
197
+ WriteDictionaryDataOnNodalVariable(objGradientDict, self.optimization_model_part, KSO.DF1DX)
198
+
199
+ if self.objectives[0]["project_gradient_on_surface_normals"].GetBool():
200
+ self.model_part_controller.ProjectNodalVariableOnUnitSurfaceNormals(KSO.DF1DX)
201
+
202
+ self.model_part_controller.DampNodalSensitivityVariableIfSpecified(KSO.DF1DX)
203
+
204
+ # project and damp constraint gradients
205
+ for constraint in self.constraints.values():
206
+ con_id = constraint["identifier"].GetString()
207
+ conGradientDict = self.communicator.getStandardizedGradient(con_id)
208
+ gradient_variable = self.constraint_gradient_variables[con_id]["gradient"]
209
+ WriteDictionaryDataOnNodalVariable(conGradientDict, self.optimization_model_part, gradient_variable)
210
+
211
+ if constraint["project_gradient_on_surface_normals"].GetBool():
212
+ self.model_part_controller.ProjectNodalVariableOnUnitSurfaceNormals(gradient_variable)
213
+
214
+ self.model_part_controller.DampNodalSensitivityVariableIfSpecified(gradient_variable)
215
+
216
+ # --------------------------------------------------------------------------
217
+ def __computeBufferValue(self):
218
+ # compute new buffer size and buffer values
219
+ for constraint in self.constraints.values():
220
+ identifier = constraint["identifier"].GetString()
221
+ g_i = self.communicator.getStandardizedValue(identifier)
222
+ g_i_m1 = self.constraint_buffer_variables[identifier]["g_i-1"]
223
+ buffer_size_factor = self.constraint_buffer_variables[identifier]["buffer_size_factor"]
224
+
225
+
226
+ self.constraint_buffer_variables[identifier]["buffer_value-1"] = self.constraint_buffer_variables[identifier]["buffer_value"]
227
+
228
+ if self.optimization_iteration > 1:
229
+
230
+ if abs(g_i - g_i_m1) > self.constraint_buffer_variables[identifier]["max_constraint_change"]:
231
+ self.constraint_buffer_variables[identifier]["max_constraint_change"] = abs(g_i - g_i_m1)
232
+
233
+ max_constraint_change = self.constraint_buffer_variables[identifier]["max_constraint_change"]
234
+ self.constraint_buffer_variables[identifier]["buffer_size"] = max(buffer_size_factor * max_constraint_change, 1e-12)
235
+
236
+ buffer_size = self.constraint_buffer_variables[identifier]["buffer_size"]
237
+ self.constraint_buffer_variables[identifier]["lower_buffer_value"] = self.constraint_buffer_variables[identifier]["central_buffer_value"] \
238
+ - buffer_size
239
+ self.constraint_buffer_variables[identifier]["upper_buffer_value"] = self.constraint_buffer_variables[identifier]["central_buffer_value"] \
240
+ + buffer_size
241
+
242
+ if self.__isConstraintActive(constraint):
243
+ if constraint["type"].GetString() == "=":
244
+ self.constraint_buffer_variables[identifier]["buffer_value"] = min(1 - abs(g_i) / buffer_size, 2.0)
245
+ else:
246
+ lower_buffer_value = self.constraint_buffer_variables[identifier]["lower_buffer_value"]
247
+ self.constraint_buffer_variables[identifier]["buffer_value"] = min( (g_i - lower_buffer_value) / buffer_size, 2.0 )
248
+ else:
249
+ self.constraint_buffer_variables[identifier]["buffer_value"] = 0.0
250
+
251
+ # --------------------------------------------------------------------------
252
+ def __computeShapeUpdate(self):
253
+ self.mapper.Update()
254
+ self.mapper.InverseMap(KSO.DF1DX, KSO.DF1DX_MAPPED)
255
+
256
+ for constraint in self.constraints.values():
257
+ con_id = constraint["identifier"].GetString()
258
+ gradient_variable = self.constraint_gradient_variables[con_id]["gradient"]
259
+ mapped_gradient_variable = self.constraint_gradient_variables[con_id]["mapped_gradient"]
260
+ self.mapper.InverseMap(gradient_variable, mapped_gradient_variable)
261
+
262
+ self.inner_iter = 1
263
+
264
+ while not self.__checkInnerConvergence():
265
+
266
+ self.direction_has_changed = False
267
+
268
+ Kratos.Logger.PrintInfo("ShapeOpt", "Inner Iteration to Find Shape Update = ", self.inner_iter)
269
+
270
+ self.__computeControlPointUpdate()
271
+
272
+ self.mapper.Map(KSO.CONTROL_POINT_UPDATE, KSO.SHAPE_UPDATE)
273
+ self.model_part_controller.DampNodalUpdateVariableIfSpecified(KSO.SHAPE_UPDATE)
274
+
275
+ self.d_norm = self.optimization_utilities.ComputeMaxNormOfNodalVariable(self.design_surface, KSO.SHAPE_UPDATE)
276
+
277
+ self.__checkConstraintValue()
278
+ self.inner_iter += 1
279
+ self.__saveLineSearchData()
280
+
281
+
282
+ # --------------------------------------------------------------------------
283
+
284
+ def __checkInnerConvergence(self):
285
+ Kratos.Logger.PrintInfo("Check Convergence of the inner loop:")
286
+ if self.inner_iter == 1:
287
+ return False
288
+ elif self.direction_has_changed and self.inner_iter <= self.max_inner_iter:
289
+ return False
290
+ else:
291
+ return True
292
+
293
+ def __checkConstraintValue(self):
294
+ index = -1
295
+ for constraint in self.constraints.values():
296
+ if self.__isConstraintActive(constraint):
297
+ index += 1
298
+ identifier = constraint["identifier"].GetString()
299
+ g_i = self.communicator.getStandardizedValue(identifier)
300
+ g_a_variable = self.constraint_gradient_variables[identifier]["gradient"]
301
+ shape_update = Kratos.Vector()
302
+ gradient = Kratos.Vector()
303
+ self.optimization_utilities.AssembleVector(self.design_surface, gradient, g_a_variable)
304
+ self.optimization_utilities.AssembleVector(self.design_surface, shape_update, KSO.SHAPE_UPDATE)
305
+ new_g_i = g_i + np.dot(gradient, shape_update)
306
+ Kratos.Logger.PrintInfo("Constraint ", identifier, "\n Linearized new value = ", new_g_i)
307
+ if new_g_i > 0.0:
308
+ if self.relaxation_coefficients[index] < 1.0:
309
+ self.relaxation_coefficients[index] = min(self.relaxation_coefficients[index] + self.buffer_coeff_update, 1.0)
310
+ self.direction_has_changed = True
311
+ elif self.correction_coefficients[index] < 2.0:
312
+ self.correction_coefficients[index] = min (self.correction_coefficients[index] + self.buffer_coeff_update, 2.0)
313
+ self.direction_has_changed = True
314
+ Kratos.Logger.PrintInfo("Constraint ", identifier, "\n W_R, W_C = ", self.relaxation_coefficients[index], self.correction_coefficients[index])
315
+
316
+ # --------------------------------------------------------------------------
317
+ def __LineSearch(self):
318
+ Kratos.Logger.PrintInfo("Line Search ...")
319
+ if self.line_search_type == "manual_stepping":
320
+ self.__manualStep()
321
+ elif self.line_search_type == "QNBB_method":
322
+ if self.optimization_iteration == 1:
323
+ self.max_step_size = self.step_size
324
+ # Do initial small step
325
+ self.step_size /= 5
326
+ self.__manualStep()
327
+ else:
328
+ self.__QNBBStep()
329
+ elif self.line_search_type == "BB_method":
330
+ if self.optimization_iteration == 1:
331
+ self.max_step_size = self.step_size
332
+ # Do initial small step
333
+ self.step_size /= 5
334
+ self.__manualStep()
335
+ else:
336
+ self.__BBStep()
337
+
338
+
339
+ def __manualStep(self):
340
+ step_norm = self.optimization_utilities.ComputeMaxNormOfNodalVariable(self.design_surface, KSO.CONTROL_POINT_UPDATE)
341
+ if abs(step_norm) > 1e-10:
342
+ step = Kratos.Vector()
343
+ self.optimization_utilities.AssembleVector(self.design_surface, step, KSO.CONTROL_POINT_UPDATE)
344
+ step *= 1.0 / step_norm
345
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, step, KSO.SEARCH_DIRECTION)
346
+ step *= self.step_size
347
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, step, KSO.CONTROL_POINT_UPDATE)
348
+
349
+ def __QNBBStep(self):
350
+ self.s_norm = self.optimization_utilities.ComputeMaxNormOfNodalVariable(self.design_surface, KSO.SEARCH_DIRECTION)
351
+ if abs(self.s_norm) > 1e-10:
352
+ s = Kratos.Vector()
353
+ self.optimization_utilities.AssembleVector(self.design_surface, s, KSO.SEARCH_DIRECTION)
354
+ s /= self.s_norm
355
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, s, KSO.SEARCH_DIRECTION)
356
+
357
+ for index, node in enumerate(self.design_surface.Nodes):
358
+ i = index * 3
359
+ y_i = np.array(self.prev_s[i: i+3]) - np.array(s[i: i+3])
360
+ d_i = np.array(self.d[i:i+3])
361
+ if np.dot(y_i, y_i) < 1e-9:
362
+ step_i = self.max_step_size
363
+ else:
364
+ step_i = abs(np.dot(d_i, y_i) / np.dot(y_i, y_i))
365
+ if step_i > self.max_step_size:
366
+ step_i = self.max_step_size
367
+ node.SetSolutionStepValue(KSO.INV_HESSIAN, step_i)
368
+ s[i] = s[i] * step_i
369
+ s[i+1] = s[i+1] * step_i
370
+ s[i+2] = s[i+2] * step_i
371
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, s, KSO.CONTROL_POINT_UPDATE)
372
+
373
+ def __BBStep(self):
374
+ self.s_norm = self.optimization_utilities.ComputeMaxNormOfNodalVariable(self.design_surface, KSO.SEARCH_DIRECTION)
375
+ if abs(self.s_norm) > 1e-10:
376
+ s = Kratos.Vector()
377
+ self.optimization_utilities.AssembleVector(self.design_surface, s, KSO.SEARCH_DIRECTION)
378
+ s /= self.s_norm
379
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, s, KSO.SEARCH_DIRECTION)
380
+ y = self.prev_s - s
381
+ if np.dot(y, y) < 1e-9:
382
+ step = self.max_step_size
383
+ else:
384
+ step = abs(np.dot(y, self.d) / np.dot(y, y))
385
+ if step > self.max_step_size:
386
+ step = self.max_step_size
387
+ s = s * step
388
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, s, KSO.CONTROL_POINT_UPDATE)
389
+
390
+ def __saveLineSearchData(self):
391
+ self.prev_s = Kratos.Vector()
392
+ self.d = Kratos.Vector()
393
+ self.optimization_utilities.AssembleVector(self.design_surface, self.d, KSO.CONTROL_POINT_UPDATE)
394
+ self.optimization_utilities.AssembleVector(self.design_surface, self.prev_s, KSO.SEARCH_DIRECTION)
395
+
396
+ # --------------------------------------------------------------------------
397
+ def __computeControlPointUpdate(self):
398
+ """adapted from https://msulaiman.org/onewebmedia/GradProj_2.pdf"""
399
+ if self.inner_iter == 1:
400
+ self.g_a, self.g_a_variables, self.relaxation_coefficients, self.correction_coefficients = self.__getActiveConstraints()
401
+
402
+ Kratos.Logger.PrintInfo("ShapeOpt", "Assemble vector of objective gradient.")
403
+ nabla_f = Kratos.Vector()
404
+ p = Kratos.Vector()
405
+ self.optimization_utilities.AssembleVector(self.design_surface, nabla_f, KSO.DF1DX_MAPPED)
406
+ f_norm = self.optimization_utilities.ComputeMaxNormOfNodalVariable(self.design_surface, KSO.DF1DX_MAPPED)
407
+
408
+ if abs(f_norm) > 1e-10:
409
+ nabla_f *= 1.0/f_norm
410
+
411
+ if len(self.g_a) == 0:
412
+ Kratos.Logger.PrintInfo("ShapeOpt", "No constraints active, use negative objective gradient as search direction.")
413
+ p = nabla_f * (-1.0)
414
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, p, KSO.SEARCH_DIRECTION)
415
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, p, KSO.PROJECTION)
416
+ Kratos.VariableUtils().SetHistoricalVariableToZero(KSO.CORRECTION, self.design_surface.Nodes)
417
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, p, KSO.CONTROL_POINT_UPDATE)
418
+ self.__LineSearch()
419
+ return
420
+
421
+ omega_r = Kratos.Matrix()
422
+ self.optimization_utilities.AssembleBufferMatrix(omega_r, self.relaxation_coefficients)
423
+ omega_c = Kratos.Vector(self.correction_coefficients)
424
+
425
+ Kratos.Logger.PrintInfo("ShapeOpt", "Assemble matrix of constraint gradient.")
426
+ N = Kratos.Matrix()
427
+ self.optimization_utilities.AssembleMatrix(self.design_surface, N, self.g_a_variables)
428
+
429
+ settings = Kratos.Parameters('{ "solver_type" : "LinearSolversApplication.dense_col_piv_householder_qr" }')
430
+ solver = dense_linear_solver_factory.ConstructSolver(settings)
431
+
432
+ c = Kratos.Vector()
433
+
434
+ Kratos.Logger.PrintInfo("ShapeOpt", "Calculate projected search direction and correction.")
435
+ self.optimization_utilities.CalculateRelaxedProjectedSearchDirectionAndCorrection(
436
+ nabla_f,
437
+ N,
438
+ omega_r,
439
+ omega_c,
440
+ solver,
441
+ p,
442
+ c)
443
+
444
+ # additional normalization step
445
+
446
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, p, KSO.PROJECTION)
447
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, c, KSO.CORRECTION)
448
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, p+c, KSO.SEARCH_DIRECTION)
449
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, p+c, KSO.CONTROL_POINT_UPDATE)
450
+ self.__LineSearch()
451
+
452
+
453
+
454
+ # --------------------------------------------------------------------------
455
+ def __getActiveConstraints(self):
456
+ active_constraint_values = []
457
+ active_constraint_variables = []
458
+ active_relaxation_coefficient = []
459
+ active_correction_coefficient = []
460
+
461
+ for constraint in self.constraints.values():
462
+ if self.__isConstraintActive(constraint):
463
+ identifier = constraint["identifier"].GetString()
464
+ g_i = self.communicator.getStandardizedValue(identifier)
465
+ buffer_value = self.constraint_buffer_variables[identifier]["buffer_value"]
466
+
467
+ active_constraint_values.append(g_i)
468
+ g_a_variable = self.constraint_gradient_variables[identifier]["mapped_gradient"]
469
+ g_a_norm = self.optimization_utilities.ComputeMaxNormOfNodalVariable(self.design_surface, g_a_variable)
470
+ g_a_variable_vector = Kratos.Vector()
471
+ self.optimization_utilities.AssembleVector(self.design_surface, g_a_variable_vector, g_a_variable)
472
+ if abs(g_a_norm) > 1e-10:
473
+ g_a_variable_vector /= g_a_norm
474
+
475
+ self.optimization_utilities.AssignVectorToVariable(self.design_surface, g_a_variable_vector, g_a_variable)
476
+
477
+ active_constraint_variables.append(g_a_variable)
478
+ active_relaxation_coefficient.append(min(buffer_value,1.0))
479
+
480
+ max_buffer = 2.0
481
+ if buffer_value > 1.0:
482
+ if buffer_value < max_buffer:
483
+ active_correction_coefficient.append(2*(buffer_value - 1))
484
+ else:
485
+ active_correction_coefficient.append(2*(max_buffer-1))
486
+ else:
487
+ active_correction_coefficient.append(0.0)
488
+
489
+
490
+ return active_constraint_values, active_constraint_variables, active_relaxation_coefficient, active_correction_coefficient
491
+
492
+ # --------------------------------------------------------------------------
493
+ def __isConstraintActive(self, constraint):
494
+ identifier = constraint["identifier"].GetString()
495
+ g_i = self.communicator.getStandardizedValue(identifier)
496
+ if constraint["type"].GetString() == "=":
497
+ return True
498
+ elif g_i >= self.constraint_buffer_variables[identifier]["lower_buffer_value"]:
499
+ return True
500
+ else:
501
+ return False
502
+ # --------------------------------------------------------------------------
503
+ def __updateBufferZone(self):
504
+ # adapt the buffer zones for zig-zagging, too much or too little correction
505
+ for constraint in self.constraints.values():
506
+
507
+ identifier = constraint["identifier"].GetString()
508
+ g_i = self.communicator.getStandardizedValue(identifier)
509
+ g_i_m1 = self.constraint_buffer_variables[identifier]["g_i-1"]
510
+ g_i_m2 = self.constraint_buffer_variables[identifier]["g_i-2"]
511
+ g_i_m3 = self.constraint_buffer_variables[identifier]["g_i-3"]
512
+
513
+ buffer_value = self.constraint_buffer_variables[identifier]["buffer_value"]
514
+ buffer_value_m1 = self.constraint_buffer_variables[identifier]["buffer_value-1"]
515
+
516
+ if self.optimization_iteration > 3:
517
+ delta_g_1 = g_i - g_i_m1
518
+ delta_g_2 = g_i_m1 -g_i_m2
519
+ delta_g_3 = g_i_m2 -g_i_m3
520
+
521
+ if delta_g_1*delta_g_2 < 0 and delta_g_2*delta_g_3 < 0:
522
+ self.constraint_buffer_variables[identifier]["buffer_size_factor"] += abs(buffer_value - buffer_value_m1)
523
+
524
+ if self.optimization_iteration > 1:
525
+ delta_g = g_i - g_i_m1
526
+ if delta_g >= 0.0 and g_i_m1 > 0:
527
+ self.constraint_buffer_variables[identifier]["central_buffer_value"] -= g_i_m1
528
+ elif delta_g <= 0.0 and g_i_m1 < 0:
529
+ self.constraint_buffer_variables[identifier]["central_buffer_value"] += g_i_m1
530
+ self.constraint_buffer_variables[identifier]["central_buffer_value"] = \
531
+ max(self.constraint_buffer_variables[identifier]["central_buffer_value"], 0.0)
532
+
533
+ self.constraint_buffer_variables[identifier]["g_i-3"] = g_i_m2
534
+ self.constraint_buffer_variables[identifier]["g_i-2"] = g_i_m1
535
+ self.constraint_buffer_variables[identifier]["g_i-1"] = g_i
536
+
537
+ # --------------------------------------------------------------------------
538
+ def __logCurrentOptimizationStep(self):
539
+ additional_values_to_log = {}
540
+ additional_values_to_log["step_size"] = self.d_norm
541
+ additional_values_to_log["inf_norm_p"] = self.optimization_utilities.ComputeMaxNormOfNodalVariable(self.design_surface, KSO.PROJECTION)
542
+ additional_values_to_log["inf_norm_c"] = self.optimization_utilities.ComputeMaxNormOfNodalVariable(self.design_surface, KSO.CORRECTION)
543
+ additional_values_to_log["projection_norm"] = self.s_norm
544
+ itr = 0
545
+ for constraint in self.constraints.values():
546
+ identifier = constraint["identifier"].GetString()
547
+ additional_values_to_log["c"+str(itr+1)+"_buffer_value"] = self.constraint_buffer_variables[identifier]["buffer_value"]
548
+ additional_values_to_log["c"+str(itr+1)+"_buffer_size"] = self.constraint_buffer_variables[identifier]["buffer_size"]
549
+ additional_values_to_log["c"+str(itr+1)+"_buffer_size_factor"] = self.constraint_buffer_variables[identifier]["buffer_size_factor"]
550
+ additional_values_to_log["c"+str(itr+1)+"_central_buffer_value"] = self.constraint_buffer_variables[identifier]["central_buffer_value"]
551
+ additional_values_to_log["c"+str(itr+1)+"_lower_buffer_value"] = self.constraint_buffer_variables[identifier]["lower_buffer_value"]
552
+ additional_values_to_log["c"+str(itr+1)+"_upper_buffer_value"] = self.constraint_buffer_variables[identifier]["upper_buffer_value"]
553
+ itr += 1
554
+ self.data_logger.LogCurrentValues(self.optimization_iteration, additional_values_to_log)
555
+ self.data_logger.LogCurrentDesign(self.optimization_iteration)
556
+
557
+ # --------------------------------------------------------------------------
558
+ def __isAlgorithmConverged(self):
559
+
560
+ if self.optimization_iteration > 1 :
561
+
562
+ # Check if maximum iterations were reached
563
+ if self.optimization_iteration == self.max_iterations:
564
+ Kratos.Logger.Print("")
565
+ Kratos.Logger.PrintInfo("ShapeOpt", "Maximal iterations of optimization problem reached!")
566
+ return True
567
+
568
+ # Check for relative tolerance
569
+ relative_change_of_objective_value = self.data_logger.GetValues("rel_change_objective")[self.optimization_iteration]
570
+ if abs(relative_change_of_objective_value) < self.relative_tolerance:
571
+ Kratos.Logger.Print("")
572
+ Kratos.Logger.PrintInfo("ShapeOpt", "Optimization problem converged within a relative objective tolerance of ",self.relative_tolerance,"%.")
573
+ return True
574
+
575
+ # --------------------------------------------------------------------------
576
+ def __determineAbsoluteChanges(self):
577
+ self.optimization_utilities.AddFirstVariableToSecondVariable(self.design_surface, KSO.CONTROL_POINT_UPDATE, KSO.CONTROL_POINT_CHANGE)
578
+ self.optimization_utilities.AddFirstVariableToSecondVariable(self.design_surface, KSO.SHAPE_UPDATE, KSO.SHAPE_CHANGE)
579
+
580
+ # ==============================================================================