KratosShapeOptimizationApplication 10.4.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- KratosMultiphysics/.libs/KratosShapeOptimizationApplication.so +0 -0
- KratosMultiphysics/.libs/libKratosShapeOptimizationCore.dylib +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/TemplateMainKratosShapeOptimization.py +31 -0
- KratosMultiphysics/ShapeOptimizationApplication/__init__.py +19 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_base.py +31 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_bead_optimization.py +412 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_factory.py +62 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_gradient_projection.py +317 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_penalized_projection.py +225 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_relaxed_gradient_projection.py +580 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_shape_fraction_optimization.py +622 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_steepest_descent.py +255 -0
- KratosMultiphysics/ShapeOptimizationApplication/algorithms/algorithm_trust_region.py +657 -0
- KratosMultiphysics/ShapeOptimizationApplication/analyzers/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/analyzers/analyzer_base.py +30 -0
- KratosMultiphysics/ShapeOptimizationApplication/analyzers/analyzer_empty.py +21 -0
- KratosMultiphysics/ShapeOptimizationApplication/analyzers/analyzer_factory.py +310 -0
- KratosMultiphysics/ShapeOptimizationApplication/analyzers/analyzer_internal.py +155 -0
- KratosMultiphysics/ShapeOptimizationApplication/communicator_factory.py +259 -0
- KratosMultiphysics/ShapeOptimizationApplication/custom_ios/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/custom_ios/wrl_io.py +82 -0
- KratosMultiphysics/ShapeOptimizationApplication/custom_ios/wrl_reader.py +119 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/data_logger_factory.py +199 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/design_logger_base.py +28 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/design_logger_gid.py +112 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/design_logger_unv.py +73 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/design_logger_vtk.py +96 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/sensitivity_heatmap_logger.py +91 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_base.py +128 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_bead_optimization.py +79 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_gradient_projection.py +80 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_penalized_projection.py +79 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_relaxed_gradient_projection.py +108 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_shape_fraction_optimization.py +92 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_steepest_descent.py +64 -0
- KratosMultiphysics/ShapeOptimizationApplication/loggers/value_logger_trust_region.py +100 -0
- KratosMultiphysics/ShapeOptimizationApplication/mapper_factory.py +100 -0
- KratosMultiphysics/ShapeOptimizationApplication/mapping/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/mapping/in_plane_vertex_morphing_mapper.py +140 -0
- KratosMultiphysics/ShapeOptimizationApplication/mapping/sliding_vertex_morphing_mapper.py +378 -0
- KratosMultiphysics/ShapeOptimizationApplication/mesh_controllers/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/mesh_controllers/mesh_controller_base.py +22 -0
- KratosMultiphysics/ShapeOptimizationApplication/mesh_controllers/mesh_controller_basic_updating.py +35 -0
- KratosMultiphysics/ShapeOptimizationApplication/mesh_controllers/mesh_controller_with_solver.py +237 -0
- KratosMultiphysics/ShapeOptimizationApplication/model_part_controller_factory.py +197 -0
- KratosMultiphysics/ShapeOptimizationApplication/optimizer_factory.py +235 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/airfoil_2d_responses.py +189 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/face_angle.py +140 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/mesh_based_packaging.py +70 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/packaging_response_base.py +156 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/plane_based_packaging.py +61 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/response_function_factory.py +40 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/surface_normal_shape_change.py +125 -0
- KratosMultiphysics/ShapeOptimizationApplication/response_functions/total_volume.py +56 -0
- KratosMultiphysics/ShapeOptimizationApplication/utilities/__init__.py +0 -0
- KratosMultiphysics/ShapeOptimizationApplication/utilities/custom_math.py +443 -0
- KratosMultiphysics/ShapeOptimizationApplication/utilities/custom_sensitivity_heatmap.py +235 -0
- KratosMultiphysics/ShapeOptimizationApplication/utilities/custom_timer.py +47 -0
- KratosMultiphysics/ShapeOptimizationApplication/utilities/custom_variable_utilities.py +54 -0
- kratosshapeoptimizationapplication-10.4.4.dist-info/METADATA +31 -0
- kratosshapeoptimizationapplication-10.4.4.dist-info/RECORD +69 -0
- kratosshapeoptimizationapplication-10.4.4.dist-info/WHEEL +6 -0
- kratosshapeoptimizationapplication.dylibs/libKratosCore.dylib +4 -0
- kratosshapeoptimizationapplication.dylibs/libgcc_s.1.1.dylib +0 -0
- kratosshapeoptimizationapplication.dylibs/libgomp.1.dylib +0 -0
- kratosshapeoptimizationapplication.dylibs/libstdc++.6.dylib +0 -0
|
@@ -0,0 +1,657 @@
|
|
|
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
|
+
# Kratos Core and Apps
|
|
13
|
+
import KratosMultiphysics as KM
|
|
14
|
+
import KratosMultiphysics.ShapeOptimizationApplication as KSO
|
|
15
|
+
|
|
16
|
+
# Additional imports
|
|
17
|
+
from KratosMultiphysics.ShapeOptimizationApplication.algorithms.algorithm_base import OptimizationAlgorithm
|
|
18
|
+
from KratosMultiphysics.ShapeOptimizationApplication import mapper_factory
|
|
19
|
+
from KratosMultiphysics.ShapeOptimizationApplication.loggers import data_logger_factory
|
|
20
|
+
from KratosMultiphysics.ShapeOptimizationApplication.utilities import custom_math as cm
|
|
21
|
+
from KratosMultiphysics.ShapeOptimizationApplication.utilities.custom_timer import Timer
|
|
22
|
+
from KratosMultiphysics.ShapeOptimizationApplication.utilities.custom_variable_utilities import WriteDictionaryDataOnNodalVariable, ReadNodalVariableToList, WriteListToNodalVariable
|
|
23
|
+
import copy
|
|
24
|
+
|
|
25
|
+
# ==============================================================================
|
|
26
|
+
class AlgorithmTrustRegion(OptimizationAlgorithm):
|
|
27
|
+
# --------------------------------------------------------------------------
|
|
28
|
+
def __init__(self, optimization_settings, analyzer, communicator, model_part_controller):
|
|
29
|
+
default_algorithm_settings = KM.Parameters("""
|
|
30
|
+
{
|
|
31
|
+
"name" : "trust_region",
|
|
32
|
+
"max_step_length" : 1.0,
|
|
33
|
+
"step_length_tolerance" : 1e-3,
|
|
34
|
+
"step_length_reduction_factor" : 0.5,
|
|
35
|
+
"max_iterations" : 10,
|
|
36
|
+
"far_away_length" : 2.0,
|
|
37
|
+
"subopt_max_itr" : 50,
|
|
38
|
+
"subopt_tolerance" : 1e-10,
|
|
39
|
+
"bisectioning_max_itr" : 30,
|
|
40
|
+
"bisectioning_tolerance" : 1e-2,
|
|
41
|
+
"relative_tolerance" : 1e-12,
|
|
42
|
+
"obj_share_during_correction" : 1
|
|
43
|
+
}""")
|
|
44
|
+
self.algorithm_settings = optimization_settings["optimization_algorithm"]
|
|
45
|
+
self.algorithm_settings.RecursivelyValidateAndAssignDefaults(default_algorithm_settings)
|
|
46
|
+
|
|
47
|
+
self.optimization_settings = optimization_settings
|
|
48
|
+
self.mapper_settings = optimization_settings["design_variables"]["filter"]
|
|
49
|
+
|
|
50
|
+
self.analyzer = analyzer
|
|
51
|
+
self.communicator = communicator
|
|
52
|
+
self.model_part_controller = model_part_controller
|
|
53
|
+
|
|
54
|
+
self.design_surface = None
|
|
55
|
+
self.mapper = None
|
|
56
|
+
self.data_logger = None
|
|
57
|
+
self.optimization_utilities = None
|
|
58
|
+
|
|
59
|
+
self.objectives = optimization_settings["objectives"]
|
|
60
|
+
self.constraints = optimization_settings["constraints"]
|
|
61
|
+
|
|
62
|
+
self.optimization_model_part = model_part_controller.GetOptimizationModelPart()
|
|
63
|
+
|
|
64
|
+
# --------------------------------------------------------------------------
|
|
65
|
+
def CheckApplicability(self):
|
|
66
|
+
if self.objectives.size() > 1:
|
|
67
|
+
raise RuntimeError("Trust-region algorithm only supports one objective function!")
|
|
68
|
+
|
|
69
|
+
# --------------------------------------------------------------------------
|
|
70
|
+
def InitializeOptimizationLoop(self):
|
|
71
|
+
self.model_part_controller.Initialize()
|
|
72
|
+
|
|
73
|
+
self.analyzer.InitializeBeforeOptimizationLoop()
|
|
74
|
+
|
|
75
|
+
self.design_surface = self.model_part_controller.GetDesignSurface()
|
|
76
|
+
|
|
77
|
+
self.mapper = mapper_factory.CreateMapper(self.design_surface, self.design_surface, self.mapper_settings)
|
|
78
|
+
self.mapper.Initialize()
|
|
79
|
+
self.model_part_controller.InitializeDamping()
|
|
80
|
+
|
|
81
|
+
self.data_logger = data_logger_factory.CreateDataLogger(self.model_part_controller, self.communicator, self.optimization_settings)
|
|
82
|
+
self.data_logger.InitializeDataLogging()
|
|
83
|
+
|
|
84
|
+
self.optimization_utilities = KSO.OptimizationUtilities
|
|
85
|
+
|
|
86
|
+
# --------------------------------------------------------------------------
|
|
87
|
+
def RunOptimizationLoop(self):
|
|
88
|
+
timer = Timer()
|
|
89
|
+
timer.StartTimer()
|
|
90
|
+
|
|
91
|
+
for self.opt_iteration in range(1,self.algorithm_settings["max_iterations"].GetInt()+1):
|
|
92
|
+
KM.Logger.Print("")
|
|
93
|
+
KM.Logger.Print("===============================================================================")
|
|
94
|
+
KM.Logger.PrintInfo("ShapeOpt", timer.GetTimeStamp(), ": Starting optimization iteration ",self.opt_iteration)
|
|
95
|
+
KM.Logger.Print("===============================================================================\n")
|
|
96
|
+
|
|
97
|
+
timer.StartNewLap()
|
|
98
|
+
|
|
99
|
+
self.__InitializeNewShape()
|
|
100
|
+
|
|
101
|
+
self.__AnalyzeShape()
|
|
102
|
+
|
|
103
|
+
self.__PostProcessGradientsObtainedFromAnalysis()
|
|
104
|
+
|
|
105
|
+
len_obj, dir_obj, len_eqs, dir_eqs, len_ineqs, dir_ineqs = self.__ConvertAnalysisResultsToLengthDirectionFormat()
|
|
106
|
+
|
|
107
|
+
step_length = self.__DetermineMaxStepLength()
|
|
108
|
+
|
|
109
|
+
len_bar_obj, len_bar_eqs, len_bar_ineqs = self.__ExpressInStepLengthUnit(len_obj, len_eqs, len_ineqs, step_length)
|
|
110
|
+
|
|
111
|
+
dX_bar, process_details = self.__DetermineStep(len_bar_obj, dir_obj, len_bar_eqs, dir_eqs, len_bar_ineqs, dir_ineqs)
|
|
112
|
+
|
|
113
|
+
dX = self.__ComputeShapeUpdate(dX_bar, step_length)
|
|
114
|
+
|
|
115
|
+
values_to_be_logged = {}
|
|
116
|
+
values_to_be_logged["len_bar_obj"] = len_bar_obj
|
|
117
|
+
values_to_be_logged["len_bar_cons"] = self.__CombineConstraintDataToOrderedList(len_bar_eqs, len_bar_ineqs)
|
|
118
|
+
values_to_be_logged["step_length"] = step_length
|
|
119
|
+
values_to_be_logged["test_norm_dX_bar"] = process_details["test_norm_dX"]
|
|
120
|
+
values_to_be_logged["bi_itrs"] = process_details["bi_itrs"]
|
|
121
|
+
values_to_be_logged["bi_err"] = process_details["bi_err"]
|
|
122
|
+
values_to_be_logged["adj_len_bar_obj"] = process_details["adj_len_obj"]
|
|
123
|
+
values_to_be_logged["adj_len_bar_cons"] = self.__CombineConstraintDataToOrderedList(process_details["adj_len_eqs"], process_details["adj_len_ineqs"])
|
|
124
|
+
values_to_be_logged["norm_dX"] = cm.NormInf3D(dX)
|
|
125
|
+
|
|
126
|
+
self.__LogCurrentOptimizationStep(values_to_be_logged)
|
|
127
|
+
|
|
128
|
+
KM.Logger.Print("")
|
|
129
|
+
KM.Logger.PrintInfo("ShapeOpt", "Time needed for current optimization step = ", timer.GetLapTime(), "s")
|
|
130
|
+
KM.Logger.PrintInfo("ShapeOpt", "Time needed for total optimization so far = ", timer.GetTotalTime(), "s")
|
|
131
|
+
|
|
132
|
+
if self.__isAlgorithmConverged():
|
|
133
|
+
break
|
|
134
|
+
|
|
135
|
+
# --------------------------------------------------------------------------
|
|
136
|
+
def FinalizeOptimizationLoop(self):
|
|
137
|
+
self.analyzer.FinalizeAfterOptimizationLoop()
|
|
138
|
+
self.data_logger.FinalizeDataLogging()
|
|
139
|
+
|
|
140
|
+
# --------------------------------------------------------------------------
|
|
141
|
+
def __isAlgorithmConverged(self):
|
|
142
|
+
|
|
143
|
+
if self.opt_iteration > 1 :
|
|
144
|
+
# Check if maximum iterations were reached
|
|
145
|
+
if self.opt_iteration == self.algorithm_settings["max_iterations"].GetInt():
|
|
146
|
+
KM.Logger.Print("")
|
|
147
|
+
KM.Logger.PrintInfo("ShapeOpt", "Maximal iterations of optimization problem reached!")
|
|
148
|
+
return True
|
|
149
|
+
|
|
150
|
+
# Check for relative tolerance
|
|
151
|
+
relative_change_of_objective_value = self.data_logger.GetValues("rel_change_objective")[self.opt_iteration]
|
|
152
|
+
if abs(relative_change_of_objective_value) < self.algorithm_settings["relative_tolerance"].GetDouble():
|
|
153
|
+
KM.Logger.Print("")
|
|
154
|
+
KM.Logger.PrintInfo("ShapeOpt", "Optimization problem converged within a relative objective tolerance of ",self.algorithm_settings["relative_tolerance"].GetDouble(),"%.")
|
|
155
|
+
return True
|
|
156
|
+
|
|
157
|
+
# --------------------------------------------------------------------------
|
|
158
|
+
def __InitializeNewShape(self):
|
|
159
|
+
self.model_part_controller.UpdateTimeStep(self.opt_iteration)
|
|
160
|
+
self.model_part_controller.UpdateMeshAccordingInputVariable(KSO.SHAPE_UPDATE)
|
|
161
|
+
self.model_part_controller.SetReferenceMeshToMesh()
|
|
162
|
+
|
|
163
|
+
# --------------------------------------------------------------------------
|
|
164
|
+
def __AnalyzeShape(self):
|
|
165
|
+
self.communicator.initializeCommunication()
|
|
166
|
+
|
|
167
|
+
obj_id = self.objectives[0]["identifier"].GetString()
|
|
168
|
+
self.communicator.requestValueOf(obj_id)
|
|
169
|
+
self.communicator.requestGradientOf(obj_id)
|
|
170
|
+
|
|
171
|
+
for itr in range(self.constraints.size()):
|
|
172
|
+
con_id = self.constraints[itr]["identifier"].GetString()
|
|
173
|
+
self.communicator.requestValueOf(con_id)
|
|
174
|
+
self.communicator.requestGradientOf(con_id)
|
|
175
|
+
|
|
176
|
+
self.analyzer.AnalyzeDesignAndReportToCommunicator(self.optimization_model_part, self.opt_iteration, self.communicator)
|
|
177
|
+
|
|
178
|
+
# --------------------------------------------------------------------------
|
|
179
|
+
def __PostProcessGradientsObtainedFromAnalysis(self):
|
|
180
|
+
# Compute surface normals if required
|
|
181
|
+
if self.objectives[0]["project_gradient_on_surface_normals"].GetBool():
|
|
182
|
+
self.model_part_controller.ComputeUnitSurfaceNormals()
|
|
183
|
+
else:
|
|
184
|
+
for itr in range(self.constraints.size()):
|
|
185
|
+
if self.constraints[itr]["project_gradient_on_surface_normals"].GetBool():
|
|
186
|
+
self.model_part_controller.ComputeUnitSurfaceNormals()
|
|
187
|
+
|
|
188
|
+
# Process objective gradients
|
|
189
|
+
obj = self.objectives[0]
|
|
190
|
+
obj_id = obj["identifier"].GetString()
|
|
191
|
+
|
|
192
|
+
obj_gradients_dict = self.communicator.getStandardizedGradient(obj_id)
|
|
193
|
+
|
|
194
|
+
nodal_variable = KM.KratosGlobals.GetVariable("DF1DX")
|
|
195
|
+
WriteDictionaryDataOnNodalVariable(obj_gradients_dict, self.optimization_model_part, nodal_variable)
|
|
196
|
+
|
|
197
|
+
# Projection on surface normals
|
|
198
|
+
if obj["project_gradient_on_surface_normals"].GetBool():
|
|
199
|
+
self.model_part_controller.ProjectNodalVariableOnUnitSurfaceNormals(nodal_variable)
|
|
200
|
+
|
|
201
|
+
# Damping
|
|
202
|
+
self.model_part_controller.DampNodalSensitivityVariableIfSpecified(nodal_variable)
|
|
203
|
+
|
|
204
|
+
# Mapping
|
|
205
|
+
nodal_variable_mapped = KM.KratosGlobals.GetVariable("DF1DX_MAPPED")
|
|
206
|
+
self.mapper.Update()
|
|
207
|
+
self.mapper.InverseMap(nodal_variable, nodal_variable_mapped)
|
|
208
|
+
self.mapper.Map(nodal_variable_mapped, nodal_variable_mapped)
|
|
209
|
+
|
|
210
|
+
# Damping
|
|
211
|
+
self.model_part_controller.DampNodalUpdateVariableIfSpecified(nodal_variable_mapped)
|
|
212
|
+
|
|
213
|
+
# Process constraint gradients
|
|
214
|
+
for itr in range(self.constraints.size()):
|
|
215
|
+
con = self.constraints[itr]
|
|
216
|
+
con_id = con["identifier"].GetString()
|
|
217
|
+
|
|
218
|
+
eq_gradients_dict = self.communicator.getStandardizedGradient(con_id)
|
|
219
|
+
|
|
220
|
+
nodal_variable = KM.KratosGlobals.GetVariable("DC"+str(itr+1)+"DX")
|
|
221
|
+
WriteDictionaryDataOnNodalVariable(eq_gradients_dict, self.optimization_model_part, nodal_variable)
|
|
222
|
+
|
|
223
|
+
# Projection on surface normals
|
|
224
|
+
if con["project_gradient_on_surface_normals"].GetBool():
|
|
225
|
+
self.model_part_controller.ProjectNodalVariableOnUnitSurfaceNormals(nodal_variable)
|
|
226
|
+
|
|
227
|
+
# Damping
|
|
228
|
+
self.model_part_controller.DampNodalSensitivityVariableIfSpecified(nodal_variable)
|
|
229
|
+
|
|
230
|
+
# Mapping
|
|
231
|
+
nodal_variable_mapped = KM.KratosGlobals.GetVariable(f"DC{(itr+1)}DX_MAPPED")
|
|
232
|
+
self.mapper.InverseMap(nodal_variable, nodal_variable_mapped)
|
|
233
|
+
self.mapper.Map(nodal_variable_mapped, nodal_variable_mapped)
|
|
234
|
+
|
|
235
|
+
# Damping
|
|
236
|
+
self.model_part_controller.DampNodalUpdateVariableIfSpecified(nodal_variable_mapped)
|
|
237
|
+
|
|
238
|
+
# --------------------------------------------------------------------------
|
|
239
|
+
def __ConvertAnalysisResultsToLengthDirectionFormat(self):
|
|
240
|
+
# Convert objective results
|
|
241
|
+
obj = self.objectives[0]
|
|
242
|
+
obj_id = obj["identifier"].GetString()
|
|
243
|
+
|
|
244
|
+
nodal_variable = KM.KratosGlobals.GetVariable("DF1DX")
|
|
245
|
+
nodal_variable_mapped = KM.KratosGlobals.GetVariable("DF1DX_MAPPED")
|
|
246
|
+
|
|
247
|
+
obj_value = self.communicator.getStandardizedValue(obj_id)
|
|
248
|
+
obj_gradient = ReadNodalVariableToList(self.design_surface, nodal_variable)
|
|
249
|
+
obj_gradient_mapped = ReadNodalVariableToList(self.design_surface, nodal_variable_mapped)
|
|
250
|
+
|
|
251
|
+
dir_obj, len_obj = self.__ConvertToLengthDirectionFormat(obj_value, obj_gradient, obj_gradient_mapped)
|
|
252
|
+
dir_obj = dir_obj
|
|
253
|
+
|
|
254
|
+
# Convert constraints
|
|
255
|
+
len_eqs = []
|
|
256
|
+
dir_eqs = []
|
|
257
|
+
len_ineqs = []
|
|
258
|
+
dir_ineqs = []
|
|
259
|
+
|
|
260
|
+
for itr in range(self.constraints.size()):
|
|
261
|
+
con = self.constraints[itr]
|
|
262
|
+
con_id = con["identifier"].GetString()
|
|
263
|
+
|
|
264
|
+
nodal_variable = KM.KratosGlobals.GetVariable(f"DC{(itr+1)}DX")
|
|
265
|
+
nodal_variable_mapped = KM.KratosGlobals.GetVariable(f"DC{(itr+1)}DX_MAPPED")
|
|
266
|
+
|
|
267
|
+
value = self.communicator.getStandardizedValue(con_id)
|
|
268
|
+
gradient = ReadNodalVariableToList(self.design_surface, nodal_variable)
|
|
269
|
+
gradient_mapped = ReadNodalVariableToList(self.design_surface, nodal_variable_mapped)
|
|
270
|
+
|
|
271
|
+
direction, length = self.__ConvertToLengthDirectionFormat(value, gradient, gradient_mapped)
|
|
272
|
+
|
|
273
|
+
if con["type"].GetString()=="=":
|
|
274
|
+
dir_eqs.append(direction)
|
|
275
|
+
len_eqs.append(length)
|
|
276
|
+
else:
|
|
277
|
+
dir_ineqs.append(direction)
|
|
278
|
+
len_ineqs.append(length)
|
|
279
|
+
|
|
280
|
+
return len_obj, dir_obj, len_eqs, dir_eqs, len_ineqs, dir_ineqs
|
|
281
|
+
|
|
282
|
+
# --------------------------------------------------------------------------
|
|
283
|
+
@staticmethod
|
|
284
|
+
def __ConvertToLengthDirectionFormat(value, gradient, modified_gradient):
|
|
285
|
+
norm_inf = cm.NormInf3D(modified_gradient)
|
|
286
|
+
if norm_inf > 1e-12:
|
|
287
|
+
direction = cm.ScalarVectorProduct(-1/norm_inf,modified_gradient)
|
|
288
|
+
length = -value/cm.Dot(gradient, direction)
|
|
289
|
+
else:
|
|
290
|
+
KM.Logger.PrintWarning("ShapeOpt::AlgorithmTrustRegion", "Vanishing norm-infinity for gradient detected!")
|
|
291
|
+
direction = modified_gradient
|
|
292
|
+
length = 0.0
|
|
293
|
+
|
|
294
|
+
return direction, length
|
|
295
|
+
|
|
296
|
+
# --------------------------------------------------------------------------
|
|
297
|
+
def __DetermineMaxStepLength(self):
|
|
298
|
+
if self.opt_iteration < 4:
|
|
299
|
+
return self.algorithm_settings["max_step_length"].GetDouble()
|
|
300
|
+
else:
|
|
301
|
+
obj_id = self.objectives[0]["identifier"].GetString()
|
|
302
|
+
current_obj_val = self.communicator.getStandardizedValue(obj_id)
|
|
303
|
+
obj_history = self.data_logger.GetValues("response_value")[obj_id]
|
|
304
|
+
step_history = self.data_logger.GetValues("step_length")
|
|
305
|
+
|
|
306
|
+
# Check for osciallation
|
|
307
|
+
objective_is_oscillating = False
|
|
308
|
+
is_decrease_1 = (current_obj_val - obj_history[self.opt_iteration-1])< 0
|
|
309
|
+
is_decrease_2 = (obj_history[self.opt_iteration-1] - obj_history[self.opt_iteration-2])<0
|
|
310
|
+
is_decrease_3 = (current_obj_val - obj_history[self.opt_iteration-3])< 0
|
|
311
|
+
if (is_decrease_1 and is_decrease_2== False and is_decrease_3) or (is_decrease_1== False and is_decrease_2 and is_decrease_3==False):
|
|
312
|
+
objective_is_oscillating = True
|
|
313
|
+
|
|
314
|
+
# Reduce step length if certain conditions are fullfilled
|
|
315
|
+
if objective_is_oscillating:
|
|
316
|
+
return step_history[self.opt_iteration-1]*self.algorithm_settings["step_length_reduction_factor"].GetDouble()
|
|
317
|
+
else:
|
|
318
|
+
return step_history[self.opt_iteration-1]
|
|
319
|
+
|
|
320
|
+
# --------------------------------------------------------------------------
|
|
321
|
+
@staticmethod
|
|
322
|
+
def __ExpressInStepLengthUnit(len_obj, len_eqs, len_ineqs, step_length):
|
|
323
|
+
len_bar_obj = 1/step_length * len_obj
|
|
324
|
+
len_bar_eqs = cm.ScalarVectorProduct(1/step_length, len_eqs)
|
|
325
|
+
len_bar_ineqs = cm.ScalarVectorProduct(1/step_length, len_ineqs)
|
|
326
|
+
return len_bar_obj, len_bar_eqs, len_bar_ineqs
|
|
327
|
+
|
|
328
|
+
# --------------------------------------------------------------------------
|
|
329
|
+
def __DetermineStep(self, len_obj, dir_obj, len_eqs, dir_eqs, len_ineqs, dir_ineqs):
|
|
330
|
+
KM.Logger.Print("")
|
|
331
|
+
KM.Logger.PrintInfo("ShapeOpt", "Starting determination of step...")
|
|
332
|
+
|
|
333
|
+
timer = Timer()
|
|
334
|
+
timer.StartTimer()
|
|
335
|
+
|
|
336
|
+
# Create projector object wich can do the projection in the orthogonalized subspace
|
|
337
|
+
projector = Projector(len_obj, dir_obj, len_eqs, dir_eqs, len_ineqs, dir_ineqs, self.algorithm_settings)
|
|
338
|
+
|
|
339
|
+
# 1. Test projection if there is room for objective improvement
|
|
340
|
+
# I.e., the actual step length to become feasible for an inactive threshold is smaller than 1 and hence a part of the step can be dedicated to objective improvement
|
|
341
|
+
len_obj_test = 0.01
|
|
342
|
+
inactive_threshold = 100
|
|
343
|
+
test_norm_dX, is_projection_sucessfull = projector.RunProjection(len_obj_test, inactive_threshold)
|
|
344
|
+
|
|
345
|
+
KM.Logger.PrintInfo("ShapeOpt", "Time needed for one projection step = ", timer.GetTotalTime(), "s")
|
|
346
|
+
|
|
347
|
+
# 2. Determine step following two different modes depending on the previos found step length to the feasible domain
|
|
348
|
+
if is_projection_sucessfull:
|
|
349
|
+
if test_norm_dX < 1: # Minimizing mode
|
|
350
|
+
KM.Logger.Print("")
|
|
351
|
+
KM.Logger.PrintInfo("ShapeOpt", "Computing projection case 1...")
|
|
352
|
+
|
|
353
|
+
func = lambda len_obj: projector.RunProjection(len_obj, inactive_threshold)
|
|
354
|
+
|
|
355
|
+
len_obj_min = len_obj_test
|
|
356
|
+
len_obj_max = 1.3
|
|
357
|
+
bi_target = 1
|
|
358
|
+
bi_tolerance = self.algorithm_settings["bisectioning_tolerance"].GetDouble()
|
|
359
|
+
bi_max_itr = self.algorithm_settings["bisectioning_max_itr"].GetInt()
|
|
360
|
+
len_obj_result, bi_itrs, bi_err = cm.PerformBisectioning(func, len_obj_min, len_obj_max, bi_target, bi_tolerance, bi_max_itr)
|
|
361
|
+
|
|
362
|
+
projection_results = projector.GetDetailedResultsOfLatestProjection()
|
|
363
|
+
|
|
364
|
+
else: # Correction mode
|
|
365
|
+
KM.Logger.Print("")
|
|
366
|
+
KM.Logger.PrintInfo("ShapeOpt", "Computing projection case 2...")
|
|
367
|
+
|
|
368
|
+
len_obj = self.algorithm_settings["obj_share_during_correction"].GetDouble()
|
|
369
|
+
func = lambda threshold: projector.RunProjection(len_obj, threshold)
|
|
370
|
+
|
|
371
|
+
threshold_min = 0
|
|
372
|
+
threshold_max = 1.3
|
|
373
|
+
bi_target = 1
|
|
374
|
+
bi_tolerance = self.algorithm_settings["bisectioning_tolerance"].GetDouble()
|
|
375
|
+
bi_max_itr = self.algorithm_settings["bisectioning_max_itr"].GetInt()
|
|
376
|
+
l_threshold_result, bi_itrs, bi_err = cm.PerformBisectioning(func, threshold_min, threshold_max, bi_target, bi_tolerance, bi_max_itr)
|
|
377
|
+
|
|
378
|
+
projection_results = projector.GetDetailedResultsOfLatestProjection()
|
|
379
|
+
else:
|
|
380
|
+
raise RuntimeError("Case of not converged test projection not yet implemented yet!")
|
|
381
|
+
|
|
382
|
+
KM.Logger.Print("")
|
|
383
|
+
KM.Logger.PrintInfo("ShapeOpt", "Time needed for determining step = ", timer.GetTotalTime(), "s")
|
|
384
|
+
|
|
385
|
+
process_details = { "test_norm_dX": test_norm_dX,
|
|
386
|
+
"bi_itrs":bi_itrs,
|
|
387
|
+
"bi_err":bi_err,
|
|
388
|
+
"adj_len_obj": projection_results["adj_len_obj"],
|
|
389
|
+
"adj_len_eqs": projection_results["adj_len_eqs"],
|
|
390
|
+
"adj_len_ineqs": projection_results["adj_len_ineqs"] }
|
|
391
|
+
|
|
392
|
+
return projection_results["dX"], process_details
|
|
393
|
+
|
|
394
|
+
# --------------------------------------------------------------------------
|
|
395
|
+
def __ComputeShapeUpdate(self, dX_bar, step_length):
|
|
396
|
+
# Compute update in regular units
|
|
397
|
+
dX = cm.ScalarVectorProduct(step_length,dX_bar)
|
|
398
|
+
|
|
399
|
+
WriteListToNodalVariable(dX, self.design_surface, KSO.SHAPE_UPDATE)
|
|
400
|
+
self.optimization_utilities.AddFirstVariableToSecondVariable(self.design_surface, KSO.SHAPE_UPDATE, KSO.SHAPE_CHANGE)
|
|
401
|
+
|
|
402
|
+
return dX
|
|
403
|
+
|
|
404
|
+
# --------------------------------------------------------------------------
|
|
405
|
+
def __LogCurrentOptimizationStep(self, additional_values_to_log):
|
|
406
|
+
self.data_logger.LogSensitivityHeatmap(self.opt_iteration, self.mapper)
|
|
407
|
+
self.data_logger.LogCurrentValues(self.opt_iteration, additional_values_to_log)
|
|
408
|
+
self.data_logger.LogCurrentDesign(self.opt_iteration)
|
|
409
|
+
|
|
410
|
+
# --------------------------------------------------------------------------
|
|
411
|
+
def __CombineConstraintDataToOrderedList(self, eqs_data_list, ineqs_data_list):
|
|
412
|
+
num_eqs = 0
|
|
413
|
+
num_ineqs = 0
|
|
414
|
+
combined_list = []
|
|
415
|
+
|
|
416
|
+
# Order is given by appearance of constraints in optimization settings
|
|
417
|
+
for itr in range(self.constraints.size()):
|
|
418
|
+
if self.constraints[itr]["type"].GetString()=="=":
|
|
419
|
+
combined_list.append(eqs_data_list[num_eqs])
|
|
420
|
+
num_eqs = num_eqs+1
|
|
421
|
+
else:
|
|
422
|
+
combined_list.append(ineqs_data_list[num_ineqs])
|
|
423
|
+
num_ineqs = num_ineqs+1
|
|
424
|
+
|
|
425
|
+
return combined_list
|
|
426
|
+
|
|
427
|
+
# ==============================================================================
|
|
428
|
+
class Projector():
|
|
429
|
+
# --------------------------------------------------------------------------
|
|
430
|
+
def __init__(self, len_obj, dir_obj, len_eqs, dir_eqs, len_ineqs, dir_ineqs, settings):
|
|
431
|
+
|
|
432
|
+
# Store settings
|
|
433
|
+
self.far_away_length = settings["far_away_length"].GetDouble()
|
|
434
|
+
self.subopt_max_itr = settings["subopt_max_itr"].GetInt()
|
|
435
|
+
self.subopt_tolerance = settings["subopt_tolerance"].GetDouble()
|
|
436
|
+
|
|
437
|
+
# Initialize projection results
|
|
438
|
+
self.are_projection_restuls_stored = False
|
|
439
|
+
self.projection_results = {}
|
|
440
|
+
|
|
441
|
+
# Reduce input data to relevant info
|
|
442
|
+
self.input_len_obj = len_obj
|
|
443
|
+
self.input_len_eqs = len_eqs
|
|
444
|
+
self.input_len_ineqs = len_ineqs
|
|
445
|
+
|
|
446
|
+
len_eqs, dir_eqs, remaining_eqs_entries = self.__ReduceToRelevantEqualityConstraints(len_eqs, dir_eqs)
|
|
447
|
+
len_ineqs, dir_ineqs, remaining_ineqs_entries = self.__ReduceToRelevantInequalityConstraints(len_ineqs, dir_ineqs)
|
|
448
|
+
|
|
449
|
+
# Store some working variables depening on data reduction
|
|
450
|
+
self.remaining_eqs_entries = remaining_eqs_entries
|
|
451
|
+
self.remaining_ineqs_entries = remaining_ineqs_entries
|
|
452
|
+
self.len_eqs = len_eqs
|
|
453
|
+
self.len_ineqs = len_ineqs
|
|
454
|
+
self.num_eqs = len(len_eqs)
|
|
455
|
+
self.num_ineqs = len(len_ineqs)
|
|
456
|
+
self.num_unknowns = 1 + self.num_eqs + self.num_ineqs
|
|
457
|
+
|
|
458
|
+
# Create orthogonal basis
|
|
459
|
+
vector_space = [dir_obj]
|
|
460
|
+
for itr in range(len(dir_eqs)):
|
|
461
|
+
vector_space = cm.HorzCat(vector_space, dir_eqs[itr])
|
|
462
|
+
for itr in range(len(dir_ineqs)):
|
|
463
|
+
vector_space = cm.HorzCat(vector_space, dir_ineqs[itr])
|
|
464
|
+
self.ortho_basis = cm.PerformGramSchmidtOrthogonalization(vector_space)
|
|
465
|
+
|
|
466
|
+
# Transform directions to orthogonal space since they don't change with different projections
|
|
467
|
+
self.dir_obj_o = cm.TranslateToNewBasis(dir_obj, self.ortho_basis)
|
|
468
|
+
self.dir_eqs_o = cm.TranslateToNewBasis(dir_eqs, self.ortho_basis)
|
|
469
|
+
self.dir_ineqs_o = cm.TranslateToNewBasis(dir_ineqs, self.ortho_basis)
|
|
470
|
+
|
|
471
|
+
# Make sure directions of constraints are stored as matrix
|
|
472
|
+
self.dir_eqs_o = cm.SafeConvertVectorToMatrix(self.dir_eqs_o)
|
|
473
|
+
self.dir_ineqs_o = cm.SafeConvertVectorToMatrix(self.dir_ineqs_o)
|
|
474
|
+
|
|
475
|
+
# --------------------------------------------------------------------------
|
|
476
|
+
def RunProjection(self, len_obj, threshold):
|
|
477
|
+
|
|
478
|
+
# Adjust halfspaces according input
|
|
479
|
+
adj_len_obj, adj_len_eqs, adj_len_ineqs = self.__AdjustHalfSpacesAndHyperplanes(len_obj, threshold)
|
|
480
|
+
|
|
481
|
+
# Determine position of border of halfspaces and hyperplanes
|
|
482
|
+
pos_obj_o, pos_eqs_o, pos_ineqs_o = self.__DetermineConstraintBorders(adj_len_obj, adj_len_eqs, adj_len_ineqs)
|
|
483
|
+
|
|
484
|
+
# Project current position onto intersection of
|
|
485
|
+
current_position = cm.ZeroVector(self.num_unknowns)
|
|
486
|
+
dlambda_hp = self.__ProjectToHyperplanes(current_position, self.dir_eqs_o, pos_eqs_o)
|
|
487
|
+
|
|
488
|
+
# Project position and direction of halfspaces onto intersection of hyperplanes
|
|
489
|
+
zero_position_eqs_o = cm.ZeroMatrix(self.num_unknowns,self.num_eqs)
|
|
490
|
+
|
|
491
|
+
pos_obj_hp = self.__ProjectToHyperplanes(pos_obj_o, cm.HorzCat(self.dir_eqs_o, self.dir_obj_o), cm.HorzCat(pos_eqs_o, pos_obj_o))
|
|
492
|
+
dir_obj_hp = self.__ProjectToHyperplanes(self.dir_obj_o, self.dir_eqs_o, zero_position_eqs_o)
|
|
493
|
+
|
|
494
|
+
pos_ineqs_hp = []
|
|
495
|
+
dir_ineqs_hp = []
|
|
496
|
+
for itr in range(self.num_ineqs):
|
|
497
|
+
pos_ineqs_hp_i = self.__ProjectToHyperplanes(pos_ineqs_o[itr], cm.HorzCat(self.dir_eqs_o, self.dir_ineqs_o[itr]), cm.HorzCat(pos_eqs_o, pos_ineqs_o[itr]))
|
|
498
|
+
dir_ineqs_hp_i = self.__ProjectToHyperplanes(self.dir_ineqs_o[itr], self.dir_eqs_o, zero_position_eqs_o)
|
|
499
|
+
|
|
500
|
+
pos_ineqs_hp.append(pos_ineqs_hp_i)
|
|
501
|
+
dir_ineqs_hp.append(dir_ineqs_hp_i)
|
|
502
|
+
|
|
503
|
+
# Project onto adjusted halfspaces along the intersection of hyperplanes
|
|
504
|
+
dX_o, _, _, exit_code = self.__ProjectToHalfSpaces(dlambda_hp, cm.HorzCat(pos_ineqs_hp, pos_obj_hp), cm.HorzCat(dir_ineqs_hp, dir_obj_hp))
|
|
505
|
+
|
|
506
|
+
# Determine return values
|
|
507
|
+
if exit_code == 0:
|
|
508
|
+
is_projection_sucessfull = True
|
|
509
|
+
|
|
510
|
+
# Backtransformation and multiplication with -1 because the direction vectors are chosen opposite to the gradients such that the lengths are positive if violated
|
|
511
|
+
dX = cm.ScalarVectorProduct(-1, cm.TranslateToOriginalBasis(dX_o, self.ortho_basis))
|
|
512
|
+
norm_dX = cm.NormInf3D(dX)
|
|
513
|
+
else:
|
|
514
|
+
is_projection_sucessfull = False
|
|
515
|
+
|
|
516
|
+
dX = []
|
|
517
|
+
norm_dX = 1e10
|
|
518
|
+
|
|
519
|
+
self.__StoreProjectionResults(norm_dX, dX, is_projection_sucessfull, adj_len_obj, adj_len_eqs, adj_len_ineqs)
|
|
520
|
+
|
|
521
|
+
return norm_dX, is_projection_sucessfull
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
# --------------------------------------------------------------------------
|
|
525
|
+
def GetDetailedResultsOfLatestProjection(self):
|
|
526
|
+
if self.are_projection_restuls_stored == False:
|
|
527
|
+
raise RuntimeError("Projector::__StoreProjectionResults: No projection results stored yet!")
|
|
528
|
+
|
|
529
|
+
return self.projection_results
|
|
530
|
+
|
|
531
|
+
# --------------------------------------------------------------------------
|
|
532
|
+
@staticmethod
|
|
533
|
+
def __ReduceToRelevantEqualityConstraints(len_eqs, dir_eqs):
|
|
534
|
+
len_eqs_relevant = []
|
|
535
|
+
dir_eqs_relevant = []
|
|
536
|
+
remaining_entries = []
|
|
537
|
+
|
|
538
|
+
for itr in range(len(dir_eqs)):
|
|
539
|
+
len_i = len_eqs[itr]
|
|
540
|
+
dir_i = dir_eqs[itr]
|
|
541
|
+
|
|
542
|
+
is_no_gradient_info_available = cm.NormInf3D(dir_i) < 1e-13
|
|
543
|
+
|
|
544
|
+
if is_no_gradient_info_available:
|
|
545
|
+
pass
|
|
546
|
+
else:
|
|
547
|
+
remaining_entries.append(itr)
|
|
548
|
+
len_eqs_relevant.append(len_i)
|
|
549
|
+
dir_eqs_relevant.append(dir_i)
|
|
550
|
+
|
|
551
|
+
return len_eqs_relevant, dir_eqs_relevant, remaining_entries
|
|
552
|
+
|
|
553
|
+
# --------------------------------------------------------------------------
|
|
554
|
+
def __ReduceToRelevantInequalityConstraints(self, len_ineqs, dir_ineqs):
|
|
555
|
+
len_ineqs_relevant = []
|
|
556
|
+
dir_ineqs_relevant = []
|
|
557
|
+
remaining_entries = []
|
|
558
|
+
|
|
559
|
+
for itr in range(len(dir_ineqs)):
|
|
560
|
+
len_i = len_ineqs[itr]
|
|
561
|
+
dir_i = dir_ineqs[itr]
|
|
562
|
+
|
|
563
|
+
is_no_gradient_info_available = cm.NormInf3D(dir_i) < 1e-13
|
|
564
|
+
is_constraint_inactive_and_far_away = len_i < -self.far_away_length
|
|
565
|
+
|
|
566
|
+
if is_no_gradient_info_available or is_constraint_inactive_and_far_away:
|
|
567
|
+
pass
|
|
568
|
+
else:
|
|
569
|
+
remaining_entries.append(itr)
|
|
570
|
+
len_ineqs_relevant.append(len_i)
|
|
571
|
+
dir_ineqs_relevant.append(dir_i)
|
|
572
|
+
|
|
573
|
+
return len_ineqs_relevant, dir_ineqs_relevant, remaining_entries
|
|
574
|
+
|
|
575
|
+
# --------------------------------------------------------------------------
|
|
576
|
+
def __AdjustHalfSpacesAndHyperplanes(self, len_obj, threshold):
|
|
577
|
+
if threshold<len_obj:
|
|
578
|
+
len_obj = threshold
|
|
579
|
+
|
|
580
|
+
len_eqs = copy.deepcopy(self.len_eqs)
|
|
581
|
+
len_ineqs = copy.deepcopy(self.len_ineqs)
|
|
582
|
+
|
|
583
|
+
for itr in range(self.num_eqs):
|
|
584
|
+
len_eqs[itr] = min(max(self.len_eqs[itr],-threshold),threshold)
|
|
585
|
+
|
|
586
|
+
for itr in range(self.num_ineqs):
|
|
587
|
+
len_ineqs[itr] = min(self.len_ineqs[itr],threshold)
|
|
588
|
+
|
|
589
|
+
return len_obj, len_eqs, len_ineqs
|
|
590
|
+
|
|
591
|
+
# --------------------------------------------------------------------------
|
|
592
|
+
def __DetermineConstraintBorders(self, len_obj, len_eqs, len_ineqs):
|
|
593
|
+
pos_obj = cm.ScalarVectorProduct(-len_obj,self.dir_obj_o)
|
|
594
|
+
|
|
595
|
+
pos_eqs = []
|
|
596
|
+
pos_ineqs = []
|
|
597
|
+
for i in range(self.num_eqs):
|
|
598
|
+
pos_eqs.append(cm.ScalarVectorProduct(-len_eqs[i],self.dir_eqs_o[i]))
|
|
599
|
+
|
|
600
|
+
for i in range(self.num_ineqs):
|
|
601
|
+
pos_ineqs.append(cm.ScalarVectorProduct(-len_ineqs[i],self.dir_ineqs_o[i]))
|
|
602
|
+
|
|
603
|
+
return pos_obj, pos_eqs, pos_ineqs
|
|
604
|
+
|
|
605
|
+
# --------------------------------------------------------------------------
|
|
606
|
+
@staticmethod
|
|
607
|
+
def __ProjectToHyperplanes(vector, dir_hps, pos_hps):
|
|
608
|
+
if cm.IsEmpty(dir_hps):
|
|
609
|
+
return vector
|
|
610
|
+
|
|
611
|
+
num_hps = len(dir_hps)
|
|
612
|
+
|
|
613
|
+
tmp_mat = cm.Prod(cm.Trans(dir_hps),dir_hps)
|
|
614
|
+
tmp_vec = [ cm.Dot(dir_hps[j],cm.Minus(pos_hps[j],vector)) for j in range(num_hps) ]
|
|
615
|
+
|
|
616
|
+
tmp_solution = cm.SolveLinearSystem(tmp_mat,tmp_vec)
|
|
617
|
+
|
|
618
|
+
return cm.Plus(cm.Prod(dir_hps,tmp_solution),vector)
|
|
619
|
+
|
|
620
|
+
# --------------------------------------------------------------------------
|
|
621
|
+
def __ProjectToHalfSpaces(self, dX0, pos_hss, dir_hss):
|
|
622
|
+
A = cm.Trans(dir_hss)
|
|
623
|
+
b = [ cm.Dot(pos_hss[i],dir_hss[i]) for i in range(cm.RowSize(A)) ]
|
|
624
|
+
|
|
625
|
+
dX_o, subopt_itr, error, exit_code = cm.QuadProg(A, b, self.subopt_max_itr, self.subopt_tolerance)
|
|
626
|
+
|
|
627
|
+
# Consider initial delta
|
|
628
|
+
dX_o = cm.Plus(dX_o,dX0)
|
|
629
|
+
|
|
630
|
+
return dX_o, subopt_itr, error, exit_code
|
|
631
|
+
|
|
632
|
+
# --------------------------------------------------------------------------
|
|
633
|
+
def __StoreProjectionResults(self, norm_dX, dX, is_projection_sucessfull, adj_len_obj, adj_len_eqs, adj_len_ineqs):
|
|
634
|
+
self.are_projection_restuls_stored = True
|
|
635
|
+
self.projection_results["norm_dX"] = norm_dX
|
|
636
|
+
self.projection_results["dX"] = dX
|
|
637
|
+
self.projection_results["is_projection_sucessfull"] = is_projection_sucessfull
|
|
638
|
+
self.projection_results["adj_len_obj"] = adj_len_obj
|
|
639
|
+
self.projection_results["adj_len_eqs"], self.projection_results["adj_len_ineqs"] = self.__CompleteConstraintLengthsWithRemovedEntries(adj_len_eqs, adj_len_ineqs)
|
|
640
|
+
|
|
641
|
+
# --------------------------------------------------------------------------
|
|
642
|
+
def __CompleteConstraintLengthsWithRemovedEntries(self, len_eqs, len_ineqs):
|
|
643
|
+
# Complete list of eqs
|
|
644
|
+
complete_list_eqs = copy.deepcopy(self.input_len_eqs)
|
|
645
|
+
for itr in range(len(len_eqs)):
|
|
646
|
+
original_eq_number = self.remaining_eqs_entries[itr]
|
|
647
|
+
complete_list_eqs[original_eq_number] = len_eqs[itr]
|
|
648
|
+
|
|
649
|
+
# Complete list of ineqs
|
|
650
|
+
complete_list_ineqs = copy.deepcopy(self.input_len_ineqs)
|
|
651
|
+
for itr in range(len(len_ineqs)):
|
|
652
|
+
original_eq_number = self.remaining_ineqs_entries[itr]
|
|
653
|
+
complete_list_ineqs[original_eq_number] = len_ineqs[itr]
|
|
654
|
+
|
|
655
|
+
return complete_list_eqs, complete_list_ineqs
|
|
656
|
+
|
|
657
|
+
# ==============================================================================
|
|
File without changes
|