KratosOptimizationApplication 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/KratosOptimizationApplication.so +0 -0
- KratosMultiphysics/.libs/libKratosOptimizationCore.dylib +0 -0
- KratosMultiphysics/OptimizationApplication/__init__.py +19 -0
- KratosMultiphysics/OptimizationApplication/algorithms/NLOPT_algorithms.py +255 -0
- KratosMultiphysics/OptimizationApplication/algorithms/SciPy_algorithms.py +154 -0
- KratosMultiphysics/OptimizationApplication/algorithms/__init__.py +0 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm.py +78 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_adam.py +68 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_base.py +393 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_gradient_projection.py +355 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_momentum_relaxed_gradient_projection.py +70 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_nesterov_accelarated_gradient.py +60 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_relaxed_gradient_projection.py +263 -0
- KratosMultiphysics/OptimizationApplication/algorithms/algorithm_steepest_descent.py +205 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_NLOPT_constraint.py +194 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_NLOPT_objective.py +191 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_SciPy_constraint.py +123 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_SciPy_objective.py +148 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_constraint.py +180 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_objective.py +133 -0
- KratosMultiphysics/OptimizationApplication/algorithms/standardized_rgp_constraint.py +268 -0
- KratosMultiphysics/OptimizationApplication/analyses_controller.py +75 -0
- KratosMultiphysics/OptimizationApplication/controls/control.py +123 -0
- KratosMultiphysics/OptimizationApplication/controls/external_response_function_control.py +149 -0
- KratosMultiphysics/OptimizationApplication/controls/master_control.py +198 -0
- KratosMultiphysics/OptimizationApplication/controls/material/material_properties_control.py +115 -0
- KratosMultiphysics/OptimizationApplication/controls/material/simp_control.py +229 -0
- KratosMultiphysics/OptimizationApplication/controls/shape/vertex_morphing_shape_control.py +289 -0
- KratosMultiphysics/OptimizationApplication/controls/thickness/shell_thickness_control.py +180 -0
- KratosMultiphysics/OptimizationApplication/controls_controller.py +205 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/avg_abs_improvement_conv_criterion.py +98 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/combined_conv_criterion.py +87 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/constraint_conv_criterion.py +68 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/convergence_criterion.py +26 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/l2_conv_criterion.py +77 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/magnitude_reduction_conv_criterion.py +85 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/max_iter_conv_criterion.py +48 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/patience_conv_criterion.py +116 -0
- KratosMultiphysics/OptimizationApplication/convergence_criteria/target_value_conv_criterion.py +64 -0
- KratosMultiphysics/OptimizationApplication/execution_policies/execution_policy.py +46 -0
- KratosMultiphysics/OptimizationApplication/execution_policies/execution_policy_decorator.py +67 -0
- KratosMultiphysics/OptimizationApplication/execution_policies/independent_analysis_execution_policy.py +78 -0
- KratosMultiphysics/OptimizationApplication/execution_policies/kratos_analysis_execution_policy.py +137 -0
- KratosMultiphysics/OptimizationApplication/execution_policies/stepping_analysis_execution_policy.py +88 -0
- KratosMultiphysics/OptimizationApplication/filtering/explicit_filter.py +124 -0
- KratosMultiphysics/OptimizationApplication/filtering/filter.py +188 -0
- KratosMultiphysics/OptimizationApplication/filtering/filter_utils.py +55 -0
- KratosMultiphysics/OptimizationApplication/filtering/helmholtz_analysis.py +139 -0
- KratosMultiphysics/OptimizationApplication/filtering/helmholtz_scalar_solver.py +39 -0
- KratosMultiphysics/OptimizationApplication/filtering/helmholtz_shape_solver.py +67 -0
- KratosMultiphysics/OptimizationApplication/filtering/helmholtz_solver_base.py +275 -0
- KratosMultiphysics/OptimizationApplication/filtering/helmholtz_vector_solver.py +39 -0
- KratosMultiphysics/OptimizationApplication/filtering/implicit_filter.py +192 -0
- KratosMultiphysics/OptimizationApplication/filtering/python_solvers_wrapper_implicit_filters.py +56 -0
- KratosMultiphysics/OptimizationApplication/model_part_controllers/connectivity_preserving_model_part_controller.py +72 -0
- KratosMultiphysics/OptimizationApplication/model_part_controllers/external_response_function_model_part_controller.py +110 -0
- KratosMultiphysics/OptimizationApplication/model_part_controllers/mdpa_model_part_controller.py +44 -0
- KratosMultiphysics/OptimizationApplication/model_part_controllers/model_part_controller.py +19 -0
- KratosMultiphysics/OptimizationApplication/model_parts_controller.py +92 -0
- KratosMultiphysics/OptimizationApplication/optimization_analysis.py +146 -0
- KratosMultiphysics/OptimizationApplication/optimizations_controller.py +223 -0
- KratosMultiphysics/OptimizationApplication/optimizer.py +61 -0
- KratosMultiphysics/OptimizationApplication/processes/optimization_problem_ascii_output_process.py +212 -0
- KratosMultiphysics/OptimizationApplication/processes/optimization_problem_field_output_process.py +122 -0
- KratosMultiphysics/OptimizationApplication/processes/optimization_problem_graph_output_process.py +184 -0
- KratosMultiphysics/OptimizationApplication/processes/optimization_problem_hdf5_output_process.py +84 -0
- KratosMultiphysics/OptimizationApplication/processes/optimization_problem_vtu_output_process.py +94 -0
- KratosMultiphysics/OptimizationApplication/processes/spatial_statistics_computation_process.py +81 -0
- KratosMultiphysics/OptimizationApplication/responses/__init__.py +0 -0
- KratosMultiphysics/OptimizationApplication/responses/additive_manufacturing_responses.py +410 -0
- KratosMultiphysics/OptimizationApplication/responses/analysis_based_response_function_factory.py +14 -0
- KratosMultiphysics/OptimizationApplication/responses/analysis_free_response_function_factory.py +14 -0
- KratosMultiphysics/OptimizationApplication/responses/base_response.py +66 -0
- KratosMultiphysics/OptimizationApplication/responses/binary_operator_response_function.py +103 -0
- KratosMultiphysics/OptimizationApplication/responses/combined_response_function.py +127 -0
- KratosMultiphysics/OptimizationApplication/responses/discrete_value_residual_response_function.py +131 -0
- KratosMultiphysics/OptimizationApplication/responses/evaluation_response_function.py +68 -0
- KratosMultiphysics/OptimizationApplication/responses/external_response_function.py +87 -0
- KratosMultiphysics/OptimizationApplication/responses/geometric_centroid_deviation_response_function.py +97 -0
- KratosMultiphysics/OptimizationApplication/responses/linear_strain_energy_response_function.py +72 -0
- KratosMultiphysics/OptimizationApplication/responses/literal_value_response_function.py +33 -0
- KratosMultiphysics/OptimizationApplication/responses/log_response_function.py +47 -0
- KratosMultiphysics/OptimizationApplication/responses/mass_response_function.py +71 -0
- KratosMultiphysics/OptimizationApplication/responses/response_function.py +126 -0
- KratosMultiphysics/OptimizationApplication/responses/response_routine.py +158 -0
- KratosMultiphysics/OptimizationApplication/responses/structural_responses.py +335 -0
- KratosMultiphysics/OptimizationApplication/responses_controller.py +390 -0
- KratosMultiphysics/OptimizationApplication/utilities/buffered_dict.py +399 -0
- KratosMultiphysics/OptimizationApplication/utilities/component_data_view.py +74 -0
- KratosMultiphysics/OptimizationApplication/utilities/helper_utilities.py +40 -0
- KratosMultiphysics/OptimizationApplication/utilities/logger_utilities.py +222 -0
- KratosMultiphysics/OptimizationApplication/utilities/model_part_utilities.py +117 -0
- KratosMultiphysics/OptimizationApplication/utilities/opt_line_search.py +173 -0
- KratosMultiphysics/OptimizationApplication/utilities/opt_projection.py +191 -0
- KratosMultiphysics/OptimizationApplication/utilities/optimization_problem.py +237 -0
- KratosMultiphysics/OptimizationApplication/utilities/optimization_problem_utilities.py +237 -0
- KratosMultiphysics/OptimizationApplication/utilities/response_utilities.py +249 -0
- KratosMultiphysics/OptimizationApplication/utilities/timer.py +45 -0
- KratosMultiphysics/OptimizationApplication/utilities/union_utilities.py +6 -0
- kratosoptimizationapplication-10.4.4.dist-info/METADATA +25 -0
- kratosoptimizationapplication-10.4.4.dist-info/RECORD +106 -0
- kratosoptimizationapplication-10.4.4.dist-info/WHEEL +6 -0
- kratosoptimizationapplication.dylibs/libKratosCore.dylib +4 -0
- kratosoptimizationapplication.dylibs/libgcc_s.1.1.dylib +0 -0
- kratosoptimizationapplication.dylibs/libgomp.1.dylib +0 -0
- kratosoptimizationapplication.dylibs/libstdc++.6.dylib +0 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
import numpy
|
|
3
|
+
import KratosMultiphysics as Kratos
|
|
4
|
+
import KratosMultiphysics.OptimizationApplication as KratosOA
|
|
5
|
+
from KratosMultiphysics.OptimizationApplication.controls.control import Control
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.utilities.union_utilities import SupportedSensitivityFieldVariableTypes
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.utilities.model_part_utilities import ModelPartOperation
|
|
9
|
+
from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
|
|
10
|
+
from KratosMultiphysics.OptimizationApplication.filtering.filter import Factory as FilterFactory
|
|
11
|
+
from KratosMultiphysics.OptimizationApplication.utilities.opt_projection import CreateProjection
|
|
12
|
+
|
|
13
|
+
def Factory(model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem) -> Control:
|
|
14
|
+
if not parameters.Has("name"):
|
|
15
|
+
raise RuntimeError(f"SimpControl instantiation requires a \"name\" in parameters [ parameters = {parameters}].")
|
|
16
|
+
if not parameters.Has("settings"):
|
|
17
|
+
raise RuntimeError(f"SimpControl instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
|
|
18
|
+
return SimpControl(parameters["name"].GetString(), model, parameters["settings"], optimization_problem)
|
|
19
|
+
|
|
20
|
+
class Materials:
|
|
21
|
+
def __init__(self, parameters: 'list[Kratos.Parameters]') -> None:
|
|
22
|
+
default_parameters = Kratos.Parameters("""{
|
|
23
|
+
"density" : 1.0,
|
|
24
|
+
"young_modulus": 1.0
|
|
25
|
+
}""")
|
|
26
|
+
|
|
27
|
+
self.__list_of_densities: 'list[float]' = []
|
|
28
|
+
self.__list_of_young_modulus: 'list[float]' = []
|
|
29
|
+
self.__phi: 'list[float]' = []
|
|
30
|
+
|
|
31
|
+
data: 'list[tuple[float, float]]' = []
|
|
32
|
+
for params in parameters:
|
|
33
|
+
params.ValidateAndAssignDefaults(default_parameters)
|
|
34
|
+
data.append((params["density"].GetDouble(), params["young_modulus"].GetDouble()))
|
|
35
|
+
|
|
36
|
+
# sort in ascending order of densities
|
|
37
|
+
data = sorted(data, key=lambda x: x[0])
|
|
38
|
+
|
|
39
|
+
# now check whether the young modulus is also arranged in the ascending order
|
|
40
|
+
for i, (_, young_modulus) in enumerate(data[:-1]):
|
|
41
|
+
if young_modulus > data[i+1][1]:
|
|
42
|
+
raise RuntimeError("Young modulus and densities are not in the ascending order.")
|
|
43
|
+
|
|
44
|
+
for i, (density, young_modulus) in enumerate(data):
|
|
45
|
+
self.__phi.append(i)
|
|
46
|
+
self.__list_of_densities.append(density)
|
|
47
|
+
self.__list_of_young_modulus.append(young_modulus)
|
|
48
|
+
|
|
49
|
+
def GetDensities(self) -> 'list[float]':
|
|
50
|
+
return self.__list_of_densities
|
|
51
|
+
|
|
52
|
+
def GetYoungModulus(self) -> 'list[float]':
|
|
53
|
+
return self.__list_of_young_modulus
|
|
54
|
+
|
|
55
|
+
def GetPhi(self) -> 'list[float]':
|
|
56
|
+
return self.__phi
|
|
57
|
+
|
|
58
|
+
class SimpControl(Control):
|
|
59
|
+
def __init__(self, name: str, model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem) -> None:
|
|
60
|
+
super().__init__(name)
|
|
61
|
+
|
|
62
|
+
self.parameters = parameters
|
|
63
|
+
self.model = model
|
|
64
|
+
self.optimization_problem = optimization_problem
|
|
65
|
+
|
|
66
|
+
default_settings = Kratos.Parameters("""{
|
|
67
|
+
"controlled_model_part_names" : [""],
|
|
68
|
+
"output_all_fields" : true,
|
|
69
|
+
"echo_level" : 0,
|
|
70
|
+
"consider_recursive_property_update": false,
|
|
71
|
+
"density_projection_settings" : {},
|
|
72
|
+
"young_modulus_projection_settings" : {},
|
|
73
|
+
"filter_settings" : {},
|
|
74
|
+
"list_of_materials" : [
|
|
75
|
+
{
|
|
76
|
+
"density" : 1.0,
|
|
77
|
+
"young_modulus": 1.0
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}""")
|
|
81
|
+
|
|
82
|
+
parameters.ValidateAndAssignDefaults(default_settings)
|
|
83
|
+
|
|
84
|
+
self.output_all_fields = parameters["output_all_fields"].GetBool()
|
|
85
|
+
self.echo_level = parameters["echo_level"].GetInt()
|
|
86
|
+
|
|
87
|
+
self.controlled_physical_variables = [Kratos.DENSITY, Kratos.YOUNG_MODULUS]
|
|
88
|
+
|
|
89
|
+
self.materials = Materials(parameters["list_of_materials"].values())
|
|
90
|
+
|
|
91
|
+
self.density_projection = CreateProjection(parameters["density_projection_settings"], self.optimization_problem)
|
|
92
|
+
self.young_modulus_projection = CreateProjection(parameters["young_modulus_projection_settings"], self.optimization_problem)
|
|
93
|
+
|
|
94
|
+
controlled_model_names_parts = parameters["controlled_model_part_names"].GetStringArray()
|
|
95
|
+
if len(controlled_model_names_parts) == 0:
|
|
96
|
+
raise RuntimeError(f"No model parts are provided for SimpControl. [ control name = \"{self.GetName()}\"]")
|
|
97
|
+
self.model_part_operation = ModelPartOperation(self.model, ModelPartOperation.OperationType.UNION, f"control_{self.GetName()}", controlled_model_names_parts, False)
|
|
98
|
+
self.model_part: 'typing.Optional[Kratos.ModelPart]' = None
|
|
99
|
+
|
|
100
|
+
self.consider_recursive_property_update = parameters["consider_recursive_property_update"].GetBool()
|
|
101
|
+
|
|
102
|
+
# filtering settings
|
|
103
|
+
self.filter = FilterFactory(self.model, self.model_part_operation.GetModelPartFullName(), Kratos.DENSITY, Kratos.Globals.DataLocation.Element, parameters["filter_settings"])
|
|
104
|
+
|
|
105
|
+
def Initialize(self) -> None:
|
|
106
|
+
self.un_buffered_data = ComponentDataView(self, self.optimization_problem).GetUnBufferedData()
|
|
107
|
+
|
|
108
|
+
# init model parts
|
|
109
|
+
self.model_part = self.model_part_operation.GetModelPart()
|
|
110
|
+
|
|
111
|
+
# Creating element specific properties for Youngs Modulus and Density
|
|
112
|
+
if not KratosOA.OptAppModelPartUtils.CheckModelPartStatus(self.model_part, "element_specific_properties_created"):
|
|
113
|
+
KratosOA.OptimizationUtils.CreateEntitySpecificPropertiesForContainer(self.model_part, self.model_part.Elements, self.consider_recursive_property_update)
|
|
114
|
+
KratosOA.OptAppModelPartUtils.LogModelPartStatus(self.model_part, "element_specific_properties_created")
|
|
115
|
+
|
|
116
|
+
self.filter.SetComponentDataView(ComponentDataView(self, self.optimization_problem))
|
|
117
|
+
self.filter.Initialize()
|
|
118
|
+
|
|
119
|
+
# initialize the projections
|
|
120
|
+
self.density_projection.SetProjectionSpaces(self.materials.GetPhi(), self.materials.GetDensities())
|
|
121
|
+
self.young_modulus_projection.SetProjectionSpaces(self.materials.GetPhi(), self.materials.GetYoungModulus())
|
|
122
|
+
|
|
123
|
+
# check if the density or Young's modulus is defined
|
|
124
|
+
element: Kratos.Element
|
|
125
|
+
for element in self.model_part.Elements:
|
|
126
|
+
break
|
|
127
|
+
is_density_defined = element.Properties.Has(Kratos.DENSITY)
|
|
128
|
+
is_youngs_modulus_defined = element.Properties.Has(Kratos.YOUNG_MODULUS)
|
|
129
|
+
if is_density_defined:
|
|
130
|
+
if is_youngs_modulus_defined:
|
|
131
|
+
Kratos.Logger.PrintWarning(self.__class__.__name__, f"Elements of {self.model_part.FullName()} defines both DENSITY and YOUNG_MODULUS. Using DENSITY for initial field calculation and ignoring YOUNG_MODULUS.")
|
|
132
|
+
density = KratosOA.TensorAdaptors.PropertiesVariableTensorAdaptor(self.model_part.Elements, Kratos.DENSITY)
|
|
133
|
+
density.CollectData()
|
|
134
|
+
self.simp_physical_phi = self.density_projection.ProjectBackward(density)
|
|
135
|
+
elif is_youngs_modulus_defined:
|
|
136
|
+
young_modulus = KratosOA.TensorAdaptors.PropertiesVariableTensorAdaptor(self.model_part.Elements, Kratos.YOUNG_MODULUS)
|
|
137
|
+
young_modulus.CollectData()
|
|
138
|
+
self.simp_physical_phi = self.young_modulus_projection.ProjectBackward(young_modulus)
|
|
139
|
+
else:
|
|
140
|
+
raise RuntimeError(f"Elements of {self.model_part.FullName()} does not define either DENSITY or YOUNG_MODULUS.")
|
|
141
|
+
|
|
142
|
+
# get the control field
|
|
143
|
+
self.control_phi = self.filter.UnfilterField(self.simp_physical_phi)
|
|
144
|
+
|
|
145
|
+
self._UpdateAndOutputFields(self.GetEmptyField())
|
|
146
|
+
|
|
147
|
+
def Check(self) -> None:
|
|
148
|
+
self.filter.Check()
|
|
149
|
+
|
|
150
|
+
def Finalize(self) -> None:
|
|
151
|
+
self.filter.Finalize()
|
|
152
|
+
|
|
153
|
+
def GetPhysicalKratosVariables(self) -> 'list[SupportedSensitivityFieldVariableTypes]':
|
|
154
|
+
return self.controlled_physical_variables
|
|
155
|
+
|
|
156
|
+
def GetEmptyField(self) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
157
|
+
field = Kratos.TensorAdaptors.VariableTensorAdaptor(self.model_part.Elements, Kratos.DENSITY)
|
|
158
|
+
field.data[:] = 0.0
|
|
159
|
+
return Kratos.TensorAdaptors.DoubleTensorAdaptor(field, copy=False)
|
|
160
|
+
|
|
161
|
+
def GetControlField(self) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
162
|
+
return Kratos.TensorAdaptors.DoubleTensorAdaptor(self.control_phi) # returning a copy
|
|
163
|
+
|
|
164
|
+
def MapGradient(self, physical_variable_gradient_map: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleTensorAdaptor]') -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
165
|
+
keys = physical_variable_gradient_map.keys()
|
|
166
|
+
if len(keys) != 2:
|
|
167
|
+
raise RuntimeError(f"Not provided required gradient fields for control \"{self.GetName()}\". Following are the variables:\n\t" + "\n\t".join([k.Name() for k in keys]))
|
|
168
|
+
if Kratos.DENSITY not in keys or Kratos.YOUNG_MODULUS not in keys:
|
|
169
|
+
raise RuntimeError(f"The required gradient for control \"{self.GetName()}\" w.r.t. DENSITY or YOUNG_MODULUS not found. Followings are the variables:\n\t" + "\n\t".join([k.Name() for k in keys]))
|
|
170
|
+
|
|
171
|
+
# first calculate the density partial sensitivity of the response function
|
|
172
|
+
d_j_d_density = physical_variable_gradient_map[Kratos.DENSITY]
|
|
173
|
+
|
|
174
|
+
# second calculate the young modulus partial sensitivity of the response function
|
|
175
|
+
d_j_d_youngs = physical_variable_gradient_map[Kratos.YOUNG_MODULUS]
|
|
176
|
+
|
|
177
|
+
# now compute response function total sensitivity w.r.t. phi
|
|
178
|
+
d_j_d_phi = Kratos.TensorAdaptors.DoubleTensorAdaptor(d_j_d_density)
|
|
179
|
+
d_j_d_phi.data = d_j_d_density.data * self.d_density_d_phi.data + d_j_d_youngs.data * self.d_young_modulus_d_phi.data
|
|
180
|
+
|
|
181
|
+
return self.filter.BackwardFilterIntegratedField(d_j_d_phi)
|
|
182
|
+
|
|
183
|
+
def Update(self, control_field: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> bool:
|
|
184
|
+
if control_field.GetContainer() != self.model_part.Elements:
|
|
185
|
+
raise RuntimeError(f"Updates for the required element container not found for control \"{self.GetName()}\". [ required model part name: {self.model_part.FullName()} ]")
|
|
186
|
+
|
|
187
|
+
update = Kratos.TensorAdaptors.DoubleTensorAdaptor(control_field)
|
|
188
|
+
update.data = control_field.data - self.control_phi.data
|
|
189
|
+
if numpy.linalg.norm(update.data) > 1e-15:
|
|
190
|
+
self.control_phi.data[:] = control_field.data[:]
|
|
191
|
+
self._UpdateAndOutputFields(update)
|
|
192
|
+
self.density_projection.Update()
|
|
193
|
+
self.young_modulus_projection.Update()
|
|
194
|
+
return True
|
|
195
|
+
|
|
196
|
+
self.density_projection.Update()
|
|
197
|
+
self.young_modulus_projection.Update()
|
|
198
|
+
return False
|
|
199
|
+
|
|
200
|
+
def _UpdateAndOutputFields(self, update: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> None:
|
|
201
|
+
# filter the control field
|
|
202
|
+
physical_phi_update = self.filter.ForwardFilterField(update)
|
|
203
|
+
self.simp_physical_phi.data += physical_phi_update.data
|
|
204
|
+
|
|
205
|
+
density = self.density_projection.ProjectForward(self.simp_physical_phi)
|
|
206
|
+
KratosOA.TensorAdaptors.PropertiesVariableTensorAdaptor(density, Kratos.DENSITY, copy=False).StoreData()
|
|
207
|
+
if self.consider_recursive_property_update:
|
|
208
|
+
KratosOA.OptimizationUtils.UpdatePropertiesVariableWithRootValueRecursively(density.GetContainer(), Kratos.DENSITY)
|
|
209
|
+
self.un_buffered_data.SetValue("DENSITY", density, overwrite=True)
|
|
210
|
+
|
|
211
|
+
youngs_modulus = self.young_modulus_projection.ProjectForward(self.simp_physical_phi)
|
|
212
|
+
KratosOA.TensorAdaptors.PropertiesVariableTensorAdaptor(youngs_modulus, Kratos.YOUNG_MODULUS, copy=False).StoreData()
|
|
213
|
+
if self.consider_recursive_property_update:
|
|
214
|
+
KratosOA.OptimizationUtils.UpdatePropertiesVariableWithRootValueRecursively(youngs_modulus.GetContainer(), Kratos.YOUNG_MODULUS)
|
|
215
|
+
self.un_buffered_data.SetValue("YOUNG_MODULUS", youngs_modulus, overwrite=True)
|
|
216
|
+
|
|
217
|
+
# now calculate the total sensitivities of density w.r.t. phi
|
|
218
|
+
self.d_density_d_phi = self.density_projection.ForwardProjectionGradient(self.simp_physical_phi)
|
|
219
|
+
|
|
220
|
+
# now calculate the total sensitivities of young modulus w.r.t. simp_physical_phi
|
|
221
|
+
self.d_young_modulus_d_phi = self.young_modulus_projection.ForwardProjectionGradient(self.simp_physical_phi)
|
|
222
|
+
|
|
223
|
+
# now output the fields
|
|
224
|
+
un_buffered_data = ComponentDataView(self, self.optimization_problem).GetUnBufferedData()
|
|
225
|
+
un_buffered_data.SetValue(f"{self.GetName()}", self.simp_physical_phi.Clone(),overwrite=True)
|
|
226
|
+
if self.output_all_fields:
|
|
227
|
+
un_buffered_data.SetValue(f"{self.GetName()}_update", physical_phi_update, overwrite=True)
|
|
228
|
+
un_buffered_data.SetValue(f"dDENSITY_d{self.GetName()}", self.d_density_d_phi.Clone(), overwrite=True)
|
|
229
|
+
un_buffered_data.SetValue(f"dYOUNG_MODULUS_d{self.GetName()}", self.d_young_modulus_d_phi.Clone(), overwrite=True)
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import numpy
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
import KratosMultiphysics as Kratos
|
|
5
|
+
import KratosMultiphysics.OptimizationApplication as KratosOA
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.controls.control import Control
|
|
7
|
+
from KratosMultiphysics.OptimizationApplication.utilities.union_utilities import SupportedSensitivityFieldVariableTypes
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.utilities.model_part_utilities import ModelPartOperation
|
|
9
|
+
from KratosMultiphysics.OptimizationApplication.utilities.component_data_view import ComponentDataView
|
|
10
|
+
from KratosMultiphysics.OptimizationApplication.utilities.optimization_problem import OptimizationProblem
|
|
11
|
+
from KratosMultiphysics.OptimizationApplication.utilities.logger_utilities import time_decorator
|
|
12
|
+
from KratosMultiphysics.OptimizationApplication.filtering.filter import Factory as FilterFactory
|
|
13
|
+
import math
|
|
14
|
+
|
|
15
|
+
def Factory(model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem) -> Control:
|
|
16
|
+
if not parameters.Has("name"):
|
|
17
|
+
raise RuntimeError(f"VertexMorphingShapeControl instantiation requires a \"name\" in parameters [ parameters = {parameters}].")
|
|
18
|
+
if not parameters.Has("settings"):
|
|
19
|
+
raise RuntimeError(f"VertexMorphingShapeControl instantiation requires a \"settings\" in parameters [ parameters = {parameters}].")
|
|
20
|
+
|
|
21
|
+
return VertexMorphingShapeControl(parameters["name"].GetString(), model, parameters["settings"], optimization_problem)
|
|
22
|
+
|
|
23
|
+
class VertexMorphingShapeControl(Control):
|
|
24
|
+
"""Node-based shape control using implicit and explicit Vertex Morphing techniques
|
|
25
|
+
|
|
26
|
+
This is filtering-based discrete shape control which parametrizes and controls
|
|
27
|
+
discrete shell and solid geometries.
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
def __init__(self, name: str, model: Kratos.Model, parameters: Kratos.Parameters, optimization_problem: OptimizationProblem):
|
|
31
|
+
super().__init__(name)
|
|
32
|
+
|
|
33
|
+
self.parameters = parameters
|
|
34
|
+
self.model = model
|
|
35
|
+
self.optimization_problem = optimization_problem
|
|
36
|
+
|
|
37
|
+
default_settings = Kratos.Parameters("""{
|
|
38
|
+
"controlled_model_part_names": [],
|
|
39
|
+
"filter_settings" : {},
|
|
40
|
+
"mesh_motion_solver_type" : "none",
|
|
41
|
+
"skin_model_part_names" : [],
|
|
42
|
+
"mesh_motion_solver_settings": {},
|
|
43
|
+
"output_all_fields" : false
|
|
44
|
+
}""")
|
|
45
|
+
|
|
46
|
+
self.parameters.ValidateAndAssignDefaults(default_settings)
|
|
47
|
+
|
|
48
|
+
self.output_all_fields = self.parameters["output_all_fields"].GetBool()
|
|
49
|
+
|
|
50
|
+
controlled_model_names_parts = parameters["controlled_model_part_names"].GetStringArray()
|
|
51
|
+
if len(controlled_model_names_parts) == 0:
|
|
52
|
+
raise RuntimeError(f"No model parts are provided for VertexMorphingShapeControl. [ control name = \"{self.GetName()}\"]")
|
|
53
|
+
|
|
54
|
+
self.model_part_operation = ModelPartOperation(self.model, ModelPartOperation.OperationType.UNION, f"control_{self.GetName()}", controlled_model_names_parts, False)
|
|
55
|
+
self.model_part: 'Optional[Kratos.ModelPart]' = None
|
|
56
|
+
|
|
57
|
+
self.filter = FilterFactory(self.model, self.model_part_operation.GetModelPartFullName(), KratosOA.SHAPE, Kratos.Globals.DataLocation.NodeHistorical, self.parameters["filter_settings"])
|
|
58
|
+
|
|
59
|
+
# now setup mesh motion
|
|
60
|
+
self.__mesh_moving_analysis: 'Optional[MeshMovingAnalysis]' = None
|
|
61
|
+
self.__boundary_model_part: 'Optional[Kratos.ModelPart]' = None
|
|
62
|
+
|
|
63
|
+
self.mesh_motion_solver_type = self.parameters["mesh_motion_solver_type"].GetString()
|
|
64
|
+
supported_mesh_motion_solver_types = ["mesh_moving_analysis", "filter_based", "none"]
|
|
65
|
+
if self.mesh_motion_solver_type not in supported_mesh_motion_solver_types:
|
|
66
|
+
raise RuntimeError(f"Unsupported mesh_motion_solver_type = \"{self.mesh_motion_solver_type}\" requested. Supported types are:\n\t" + "\n\t".join(supported_mesh_motion_solver_types))
|
|
67
|
+
|
|
68
|
+
if self.mesh_motion_solver_type == "mesh_moving_analysis":
|
|
69
|
+
# import is done here, so that, if it is not required to use mesh_motion,
|
|
70
|
+
# then it is not loaded, hence not even required to have MeshMovingApplication
|
|
71
|
+
# compiled.
|
|
72
|
+
from KratosMultiphysics.MeshMovingApplication.mesh_moving_analysis import MeshMovingAnalysis
|
|
73
|
+
self.__mesh_moving_analysis = MeshMovingAnalysis(self.model, self.parameters["mesh_motion_solver_settings"])
|
|
74
|
+
|
|
75
|
+
@time_decorator(methodName="GetName")
|
|
76
|
+
def Initialize(self) -> None:
|
|
77
|
+
self.model_part = self.model_part_operation.GetModelPart()
|
|
78
|
+
|
|
79
|
+
# initialize filters
|
|
80
|
+
self.filter.SetComponentDataView(ComponentDataView(self, self.optimization_problem))
|
|
81
|
+
self.filter.Initialize()
|
|
82
|
+
|
|
83
|
+
self.control_field = self.filter.UnfilterField(self.GetPhysicalField())
|
|
84
|
+
|
|
85
|
+
# initialize_mesh_motion if defined.
|
|
86
|
+
if not self.__mesh_moving_analysis is None:
|
|
87
|
+
self.__mesh_moving_analysis.Initialize()
|
|
88
|
+
|
|
89
|
+
def recursively_increase_usage(model_part: Kratos.ModelPart) -> None:
|
|
90
|
+
if not model_part.Has(KratosOA.NUMBER_OF_SOLVERS_USING_NODES):
|
|
91
|
+
model_part[KratosOA.NUMBER_OF_SOLVERS_USING_NODES] = 0
|
|
92
|
+
model_part[KratosOA.NUMBER_OF_SOLVERS_USING_NODES] += 1
|
|
93
|
+
|
|
94
|
+
for sub_model_part in model_part.SubModelParts:
|
|
95
|
+
recursively_increase_usage(sub_model_part)
|
|
96
|
+
|
|
97
|
+
# we increase the usage of all the sub-model parts because, mesh moving works with
|
|
98
|
+
# root model parts, and all the sub model parts are suing the root model parts. Hence
|
|
99
|
+
# mesh moving will affect all the shared sub-model parts
|
|
100
|
+
recursively_increase_usage(self.__mesh_moving_analysis._GetSolver().GetComputingModelPart())
|
|
101
|
+
|
|
102
|
+
# now update
|
|
103
|
+
self._UpdateAndOutputFields(self.GetEmptyField())
|
|
104
|
+
|
|
105
|
+
def Check(self) -> None:
|
|
106
|
+
self.filter.Check()
|
|
107
|
+
|
|
108
|
+
def Finalize(self) -> None:
|
|
109
|
+
self.filter.Finalize()
|
|
110
|
+
if not self.__mesh_moving_analysis is None:
|
|
111
|
+
self.__mesh_moving_analysis.Finalize()
|
|
112
|
+
del self.__mesh_moving_analysis
|
|
113
|
+
|
|
114
|
+
def GetPhysicalKratosVariables(self) -> 'list[SupportedSensitivityFieldVariableTypes]':
|
|
115
|
+
return [KratosOA.SHAPE]
|
|
116
|
+
|
|
117
|
+
def GetEmptyField(self) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
118
|
+
field = Kratos.TensorAdaptors.VariableTensorAdaptor(self.__GetPhysicalModelPart().Nodes, KratosOA.SHAPE)
|
|
119
|
+
field.data[:] = 0.0
|
|
120
|
+
return field
|
|
121
|
+
|
|
122
|
+
def GetControlField(self) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
123
|
+
return Kratos.TensorAdaptors.DoubleTensorAdaptor(self.control_field)
|
|
124
|
+
|
|
125
|
+
def GetPhysicalField(self) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
126
|
+
physical_shape_field = Kratos.TensorAdaptors.NodePositionTensorAdaptor(self.__GetPhysicalModelPart().Nodes, Kratos.Configuration.Initial)
|
|
127
|
+
physical_shape_field.CollectData()
|
|
128
|
+
return physical_shape_field
|
|
129
|
+
|
|
130
|
+
@time_decorator(methodName="GetName")
|
|
131
|
+
def MapGradient(self, physical_variable_gradient_map: 'dict[SupportedSensitivityFieldVariableTypes, Kratos.TensorAdaptors.DoubleTensorAdaptor]') -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
132
|
+
keys = physical_variable_gradient_map.keys()
|
|
133
|
+
if len(keys) != 1:
|
|
134
|
+
raise RuntimeError(f"Provided more than required gradient fields for control \"{self.GetName()}\". Following are the variables:\n\t" + "\n\t".join([k.Name() for k in keys]))
|
|
135
|
+
if KratosOA.SHAPE not in keys:
|
|
136
|
+
raise RuntimeError(f"The required gradient for control \"{self.GetName()}\" w.r.t. {KratosOA.SHAPE.Name()} not found. Followings are the variables:\n\t" + "\n\t".join([k.Name() for k in keys]))
|
|
137
|
+
|
|
138
|
+
physical_gradient = physical_variable_gradient_map[KratosOA.SHAPE]
|
|
139
|
+
if physical_gradient.GetContainer() != self.__GetPhysicalModelPart().Nodes:
|
|
140
|
+
raise RuntimeError(f"Gradients for the required element container not found for control \"{self.GetName()}\". [ required model part name: {self.model_part.FullName()}, given model part name: {physical_gradient.GetModelPart().FullName()} ]")
|
|
141
|
+
|
|
142
|
+
filtered_gradient = self.filter.BackwardFilterIntegratedField(self.__ExtractDesignSurfaceData(physical_gradient, self.model_part.Nodes))
|
|
143
|
+
|
|
144
|
+
return self.__ExtractDesignSurfaceData(filtered_gradient, self.__GetPhysicalModelPart().Nodes)
|
|
145
|
+
|
|
146
|
+
@time_decorator(methodName="GetName")
|
|
147
|
+
def Update(self, new_control_field: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> bool:
|
|
148
|
+
if new_control_field.GetContainer() != self.__GetPhysicalModelPart().Nodes:
|
|
149
|
+
raise RuntimeError(f"Updates for the required element container not found for control \"{self.GetName()}\". [ required model part name: {self.model_part.FullName()}, given model part name: {new_control_field.GetModelPart().FullName()} ]")
|
|
150
|
+
|
|
151
|
+
control_update = Kratos.TensorAdaptors.DoubleTensorAdaptor(new_control_field)
|
|
152
|
+
control_update.data = new_control_field.data - self.control_field.data
|
|
153
|
+
if not math.isclose(numpy.linalg.norm(control_update.data), 0.0, abs_tol=1e-16):
|
|
154
|
+
# update the control SHAPE field
|
|
155
|
+
self.control_field.data[:] = new_control_field.data[:]
|
|
156
|
+
# now update the physical field
|
|
157
|
+
self._UpdateAndOutputFields(control_update)
|
|
158
|
+
|
|
159
|
+
self.filter.Update()
|
|
160
|
+
return True
|
|
161
|
+
return False
|
|
162
|
+
|
|
163
|
+
def _UpdateAndOutputFields(self, control_update: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> None:
|
|
164
|
+
# compute the shape update
|
|
165
|
+
if self.mesh_motion_solver_type == "filter_based":
|
|
166
|
+
shape_update = self.filter.ForwardFilterField(control_update)
|
|
167
|
+
else:
|
|
168
|
+
shape_update = self.filter.ForwardFilterField(self.__ExtractDesignSurfaceData(control_update, self.model_part.Nodes))
|
|
169
|
+
|
|
170
|
+
# now update the shape
|
|
171
|
+
self._UpdateMesh(shape_update)
|
|
172
|
+
|
|
173
|
+
# now output the fields
|
|
174
|
+
un_buffered_data = ComponentDataView(self, self.optimization_problem).GetUnBufferedData()
|
|
175
|
+
un_buffered_data.SetValue("shape_update", shape_update,overwrite=True)
|
|
176
|
+
if self.output_all_fields:
|
|
177
|
+
un_buffered_data.SetValue("shape_control", self.control_field.Clone(), overwrite=True)
|
|
178
|
+
un_buffered_data.SetValue("shape_control_update", control_update.Clone(), overwrite=True)
|
|
179
|
+
|
|
180
|
+
def _UpdateMesh(self, shape_update: Kratos.TensorAdaptors.DoubleTensorAdaptor) -> None:
|
|
181
|
+
if self.mesh_motion_solver_type != "none":
|
|
182
|
+
if not self.__mesh_moving_analysis is None:
|
|
183
|
+
mm_computing_model_part: Kratos.ModelPart = self.__mesh_moving_analysis._GetSolver().GetComputingModelPart()
|
|
184
|
+
time_before_update = mm_computing_model_part.ProcessInfo.GetValue(Kratos.TIME)
|
|
185
|
+
step_before_update = mm_computing_model_part.ProcessInfo.GetValue(Kratos.STEP)
|
|
186
|
+
delta_time_before_update = mm_computing_model_part.ProcessInfo.GetValue(Kratos.DELTA_TIME)
|
|
187
|
+
|
|
188
|
+
# Reset step/time iterators such that they match the current iteration after calling RunSolutionLoop (which internally calls CloneTimeStep)
|
|
189
|
+
mm_computing_model_part.ProcessInfo.SetValue(Kratos.STEP, step_before_update-1)
|
|
190
|
+
mm_computing_model_part.ProcessInfo.SetValue(Kratos.TIME, time_before_update-1)
|
|
191
|
+
mm_computing_model_part.ProcessInfo.SetValue(Kratos.DELTA_TIME, 0)
|
|
192
|
+
|
|
193
|
+
# first reset the MESH_DISPLACEMENTS
|
|
194
|
+
Kratos.VariableUtils().SetHistoricalVariableToZero(Kratos.MESH_DISPLACEMENT, mm_computing_model_part.Nodes)
|
|
195
|
+
|
|
196
|
+
# assign the design surface MESH_DISPLACEMENTS
|
|
197
|
+
Kratos.TensorAdaptors.HistoricalVariableTensorAdaptor(shape_update, Kratos.MESH_DISPLACEMENT, copy=False).StoreData()
|
|
198
|
+
|
|
199
|
+
# since we know that the nodes in the shape_update model part needs to be fixed to correctly
|
|
200
|
+
# compute the MESH_DISPLACEMENT. We Only do that in here by first freeing all the MESH_DISPLACEMENT
|
|
201
|
+
# dofs, then followed by fixing the shape_update model part nodes' MESH_DISPLACEMENTs. If further
|
|
202
|
+
# boundaries needs fixing, then they need to be specified in the mesh_motion_solver settings
|
|
203
|
+
# using fix_vector_variable_process.
|
|
204
|
+
mesh_displacement_comps = [Kratos.MESH_DISPLACEMENT_X, Kratos.MESH_DISPLACEMENT_Y, Kratos.MESH_DISPLACEMENT_Z]
|
|
205
|
+
for i_comp, mesh_displacement_var in enumerate(mesh_displacement_comps):
|
|
206
|
+
# first free the mesh displacement component
|
|
207
|
+
Kratos.VariableUtils().ApplyFixity(mesh_displacement_var, False, mm_computing_model_part.Nodes)
|
|
208
|
+
# now fix the design surface component
|
|
209
|
+
Kratos.VariableUtils().ApplyFixity(mesh_displacement_var, True, shape_update.GetContainer())
|
|
210
|
+
# now fix boundary condition components
|
|
211
|
+
model_parts = self.filter.GetBoundaryConditions()
|
|
212
|
+
for model_part in model_parts[i_comp]:
|
|
213
|
+
Kratos.VariableUtils().ApplyFixity(mesh_displacement_var, True, model_part.Nodes)
|
|
214
|
+
|
|
215
|
+
# solve for the volume mesh displacements
|
|
216
|
+
if not self.__mesh_moving_analysis.time < self.__mesh_moving_analysis.end_time:
|
|
217
|
+
self.__mesh_moving_analysis.end_time += 1
|
|
218
|
+
self.__mesh_moving_analysis.RunSolutionLoop()
|
|
219
|
+
|
|
220
|
+
mesh_displacement_field = Kratos.TensorAdaptors.HistoricalVariableTensorAdaptor(self.model_part_operation.GetRootModelPart().Nodes, Kratos.MESH_DISPLACEMENT)
|
|
221
|
+
mesh_displacement_field.CollectData()
|
|
222
|
+
|
|
223
|
+
mm_computing_model_part.ProcessInfo.SetValue(Kratos.STEP, step_before_update)
|
|
224
|
+
mm_computing_model_part.ProcessInfo.SetValue(Kratos.TIME, time_before_update)
|
|
225
|
+
mm_computing_model_part.ProcessInfo.SetValue(Kratos.DELTA_TIME, delta_time_before_update)
|
|
226
|
+
else:
|
|
227
|
+
# filter based mesh motion is used. Hence read the value from the filter. then the shape update is the mesh displacement
|
|
228
|
+
mesh_displacement_field = shape_update
|
|
229
|
+
|
|
230
|
+
# a mesh motion is solved (either by mesh motion solver or the filter), and MESH_DISPLACEMENT variable is filled
|
|
231
|
+
# Hence, update the coords
|
|
232
|
+
physical_field = Kratos.TensorAdaptors.NodePositionTensorAdaptor(mesh_displacement_field.GetContainer(), Kratos.Configuration.Initial)
|
|
233
|
+
physical_field.CollectData()
|
|
234
|
+
physical_field.data += mesh_displacement_field.data
|
|
235
|
+
|
|
236
|
+
Kratos.TensorAdaptors.NodePositionTensorAdaptor(physical_field, Kratos.Configuration.Initial, copy=False).StoreData()
|
|
237
|
+
Kratos.TensorAdaptors.NodePositionTensorAdaptor(physical_field, Kratos.Configuration.Current, copy=False).StoreData()
|
|
238
|
+
Kratos.Logger.PrintInfo(self.__class__.__name__, "Applied MESH_DISPLACEMENT to the mesh.")
|
|
239
|
+
else:
|
|
240
|
+
# no mesh motion is preferred, hence only updating the design field
|
|
241
|
+
physical_field = self.GetPhysicalField()
|
|
242
|
+
physical_field.data += shape_update.data
|
|
243
|
+
Kratos.TensorAdaptors.NodePositionTensorAdaptor(physical_field, Kratos.Configuration.Initial, copy=False).StoreData()
|
|
244
|
+
Kratos.TensorAdaptors.NodePositionTensorAdaptor(physical_field, Kratos.Configuration.Current, copy=False).StoreData()
|
|
245
|
+
|
|
246
|
+
def __GetPhysicalModelPart(self) -> Kratos.ModelPart:
|
|
247
|
+
if self.mesh_motion_solver_type == "none":
|
|
248
|
+
# this control does not require mesh_motion, hence this does not
|
|
249
|
+
# have any influence on the volume domain. So the physical model part
|
|
250
|
+
# is the controlled model part
|
|
251
|
+
return self.model_part
|
|
252
|
+
else:
|
|
253
|
+
# this is the case where mesh motion is required, that means this control will control the
|
|
254
|
+
# whole domain by moving its internal nodes because, the controlled model part represents
|
|
255
|
+
# a surface of the volume domain. hence the physical field should be the whole
|
|
256
|
+
# model part
|
|
257
|
+
return self.model_part.GetRootModelPart()
|
|
258
|
+
|
|
259
|
+
def __ExtractDesignSurfaceData(self, tensor_adaptor: Kratos.TensorAdaptors.DoubleTensorAdaptor, nodes_container: Kratos.NodesArray) -> Kratos.TensorAdaptors.DoubleTensorAdaptor:
|
|
260
|
+
"""\
|
|
261
|
+
@brief This method is used to extract data from model part to @ref TensorAdaptor.
|
|
262
|
+
|
|
263
|
+
@details If the nodes container used in the @p tensor_adaptor is different from the @p nodes_container
|
|
264
|
+
then, this method extracts values from the nodes of the container into the @p tensor_adaptor
|
|
265
|
+
to a @ref TensorAdaptor having @p nodes_container as the nodes.
|
|
266
|
+
|
|
267
|
+
Eg:
|
|
268
|
+
This is required, if mesh motion based filters are used in the filtering, then
|
|
269
|
+
smoothened update from filtering will be computed on the whole domain including the design surface.
|
|
270
|
+
But, for computation of the shape_update and checking it if it actually changes the design surface, first
|
|
271
|
+
we need to get only the design surface update. Hence, this method is used.
|
|
272
|
+
|
|
273
|
+
@param tensor_adaptor (Kratos.TensorAdaptors.DoubleTensorAdaptor): @ref TensorAdaptor with the data.
|
|
274
|
+
@param nodes_container (Kratos.NodesArray): list of nodes on which you needs data transferred.
|
|
275
|
+
@returns: @ref TensorAdaptor having the @p nodes_container as the container, having values extracted from corresponding nodes in the container of @p tensor_adaptor .
|
|
276
|
+
"""
|
|
277
|
+
if nodes_container != tensor_adaptor.GetContainer():
|
|
278
|
+
Kratos.VariableUtils().SetNonHistoricalVariableToZero(KratosOA.SHAPE, tensor_adaptor.GetContainer())
|
|
279
|
+
Kratos.VariableUtils().SetNonHistoricalVariableToZero(KratosOA.SHAPE, nodes_container)
|
|
280
|
+
|
|
281
|
+
Kratos.TensorAdaptors.VariableTensorAdaptor(tensor_adaptor, KratosOA.SHAPE, copy=False).StoreData()
|
|
282
|
+
ta = Kratos.TensorAdaptors.VariableTensorAdaptor(nodes_container, KratosOA.SHAPE)
|
|
283
|
+
ta.CollectData()
|
|
284
|
+
return ta
|
|
285
|
+
else:
|
|
286
|
+
return tensor_adaptor
|
|
287
|
+
|
|
288
|
+
def __str__(self) -> str:
|
|
289
|
+
return f"Control [type = {self.__class__.__name__}, name = {self.GetName()}, model part name = {self.model_part.FullName()}, control variable = SHAPE ]"
|