diff --git a/applications/ContactStructuralMechanicsApplication/python_scripts/contact_structural_mechanics_implicit_dynamic_solver.py b/applications/ContactStructuralMechanicsApplication/python_scripts/contact_structural_mechanics_implicit_dynamic_solver.py index dcf74c1af461..6727bd90956f 100644 --- a/applications/ContactStructuralMechanicsApplication/python_scripts/contact_structural_mechanics_implicit_dynamic_solver.py +++ b/applications/ContactStructuralMechanicsApplication/python_scripts/contact_structural_mechanics_implicit_dynamic_solver.py @@ -137,9 +137,11 @@ def _CreateLinearSolver(self): def _CreateBuilderAndSolver(self): if self.contact_settings["mortar_type"].GetString() != "": linear_solver = self._GetLinearSolver() - if self.settings["builder_and_solver_settings"]["use_block_builder"].GetBool(): + builder_and_solver_type: str = self.settings["builder_and_solver_settings"]["type"].GetString() + + if builder_and_solver_type == "block": builder_and_solver = CSMA.ContactResidualBasedBlockBuilderAndSolver(linear_solver) - else: + elif builder_and_solver_type == "elimination": # We use the elimination builder and solver if self.settings["multi_point_constraints_used"].GetBool(): if (self.GetComputingModelPart().NumberOfMasterSlaveConstraints() > 0): @@ -147,6 +149,8 @@ def _CreateBuilderAndSolver(self): builder_and_solver = CSMA.ContactResidualBasedEliminationBuilderAndSolverWithConstraints(linear_solver) else: builder_and_solver = CSMA.ContactResidualBasedEliminationBuilderAndSolver(linear_solver) + else: + raise ValueError(f"Unsupported builder and solver type: {builder_and_solver_type}") else: builder_and_solver = super()._CreateBuilderAndSolver() diff --git a/applications/ContactStructuralMechanicsApplication/python_scripts/contact_structural_mechanics_static_solver.py b/applications/ContactStructuralMechanicsApplication/python_scripts/contact_structural_mechanics_static_solver.py index 0c6b1870eaf1..416ad196850b 100644 --- a/applications/ContactStructuralMechanicsApplication/python_scripts/contact_structural_mechanics_static_solver.py +++ b/applications/ContactStructuralMechanicsApplication/python_scripts/contact_structural_mechanics_static_solver.py @@ -138,7 +138,9 @@ def _CreateLinearSolver(self): def _CreateBuilderAndSolver(self): if self.contact_settings["mortar_type"].GetString() != "": linear_solver = self._GetLinearSolver() - if self.settings["builder_and_solver_settings"]["use_block_builder"].GetBool(): + builder_and_solver_type: str = self.settings["builder_and_solver_settings"]["type"].GetString() + + if builder_and_solver_type == "block": builder_and_solver = CSMA.ContactResidualBasedBlockBuilderAndSolver(linear_solver) else: # We use the elimination builder and solver diff --git a/applications/ContactStructuralMechanicsApplication/tests/ALM_frictionless_contact_test_2D/hyper_simple_patch_test_with_elimination_parameters.json b/applications/ContactStructuralMechanicsApplication/tests/ALM_frictionless_contact_test_2D/hyper_simple_patch_test_with_elimination_parameters.json index 96c0a972f446..faa8c12ea4c9 100755 --- a/applications/ContactStructuralMechanicsApplication/tests/ALM_frictionless_contact_test_2D/hyper_simple_patch_test_with_elimination_parameters.json +++ b/applications/ContactStructuralMechanicsApplication/tests/ALM_frictionless_contact_test_2D/hyper_simple_patch_test_with_elimination_parameters.json @@ -28,7 +28,7 @@ "time_step" : 1.1 }, "builder_and_solver_settings" : { - "use_block_builder" : false + "type" : "elimination" }, "clear_storage" : true, "compute_reactions" : false, diff --git a/applications/ContactStructuralMechanicsApplication/tests/ALM_frictionless_contact_test_2D/hyper_simple_patch_test_with_elimination_with_constraints_parameters.json b/applications/ContactStructuralMechanicsApplication/tests/ALM_frictionless_contact_test_2D/hyper_simple_patch_test_with_elimination_with_constraints_parameters.json index ccce94990594..0106bb07330c 100644 --- a/applications/ContactStructuralMechanicsApplication/tests/ALM_frictionless_contact_test_2D/hyper_simple_patch_test_with_elimination_with_constraints_parameters.json +++ b/applications/ContactStructuralMechanicsApplication/tests/ALM_frictionless_contact_test_2D/hyper_simple_patch_test_with_elimination_with_constraints_parameters.json @@ -28,7 +28,7 @@ "time_step" : 1.1 }, "builder_and_solver_settings" : { - "use_block_builder" : false + "type" : "elimination" }, "clear_storage" : true, "compute_reactions" : false, diff --git a/applications/StructuralMechanicsApplication/python_scripts/structural_mechanics_custom_scipy_base_solver.py b/applications/StructuralMechanicsApplication/python_scripts/structural_mechanics_custom_scipy_base_solver.py index 4831c4eff767..ab60e1ce4102 100644 --- a/applications/StructuralMechanicsApplication/python_scripts/structural_mechanics_custom_scipy_base_solver.py +++ b/applications/StructuralMechanicsApplication/python_scripts/structural_mechanics_custom_scipy_base_solver.py @@ -60,7 +60,8 @@ def _CreateLinearSolver(self): return KratosMultiphysics.LinearSolver() def _CreateSolutionStrategy(self): - if self.settings["builder_and_solver_settings"]["use_block_builder"].GetBool(): + builder_and_solver_type: str = self.settings["builder_and_solver_settings"]["type"].GetString() + if builder_and_solver_type == "block" or builder_and_solver_type == "block_lagrange": warn_msg = "In case an eigenvalue problem is computed an elimantion builder shall be used to ensure boundary conditions are applied correctly!" KratosMultiphysics.Logger.PrintWarning("CustomScipyBaseSolver", warn_msg) diff --git a/applications/StructuralMechanicsApplication/python_scripts/structural_mechanics_solver.py b/applications/StructuralMechanicsApplication/python_scripts/structural_mechanics_solver.py index 16706ca19bd8..cb7e13a2ce6b 100755 --- a/applications/StructuralMechanicsApplication/python_scripts/structural_mechanics_solver.py +++ b/applications/StructuralMechanicsApplication/python_scripts/structural_mechanics_solver.py @@ -43,39 +43,7 @@ class MechanicalSolver(PythonSolver): settings -- Kratos parameters containing solver settings. """ def __init__(self, model, custom_settings): - old_unused_settings = [ - "use_computing_model_part", - "computing_model_part_name", - "problem_domain_sub_model_part_list", - "processes_sub_model_part_list" - ] - - for old_setting in old_unused_settings: - if custom_settings.Has(old_setting): - KratosMultiphysics.Logger.PrintWarning("::[MechanicalSolver]:: ", 'Settings contain no longer used setting, please remove it: "{}"'.format(old_setting)) - custom_settings.RemoveValue(old_setting) - - - settings_have_use_block_builder = custom_settings.Has("block_builder") - if settings_have_use_block_builder: - kratos_utilities.IssueDeprecationWarning('MechanicalSolver', 'Using "block_builder", please move it to "builder_and_solver_settings" as "use_block_builder"') - if not custom_settings.Has("builder_and_solver_settings"): - custom_settings.AddEmptyValue("builder_and_solver_settings") - - custom_settings["builder_and_solver_settings"].AddValue("use_block_builder", custom_settings["block_builder"]) - custom_settings.RemoveValue("block_builder") - - settings_have_line_search = custom_settings.Has("line_search") - if settings_have_line_search: - kratos_utilities.IssueDeprecationWarning('MechanicalSolver', 'Using "line_search", please move it to "solving_strategy_settings" as "type"') - if custom_settings["line_search"].GetBool(): - if not custom_settings.Has("solving_strategy_settings"): - custom_settings.AddEmptyValue("solving_strategy_settings") - - custom_settings["solving_strategy_settings"].AddEmptyValue("type") - custom_settings["solving_strategy_settings"]["type"].SetString("line_search") - custom_settings.RemoveValue("line_search") - + self.__ConvertDeprecatedSettings(custom_settings) self._validate_settings_in_baseclass=True # To be removed eventually super().__init__(model, custom_settings) @@ -140,8 +108,7 @@ def GetDefaultParameters(cls): "advanced_settings" : { } }, "builder_and_solver_settings" : { - "use_block_builder" : true, - "use_lagrange_BS" : false, + "type" : "block", "advanced_settings" : { } }, "clear_storage": false, @@ -379,9 +346,10 @@ def _GetLinearSolver(self): return self._linear_solver def _GetBuilderAndSolver(self): + builder_and_solver_type: str = self.settings["builder_and_solver_settings"]["type"].GetString() if not hasattr(self, '_builder_and_solver'): self._builder_and_solver = self._CreateBuilderAndSolver() - elif not self.settings["builder_and_solver_settings"]["use_block_builder"].GetBool(): # Block builder and solver are unified with MPC and without. In the case of the elimination this could be a problem + elif builder_and_solver_type == "elimination": # Block builder and solver are unified with MPC and without. In the case of the elimination this could be a problem if self.GetComputingModelPart().NumberOfMasterSlaveConstraints() > 0 and not self.mpc_block_builder_initialized: self.settings["multi_point_constraints_used"].SetBool(True) self._builder_and_solver = self._CreateBuilderAndSolver() @@ -389,9 +357,10 @@ def _GetBuilderAndSolver(self): return self._builder_and_solver def _GetSolutionStrategy(self): + builder_and_solver_type: str = self.settings["builder_and_solver_settings"]["type"].GetString() if not hasattr(self, '_mechanical_solution_strategy'): self._mechanical_solution_strategy = self._CreateSolutionStrategy() - elif not self.settings["builder_and_solver_settings"]["use_block_builder"].GetBool(): # Block builder and solver are unified with MPC and without. In the case of the elimination this could be a problem + elif builder_and_solver_type == "elimination": # Block builder and solver are unified with MPC and without. In the case of the elimination this could be a problem if self.GetComputingModelPart().NumberOfMasterSlaveConstraints() > 0 and not self.mpc_block_builder_initialized: self._mechanical_solution_strategy = self._CreateSolutionStrategy() return self._mechanical_solution_strategy @@ -487,20 +456,29 @@ def _CreateLinearSolver(self): KratosMultiphysics.Logger.PrintInfo('::[MechanicalSolver]:: No linear solver was specified, using fastest available solver') return linear_solver_factory.CreateFastestAvailableDirectLinearSolver() - def _CreateBuilderAndSolver(self): - linear_solver = self._GetLinearSolver() - if self.settings["builder_and_solver_settings"]["use_block_builder"].GetBool(): + def _CreateBuilderAndSolver(self) -> KratosMultiphysics.BuilderAndSolver: + if not self.settings["builder_and_solver_settings"].Has("type"): + return self.__DeprecatedBuilderAndSolverFactory() + + linear_solver: KratosMultiphysics.LinearSolver = self._GetLinearSolver() + builder_and_solver_name: str = self.settings["builder_and_solver_settings"]["type"].GetString() + + if builder_and_solver_name == "block": bs_params = self.settings["builder_and_solver_settings"]["advanced_settings"] - if not self.settings["builder_and_solver_settings"]["use_lagrange_BS"].GetBool(): - builder_and_solver = KratosMultiphysics.ResidualBasedBlockBuilderAndSolver(linear_solver, bs_params) - else: - builder_and_solver = KratosMultiphysics.ResidualBasedBlockBuilderAndSolverWithLagrangeMultiplier(linear_solver, bs_params) - else: + return KratosMultiphysics.ResidualBasedBlockBuilderAndSolver(linear_solver, bs_params) + elif builder_and_solver_name == "block_lagrange": + return KratosMultiphysics.ResidualBasedBlockBuilderAndSolverWithLagrangeMultiplier(linear_solver, bs_params) + elif builder_and_solver_name == "elimination": if self.settings["multi_point_constraints_used"].GetBool(): - builder_and_solver = KratosMultiphysics.ResidualBasedEliminationBuilderAndSolverWithConstraints(linear_solver) + return KratosMultiphysics.ResidualBasedEliminationBuilderAndSolverWithConstraints(linear_solver) else: - builder_and_solver = KratosMultiphysics.ResidualBasedEliminationBuilderAndSolver(linear_solver) - return builder_and_solver + return KratosMultiphysics.ResidualBasedEliminationBuilderAndSolver(linear_solver) + else: + message: str = f"Invalid type for builder and solver '{builder_and_solver_name}'. Options are:\n" + message += "'block'\n" + message += "'block_lagrange'\n" + message += "'elimination'" + raise ValueError(message) def _CreateScheme(self): """Create the solution scheme for the structural problem. @@ -584,3 +562,59 @@ def _create_arc_length_strategy(self): self._GetBuilderAndSolver(), settings) return solving_strategy + + def __ConvertDeprecatedSettings(self, settings: KratosMultiphysics.Parameters) -> None: + old_unused_settings = [ + "use_computing_model_part", + "computing_model_part_name", + "problem_domain_sub_model_part_list", + "processes_sub_model_part_list" + ] + + for old_setting in old_unused_settings: + if settings.Has(old_setting): + KratosMultiphysics.Logger.PrintWarning("::[MechanicalSolver]:: ", 'Settings contain no longer used setting, please remove it: "{}"'.format(old_setting)) + settings.RemoveValue(old_setting) + + settings_have_use_block_builder = settings.Has("block_builder") + if settings_have_use_block_builder: + kratos_utilities.IssueDeprecationWarning('MechanicalSolver', 'Using "block_builder", please move it to "builder_and_solver_settings" as "use_block_builder"') + if not settings.Has("builder_and_solver_settings"): + settings.AddEmptyValue("builder_and_solver_settings") + + settings["builder_and_solver_settings"].AddValue("use_block_builder", settings["block_builder"]) + settings.RemoveValue("block_builder") + + settings_have_line_search = settings.Has("line_search") + if settings_have_line_search: + kratos_utilities.IssueDeprecationWarning('MechanicalSolver', 'Using "line_search", please move it to "solving_strategy_settings" as "type"') + if settings["line_search"].GetBool(): + if not settings.Has("solving_strategy_settings"): + settings.AddEmptyValue("solving_strategy_settings") + + settings["solving_strategy_settings"].AddEmptyValue("type") + settings["solving_strategy_settings"]["type"].SetString("line_search") + settings.RemoveValue("line_search") + + if settings.Has("builder_and_solver_settings") and not settings["builder_and_solver_settings"].Has("type"): + kratos_utilities.IssueDeprecationWarning( + "MechanicalSolver", + "Using deprecated builder and solver settings. Provide 'type' and 'advanced_settings' in the new system.") + bs_settings = settings["builder_and_solver_settings"] + updated_bs_settings = KratosMultiphysics.Parameters("""{}""") + if bs_settings.Has("use_block_builder"): + if bs_settings["use_block_builder"].GetBool(): + if bs_settings.Has("use_lagrange_BS") and bs_settings["use_lagrange_BS"].GetBool(): + updated_bs_settings.AddString("type", "block_lagrange") + else: + updated_bs_settings.AddString("type", "block") + else: + updated_bs_settings.AddString("type", "elimination") + else: + updated_bs_settings.AddString("type", "block") + + if bs_settings.Has("advanced_settings"): + updated_bs_settings.AddValue("advanced_settings", bs_settings["advanced_settings"]) + + settings.RemoveValue("builder_and_solver_settings") + settings.AddValue("builder_and_solver_settings", updated_bs_settings) diff --git a/applications/StructuralMechanicsApplication/python_scripts/trilinos_structural_mechanics_solver.py b/applications/StructuralMechanicsApplication/python_scripts/trilinos_structural_mechanics_solver.py index 216aed09cce8..e2873bf738af 100644 --- a/applications/StructuralMechanicsApplication/python_scripts/trilinos_structural_mechanics_solver.py +++ b/applications/StructuralMechanicsApplication/python_scripts/trilinos_structural_mechanics_solver.py @@ -92,14 +92,19 @@ def _CreateBuilderAndSolver(self): guess_row_size = 15 else: guess_row_size = 45 - if self.settings["builder_and_solver_settings"]["use_block_builder"].GetBool(): + + builder_and_solver_type: str = self.settings["builder_and_solver_settings"]["type"].GetString() + if builder_and_solver_type == "block": builder_and_solver = TrilinosApplication.TrilinosBlockBuilderAndSolver(epetra_communicator, guess_row_size, linear_solver) - else: + elif builder_and_solver_type == "elimination": builder_and_solver = TrilinosApplication.TrilinosEliminationBuilderAndSolver(epetra_communicator, guess_row_size, linear_solver) + else: + raise ValueError(f"Unsupported builder and solver type '{builder_and_solver_type}'. Options are 'block', 'elimination'.") + return builder_and_solver def _create_linear_strategy(self): diff --git a/applications/StructuralMechanicsApplication/tests/rigid_test/test_elimination_mpc_parameters.json b/applications/StructuralMechanicsApplication/tests/rigid_test/test_elimination_mpc_parameters.json index 07f25d4e9a08..cd0ac0e133c3 100755 --- a/applications/StructuralMechanicsApplication/tests/rigid_test/test_elimination_mpc_parameters.json +++ b/applications/StructuralMechanicsApplication/tests/rigid_test/test_elimination_mpc_parameters.json @@ -22,7 +22,9 @@ "time_stepping" : { "time_step" : 1.1 }, - "block_builder" : false, + "builder_and_solver_settings" : { + "type" : "elimination" + }, "line_search" : false, "convergence_criterion" : "residual_criterion", "displacement_relative_tolerance" : 0.0001,