KratosShapeOptimizationApplication 10.4.2__2-cp39-cp39-win_amd64.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.pyd +0 -0
- KratosMultiphysics/.libs/KratosShapeOptimizationCore.dll +0 -0
- KratosMultiphysics/.libs/KratosShapeOptimizationCore.lib +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.2.dist-info/METADATA +31 -0
- kratosshapeoptimizationapplication-10.4.2.dist-info/RECORD +66 -0
- kratosshapeoptimizationapplication-10.4.2.dist-info/WHEEL +5 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import KratosMultiphysics
|
|
2
|
+
from KratosMultiphysics.ShapeOptimizationApplication.optimizer_factory import Optimizer
|
|
3
|
+
|
|
4
|
+
import shutil
|
|
5
|
+
import os, time, datetime
|
|
6
|
+
|
|
7
|
+
if __name__ == "__main__":
|
|
8
|
+
from sys import argv
|
|
9
|
+
|
|
10
|
+
if len(argv) > 2:
|
|
11
|
+
err_msg = 'Too many input arguments!\n'
|
|
12
|
+
err_msg += 'Use this script in the following way:\n'
|
|
13
|
+
err_msg += '- With default ProjectParameters (read from "ProjectParameters.json"):\n'
|
|
14
|
+
err_msg += ' "python3 structural_mechanics_analysis.py"\n'
|
|
15
|
+
err_msg += '- With custom ProjectParameters:\n'
|
|
16
|
+
err_msg += ' "python3 structural_mechanics_analysis.py CustomProjectParameters.json"\n'
|
|
17
|
+
raise Exception(err_msg)
|
|
18
|
+
|
|
19
|
+
if len(argv) == 2: # ProjectParameters is being passed from outside
|
|
20
|
+
project_parameters_file_name = argv[1]
|
|
21
|
+
else: # using default name
|
|
22
|
+
project_parameters_file_name = "optimization_parameters.json"
|
|
23
|
+
|
|
24
|
+
with open(project_parameters_file_name,'r') as parameter_file:
|
|
25
|
+
parameters = KratosMultiphysics.Parameters(parameter_file.read())
|
|
26
|
+
|
|
27
|
+
model = KratosMultiphysics.Model()
|
|
28
|
+
# Create optimizer and perform optimization
|
|
29
|
+
optimizer = Optimizer(model, parameters["optimization_settings"])
|
|
30
|
+
optimizer.Optimize()
|
|
31
|
+
shutil.copyfile("optimization_parameters.json", "Optimization_Results/optimization_parameters.json")
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
# Imports
|
|
13
|
+
# ------------------------------------------------------------------------------
|
|
14
|
+
from KratosMultiphysics import _ImportApplication
|
|
15
|
+
from KratosShapeOptimizationApplication import *
|
|
16
|
+
application = KratosShapeOptimizationApplication()
|
|
17
|
+
application_name = "KratosShapeOptimizationApplication"
|
|
18
|
+
|
|
19
|
+
_ImportApplication(application, application_name)
|
|
File without changes
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
# ==============================================================================
|
|
14
|
+
class OptimizationAlgorithm:
|
|
15
|
+
# --------------------------------------------------------------------------
|
|
16
|
+
def CheckApplicability( self ):
|
|
17
|
+
raise RuntimeError("Algorithm base class is called. Please check your implementation of the function >> CheckApplicability << .")
|
|
18
|
+
|
|
19
|
+
# --------------------------------------------------------------------------
|
|
20
|
+
def InitializeOptimizationLoop( self ):
|
|
21
|
+
raise RuntimeError("Algorithm base class is called. Please check your implementation of the function >> InitializeOptimizationLoop << .")
|
|
22
|
+
|
|
23
|
+
# --------------------------------------------------------------------------
|
|
24
|
+
def RunOptimizationLoop( self ):
|
|
25
|
+
raise RuntimeError("Algorithm base class is called. Please check your implementation of the function >> RunOptimizationLoop << .")
|
|
26
|
+
|
|
27
|
+
# --------------------------------------------------------------------------
|
|
28
|
+
def FinalizeOptimizationLoop( self ):
|
|
29
|
+
raise RuntimeError("Algorithm base class is called. Please check your implementation of the function >> FinalizeOptimizationLoop << .")
|
|
30
|
+
|
|
31
|
+
# ==============================================================================
|
|
@@ -0,0 +1,412 @@
|
|
|
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
|
+
import math
|
|
24
|
+
|
|
25
|
+
# ==============================================================================
|
|
26
|
+
class AlgorithmBeadOptimization(OptimizationAlgorithm):
|
|
27
|
+
# --------------------------------------------------------------------------
|
|
28
|
+
def __init__(self, optimization_settings, analyzer, communicator, model_part_controller):
|
|
29
|
+
default_algorithm_settings = KM.Parameters("""
|
|
30
|
+
{
|
|
31
|
+
"name" : "bead_optimization",
|
|
32
|
+
"bead_height" : 1.0,
|
|
33
|
+
"bead_direction" : [],
|
|
34
|
+
"bead_side" : "both",
|
|
35
|
+
"fix_boundaries" : [],
|
|
36
|
+
"estimated_lagrange_multiplier" : 1.0,
|
|
37
|
+
"max_total_iterations" : 10000,
|
|
38
|
+
"max_outer_iterations" : 10000,
|
|
39
|
+
"max_inner_iterations" : 30,
|
|
40
|
+
"min_inner_iterations" : 3,
|
|
41
|
+
"inner_iteration_tolerance" : 1e-3,
|
|
42
|
+
"line_search" : {
|
|
43
|
+
"line_search_type" : "manual_stepping",
|
|
44
|
+
"normalize_search_direction" : true,
|
|
45
|
+
"step_size" : 1.0
|
|
46
|
+
},
|
|
47
|
+
"filter_penalty_term" : false,
|
|
48
|
+
"penalty_filter_radius" : -1.0
|
|
49
|
+
}""")
|
|
50
|
+
self.algorithm_settings = optimization_settings["optimization_algorithm"]
|
|
51
|
+
self.algorithm_settings.RecursivelyValidateAndAssignDefaults(default_algorithm_settings)
|
|
52
|
+
|
|
53
|
+
self.optimization_settings = optimization_settings
|
|
54
|
+
self.mapper_settings = optimization_settings["design_variables"]["filter"]
|
|
55
|
+
|
|
56
|
+
if self.algorithm_settings["filter_penalty_term"].GetBool():
|
|
57
|
+
if self.algorithm_settings["penalty_filter_radius"].GetDouble() == -1.0:
|
|
58
|
+
raise RuntimeError("The parameter `penalty_filter_radius` is missing in order to filter the penalty term!")
|
|
59
|
+
|
|
60
|
+
self.analyzer = analyzer
|
|
61
|
+
self.communicator = communicator
|
|
62
|
+
self.model_part_controller = model_part_controller
|
|
63
|
+
|
|
64
|
+
self.design_surface = None
|
|
65
|
+
self.mapper = None
|
|
66
|
+
self.penalty_filter = None
|
|
67
|
+
self.data_logger = None
|
|
68
|
+
self.optimization_utilities = None
|
|
69
|
+
|
|
70
|
+
self.objectives = optimization_settings["objectives"]
|
|
71
|
+
self.constraints = optimization_settings["constraints"]
|
|
72
|
+
|
|
73
|
+
self.bead_height = self.algorithm_settings["bead_height"].GetDouble()
|
|
74
|
+
self.bead_side = self.algorithm_settings["bead_side"].GetString()
|
|
75
|
+
self.filter_penalty_term = self.algorithm_settings["filter_penalty_term"].GetBool()
|
|
76
|
+
self.estimated_lagrange_multiplier = self.algorithm_settings["estimated_lagrange_multiplier"].GetDouble()
|
|
77
|
+
self.max_total_iterations = self.algorithm_settings["max_total_iterations"].GetInt()
|
|
78
|
+
self.max_outer_iterations = self.algorithm_settings["max_outer_iterations"].GetInt()
|
|
79
|
+
self.max_inner_iterations = self.algorithm_settings["max_inner_iterations"].GetInt()
|
|
80
|
+
self.min_inner_iterations = self.algorithm_settings["min_inner_iterations"].GetInt()
|
|
81
|
+
self.inner_iteration_tolerance = self.algorithm_settings["inner_iteration_tolerance"].GetDouble()
|
|
82
|
+
self.step_size = self.algorithm_settings["line_search"]["step_size"].GetDouble()
|
|
83
|
+
|
|
84
|
+
self.lower_bound = None
|
|
85
|
+
self.upper_bound = None
|
|
86
|
+
|
|
87
|
+
self.lambda0 = 0.0
|
|
88
|
+
self.penalty_scaling_0 = 1.0
|
|
89
|
+
self.penalty_factor_0 = 1.0
|
|
90
|
+
|
|
91
|
+
self.optimization_model_part = model_part_controller.GetOptimizationModelPart()
|
|
92
|
+
self.optimization_model_part.AddNodalSolutionStepVariable(KSO.ALPHA)
|
|
93
|
+
self.optimization_model_part.AddNodalSolutionStepVariable(KSO.ALPHA_MAPPED)
|
|
94
|
+
self.optimization_model_part.AddNodalSolutionStepVariable(KSO.DF1DALPHA)
|
|
95
|
+
self.optimization_model_part.AddNodalSolutionStepVariable(KSO.DF1DALPHA_MAPPED)
|
|
96
|
+
self.optimization_model_part.AddNodalSolutionStepVariable(KSO.DPDALPHA)
|
|
97
|
+
self.optimization_model_part.AddNodalSolutionStepVariable(KSO.DPDALPHA_MAPPED)
|
|
98
|
+
self.optimization_model_part.AddNodalSolutionStepVariable(KSO.DLDALPHA)
|
|
99
|
+
|
|
100
|
+
# --------------------------------------------------------------------------
|
|
101
|
+
def CheckApplicability(self):
|
|
102
|
+
if self.objectives.size() > 1:
|
|
103
|
+
raise RuntimeError("The augmented lagrange algorithm for bead optimization only supports one objective function!")
|
|
104
|
+
if self.constraints.size() > 0:
|
|
105
|
+
raise RuntimeError("The augmented lagrange algorithm for bead does not allow for any constraints!")
|
|
106
|
+
|
|
107
|
+
# --------------------------------------------------------------------------
|
|
108
|
+
def InitializeOptimizationLoop(self):
|
|
109
|
+
self.model_part_controller.Initialize()
|
|
110
|
+
self.model_part_controller.SetMinimalBufferSize(2)
|
|
111
|
+
|
|
112
|
+
self.analyzer.InitializeBeforeOptimizationLoop()
|
|
113
|
+
|
|
114
|
+
self.design_surface = self.model_part_controller.GetDesignSurface()
|
|
115
|
+
|
|
116
|
+
self.mapper = mapper_factory.CreateMapper(self.design_surface, self.design_surface, self.mapper_settings)
|
|
117
|
+
self.mapper.Initialize()
|
|
118
|
+
self.model_part_controller.InitializeDamping()
|
|
119
|
+
|
|
120
|
+
if self.filter_penalty_term:
|
|
121
|
+
penalty_filter_radius = self.algorithm_settings["penalty_filter_radius"].GetDouble()
|
|
122
|
+
filter_radius = self.mapper_settings["filter_radius"].GetDouble()
|
|
123
|
+
if abs(filter_radius - penalty_filter_radius) > 1e-9:
|
|
124
|
+
penalty_filter_settings = self.mapper_settings.Clone()
|
|
125
|
+
penalty_filter_settings["filter_radius"].SetDouble(self.algorithm_settings["penalty_filter_radius"].GetDouble())
|
|
126
|
+
self.penalty_filter = mapper_factory.CreateMapper(self.design_surface, self.design_surface, penalty_filter_settings)
|
|
127
|
+
self.penalty_filter.Initialize()
|
|
128
|
+
else:
|
|
129
|
+
self.penalty_filter = self.mapper
|
|
130
|
+
|
|
131
|
+
self.data_logger = data_logger_factory.CreateDataLogger(self.model_part_controller, self.communicator, self.optimization_settings)
|
|
132
|
+
self.data_logger.InitializeDataLogging()
|
|
133
|
+
|
|
134
|
+
self.optimization_utilities = KSO.OptimizationUtilities
|
|
135
|
+
|
|
136
|
+
# Identify fixed design areas
|
|
137
|
+
KM.VariableUtils().SetFlag(KM.BOUNDARY, False, self.optimization_model_part.Nodes)
|
|
138
|
+
|
|
139
|
+
radius = self.mapper_settings["filter_radius"].GetDouble()
|
|
140
|
+
search_based_functions = KSO.SearchBasedFunctions(self.design_surface)
|
|
141
|
+
|
|
142
|
+
for itr in range(self.algorithm_settings["fix_boundaries"].size()):
|
|
143
|
+
sub_model_part_name = self.algorithm_settings["fix_boundaries"][itr].GetString()
|
|
144
|
+
node_set = self.optimization_model_part.GetSubModelPart(sub_model_part_name).Nodes
|
|
145
|
+
search_based_functions.FlagNodesInRadius(node_set, KM.BOUNDARY, radius)
|
|
146
|
+
|
|
147
|
+
# Specify bounds and assign starting values for ALPHA
|
|
148
|
+
if self.bead_side == "positive":
|
|
149
|
+
KM.VariableUtils().SetScalarVar(KSO.ALPHA, 0.5, self.design_surface.Nodes, KM.BOUNDARY, False)
|
|
150
|
+
self.lower_bound = 0.0
|
|
151
|
+
self.upper_bound = 1.0
|
|
152
|
+
elif self.bead_side == "negative":
|
|
153
|
+
KM.VariableUtils().SetScalarVar(KSO.ALPHA, -0.5, self.design_surface.Nodes, KM.BOUNDARY, False)
|
|
154
|
+
self.lower_bound = -1.0
|
|
155
|
+
self.upper_bound = 0.0
|
|
156
|
+
elif self.bead_side == "both":
|
|
157
|
+
KM.VariableUtils().SetScalarVar(KSO.ALPHA, 0.0, self.design_surface.Nodes, KM.BOUNDARY, False)
|
|
158
|
+
self.lower_bound = -1.0
|
|
159
|
+
self.upper_bound = 1.0
|
|
160
|
+
else:
|
|
161
|
+
raise RuntimeError("Specified bead direction mode not supported!")
|
|
162
|
+
|
|
163
|
+
# Initialize ALPHA_MAPPED according to initial ALPHA values
|
|
164
|
+
self.mapper.Map(KSO.ALPHA, KSO.ALPHA_MAPPED)
|
|
165
|
+
|
|
166
|
+
# Specify bead direction
|
|
167
|
+
bead_direction = self.algorithm_settings["bead_direction"].GetVector()
|
|
168
|
+
if len(bead_direction) == 0:
|
|
169
|
+
self.model_part_controller.ComputeUnitSurfaceNormals()
|
|
170
|
+
for node in self.design_surface.Nodes:
|
|
171
|
+
normalized_normal = node.GetSolutionStepValue(KSO.NORMALIZED_SURFACE_NORMAL)
|
|
172
|
+
node.SetValue(KSO.BEAD_DIRECTION,normalized_normal)
|
|
173
|
+
|
|
174
|
+
elif len(bead_direction) == 3:
|
|
175
|
+
norm = math.sqrt(bead_direction[0]**2 + bead_direction[1]**2 + bead_direction[2]**2)
|
|
176
|
+
normalized_bead_direction = [value/norm for value in bead_direction]
|
|
177
|
+
KM.VariableUtils().SetNonHistoricalVectorVar(KSO.BEAD_DIRECTION, normalized_bead_direction, self.design_surface.Nodes)
|
|
178
|
+
else:
|
|
179
|
+
raise RuntimeError("Wrong definition of bead direction. Options are: 1) [] -> takes surface normal, 2) [x.x,x.x,x.x] -> takes specified vector.")
|
|
180
|
+
|
|
181
|
+
# --------------------------------------------------------------------------
|
|
182
|
+
def RunOptimizationLoop(self):
|
|
183
|
+
timer = Timer()
|
|
184
|
+
timer.StartTimer()
|
|
185
|
+
|
|
186
|
+
current_lambda = self.lambda0
|
|
187
|
+
penalty_scaling = self.penalty_scaling_0
|
|
188
|
+
penalty_factor = self.penalty_factor_0
|
|
189
|
+
|
|
190
|
+
total_iteration = 0
|
|
191
|
+
is_design_converged = False
|
|
192
|
+
is_max_total_iterations_reached = False
|
|
193
|
+
previos_L = None
|
|
194
|
+
|
|
195
|
+
for outer_iteration in range(1,self.max_outer_iterations+1):
|
|
196
|
+
for inner_iteration in range(1,self.max_inner_iterations+1):
|
|
197
|
+
|
|
198
|
+
total_iteration += 1
|
|
199
|
+
timer.StartNewLap()
|
|
200
|
+
|
|
201
|
+
KM.Logger.Print("=======================================================================================")
|
|
202
|
+
KM.Logger.PrintInfo("ShapeOpt", timer.GetTimeStamp(), ": Starting iteration ",outer_iteration,".",inner_iteration,".",total_iteration,"(outer . inner . total)")
|
|
203
|
+
KM.Logger.Print("=======================================================================================\n")
|
|
204
|
+
|
|
205
|
+
# Initialize new shape
|
|
206
|
+
self.model_part_controller.UpdateTimeStep(total_iteration)
|
|
207
|
+
|
|
208
|
+
for node in self.design_surface.Nodes:
|
|
209
|
+
new_shape_change = node.GetSolutionStepValue(KSO.ALPHA_MAPPED) * node.GetValue(KSO.BEAD_DIRECTION) * self.bead_height
|
|
210
|
+
node.SetSolutionStepValue(KSO.SHAPE_CHANGE, new_shape_change)
|
|
211
|
+
|
|
212
|
+
self.model_part_controller.DampNodalUpdateVariableIfSpecified(KSO.SHAPE_CHANGE)
|
|
213
|
+
|
|
214
|
+
for node in self.design_surface.Nodes:
|
|
215
|
+
shape_update = node.GetSolutionStepValue(KSO.SHAPE_CHANGE,0) - node.GetSolutionStepValue(KSO.SHAPE_CHANGE,1)
|
|
216
|
+
node.SetSolutionStepValue(KSO.SHAPE_UPDATE, shape_update)
|
|
217
|
+
|
|
218
|
+
self.model_part_controller.UpdateMeshAccordingInputVariable(KSO.SHAPE_UPDATE)
|
|
219
|
+
self.model_part_controller.SetReferenceMeshToMesh()
|
|
220
|
+
|
|
221
|
+
# Analyze shape
|
|
222
|
+
self.communicator.initializeCommunication()
|
|
223
|
+
self.communicator.requestValueOf(self.objectives[0]["identifier"].GetString())
|
|
224
|
+
self.communicator.requestGradientOf(self.objectives[0]["identifier"].GetString())
|
|
225
|
+
|
|
226
|
+
self.analyzer.AnalyzeDesignAndReportToCommunicator(self.optimization_model_part, total_iteration, self.communicator)
|
|
227
|
+
|
|
228
|
+
objective_value = self.communicator.getStandardizedValue(self.objectives[0]["identifier"].GetString())
|
|
229
|
+
objGradientDict = self.communicator.getStandardizedGradient(self.objectives[0]["identifier"].GetString())
|
|
230
|
+
WriteDictionaryDataOnNodalVariable(objGradientDict, self.optimization_model_part, KSO.DF1DX)
|
|
231
|
+
|
|
232
|
+
self.model_part_controller.DampNodalSensitivityVariableIfSpecified(KSO.DF1DX)
|
|
233
|
+
|
|
234
|
+
# Compute sensitivities w.r.t. scalar design variable alpha
|
|
235
|
+
for node in self.design_surface.Nodes:
|
|
236
|
+
raw_gradient = node.GetSolutionStepValue(KSO.DF1DX)
|
|
237
|
+
bead_dir = node.GetValue(KSO.BEAD_DIRECTION)
|
|
238
|
+
|
|
239
|
+
dF1dalpha_i = self.bead_height*(raw_gradient[0]*bead_dir[0] + raw_gradient[1]*bead_dir[1] + raw_gradient[2]*bead_dir[2])
|
|
240
|
+
node.SetSolutionStepValue(KSO.DF1DALPHA, dF1dalpha_i)
|
|
241
|
+
|
|
242
|
+
# Map gradient of objective
|
|
243
|
+
self.mapper.InverseMap(KSO.DF1DALPHA, KSO.DF1DALPHA_MAPPED)
|
|
244
|
+
|
|
245
|
+
# Compute scaling
|
|
246
|
+
max_norm_objective_gradient = self.optimization_utilities.ComputeMaxNormOfNodalVariable(self.design_surface, KSO.DF1DALPHA_MAPPED)
|
|
247
|
+
|
|
248
|
+
if outer_iteration == 1 and inner_iteration == min(3,self.max_inner_iterations):
|
|
249
|
+
if self.bead_side == "positive" or self.bead_side == "negative":
|
|
250
|
+
max_norm_penalty_gradient = 1.0
|
|
251
|
+
elif self.bead_side == "both":
|
|
252
|
+
max_norm_penalty_gradient = 2.0
|
|
253
|
+
|
|
254
|
+
penalty_scaling = max_norm_objective_gradient/max_norm_penalty_gradient
|
|
255
|
+
|
|
256
|
+
# Compute penalization term
|
|
257
|
+
penalty_value = 0.0
|
|
258
|
+
if self.bead_side == "positive":
|
|
259
|
+
for node in self.design_surface.Nodes:
|
|
260
|
+
if not node.Is(KM.BOUNDARY):
|
|
261
|
+
alpha_i = node.GetSolutionStepValue(KSO.ALPHA)
|
|
262
|
+
penalty_value += penalty_scaling*(alpha_i-alpha_i**2)
|
|
263
|
+
|
|
264
|
+
penalty_gradient_i = penalty_scaling*(1-2*alpha_i)
|
|
265
|
+
node.SetSolutionStepValue(KSO.DPDALPHA, penalty_gradient_i)
|
|
266
|
+
|
|
267
|
+
elif self.bead_side == "negative":
|
|
268
|
+
for node in self.design_surface.Nodes:
|
|
269
|
+
if not node.Is(KM.BOUNDARY):
|
|
270
|
+
alpha_i = node.GetSolutionStepValue(KSO.ALPHA)
|
|
271
|
+
penalty_value += penalty_scaling*(-alpha_i-alpha_i**2)
|
|
272
|
+
|
|
273
|
+
penalty_gradient_i = penalty_scaling*(-1-2*alpha_i)
|
|
274
|
+
node.SetSolutionStepValue(KSO.DPDALPHA, penalty_gradient_i)
|
|
275
|
+
|
|
276
|
+
elif self.bead_side == "both":
|
|
277
|
+
for node in self.design_surface.Nodes:
|
|
278
|
+
if not node.Is(KM.BOUNDARY):
|
|
279
|
+
alpha_i = node.GetSolutionStepValue(KSO.ALPHA)
|
|
280
|
+
penalty_value += penalty_scaling*(-alpha_i**2+1)
|
|
281
|
+
|
|
282
|
+
penalty_gradient_i = penalty_scaling*(-2*alpha_i)
|
|
283
|
+
node.SetSolutionStepValue(KSO.DPDALPHA, penalty_gradient_i)
|
|
284
|
+
|
|
285
|
+
# Filter penalty term if specified
|
|
286
|
+
if self.filter_penalty_term:
|
|
287
|
+
self.penalty_filter.InverseMap(KSO.DPDALPHA, KSO.DPDALPHA_MAPPED)
|
|
288
|
+
|
|
289
|
+
# Compute value of Lagrange function
|
|
290
|
+
L = objective_value + current_lambda*penalty_value + 0.5*penalty_factor*penalty_value**2
|
|
291
|
+
if inner_iteration == 1:
|
|
292
|
+
dL_relative = 0.0
|
|
293
|
+
else:
|
|
294
|
+
dL_relative = 100*(L/previos_L-1)
|
|
295
|
+
|
|
296
|
+
# Compute gradient of Lagrange function
|
|
297
|
+
if self.filter_penalty_term:
|
|
298
|
+
penalty_gradient_variable = KSO.DPDALPHA_MAPPED
|
|
299
|
+
else:
|
|
300
|
+
penalty_gradient_variable = KSO.DPDALPHA
|
|
301
|
+
for node in self.design_surface.Nodes:
|
|
302
|
+
dLdalpha_i = node.GetSolutionStepValue(KSO.DF1DALPHA_MAPPED) + current_lambda*node.GetSolutionStepValue(penalty_gradient_variable)
|
|
303
|
+
node.SetSolutionStepValue(KSO.DLDALPHA, dLdalpha_i)
|
|
304
|
+
|
|
305
|
+
# Normalization using infinity norm
|
|
306
|
+
dLdalpha_for_normalization = {}
|
|
307
|
+
for node in self.design_surface.Nodes:
|
|
308
|
+
nodal_alpha = node.GetSolutionStepValue(KSO.ALPHA)
|
|
309
|
+
if nodal_alpha==self.lower_bound or nodal_alpha==self.upper_bound or node.Is(KM.BOUNDARY):
|
|
310
|
+
dLdalpha_for_normalization[node.Id] = 0.0
|
|
311
|
+
else:
|
|
312
|
+
dLdalpha_for_normalization[node.Id] = node.GetSolutionStepValue(KSO.DLDALPHA)**2
|
|
313
|
+
|
|
314
|
+
max_value = math.sqrt(max(dLdalpha_for_normalization.values()))
|
|
315
|
+
if max_value == 0.0:
|
|
316
|
+
max_value = 1.0
|
|
317
|
+
|
|
318
|
+
# Compute updated design variable
|
|
319
|
+
for node in self.design_surface.Nodes:
|
|
320
|
+
dalpha = -self.step_size*node.GetSolutionStepValue(KSO.DLDALPHA)/max_value
|
|
321
|
+
alpha_new = node.GetSolutionStepValue(KSO.ALPHA) + dalpha
|
|
322
|
+
|
|
323
|
+
# Enforce bounds
|
|
324
|
+
alpha_new = max(alpha_new, self.lower_bound)
|
|
325
|
+
alpha_new = min(alpha_new, self.upper_bound)
|
|
326
|
+
|
|
327
|
+
# Enforce constraints
|
|
328
|
+
if node.Is(KM.BOUNDARY):
|
|
329
|
+
alpha_new = 0.0
|
|
330
|
+
|
|
331
|
+
node.SetSolutionStepValue(KSO.ALPHA,alpha_new)
|
|
332
|
+
|
|
333
|
+
alpha_new_vectorized = alpha_new * node.GetValue(KSO.BEAD_DIRECTION)
|
|
334
|
+
node.SetSolutionStepValue(KSO.CONTROL_POINT_CHANGE,alpha_new_vectorized)
|
|
335
|
+
|
|
336
|
+
# Map design variables
|
|
337
|
+
self.mapper.Map(KSO.ALPHA, KSO.ALPHA_MAPPED)
|
|
338
|
+
|
|
339
|
+
# Log current optimization step and store values for next iteration
|
|
340
|
+
additional_values_to_log = {}
|
|
341
|
+
additional_values_to_log["step_size"] = self.algorithm_settings["line_search"]["step_size"].GetDouble()
|
|
342
|
+
additional_values_to_log["outer_iteration"] = outer_iteration
|
|
343
|
+
additional_values_to_log["inner_iteration"] = inner_iteration
|
|
344
|
+
additional_values_to_log["lagrange_value"] = L
|
|
345
|
+
additional_values_to_log["lagrange_value_relative_change"] = dL_relative
|
|
346
|
+
additional_values_to_log["penalty_value"] = penalty_value
|
|
347
|
+
additional_values_to_log["penalty_lambda"] = current_lambda
|
|
348
|
+
additional_values_to_log["penalty_scaling"] = penalty_scaling
|
|
349
|
+
additional_values_to_log["penalty_factor"] = penalty_factor
|
|
350
|
+
additional_values_to_log["max_norm_objective_gradient"] = max_norm_objective_gradient
|
|
351
|
+
|
|
352
|
+
self.data_logger.LogSensitivityHeatmap(total_iteration, self.mapper)
|
|
353
|
+
self.data_logger.LogCurrentValues(total_iteration, additional_values_to_log)
|
|
354
|
+
self.data_logger.LogCurrentDesign(total_iteration)
|
|
355
|
+
|
|
356
|
+
previos_L = L
|
|
357
|
+
|
|
358
|
+
# Convergence check of inner loop
|
|
359
|
+
if total_iteration == self.max_total_iterations:
|
|
360
|
+
is_max_total_iterations_reached = True
|
|
361
|
+
break
|
|
362
|
+
|
|
363
|
+
if inner_iteration >= self.min_inner_iterations and inner_iteration >1:
|
|
364
|
+
# In the first outer iteration, the constraint is not yet active and properly scaled. Therefore, the objective is used to check the relative improvement
|
|
365
|
+
if outer_iteration == 1:
|
|
366
|
+
if abs(self.data_logger.GetValues("rel_change_objective")[total_iteration]) < self.inner_iteration_tolerance:
|
|
367
|
+
break
|
|
368
|
+
else:
|
|
369
|
+
if abs(dL_relative) < self.inner_iteration_tolerance:
|
|
370
|
+
break
|
|
371
|
+
|
|
372
|
+
if penalty_value == 0.0:
|
|
373
|
+
is_design_converged = True
|
|
374
|
+
break
|
|
375
|
+
|
|
376
|
+
KM.Logger.Print("")
|
|
377
|
+
KM.Logger.PrintInfo("ShapeOpt", "Time needed for current optimization step = ", timer.GetLapTime(), "s")
|
|
378
|
+
KM.Logger.PrintInfo("ShapeOpt", "Time needed for total optimization so far = ", timer.GetTotalTime(), "s")
|
|
379
|
+
|
|
380
|
+
# Compute penalty factor such that estimated Lagrange multiplier is obtained
|
|
381
|
+
if outer_iteration==1:
|
|
382
|
+
penalty_factor = self.estimated_lagrange_multiplier/penalty_value
|
|
383
|
+
|
|
384
|
+
# Update lambda
|
|
385
|
+
current_lambda = current_lambda + penalty_factor*penalty_value
|
|
386
|
+
|
|
387
|
+
KM.Logger.Print("")
|
|
388
|
+
KM.Logger.PrintInfo("ShapeOpt", "Time needed for current optimization step = ", timer.GetLapTime(), "s")
|
|
389
|
+
KM.Logger.PrintInfo("ShapeOpt", "Time needed for total optimization so far = ", timer.GetTotalTime(), "s")
|
|
390
|
+
|
|
391
|
+
# Check convergence of outer loop
|
|
392
|
+
if outer_iteration == self.max_outer_iterations:
|
|
393
|
+
KM.Logger.Print("")
|
|
394
|
+
KM.Logger.PrintInfo("ShapeOpt", "Maximal outer iterations of optimization problem reached!")
|
|
395
|
+
break
|
|
396
|
+
|
|
397
|
+
if is_max_total_iterations_reached:
|
|
398
|
+
KM.Logger.Print("")
|
|
399
|
+
KM.Logger.PrintInfo("ShapeOpt", "Maximal total iterations of optimization problem reached!")
|
|
400
|
+
break
|
|
401
|
+
|
|
402
|
+
if is_design_converged:
|
|
403
|
+
KM.Logger.Print("")
|
|
404
|
+
KM.Logger.PrintInfo("ShapeOpt", "Update of design variables is zero. Optimization converged!")
|
|
405
|
+
break
|
|
406
|
+
|
|
407
|
+
# --------------------------------------------------------------------------
|
|
408
|
+
def FinalizeOptimizationLoop(self):
|
|
409
|
+
self.data_logger.FinalizeDataLogging()
|
|
410
|
+
self.analyzer.FinalizeAfterOptimizationLoop()
|
|
411
|
+
|
|
412
|
+
# ==============================================================================
|
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
# ==============================================================================
|
|
14
|
+
def CreateOptimizationAlgorithm(optimization_settings, analyzer, communicator, model_part_controller):
|
|
15
|
+
algorithm_name = optimization_settings["optimization_algorithm"]["name"].GetString()
|
|
16
|
+
|
|
17
|
+
if algorithm_name == "steepest_descent":
|
|
18
|
+
from .algorithm_steepest_descent import AlgorithmSteepestDescent
|
|
19
|
+
return AlgorithmSteepestDescent(optimization_settings,
|
|
20
|
+
analyzer,
|
|
21
|
+
communicator,
|
|
22
|
+
model_part_controller)
|
|
23
|
+
elif algorithm_name == "gradient_projection":
|
|
24
|
+
from .algorithm_gradient_projection import AlgorithmGradientProjection
|
|
25
|
+
return AlgorithmGradientProjection(optimization_settings,
|
|
26
|
+
analyzer,
|
|
27
|
+
communicator,
|
|
28
|
+
model_part_controller)
|
|
29
|
+
elif algorithm_name == "penalized_projection":
|
|
30
|
+
from .algorithm_penalized_projection import AlgorithmPenalizedProjection
|
|
31
|
+
return AlgorithmPenalizedProjection(optimization_settings,
|
|
32
|
+
analyzer,
|
|
33
|
+
communicator,
|
|
34
|
+
model_part_controller)
|
|
35
|
+
elif algorithm_name == "trust_region":
|
|
36
|
+
from .algorithm_trust_region import AlgorithmTrustRegion
|
|
37
|
+
return AlgorithmTrustRegion(optimization_settings,
|
|
38
|
+
analyzer,
|
|
39
|
+
communicator,
|
|
40
|
+
model_part_controller)
|
|
41
|
+
elif algorithm_name == "bead_optimization":
|
|
42
|
+
from .algorithm_bead_optimization import AlgorithmBeadOptimization
|
|
43
|
+
return AlgorithmBeadOptimization(optimization_settings,
|
|
44
|
+
analyzer,
|
|
45
|
+
communicator,
|
|
46
|
+
model_part_controller)
|
|
47
|
+
elif algorithm_name == "relaxed_gradient_projection":
|
|
48
|
+
from .algorithm_relaxed_gradient_projection import AlgorithmRelaxedGradientProjection
|
|
49
|
+
return AlgorithmRelaxedGradientProjection(optimization_settings,
|
|
50
|
+
analyzer,
|
|
51
|
+
communicator,
|
|
52
|
+
model_part_controller)
|
|
53
|
+
elif algorithm_name == "shape_fraction_optimization":
|
|
54
|
+
from .algorithm_shape_fraction_optimization import AlgorithmShapeFractionOptimization
|
|
55
|
+
return AlgorithmShapeFractionOptimization(optimization_settings,
|
|
56
|
+
analyzer,
|
|
57
|
+
communicator,
|
|
58
|
+
model_part_controller)
|
|
59
|
+
else:
|
|
60
|
+
raise NameError("The following optimization algorithm is not supported by the algorithm factory: " + algorithm_name)
|
|
61
|
+
|
|
62
|
+
# ==============================================================================
|