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,139 @@
|
|
|
1
|
+
from typing import Any, Optional
|
|
2
|
+
|
|
3
|
+
# Importing Kratos
|
|
4
|
+
import KratosMultiphysics as KM
|
|
5
|
+
import KratosMultiphysics.OptimizationApplication as KOA
|
|
6
|
+
import KratosMultiphysics.OptimizationApplication.filtering.python_solvers_wrapper_implicit_filters as implicit_filter_solvers
|
|
7
|
+
|
|
8
|
+
# Importing the base class
|
|
9
|
+
from KratosMultiphysics.analysis_stage import AnalysisStage
|
|
10
|
+
|
|
11
|
+
class HelmholtzAnalysis(AnalysisStage):
|
|
12
|
+
"""
|
|
13
|
+
This class is the main-script of the implicit filtering analysis
|
|
14
|
+
It can be imported and used as "black-box"
|
|
15
|
+
"""
|
|
16
|
+
def __init__(self, model: KM.Model, project_parameters: KM.Parameters):
|
|
17
|
+
super().__init__(model, project_parameters)
|
|
18
|
+
self.__source_data: 'Optional[KM.TensorAdaptors.DoubleTensorAdaptor]' = None
|
|
19
|
+
self.__neighbour_entities: 'dict[Any, KM.TensorAdaptors.IntTensorAdaptor]' = {}
|
|
20
|
+
|
|
21
|
+
#### Internal functions ####
|
|
22
|
+
def _CreateSolver(self):
|
|
23
|
+
""" Create the Solver (and create and import the ModelPart if it is not already in the model) """
|
|
24
|
+
return implicit_filter_solvers.CreateSolver(self.model, self.project_parameters)
|
|
25
|
+
|
|
26
|
+
def _GetSimulationName(self):
|
|
27
|
+
return "::[Helmholtz/Sobolev Analysis]:: "
|
|
28
|
+
|
|
29
|
+
def _GetComputingModelPart(self):
|
|
30
|
+
return self._GetSolver().GetComputingModelPart()
|
|
31
|
+
|
|
32
|
+
def _SetSolverMode(self, invers_mode:bool = False):
|
|
33
|
+
self._GetComputingModelPart().ProcessInfo.SetValue(KOA.COMPUTE_HELMHOLTZ_INVERSE, invers_mode)
|
|
34
|
+
|
|
35
|
+
def _SetHelmHoltzSourceMode(self, integrated_field=False):
|
|
36
|
+
self._GetComputingModelPart().ProcessInfo.SetValue(KOA.HELMHOLTZ_INTEGRATED_FIELD, integrated_field)
|
|
37
|
+
|
|
38
|
+
#### Public user interface functions ####
|
|
39
|
+
def Initialize(self):
|
|
40
|
+
super().Initialize()
|
|
41
|
+
self.InitializeFilterModelPart()
|
|
42
|
+
|
|
43
|
+
def InitializeFilterModelPart(self):
|
|
44
|
+
self._SetSolverMode()
|
|
45
|
+
self._GetSolver().SetFilterRadius(self._GetSolver().GetFilterRadius())
|
|
46
|
+
self._SetHelmHoltzSourceMode()
|
|
47
|
+
|
|
48
|
+
def RunSolver(self):
|
|
49
|
+
self.InitializeSolutionStep()
|
|
50
|
+
self._GetSolver().Predict()
|
|
51
|
+
self._GetSolver().SolveSolutionStep()
|
|
52
|
+
self.FinalizeSolutionStep()
|
|
53
|
+
|
|
54
|
+
def FilterField(self, unfiltered_field: KM.TensorAdaptors.DoubleTensorAdaptor) -> KM.TensorAdaptors.DoubleTensorAdaptor:
|
|
55
|
+
|
|
56
|
+
self.__AssignTensorDataToNodalSource(unfiltered_field)
|
|
57
|
+
self._SetSolverMode(False)
|
|
58
|
+
self._SetHelmHoltzSourceMode(False)
|
|
59
|
+
self.RunSolver()
|
|
60
|
+
return self.__AssignNodalSolutionToTensorData()
|
|
61
|
+
|
|
62
|
+
def FilterIntegratedField(self, unfiltered_field: KM.TensorAdaptors.DoubleTensorAdaptor) -> KM.TensorAdaptors.DoubleTensorAdaptor:
|
|
63
|
+
|
|
64
|
+
self.__AssignTensorDataToNodalSource(unfiltered_field)
|
|
65
|
+
self._SetSolverMode(False)
|
|
66
|
+
self._SetHelmHoltzSourceMode(True)
|
|
67
|
+
self.RunSolver()
|
|
68
|
+
return self.__AssignNodalSolutionToTensorData()
|
|
69
|
+
|
|
70
|
+
def UnFilterField(self, filtered_field: KM.TensorAdaptors.DoubleTensorAdaptor) -> KM.TensorAdaptors.DoubleTensorAdaptor:
|
|
71
|
+
|
|
72
|
+
self.__AssignTensorDataToNodalSource(filtered_field)
|
|
73
|
+
self._SetSolverMode(True)
|
|
74
|
+
self._SetHelmHoltzSourceMode(False)
|
|
75
|
+
self.RunSolver()
|
|
76
|
+
return self.__AssignNodalSolutionToTensorData()
|
|
77
|
+
|
|
78
|
+
def AssignTensorDataToNodalSolution(self, data_exp: KM.TensorAdaptors.DoubleTensorAdaptor) -> None:
|
|
79
|
+
ta = KM.TensorAdaptors.DoubleTensorAdaptor(data_exp, copy=False)
|
|
80
|
+
if not isinstance(ta.GetContainer(), KM.NodesArray):
|
|
81
|
+
neighbours = self.__GetNeighbourEntities(data_exp)
|
|
82
|
+
ta = KOA.OptimizationUtils.MapContainerDataToNodalData(data_exp, neighbours.GetContainer())
|
|
83
|
+
KM.TensorAdaptors.HistoricalVariableTensorAdaptor(ta, self._GetSolver().GetSolvingVariable(), copy=False).StoreData()
|
|
84
|
+
|
|
85
|
+
def __AssignTensorDataToNodalSource(self, data_exp: KM.TensorAdaptors.DoubleTensorAdaptor):
|
|
86
|
+
self.__source_data = KM.TensorAdaptors.DoubleTensorAdaptor(data_exp)
|
|
87
|
+
|
|
88
|
+
# it is better to work on the model part of the data_exp rather than the internal
|
|
89
|
+
# model part created with ConnectivityPreserveModelPart because, then all the outputs will
|
|
90
|
+
# be written to one vtu file automatically, otherwise, there will be outputs distributed among
|
|
91
|
+
# the helmholtz model part and the original model part. This is safer because the helmholtz modelpart
|
|
92
|
+
# is created using the ConnectivityPreserveModeller which preserves the same nodes and condition/element
|
|
93
|
+
# data containers.
|
|
94
|
+
|
|
95
|
+
ta = KM.TensorAdaptors.DoubleTensorAdaptor(data_exp, copy=False)
|
|
96
|
+
if not isinstance(ta.GetContainer(), KM.NodesArray):
|
|
97
|
+
neighbours = self.__GetNeighbourEntities(data_exp)
|
|
98
|
+
ta = KOA.OptimizationUtils.MapContainerDataToNodalData(data_exp, neighbours.GetContainer())
|
|
99
|
+
KM.TensorAdaptors.VariableTensorAdaptor(ta, self._GetSolver().GetSourceVariable(), copy=False).StoreData()
|
|
100
|
+
|
|
101
|
+
def __AssignNodalSolutionToTensorData(self) -> KM.TensorAdaptors.DoubleTensorAdaptor:
|
|
102
|
+
if self.__source_data is None:
|
|
103
|
+
raise RuntimeError("The __AssignTensorDataToNodalSource should be called first.")
|
|
104
|
+
|
|
105
|
+
# it is better to work on the model part of the data_exp rather than the internal
|
|
106
|
+
# model part created with ConnectivityPreserveModelPart because, then all the outputs will
|
|
107
|
+
# be written to one vtu file automatically, otherwise, there will be outputs distributed among
|
|
108
|
+
# the helmholtz model part and the original model part. This is safer because the helmholtz modelpart
|
|
109
|
+
# is created using the ConnectivityPreserveModeller which preserves the same nodes and condition/element
|
|
110
|
+
# data containers.
|
|
111
|
+
neighbours = self.__GetNeighbourEntities(self.__source_data)
|
|
112
|
+
solution = KM.TensorAdaptors.HistoricalVariableTensorAdaptor(neighbours.GetContainer(), self._GetSolver().GetSolvingVariable())
|
|
113
|
+
solution.CollectData()
|
|
114
|
+
|
|
115
|
+
if isinstance(self.__source_data.GetContainer(), KM.NodesArray):
|
|
116
|
+
return KM.TensorAdaptors.DoubleTensorAdaptor(solution, copy=False)
|
|
117
|
+
else:
|
|
118
|
+
return KOA.OptimizationUtils.MapNodalDataToContainerData(solution, self.__source_data.GetContainer(), neighbours)
|
|
119
|
+
|
|
120
|
+
def __GetNeighbourEntities(self, data_exp: KM.TensorAdaptors.DoubleTensorAdaptor) -> KM.TensorAdaptors.IntTensorAdaptor:
|
|
121
|
+
# following makes the number of neighbours computation to be executed once
|
|
122
|
+
# per given container, hence if the mesh element/connectivity changes
|
|
123
|
+
# this computation needs to be redone. Especially in the case if MMG is
|
|
124
|
+
# used for re-meshing.
|
|
125
|
+
key = data_exp.GetContainer()
|
|
126
|
+
if key not in self.__neighbour_entities.keys():
|
|
127
|
+
if not isinstance(key, KM.NodesArray):
|
|
128
|
+
if isinstance(data_exp.GetContainer(), KM.ConditionsArray):
|
|
129
|
+
self.__neighbour_entities[key] = KM.TensorAdaptors.Utils.CreateNodalConditionNeighboursCountTensorAdaptor(self._GetSolver().GetComputingModelPart())
|
|
130
|
+
elif isinstance(data_exp.GetContainer(), KM.ElementsArray):
|
|
131
|
+
self.__neighbour_entities[key] = KM.TensorAdaptors.Utils.CreateNodalElementNeighboursCountTensorAdaptor(self._GetSolver().GetComputingModelPart())
|
|
132
|
+
else:
|
|
133
|
+
raise RuntimeError(f"Unsupported tensor adaptor container. Only supports neighbour computation for condition or element containers [ tensor adaptor = {data_exp} ]." )
|
|
134
|
+
else:
|
|
135
|
+
ta = KM.TensorAdaptors.IntTensorAdaptor(key, KM.IntNDData([len(key)]), copy=False)
|
|
136
|
+
ta.data[:] = 1
|
|
137
|
+
self.__neighbour_entities[key] = ta
|
|
138
|
+
|
|
139
|
+
return self.__neighbour_entities[key]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Importing the Kratos Library
|
|
2
|
+
import KratosMultiphysics as KM
|
|
3
|
+
|
|
4
|
+
# Import applications
|
|
5
|
+
import KratosMultiphysics.OptimizationApplication as KOA
|
|
6
|
+
|
|
7
|
+
# Import baseclass
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.filtering.helmholtz_solver_base import HelmholtzSolverBase
|
|
9
|
+
|
|
10
|
+
def CreateSolver(model: KM.Model, custom_settings: KM.Parameters):
|
|
11
|
+
return HelmholtzScalarSolver(model, custom_settings)
|
|
12
|
+
|
|
13
|
+
class HelmholtzScalarSolver(HelmholtzSolverBase):
|
|
14
|
+
def GetSolvingVariable(self) -> KM.DoubleVariable:
|
|
15
|
+
return KOA.HELMHOLTZ_SCALAR
|
|
16
|
+
|
|
17
|
+
def _GetComputingModelPartName(self) -> str:
|
|
18
|
+
return self.GetOriginModelPart().FullName().replace(".", "_") + "_helmholtz_scalar"
|
|
19
|
+
|
|
20
|
+
def SetFilterRadius(self, filter_radius: float) -> None:
|
|
21
|
+
self.GetComputingModelPart().ProcessInfo.SetValue(KOA.HELMHOLTZ_RADIUS, filter_radius)
|
|
22
|
+
|
|
23
|
+
def _FillComputingModelPart(self) -> None:
|
|
24
|
+
if self.GetOriginModelPart().NumberOfElements() > 0:
|
|
25
|
+
# here we have to replace the elements, while keeping the
|
|
26
|
+
# geometries the same. Hence using the ConnectivityPreserveModeller
|
|
27
|
+
container = self.GetOriginModelPart().Elements
|
|
28
|
+
num_nodes = self._GetContainerTypeNumNodes(container)
|
|
29
|
+
if self._IsSurfaceContainer(container):
|
|
30
|
+
KM.ConnectivityPreserveModeler().GenerateModelPart(self.GetOriginModelPart(), self.GetComputingModelPart(), f"HelmholtzSurfaceElement3D{num_nodes}N")
|
|
31
|
+
else:
|
|
32
|
+
KM.ConnectivityPreserveModeler().GenerateModelPart(self.GetOriginModelPart(), self.GetComputingModelPart(), f"HelmholtzSolidElement3D{num_nodes}N")
|
|
33
|
+
elif self.GetOriginModelPart().NumberOfConditions() > 0:
|
|
34
|
+
# here we have conditions in the origin model part. Now we have to create elements using
|
|
35
|
+
# the geometries of the conditions. There cannot be volume conditions in Kratos, therefore,
|
|
36
|
+
# there can be only surface conditions, hence only required to create surface elements.
|
|
37
|
+
KOA.OptAppModelPartUtils.GenerateModelPart(self.GetOriginModelPart().Conditions, self.GetComputingModelPart(), f"HelmholtzSurfaceElement3D{self._GetContainerTypeNumNodes(self.GetOriginModelPart().Conditions)}N")
|
|
38
|
+
else:
|
|
39
|
+
raise RuntimeError(f"No elements or conditions found in {self.GetOriginModelPart()}.")
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Importing the Kratos Library
|
|
2
|
+
import KratosMultiphysics as KM
|
|
3
|
+
import KratosMultiphysics.OptimizationApplication as KOA
|
|
4
|
+
|
|
5
|
+
# Import baseclass
|
|
6
|
+
from KratosMultiphysics.OptimizationApplication.filtering.helmholtz_solver_base import HelmholtzSolverBase
|
|
7
|
+
|
|
8
|
+
def CreateSolver(model: KM.Model, custom_settings: KM.Parameters):
|
|
9
|
+
return HelmholtzShapeSolver(model, custom_settings)
|
|
10
|
+
|
|
11
|
+
class HelmholtzShapeSolver(HelmholtzSolverBase):
|
|
12
|
+
def GetSolvingVariable(self) -> KM.Array1DVariable3:
|
|
13
|
+
return KOA.HELMHOLTZ_VECTOR
|
|
14
|
+
|
|
15
|
+
def _GetComputingModelPartName(self) -> str:
|
|
16
|
+
return self.GetOriginModelPart().FullName().replace(".", "_") + "_helmholtz_shape"
|
|
17
|
+
|
|
18
|
+
def SetFilterRadius(self, filter_radius: float) -> None:
|
|
19
|
+
self.GetComputingModelPart().ProcessInfo.SetValue(KOA.HELMHOLTZ_RADIUS, filter_radius)
|
|
20
|
+
KOA.ImplicitFilterUtils.SetBulkRadiusForShapeFiltering(self.GetComputingModelPart())
|
|
21
|
+
|
|
22
|
+
def _FillComputingModelPart(self) -> None:
|
|
23
|
+
if self.GetOriginModelPart().NumberOfElements() > 0:
|
|
24
|
+
# here we have to replace the elements, while keeping the
|
|
25
|
+
# geometries the same. Hence using the ConnectivityPreserveModeller
|
|
26
|
+
container = self.GetOriginModelPart().Elements
|
|
27
|
+
num_nodes = self._GetContainerTypeNumNodes(container)
|
|
28
|
+
if self._IsSurfaceContainer(container):
|
|
29
|
+
KM.ConnectivityPreserveModeler().GenerateModelPart(self.GetOriginModelPart(), self.GetComputingModelPart(), f"HelmholtzVectorSurfaceElement3D{num_nodes}N")
|
|
30
|
+
else:
|
|
31
|
+
raise RuntimeError(f"Helmholtz shape solver found volume elements in {self.GetOriginModelPart().FullName()}. It can work with only either surface elements or surface conditions.")
|
|
32
|
+
elif self.GetOriginModelPart().NumberOfConditions() > 0:
|
|
33
|
+
# we have only conditions in the origin model part. Since this solver is used to
|
|
34
|
+
# do the mesh motion as well, then we need to work on the origin model part's root model part.
|
|
35
|
+
# here also we can use the connectivity preserve modeller.
|
|
36
|
+
element_num_nodes = self._GetContainerTypeNumNodes(self.GetOriginRootModelPart().Elements)
|
|
37
|
+
KM.ConnectivityPreserveModeler().GenerateModelPart(self.GetOriginRootModelPart(), self.GetComputingModelPart(), f"HelmholtzSolidShapeElement3D{element_num_nodes}N", f"HelmholtzSurfaceShapeCondition3D{self._GetContainerTypeNumNodes(self.GetOriginRootModelPart().Conditions)}N")
|
|
38
|
+
|
|
39
|
+
# now we have to add the material properties
|
|
40
|
+
properties = KM.Parameters("""{
|
|
41
|
+
"properties" : [
|
|
42
|
+
{
|
|
43
|
+
"model_part_name": \"""" + self.GetComputingModelPart().FullName() + """\",
|
|
44
|
+
"properties_id" : """ + str(self.GetComputingModelPart().NumberOfProperties() + 1) + """,
|
|
45
|
+
"Material": {
|
|
46
|
+
"constitutive_law": {
|
|
47
|
+
"name": "HelmholtzJacobianStiffened3D"
|
|
48
|
+
},
|
|
49
|
+
"Variables": {
|
|
50
|
+
"POISSON_RATIO": 0.3
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}""")
|
|
56
|
+
KM.ReadMaterialsUtility(self.model).ReadMaterials(properties)
|
|
57
|
+
|
|
58
|
+
# now we do the tetrahedral mesh orientation check and parent element
|
|
59
|
+
# assignment.
|
|
60
|
+
if element_num_nodes == 4:
|
|
61
|
+
tmoc = KM.TetrahedralMeshOrientationCheck
|
|
62
|
+
flags = (tmoc.COMPUTE_NODAL_NORMALS).AsFalse() | (tmoc.COMPUTE_CONDITION_NORMALS).AsFalse() | tmoc.ASSIGN_NEIGHBOUR_ELEMENTS_TO_CONDITIONS
|
|
63
|
+
KM.TetrahedralMeshOrientationCheck(self.GetComputingModelPart(), False, flags).Execute()
|
|
64
|
+
else:
|
|
65
|
+
raise RuntimeError("Helmholtz shape solver only supports tetrahedral elements.")
|
|
66
|
+
else:
|
|
67
|
+
raise RuntimeError(f"No elements or conditions found in {self.GetOriginModelPart()}.")
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import typing
|
|
3
|
+
import numpy
|
|
4
|
+
|
|
5
|
+
# Importing the Kratos Library
|
|
6
|
+
import KratosMultiphysics
|
|
7
|
+
import KratosMultiphysics.OptimizationApplication as KOA
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.utilities.union_utilities import SupportedSensitivityFieldVariableTypes
|
|
9
|
+
|
|
10
|
+
# Other imports
|
|
11
|
+
from KratosMultiphysics.python_solver import PythonSolver
|
|
12
|
+
from KratosMultiphysics.python_linear_solver_factory import ConstructSolver
|
|
13
|
+
|
|
14
|
+
class HelmholtzSolverBase(PythonSolver):
|
|
15
|
+
"""The base class for Helmholtz-based solvers.
|
|
16
|
+
|
|
17
|
+
This class defines the user interface to Helmholtz solvers.
|
|
18
|
+
|
|
19
|
+
"""
|
|
20
|
+
def __init__(self, model: KratosMultiphysics.Model, custom_settings: KratosMultiphysics.Parameters):
|
|
21
|
+
self._validate_settings_in_baseclass=True # To be removed eventually
|
|
22
|
+
super().__init__(model, custom_settings)
|
|
23
|
+
|
|
24
|
+
# Either retrieve the model part from the model or create a new one
|
|
25
|
+
self.filtering_model_part_name = self.settings["model_part_name"].GetString()
|
|
26
|
+
|
|
27
|
+
if self.filtering_model_part_name == "":
|
|
28
|
+
raise Exception('Please provide the model part name as the "model_part_name" (string) parameter!')
|
|
29
|
+
|
|
30
|
+
# the filtering_model_part_name can be a sub model part. Hence we need the main model part
|
|
31
|
+
# for variable and dof addition.
|
|
32
|
+
root_model_part_name = self.filtering_model_part_name.split(".")[0]
|
|
33
|
+
if self.model.HasModelPart(root_model_part_name):
|
|
34
|
+
self.origin_root_model_part = self.model.GetModelPart(root_model_part_name)
|
|
35
|
+
else:
|
|
36
|
+
self.origin_root_model_part = model.CreateModelPart(root_model_part_name)
|
|
37
|
+
|
|
38
|
+
domain_size = self.settings["domain_size"].GetInt()
|
|
39
|
+
if domain_size == -1:
|
|
40
|
+
raise Exception('Please provide the domain size as the "domain_size" (int) parameter!')
|
|
41
|
+
self.origin_root_model_part.ProcessInfo.SetValue(KratosMultiphysics.DOMAIN_SIZE, domain_size)
|
|
42
|
+
|
|
43
|
+
# we don't create the helmholtz model part here, because
|
|
44
|
+
# we need to have unique model parts for different filtering variable types
|
|
45
|
+
# hence, it cannot be determined at this point.
|
|
46
|
+
self.helmholtz_model_part: 'typing.Optional[KratosMultiphysics.ModelPart]' = None
|
|
47
|
+
|
|
48
|
+
# Get the filter radius
|
|
49
|
+
self.filter_radius = self.settings["filter_radius"].GetDouble()
|
|
50
|
+
|
|
51
|
+
KratosMultiphysics.Logger.PrintInfo("::[HelmholtzSolverBase]:: Construction finished")
|
|
52
|
+
|
|
53
|
+
@classmethod
|
|
54
|
+
def GetDefaultParameters(cls) -> KratosMultiphysics.Parameters:
|
|
55
|
+
this_defaults = KratosMultiphysics.Parameters("""{
|
|
56
|
+
"solver_type" : "helmholtz_solver_base",
|
|
57
|
+
"domain_size" : -1,
|
|
58
|
+
"filter_type" : "",
|
|
59
|
+
"filter_radius" : 0.0,
|
|
60
|
+
"model_part_name" : "",
|
|
61
|
+
"time_stepping" : {
|
|
62
|
+
"time_step" : 1.0
|
|
63
|
+
},
|
|
64
|
+
"model_import_settings" : {
|
|
65
|
+
"input_type" : "mdpa",
|
|
66
|
+
"input_filename" : "unknown_name"
|
|
67
|
+
},
|
|
68
|
+
"linear_solver_settings" : {
|
|
69
|
+
"solver_type" : "amgcl",
|
|
70
|
+
"smoother_type":"ilu0",
|
|
71
|
+
"krylov_type": "gmres",
|
|
72
|
+
"coarsening_type": "aggregation",
|
|
73
|
+
"max_iteration": 200,
|
|
74
|
+
"provide_coordinates": false,
|
|
75
|
+
"gmres_krylov_space_dimension": 100,
|
|
76
|
+
"verbosity" : 0,
|
|
77
|
+
"tolerance": 1e-7,
|
|
78
|
+
"scaling": false,
|
|
79
|
+
"block_size": 1,
|
|
80
|
+
"use_block_matrices_if_possible" : true,
|
|
81
|
+
"coarse_enough" : 5000
|
|
82
|
+
},
|
|
83
|
+
"material_properties": {}
|
|
84
|
+
}""")
|
|
85
|
+
this_defaults.AddMissingParameters(super().GetDefaultParameters())
|
|
86
|
+
return this_defaults
|
|
87
|
+
|
|
88
|
+
#### Public user interface functions ####
|
|
89
|
+
|
|
90
|
+
@abc.abstractmethod
|
|
91
|
+
def _GetComputingModelPartName(self) -> str:
|
|
92
|
+
pass
|
|
93
|
+
|
|
94
|
+
@abc.abstractmethod
|
|
95
|
+
def _FillComputingModelPart(self) -> None:
|
|
96
|
+
pass
|
|
97
|
+
|
|
98
|
+
@abc.abstractmethod
|
|
99
|
+
def GetSolvingVariable(self) -> SupportedSensitivityFieldVariableTypes:
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
@abc.abstractmethod
|
|
103
|
+
def SetFilterRadius(self, filter_radius: float) -> None:
|
|
104
|
+
pass
|
|
105
|
+
|
|
106
|
+
def AddVariables(self) -> None:
|
|
107
|
+
self.GetOriginRootModelPart().AddNodalSolutionStepVariable(self.GetSolvingVariable())
|
|
108
|
+
KratosMultiphysics.Logger.PrintInfo("::[HelmholtzSolverBase]:: Variables ADDED.")
|
|
109
|
+
|
|
110
|
+
def AddDofs(self) -> None:
|
|
111
|
+
if isinstance(self.GetSolvingVariable(), KratosMultiphysics.DoubleVariable):
|
|
112
|
+
KratosMultiphysics.VariableUtils().AddDof(self.GetSolvingVariable(), self.GetOriginRootModelPart())
|
|
113
|
+
elif isinstance(self.GetSolvingVariable(), KratosMultiphysics.Array1DVariable3):
|
|
114
|
+
KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.KratosGlobals.GetVariable(f"{self.GetSolvingVariable().Name()}_X"), self.GetOriginRootModelPart())
|
|
115
|
+
KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.KratosGlobals.GetVariable(f"{self.GetSolvingVariable().Name()}_Y"), self.GetOriginRootModelPart())
|
|
116
|
+
KratosMultiphysics.VariableUtils().AddDof(KratosMultiphysics.KratosGlobals.GetVariable(f"{self.GetSolvingVariable().Name()}_Z"), self.GetOriginRootModelPart())
|
|
117
|
+
else:
|
|
118
|
+
raise RuntimeError("Unsupported solving variable type.")
|
|
119
|
+
KratosMultiphysics.Logger.PrintInfo("::[HelmholtzSolverBase]:: DOFs ADDED.")
|
|
120
|
+
|
|
121
|
+
def AdvanceInTime(self, current_time: float) -> float:
|
|
122
|
+
dt = self.settings["time_stepping"]["time_step"].GetDouble()
|
|
123
|
+
new_time = current_time + dt
|
|
124
|
+
self.helmholtz_model_part.ProcessInfo[KratosMultiphysics.STEP] += 1
|
|
125
|
+
self.helmholtz_model_part.CloneTimeStep(new_time)
|
|
126
|
+
|
|
127
|
+
return new_time
|
|
128
|
+
|
|
129
|
+
def Initialize(self) -> None:
|
|
130
|
+
self._GetSolutionStrategy().Initialize()
|
|
131
|
+
neighbours_ta_int = KratosMultiphysics.TensorAdaptors.Utils.CreateNodalElementNeighboursCountTensorAdaptor(self.helmholtz_model_part)
|
|
132
|
+
|
|
133
|
+
writing_ta = KratosMultiphysics.TensorAdaptors.VariableTensorAdaptor(neighbours_ta_int.GetContainer(), KratosMultiphysics.NUMBER_OF_NEIGHBOUR_ELEMENTS)
|
|
134
|
+
writing_ta.SetData(neighbours_ta_int.data)
|
|
135
|
+
writing_ta.StoreData()
|
|
136
|
+
KratosMultiphysics.Logger.PrintInfo("::[HelmholtzSolverBase]:: Finished initialization.")
|
|
137
|
+
|
|
138
|
+
def InitializeSolutionStep(self) -> None:
|
|
139
|
+
self._GetSolutionStrategy().InitializeSolutionStep()
|
|
140
|
+
|
|
141
|
+
def FinalizeSolutionStep(self) -> None:
|
|
142
|
+
self._GetSolutionStrategy().FinalizeSolutionStep()
|
|
143
|
+
|
|
144
|
+
def Predict(self) -> None:
|
|
145
|
+
self._GetSolutionStrategy().Predict()
|
|
146
|
+
|
|
147
|
+
def SolveSolutionStep(self) -> None:
|
|
148
|
+
is_converged = bool(self._GetSolutionStrategy().Solve())
|
|
149
|
+
return is_converged
|
|
150
|
+
|
|
151
|
+
def SetEchoLevel(self, level: int) -> None:
|
|
152
|
+
self._GetSolutionStrategy().SetEchoLevel(level)
|
|
153
|
+
|
|
154
|
+
def GetEchoLevel(self) -> int:
|
|
155
|
+
self._GetSolutionStrategy().GetEchoLevel()
|
|
156
|
+
|
|
157
|
+
def Clear(self) -> None:
|
|
158
|
+
self._GetSolutionStrategy().Clear()
|
|
159
|
+
|
|
160
|
+
def ImportModelPart(self) -> None:
|
|
161
|
+
self._ImportModelPart(self.origin_root_model_part, self.settings["model_import_settings"])
|
|
162
|
+
|
|
163
|
+
def GetComputingModelPart(self) -> KratosMultiphysics.ModelPart:
|
|
164
|
+
return self.helmholtz_model_part
|
|
165
|
+
|
|
166
|
+
def GetOriginRootModelPart(self) -> KratosMultiphysics.ModelPart:
|
|
167
|
+
return self.origin_root_model_part
|
|
168
|
+
|
|
169
|
+
def GetOriginModelPart(self) -> KratosMultiphysics.ModelPart:
|
|
170
|
+
return self.model[self.filtering_model_part_name]
|
|
171
|
+
|
|
172
|
+
def GetFilterRadius(self) -> str:
|
|
173
|
+
return self.filter_radius
|
|
174
|
+
|
|
175
|
+
#### Protected functions ####
|
|
176
|
+
|
|
177
|
+
#### Specific internal functions ####
|
|
178
|
+
|
|
179
|
+
def _GetScheme(self):
|
|
180
|
+
if not hasattr(self, '_solution_scheme'):
|
|
181
|
+
self._solution_scheme = self._CreateScheme()
|
|
182
|
+
return self._solution_scheme
|
|
183
|
+
|
|
184
|
+
def _GetLinearSolver(self):
|
|
185
|
+
if not hasattr(self, '_linear_solver'):
|
|
186
|
+
self._linear_solver = self._CreateLinearSolver()
|
|
187
|
+
return self._linear_solver
|
|
188
|
+
|
|
189
|
+
def _GetBuilderAndSolver(self):
|
|
190
|
+
if not hasattr(self, '_builder_and_solver'):
|
|
191
|
+
self._builder_and_solver = self._CreateBuilderAndSolver()
|
|
192
|
+
return self._builder_and_solver
|
|
193
|
+
|
|
194
|
+
def _GetSolutionStrategy(self):
|
|
195
|
+
if not hasattr(self, '_solution_strategy'):
|
|
196
|
+
self._solution_strategy = self._CreateSolutionStrategy()
|
|
197
|
+
return self._solution_strategy
|
|
198
|
+
|
|
199
|
+
def _CreateBuilderAndSolver(self):
|
|
200
|
+
linear_solver = self._GetLinearSolver()
|
|
201
|
+
return KratosMultiphysics.ResidualBasedBlockBuilderAndSolver(linear_solver)
|
|
202
|
+
|
|
203
|
+
def _CreateLinearSolver(self):
|
|
204
|
+
return ConstructSolver(self.settings["linear_solver_settings"])
|
|
205
|
+
|
|
206
|
+
def _CreateScheme(self):
|
|
207
|
+
return KratosMultiphysics.ResidualBasedIncrementalUpdateStaticScheme()
|
|
208
|
+
|
|
209
|
+
def _CreateSolutionStrategy(self):
|
|
210
|
+
computing_model_part = self.GetComputingModelPart()
|
|
211
|
+
scheme = self._GetScheme()
|
|
212
|
+
builder_and_solver = self._GetBuilderAndSolver()
|
|
213
|
+
return KratosMultiphysics.ResidualBasedLinearStrategy(computing_model_part,
|
|
214
|
+
scheme,
|
|
215
|
+
builder_and_solver,
|
|
216
|
+
False,
|
|
217
|
+
False,
|
|
218
|
+
False,
|
|
219
|
+
False)
|
|
220
|
+
|
|
221
|
+
def _GetContainerTypeNumNodes(self, container: 'typing.Union[KratosMultiphysics.ConditionsArray, KratosMultiphysics.ElementsArray]') -> int:
|
|
222
|
+
num_nodes = None
|
|
223
|
+
for cont_type in container:
|
|
224
|
+
return len(cont_type.GetNodes())
|
|
225
|
+
return num_nodes
|
|
226
|
+
|
|
227
|
+
def _IsSurfaceContainer(self, container: 'typing.Union[KratosMultiphysics.ConditionsArray, KratosMultiphysics.ElementsArray]') -> bool:
|
|
228
|
+
return any(map(lambda x: x.GetGeometry().WorkingSpaceDimension() != x.GetGeometry().LocalSpaceDimension(), container))
|
|
229
|
+
|
|
230
|
+
def GetSourceVariable(self) -> SupportedSensitivityFieldVariableTypes:
|
|
231
|
+
if isinstance(self.GetSolvingVariable(), KratosMultiphysics.DoubleVariable):
|
|
232
|
+
return KOA.HELMHOLTZ_SCALAR_SOURCE
|
|
233
|
+
elif isinstance(self.GetSolvingVariable(), KratosMultiphysics.Array1DVariable3):
|
|
234
|
+
return KOA.HELMHOLTZ_VECTOR_SOURCE
|
|
235
|
+
else:
|
|
236
|
+
raise RuntimeError("Unsupported solving variable.")
|
|
237
|
+
|
|
238
|
+
def PrepareModelPart(self) -> str:
|
|
239
|
+
computing_model_part_name = self._GetComputingModelPartName()
|
|
240
|
+
|
|
241
|
+
if self.model.HasModelPart(computing_model_part_name):
|
|
242
|
+
# a same model part with same entities were already created by some other filter
|
|
243
|
+
# hence reusing it
|
|
244
|
+
self.helmholtz_model_part = self.model[computing_model_part_name]
|
|
245
|
+
else:
|
|
246
|
+
# the model part needs to be created.
|
|
247
|
+
self.helmholtz_model_part = self.model.CreateModelPart(computing_model_part_name)
|
|
248
|
+
KOA.OptimizationUtils.SetSolutionStepVariablesList(self.helmholtz_model_part, self.GetOriginRootModelPart())
|
|
249
|
+
|
|
250
|
+
# now fill with the appropriate elements and conditions
|
|
251
|
+
self._FillComputingModelPart()
|
|
252
|
+
|
|
253
|
+
self.__IncrementModelPartUsageCounter()
|
|
254
|
+
|
|
255
|
+
def __IncrementModelPartUsageCounter(self) -> None:
|
|
256
|
+
# we increase the usage number of filters using the model part.
|
|
257
|
+
# this is required to know whether we need to apply boundary conditions
|
|
258
|
+
# every time filter is used so that we don't mix-up different BCs from
|
|
259
|
+
# different filters and mesh motion solvers
|
|
260
|
+
|
|
261
|
+
# in here, the origin model part and its parents are updated. This is because,
|
|
262
|
+
# the computing model part shares nodes with the origin model part.
|
|
263
|
+
def increase_counter(model_part: KratosMultiphysics.ModelPart) -> None:
|
|
264
|
+
if not model_part.Has(KOA.NUMBER_OF_SOLVERS_USING_NODES):
|
|
265
|
+
model_part[KOA.NUMBER_OF_SOLVERS_USING_NODES] = 0
|
|
266
|
+
model_part[KOA.NUMBER_OF_SOLVERS_USING_NODES] += 1
|
|
267
|
+
|
|
268
|
+
current_model_part = self.GetOriginModelPart()
|
|
269
|
+
increase_counter(current_model_part)
|
|
270
|
+
|
|
271
|
+
# now increase the usage counter in all parent model parts.
|
|
272
|
+
while current_model_part != current_model_part.GetParentModelPart():
|
|
273
|
+
current_model_part = current_model_part.GetParentModelPart()
|
|
274
|
+
increase_counter(current_model_part)
|
|
275
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Importing the Kratos Library
|
|
2
|
+
import KratosMultiphysics as KM
|
|
3
|
+
|
|
4
|
+
# Import applications
|
|
5
|
+
import KratosMultiphysics.OptimizationApplication as KOA
|
|
6
|
+
|
|
7
|
+
# Import baseclass
|
|
8
|
+
from KratosMultiphysics.OptimizationApplication.filtering.helmholtz_solver_base import HelmholtzSolverBase
|
|
9
|
+
|
|
10
|
+
def CreateSolver(model: KM.Model, custom_settings: KM.Parameters):
|
|
11
|
+
return HelmholtzVectorSolver(model, custom_settings)
|
|
12
|
+
|
|
13
|
+
class HelmholtzVectorSolver(HelmholtzSolverBase):
|
|
14
|
+
def GetSolvingVariable(self) -> KM.Array1DVariable3:
|
|
15
|
+
return KOA.HELMHOLTZ_VECTOR
|
|
16
|
+
|
|
17
|
+
def _GetComputingModelPartName(self) -> str:
|
|
18
|
+
return self.GetOriginModelPart().FullName().replace(".", "_") + "_helmholtz_vector"
|
|
19
|
+
|
|
20
|
+
def SetFilterRadius(self, filter_radius: float) -> None:
|
|
21
|
+
self.GetComputingModelPart().ProcessInfo.SetValue(KOA.HELMHOLTZ_RADIUS, filter_radius)
|
|
22
|
+
|
|
23
|
+
def _FillComputingModelPart(self) -> None:
|
|
24
|
+
if self.GetOriginModelPart().NumberOfElements() > 0:
|
|
25
|
+
# here we have to replace the elements, while keeping the
|
|
26
|
+
# geometries the same. Hence using the ConnectivityPreserveModeller
|
|
27
|
+
container = self.GetOriginModelPart().Elements
|
|
28
|
+
num_nodes = self._GetContainerTypeNumNodes(container)
|
|
29
|
+
if self._IsSurfaceContainer(container):
|
|
30
|
+
KM.ConnectivityPreserveModeler().GenerateModelPart(self.GetOriginModelPart(), self.GetComputingModelPart(), f"HelmholtzVectorSurfaceElement3D{num_nodes}N")
|
|
31
|
+
else:
|
|
32
|
+
KM.ConnectivityPreserveModeler().GenerateModelPart(self.GetOriginModelPart(), self.GetComputingModelPart(), f"HelmholtzVectorSolidElement3D{num_nodes}N")
|
|
33
|
+
elif self.GetOriginModelPart().NumberOfConditions() > 0:
|
|
34
|
+
# here we have conditions in the origin model part. Now we have to create elements using
|
|
35
|
+
# the geometries of the conditions. There cannot be volume conditions in Kratos, therefore,
|
|
36
|
+
# there can be only surface conditions, hence only required to create surface elements.
|
|
37
|
+
KOA.OptAppModelPartUtils.GenerateModelPart(self.GetOriginModelPart().Conditions, self.GetComputingModelPart(), f"HelmholtzVectorSurfaceElement3D{self._GetContainerTypeNumNodes(self.GetOriginModelPart().Conditions)}N")
|
|
38
|
+
else:
|
|
39
|
+
raise RuntimeError(f"No elements or conditions found in {self.GetOriginModelPart()}.")
|