def ImportModelPart(self): ## Construct the distributed import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility(self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__,"MPI model reading finished.")
def ImportModelPart(self): ## Construct the distributed import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility(self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() ## Sets DENSITY, VISCOSITY and SOUND_VELOCITY KratosMultiphysics.Logger.PrintInfo("NavierStokesMPITwoFluidsSolver","MPI model reading finished.")
def ImportModelPart(self): # Construct the import model part utility from KratosMultiphysics.mpi.distributed_import_model_part_utility import DistributedImportModelPartUtility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart()
def ImportModelPart(self): KratosMultiphysics.Logger.PrintInfo("::[TrilinosMeshSolverBase]:: ", "Importing model part.") self.distributed_model_part_importer = DistributedImportModelPartUtility( self.mesh_model_part, self.settings) self.distributed_model_part_importer.ImportModelPart() KratosMultiphysics.Logger.PrintInfo("::[TrilinosMeshSolverBase]:: ", "Finished importing model part.")
def ImportModelPart(self): ## Construct the MPI import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() KratosMultiphysics.Logger.PrintInfo( "TrilinosNavierStokesSolverMonolithic", "MPI model reading finished.")
def ImportModelPart(self): if (IsDistributedRun()): ## Construct the MPI import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() else: # we can use the default implementation in the base class self._ImportModelPart(self.main_model_part, self.settings["model_import_settings"])
class NavierStokesMPIEmbeddedMonolithicSolver( navier_stokes_embedded_solver.NavierStokesEmbeddedMonolithicSolver): def __init__(self, model, custom_settings): # Call the serial base class constructor super().__init__(model, custom_settings) #TODO: Remove this once the FM-ALE is fully MPI compatible if self._FmAleIsActive(): err_msg = "FM-ALE algorithm implementation is not fully MPI compatible yet. Deactivate it setting \'fm_ale_step_frequency\' to 0." raise Exception(err_msg) KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "Construction of NavierStokesMPIEmbeddedMonolithicSolver finished." ) def AddVariables(self): super(NavierStokesMPIEmbeddedMonolithicSolver, self).AddVariables() self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "Variables for the Trilinos monolithic embedded fluid solver added correctly." ) def ImportModelPart(self): ## Construct the Distributed import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() ## Sets DENSITY, VISCOSITY and SOUND_VELOCITY KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "MPI model reading finished.") def PrepareModelPart(self): super(NavierStokesMPIEmbeddedMonolithicSolver, self).PrepareModelPart() ## Construct MPI the communicators self.distributed_model_part_importer.CreateCommunicators() def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): self._epetra_communicator = KratosTrilinos.CreateCommunicator() return self._epetra_communicator def _CreateScheme(self): domain_size = self.GetComputingModelPart().ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] # Cases in which the element manages the time integration if self.element_integrates_in_time: # "Fake" scheme for those cases in where the element manages the time integration # It is required to perform the nodal update once the current time step is solved scheme = KratosTrilinos.TrilinosResidualBasedIncrementalUpdateStaticSchemeSlip( domain_size, domain_size + 1) # In case the BDF2 scheme is used inside the element, the BDF time discretization utility is required to update the BDF coefficients if (self.settings["time_scheme"].GetString() == "bdf2"): time_order = 2 self.time_discretization = KratosMultiphysics.TimeDiscretization.BDF( time_order) else: err_msg = "Requested elemental time scheme \"" + self.settings[ "time_scheme"].GetString() + "\" is not available.\n" err_msg += "Available options are: \"bdf2\"" raise Exception(err_msg) # Cases in which a time scheme manages the time integration else: err_msg = "Custom scheme creation is not allowed. Embedded Navier-Stokes elements manage the time integration internally." raise Exception(err_msg) return scheme def _CreateLinearSolver(self): linear_solver_configuration = self.settings["linear_solver_settings"] return trilinos_linear_solver_factory.ConstructSolver( linear_solver_configuration) def _CreateConvergenceCriterion(self): convergence_criterion = KratosTrilinos.TrilinosMixedGenericCriteria([ (KratosMultiphysics.VELOCITY, self.settings["relative_velocity_tolerance"].GetDouble(), self.settings["absolute_velocity_tolerance"].GetDouble()), (KratosMultiphysics.PRESSURE, self.settings["relative_pressure_tolerance"].GetDouble(), self.settings["absolute_pressure_tolerance"].GetDouble()) ]) convergence_criterion.SetEchoLevel( self.settings["echo_level"].GetInt()) return convergence_criterion def _CreateBuilderAndSolver(self): # Set the guess_row_size (guess about the number of zero entries) for the Trilinos builder and solver domain_size = self.GetComputingModelPart().ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] if domain_size == 3: guess_row_size = 20 * 4 else: guess_row_size = 10 * 3 # Construct the Trilinos builder and solver trilinos_linear_solver = self._GetLinearSolver() epetra_communicator = self._GetEpetraCommunicator() if self.settings["consider_periodic_conditions"].GetBool(): builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolverPeriodic( epetra_communicator, guess_row_size, trilinos_linear_solver, KratosFluid.PATCH_INDEX) else: builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolver( epetra_communicator, guess_row_size, trilinos_linear_solver) return builder_and_solver def _CreateSolutionStrategy(self): computing_model_part = self.GetComputingModelPart() time_scheme = self._GetScheme() linear_solver = self._GetLinearSolver() convergence_criterion = self._GetConvergenceCriterion() builder_and_solver = self._GetBuilderAndSolver() return KratosTrilinos.TrilinosNewtonRaphsonStrategy( computing_model_part, time_scheme, linear_solver, convergence_criterion, builder_and_solver, self.settings["maximum_iterations"].GetInt(), self.settings["compute_reactions"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool(), self.settings["move_mesh_flag"].GetBool()) @classmethod def _FmAleIsActive(self): return False
class NavierStokesMPITwoFluidsSolver(NavierStokesTwoFluidsSolver): def __init__(self, model, custom_settings): super().__init__(model,custom_settings) # Avoid using features that are not available in MPI yet self._bfecc_convection = self.settings["bfecc_convection"].GetBool() if self._bfecc_convection: self._bfecc_convection = False KratosMultiphysics.Logger.PrintWarning(self.__class__.__name__, "BFECC is not implemented in MPI yet. Switching to standard level set convection.") if self.settings["formulation"].Has("surface_tension"): self.settings["formulation"]["surface_tension"].SetBool(False) self.main_model_part.ProcessInfo.SetValue(KratosFluid.SURFACE_TENSION, False) KratosMultiphysics.Logger.PrintWarning(self.__class__.__name__, "Surface tension is not implemented in MPI yet. Deactivating it.") if not self._reinitialization_type == None: if not self._reinitialization_type == "variational": self._reinitialization_type == "variational" KratosMultiphysics.Logger.PrintWarning(self.__class__.__name__, "Only variational redistancing is implemented in MPI. Switching to it.") if not self._distance_smoothing == None: if self._distance_smoothing: self._distance_smoothing = False KratosMultiphysics.Logger.PrintWarning(self.__class__.__name__, "Distance smoothing is not implemented in MPI yet. Deactivating it.") KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__,"Construction of NavierStokesMPITwoFluidsSolver finished.") def AddVariables(self): super(NavierStokesMPITwoFluidsSolver, self).AddVariables() self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__,"Variables for the Trilinos Two Fluid solver added correctly.") def ImportModelPart(self): ## Construct the distributed import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility(self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__,"MPI model reading finished.") def PrepareModelPart(self): super(NavierStokesMPITwoFluidsSolver,self).PrepareModelPart() ## Construct the MPI communicators self.distributed_model_part_importer.CreateCommunicators() def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): self._epetra_communicator = KratosTrilinos.CreateEpetraCommunicator(self.main_model_part.GetCommunicator().GetDataCommunicator()) return self._epetra_communicator def _CreateScheme(self): domain_size = self.GetComputingModelPart().ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] # Cases in which the element manages the time integration if self.element_integrates_in_time: # "Fake" scheme for those cases in where the element manages the time integration # It is required to perform the nodal update once the current time step is solved scheme = KratosTrilinos.TrilinosResidualBasedIncrementalUpdateStaticSchemeSlip( domain_size, domain_size + 1) # In case the BDF2 scheme is used inside the element, the BDF time discretization utility is required to update the BDF coefficients if (self.settings["time_scheme"].GetString() == "bdf2"): time_order = 2 self.time_discretization = KratosMultiphysics.TimeDiscretization.BDF(time_order) else: err_msg = "Requested elemental time scheme \"" + self.settings["time_scheme"].GetString()+ "\" is not available.\n" err_msg += "Available options are: \"bdf2\"" raise Exception(err_msg) # Cases in which a time scheme manages the time integration else: err_msg = "Custom scheme creation is not allowed. Two-fluids Navier-Stokes elements manage the time integration internally." raise Exception(err_msg) return scheme def _CreateLinearSolver(self): linear_solver_configuration = self.settings["linear_solver_settings"] return trilinos_linear_solver_factory.ConstructSolver(linear_solver_configuration) def _CreateConvergenceCriterion(self): convergence_criterion = KratosTrilinos.TrilinosMixedGenericCriteria( [(KratosMultiphysics.VELOCITY, self.settings["relative_velocity_tolerance"].GetDouble(), self.settings["absolute_velocity_tolerance"].GetDouble()), (KratosMultiphysics.PRESSURE, self.settings["relative_pressure_tolerance"].GetDouble(), self.settings["absolute_pressure_tolerance"].GetDouble())]) convergence_criterion.SetEchoLevel(self.settings["echo_level"].GetInt()) return convergence_criterion def _CreateBuilderAndSolver(self): # Set the guess_row_size (guess about the number of zero entries) for the Trilinos builder and solver domain_size = self.GetComputingModelPart().ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] if domain_size == 3: guess_row_size = 20*4 else: guess_row_size = 10*3 # Construct the Trilinos builder and solver trilinos_linear_solver = self._GetLinearSolver() epetra_communicator = self._GetEpetraCommunicator() if self.settings["consider_periodic_conditions"].GetBool(): builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolverPeriodic( epetra_communicator, guess_row_size, trilinos_linear_solver, KratosFluid.PATCH_INDEX) else: builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolver( epetra_communicator, guess_row_size, trilinos_linear_solver) return builder_and_solver def _CreateSolutionStrategy(self): computing_model_part = self.GetComputingModelPart() time_scheme = self._GetScheme() convergence_criterion = self._GetConvergenceCriterion() builder_and_solver = self._GetBuilderAndSolver() return KratosTrilinos.TrilinosNewtonRaphsonStrategy( computing_model_part, time_scheme, convergence_criterion, builder_and_solver, self.settings["maximum_iterations"].GetInt(), self.settings["compute_reactions"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool(), self.settings["move_mesh_flag"].GetBool()) def _CreateLevelSetConvectionProcess(self): # Construct the level set convection process domain_size = self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] levelset_linear_solver = self._GetLevelsetLinearSolver() computing_model_part = self.GetComputingModelPart() epetra_communicator = self._GetEpetraCommunicator() levelset_convection_settings = self.settings["levelset_convection_settings"] if domain_size == 2: level_set_convection_process = KratosTrilinos.TrilinosLevelSetConvectionProcess2D( epetra_communicator, computing_model_part, levelset_linear_solver, levelset_convection_settings) else: level_set_convection_process = KratosTrilinos.TrilinosLevelSetConvectionProcess3D( epetra_communicator, computing_model_part, levelset_linear_solver, levelset_convection_settings) return level_set_convection_process def _CreateDistanceReinitializationProcess(self): # Construct the variational distance calculation process maximum_iterations = 2 #TODO: Make this user-definable redistancing_linear_solver = self._GetRedistancingLinearSolver() computing_model_part = self.GetComputingModelPart() epetra_communicator = self._GetEpetraCommunicator() if self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2: variational_distance_process = KratosTrilinos.TrilinosVariationalDistanceCalculationProcess2D( epetra_communicator, computing_model_part, redistancing_linear_solver, maximum_iterations, KratosMultiphysics.VariationalDistanceCalculationProcess2D.CALCULATE_EXACT_DISTANCES_TO_PLANE) else: variational_distance_process = KratosTrilinos.TrilinosVariationalDistanceCalculationProcess3D( epetra_communicator, computing_model_part, redistancing_linear_solver, maximum_iterations, KratosMultiphysics.VariationalDistanceCalculationProcess3D.CALCULATE_EXACT_DISTANCES_TO_PLANE) return variational_distance_process
class TrilinosNavierStokesSolverFractionalStep(NavierStokesSolverFractionalStep): def __init__(self, model, custom_settings): # Call the serial base class constructor super().__init__(model,custom_settings) KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__,"Construction of TrilinosNavierStokesSolverFractionalStep solver finished.") def AddVariables(self): ## Add variables from the base class super(TrilinosNavierStokesSolverFractionalStep, self).AddVariables() ## Add specific MPI variables self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__,"variables for the trilinos fractional step solver added correctly") def ImportModelPart(self): ## Construct the MPI import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility(self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__,"MPI model reading finished.") def PrepareModelPart(self): super(TrilinosNavierStokesSolverFractionalStep,self).PrepareModelPart() ## Construct MPI communicators self.distributed_model_part_importer.CreateCommunicators() def AddDofs(self): ## Base class DOFs addition super(TrilinosNavierStokesSolverFractionalStep, self).AddDofs() KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__,"DOFs for the VMS Trilinos fluid solver added correctly in all processors.") def Initialize(self): ## Base class solver intiialization super(TrilinosNavierStokesSolverFractionalStep, self).Initialize() KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Solver initialization finished.") def Finalize(self): self._GetSolutionStrategy().Clear() def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): self._epetra_communicator = KratosTrilinos.CreateCommunicator() return self._epetra_communicator def _CreateScheme(self): pass def _CreateLinearSolver(self): # Create the pressure linear solver pressure_linear_solver_configuration = self.settings["pressure_linear_solver_settings"] pressure_linear_solver = trilinos_linear_solver_factory.ConstructSolver(pressure_linear_solver_configuration) # Create the velocity linear solver velocity_linear_solver_configuration = self.settings["velocity_linear_solver_settings"] velocity_linear_solver = trilinos_linear_solver_factory.ConstructSolver(velocity_linear_solver_configuration) # Return a tuple containing both linear solvers return (pressure_linear_solver, velocity_linear_solver) def _CreateConvergenceCriterion(self): pass def _CreateBuilderAndSolver(self): pass def _CreateSolutionStrategy(self): computing_model_part = self.GetComputingModelPart() epetra_communicator = self._GetEpetraCommunicator() domain_size = computing_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] # Create the pressure and velocity linear solvers # Note that linear_solvers is a tuple. The first item is the pressure # linear solver. The second item is the velocity linear solver. linear_solvers = self._GetLinearSolver() # Create the fractional step settings instance # TODO: next part would be much cleaner if we passed directly the parameters to the c++ if self.settings["consider_periodic_conditions"].GetBool(): fractional_step_settings = TrilinosFluid.TrilinosFractionalStepSettingsPeriodic( epetra_communicator, computing_model_part, domain_size, self.settings["time_order"].GetInt(), self.settings["use_slip_conditions"].GetBool(), self.settings["move_mesh_flag"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool(), KratosCFD.PATCH_INDEX) else: fractional_step_settings = TrilinosFluid.TrilinosFractionalStepSettings( epetra_communicator, computing_model_part, domain_size, self.settings["time_order"].GetInt(), self.settings["use_slip_conditions"].GetBool(), self.settings["move_mesh_flag"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool()) # Set the strategy echo level fractional_step_settings.SetEchoLevel(self.settings["echo_level"].GetInt()) # Set the velocity and pressure fractional step strategy settings fractional_step_settings.SetStrategy(TrilinosFluid.TrilinosStrategyLabel.Pressure, linear_solvers[0], self.settings["pressure_tolerance"].GetDouble(), self.settings["maximum_pressure_iterations"].GetInt()) fractional_step_settings.SetStrategy(TrilinosFluid.TrilinosStrategyLabel.Velocity, linear_solvers[1], self.settings["velocity_tolerance"].GetDouble(), self.settings["maximum_velocity_iterations"].GetInt()) # Create the fractional step strategy if self.settings["consider_periodic_conditions"].GetBool(): solution_strategy = TrilinosFluid.TrilinosFractionalStepStrategy( computing_model_part, fractional_step_settings, self.settings["predictor_corrector"].GetBool(), self.settings["compute_reactions"].GetBool(), KratosCFD.PATCH_INDEX) else: solution_strategy = TrilinosFluid.TrilinosFractionalStepStrategy( computing_model_part, fractional_step_settings, self.settings["predictor_corrector"].GetBool(), self.settings["compute_reactions"].GetBool()) return solution_strategy
class AdjointVMSMonolithicMPISolver(AdjointVMSMonolithicSolver): def __init__(self, model, custom_settings): super().__init__(model, custom_settings) def AddVariables(self): ## Add variables from the base class super(self.__class__, self).AddVariables() ## Add specific MPI variables self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Variables for the AdjointVMSMonolithicMPISolver added correctly in each processor.") def ImportModelPart(self): ## Construct the distributed import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility(self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ExecutePartitioningAndReading() KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "MPI model reading finished.") def PrepareModelPart(self): super(self.__class__,self).PrepareModelPart() ## Construct the MPI communicators self.distributed_model_part_importer.CreateCommunicators() def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): self._epetra_communicator = TrilinosApplication.CreateEpetraCommunicator(self.main_model_part.GetCommunicator().GetDataCommunicator()) return self._epetra_communicator def _CreateScheme(self): response_function = self.GetResponseFunction() scheme_type = self.settings["scheme_settings"]["scheme_type"].GetString() domain_size = self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] if scheme_type == "bossak": scheme = KratosCFD.TrilinosVelocityBossakAdjointScheme(self.settings["scheme_settings"], response_function, domain_size, domain_size + 1) elif scheme_type == "steady": scheme = KratosCFD.TrilinosSimpleSteadyAdjointScheme(response_function, domain_size, domain_size + 1) else: raise Exception("Invalid scheme_type: " + scheme_type) return scheme def _CreateLinearSolver(self): linear_solver_configuration = self.settings["linear_solver_settings"] return trilinos_linear_solver_factory.ConstructSolver(linear_solver_configuration) def _CreateBuilderAndSolver(self): # Set the guess_row_size (guess about the number of zero entries) for the Trilinos builder and solver domain_size = self.GetComputingModelPart().ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] if domain_size == 3: guess_row_size = 20*4 else: guess_row_size = 10*3 # Construct the Trilinos builder and solver trilinos_linear_solver = self._GetLinearSolver() epetra_communicator = self._GetEpetraCommunicator() if self.settings["consider_periodic_conditions"].GetBool(): builder_and_solver = TrilinosApplication.TrilinosBlockBuilderAndSolverPeriodic( epetra_communicator, guess_row_size, trilinos_linear_solver, KratosFluid.PATCH_INDEX) else: builder_and_solver = TrilinosApplication.TrilinosBlockBuilderAndSolver( epetra_communicator, guess_row_size, trilinos_linear_solver) return builder_and_solver def _CreateSolutionStrategy(self): computing_model_part = self.GetComputingModelPart() time_scheme = self._GetScheme() linear_solver = self._GetLinearSolver() builder_and_solver = self._GetBuilderAndSolver() calculate_reaction_flag = False reform_dof_set_at_each_step = False calculate_norm_dx_flag = False move_mesh_flag = False return TrilinosApplication.TrilinosLinearStrategy( computing_model_part, time_scheme, linear_solver, builder_and_solver, calculate_reaction_flag, reform_dof_set_at_each_step, calculate_norm_dx_flag, move_mesh_flag)
class TrilinosNavierStokesSolverFractionalStep(NavierStokesSolverFractionalStep ): @classmethod def GetDefaultSettings(cls): ## Default settings string in Json format default_settings = KratosMultiphysics.Parameters(""" { "solver_type": "FractionalStep", "model_part_name": "", "domain_size": -1, "model_import_settings": { "input_type": "mdpa", "input_filename": "unknown_name" }, "material_import_settings": { "materials_filename": "" }, "predictor_corrector": false, "maximum_velocity_iterations": 3, "maximum_pressure_iterations": 3, "velocity_tolerance": 1e-3, "pressure_tolerance": 1e-2, "dynamic_tau": 0.01, "oss_switch": 0, "echo_level": 0, "consider_periodic_conditions": false, "time_order": 2, "compute_reactions": false, "reform_dofs_at_each_step": false, "pressure_linear_solver_settings": { "solver_type" : "multi_level", "max_iteration" : 200, "tolerance" : 1e-6, "symmetric" : true, "scaling" : true, "reform_preconditioner_at_each_step" : true, "verbosity" : 0 }, "velocity_linear_solver_settings": { "solver_type" : "multi_level", "max_iteration" : 200, "tolerance" : 1e-6, "symmetric" : false, "scaling" : true, "reform_preconditioner_at_each_step" : true, "verbosity" : 0 }, "volume_model_part_name" : "volume_model_part", "skin_parts":[""], "no_skin_parts":[""], "time_stepping": { "automatic_time_step" : false, "CFL_number" : 1, "minimum_delta_time" : 1e-4, "maximum_delta_time" : 0.01 }, "move_mesh_flag": false, "use_slip_conditions": true }""") default_settings.AddMissingParameters( super(TrilinosNavierStokesSolverFractionalStep, cls).GetDefaultSettings()) return default_settings def __init__(self, model, custom_settings): self._validate_settings_in_baseclass = True # To be removed eventually # Note: deliberately calling the constructor of the base python solver (the parent of my parent) super(NavierStokesSolverFractionalStep, self).__init__(model, custom_settings) self.element_name = "FractionalStep" self.condition_name = "WallCondition" self.min_buffer_size = 3 self.element_has_nodal_properties = True ## Construct the linear solvers self.pressure_linear_solver = trilinos_linear_solver_factory.ConstructSolver( self.settings["pressure_linear_solver_settings"]) self.velocity_linear_solver = trilinos_linear_solver_factory.ConstructSolver( self.settings["velocity_linear_solver_settings"]) self.compute_reactions = self.settings["compute_reactions"].GetBool() KratosMultiphysics.Logger.PrintInfo( "TrilinosNavierStokesSolverFractionalStep", "Construction of TrilinosNavierStokesSolverFractionalStep solver finished." ) def AddVariables(self): ## Add variables from the base class super(TrilinosNavierStokesSolverFractionalStep, self).AddVariables() ## Add specific MPI variables self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PARTITION_INDEX) self.main_model_part.AddNodalSolutionStepVariable( KratosFluid.PATCH_INDEX) KratosMultiphysics.Logger.PrintInfo( "TrilinosNavierStokesSolverFractionalStep", "variables for the trilinos fractional step solver added correctly" ) def ImportModelPart(self): ## Construct the MPI import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() KratosMultiphysics.Logger.PrintInfo( "TrilinosNavierStokesSolverFractionalStep", "MPI model reading finished.") def PrepareModelPart(self): super(TrilinosNavierStokesSolverFractionalStep, self).PrepareModelPart() ## Construct MPI communicators self.distributed_model_part_importer.CreateCommunicators() def AddDofs(self): ## Base class DOFs addition super(TrilinosNavierStokesSolverFractionalStep, self).AddDofs() KratosMultiphysics.Logger.PrintInfo( "TrilinosNavierStokesSolverFractionalStep", "DOFs for the VMS Trilinos fluid solver added correctly in all processors." ) def Initialize(self): ## Construct the communicator self.EpetraComm = KratosTrilinos.CreateCommunicator() ## Get the computing model part self.computing_model_part = self.GetComputingModelPart() ## If needed, create the estimate time step utility if (self.settings["time_stepping"]["automatic_time_step"].GetBool()): self.EstimateDeltaTimeUtility = self._GetAutomaticTimeSteppingUtility( ) #TODO: next part would be much cleaner if we passed directly the parameters to the c++ if self.settings["consider_periodic_conditions"] == True: self.solver_settings = TrilinosFluid.TrilinosFractionalStepSettingsPeriodic( self.EpetraComm, self.computing_model_part, self.computing_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE], self.settings["time_order"].GetInt(), self.settings["use_slip_conditions"].GetBool(), self.settings["move_mesh_flag"].GetBool(), self.settings["reform_dofs_at_each_step]"].GetBool(), KratosFluid.PATCH_INDEX) else: self.solver_settings = TrilinosFluid.TrilinosFractionalStepSettings( self.EpetraComm, self.computing_model_part, self.computing_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE], self.settings["time_order"].GetInt(), self.settings["use_slip_conditions"].GetBool(), self.settings["move_mesh_flag"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool()) self.solver_settings.SetEchoLevel(self.settings["echo_level"].GetInt()) self.solver_settings.SetStrategy( TrilinosFluid.TrilinosStrategyLabel.Velocity, self.velocity_linear_solver, self.settings["velocity_tolerance"].GetDouble(), self.settings["maximum_velocity_iterations"].GetInt()) self.solver_settings.SetStrategy( TrilinosFluid.TrilinosStrategyLabel.Pressure, self.pressure_linear_solver, self.settings["pressure_tolerance"].GetDouble(), self.settings["maximum_pressure_iterations"].GetInt()) self.solver = TrilinosFluid.TrilinosFSStrategy( self.computing_model_part, self.solver_settings, self.settings["predictor_corrector"].GetBool(), KratosFluid.PATCH_INDEX) self.main_model_part.ProcessInfo.SetValue( KratosMultiphysics.DYNAMIC_TAU, self.settings["dynamic_tau"].GetDouble()) self.main_model_part.ProcessInfo.SetValue( KratosMultiphysics.OSS_SWITCH, self.settings["oss_switch"].GetInt()) (self.solver).Initialize() KratosMultiphysics.Logger.PrintInfo( "TrilinosNavierStokesSolverFractionalStep", "Initialization TrilinosNavierStokesSolverFractionalStep finished") def Finalize(self): self.solver.Clear()
def __execute_test(self, in_memory, all_ranks): settings = KM.Parameters("""{ "model_import_settings" : { "input_type" : "mdpa" }, "echo_level" : 0 }""") settings["model_import_settings"].AddEmptyValue( "input_filename").SetString(GetFilePath("test_mpi_communicator")) settings["model_import_settings"].AddEmptyValue( "partition_in_memory").SetBool(in_memory) data_comm_name = "World" if not all_ranks: default_data_comm = KM.ParallelEnvironment.GetDefaultDataCommunicator( ) size = default_data_comm.Size() if size < 3: self.skipTest("This test needs at least 3 mpi processes") ranks = [i for i in range(1, size)] data_comm_name = "AllExceptFirst" sub_comm = DataCommunicatorFactory.CreateFromRanksAndRegister( default_data_comm, ranks, data_comm_name) self.addCleanup(KM.ParallelEnvironment.UnregisterDataCommunicator, data_comm_name) settings["model_import_settings"].AddEmptyValue( "data_communicator_name").SetString(data_comm_name) if default_data_comm.Rank() == 0: self.assertFalse(sub_comm.IsDefinedOnThisRank()) else: self.assertTrue(sub_comm.IsDefinedOnThisRank()) if not sub_comm.IsDefinedOnThisRank(): # this rank does not participate return current_model = KM.Model() model_part = current_model.CreateModelPart("main_model_part") model_part.AddNodalSolutionStepVariable(KM.PARTITION_INDEX) model_part.AddNodalSolutionStepVariable(KM.DISPLACEMENT) model_part.AddNodalSolutionStepVariable(KM.VISCOSITY) import_util = DistributedImportModelPartUtility(model_part, settings) import_util.ImportModelPart() import_util.CreateCommunicators() # check main ModelPart self.assertTrue(model_part.IsDistributed()) self.assertEqual(model_part.GetCommunicator().GlobalNumberOfNodes(), 9) self.assertEqual(model_part.GetCommunicator().GlobalNumberOfElements(), 8) self.assertEqual( model_part.GetCommunicator().GlobalNumberOfConditions(), 8) self.assertEqual(model_part.NumberOfSubModelParts(), 1) self.assertTrue(model_part.HasSubModelPart("Skin")) # Check SubModelPart smp = model_part.GetSubModelPart("Skin") self.assertTrue(smp.IsDistributed()) self.assertEqual(smp.GetCommunicator().GlobalNumberOfNodes(), 8) self.assertEqual(smp.GetCommunicator().GlobalNumberOfElements(), 0) self.assertEqual(smp.GetCommunicator().GlobalNumberOfConditions(), 8) self.assertEqual(smp.NumberOfSubModelParts(), 1) self.assertTrue(smp.HasSubModelPart("Top_side_1")) # Check SubSubModelPart sub_smp = smp.GetSubModelPart("Top_side_1") self.assertTrue(sub_smp.IsDistributed()) self.assertEqual(sub_smp.GetCommunicator().GlobalNumberOfNodes(), 2) self.assertEqual(sub_smp.GetCommunicator().GlobalNumberOfElements(), 0) self.assertEqual(sub_smp.GetCommunicator().GlobalNumberOfConditions(), 1) self.assertEqual(sub_smp.NumberOfSubModelParts(), 0)
class AdjointVMSMonolithicMPISolver(AdjointVMSMonolithicSolver): @classmethod def GetDefaultSettings(cls): # default settings string in json format default_settings = KratosMultiphysics.Parameters(""" { "solver_type": "trilinos_adjoint_vmsmonolithic_solver", "scheme_settings" : { "scheme_type": "bossak" }, "response_function_settings" : { "response_type" : "drag" }, "sensitivity_settings" : {}, "model_import_settings": { "input_type": "mdpa", "input_filename": "unknown_name" }, "material_import_settings": { "materials_filename": "" }, "linear_solver_settings" : { "solver_type" : "amgcl" }, "volume_model_part_name" : "volume_model_part", "skin_parts": [""], "dynamic_tau": 0.0, "oss_switch": 0, "echo_level": 0, "time_stepping" : { "automatic_time_step" : false, "time_step" : -0.1 }, "domain_size": -1, "model_part_name": "", "time_stepping": { "automatic_time_step" : false, "time_step" : -0.1 }, "consider_periodic_conditions": false, "assign_neighbour_elements_to_conditions": false }""") default_settings.AddMissingParameters( super(AdjointVMSMonolithicMPISolver, cls).GetDefaultSettings()) return default_settings def __init__(self, model, custom_settings): self._validate_settings_in_baseclass = True # To be removed eventually super(AdjointVMSMonolithicSolver, self).__init__(model, custom_settings) self.element_name = "VMSAdjointElement" if self.settings["domain_size"].GetInt() == 2: self.condition_name = "LineCondition" elif self.settings["domain_size"].GetInt() == 3: self.condition_name = "SurfaceCondition" self.min_buffer_size = 2 self.element_has_nodal_properties = True self.main_model_part.ProcessInfo.SetValue( KratosMultiphysics.OSS_SWITCH, self.settings["oss_switch"].GetInt()) self.main_model_part.ProcessInfo.SetValue( KratosMultiphysics.DYNAMIC_TAU, self.settings["dynamic_tau"].GetDouble()) KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "Construction of AdjointVMSMonolithicMPISolver finished.") def AddVariables(self): ## Add variables from the base class super(self.__class__, self).AddVariables() ## Add specific MPI variables self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "Variables for the AdjointVMSMonolithicMPISolver added correctly in each processor." ) def ImportModelPart(self): ## Construct the distributed import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ExecutePartitioningAndReading() KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "MPI model reading finished.") def PrepareModelPart(self): super(self.__class__, self).PrepareModelPart() ## Construct the MPI communicators self.distributed_model_part_importer.CreateCommunicators() def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): self._epetra_communicator = TrilinosApplication.CreateCommunicator( ) return self._epetra_communicator def _CreateScheme(self): response_function = self.GetResponseFunction() scheme_type = self.settings["scheme_settings"][ "scheme_type"].GetString() if scheme_type == "bossak": scheme = TrilinosApplication.TrilinosResidualBasedAdjointBossakScheme( self.settings["scheme_settings"], response_function) elif scheme_type == "steady": scheme = TrilinosApplication.TrilinosResidualBasedAdjointSteadyScheme( response_function) else: raise Exception("Invalid scheme_type: " + scheme_type) return scheme def _CreateLinearSolver(self): linear_solver_configuration = self.settings["linear_solver_settings"] return trilinos_linear_solver_factory.ConstructSolver( linear_solver_configuration) def _CreateBuilderAndSolver(self): # Set the guess_row_size (guess about the number of zero entries) for the Trilinos builder and solver domain_size = self.GetComputingModelPart().ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] if domain_size == 3: guess_row_size = 20 * 4 else: guess_row_size = 10 * 3 # Construct the Trilinos builder and solver trilinos_linear_solver = self._GetLinearSolver() epetra_communicator = self._GetEpetraCommunicator() if self.settings["consider_periodic_conditions"].GetBool(): builder_and_solver = TrilinosApplication.TrilinosBlockBuilderAndSolverPeriodic( epetra_communicator, guess_row_size, trilinos_linear_solver, KratosFluid.PATCH_INDEX) else: builder_and_solver = TrilinosApplication.TrilinosBlockBuilderAndSolver( epetra_communicator, guess_row_size, trilinos_linear_solver) return builder_and_solver def _CreateSolutionStrategy(self): computing_model_part = self.GetComputingModelPart() time_scheme = self._GetScheme() linear_solver = self._GetLinearSolver() builder_and_solver = self._GetBuilderAndSolver() calculate_reaction_flag = False reform_dof_set_at_each_step = False calculate_norm_dx_flag = False move_mesh_flag = False return TrilinosApplication.TrilinosLinearStrategy( computing_model_part, time_scheme, linear_solver, builder_and_solver, calculate_reaction_flag, reform_dof_set_at_each_step, calculate_norm_dx_flag, move_mesh_flag)
class NavierStokesMPITwoFluidsSolver(NavierStokesTwoFluidsSolver): @classmethod def GetDefaultSettings(cls): default_settings = KratosMultiphysics.Parameters("""{ "solver_type": "TwoFluids", "model_part_name": "", "domain_size": -1, "model_import_settings": { "input_type": "mdpa", "input_filename": "unknown_name", "reorder": false }, "material_import_settings": { "materials_filename": "" }, "distance_reading_settings" : { "import_mode" : "from_mdpa", "distance_file_name" : "no_distance_file" }, "maximum_iterations": 7, "echo_level": 0, "time_order": 2, "time_scheme": "bdf2", "compute_reactions": false, "reform_dofs_at_each_step": false, "consider_periodic_conditions": false, "relative_velocity_tolerance": 1e-3, "absolute_velocity_tolerance": 1e-5, "relative_pressure_tolerance": 1e-3, "absolute_pressure_tolerance": 1e-5, "linear_solver_settings": { "solver_type": "amgcl" }, "volume_model_part_name" : "volume_model_part", "skin_parts": [""], "no_skin_parts":[""], "time_stepping": { "automatic_time_step" : true, "CFL_number" : 1, "minimum_delta_time" : 1e-4, "maximum_delta_time" : 0.01 }, "move_mesh_flag": false, "formulation": { "dynamic_tau": 1.0 }, "bfecc_convection" : false, "bfecc_number_substeps" : 10 }""") default_settings.AddMissingParameters(super(NavierStokesMPITwoFluidsSolver, cls).GetDefaultSettings()) return default_settings def __init__(self, model, custom_settings): self._validate_settings_in_baseclass=True # To be removed eventually # the constructor of the "grand-parent" (jumping constructor of parent) is called to avoid conflicts in attribute settings super(NavierStokesTwoFluidsSolver, self).__init__(model,custom_settings) self.element_name = "TwoFluidNavierStokes" self.condition_name = "NavierStokesWallCondition" self.element_integrates_in_time = True self.element_has_nodal_properties = True self.min_buffer_size = 3 self._bfecc_convection = self.settings["bfecc_convection"].GetBool() if self._bfecc_convection: self._bfecc_convection = False KratosMultiphysics.Logger.PrintWarning(self.__class__.__name__, "BFECC is not implemented in MPI yet. Switching to standard level set convection.") dynamic_tau = self.settings["formulation"]["dynamic_tau"].GetDouble() self.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.DYNAMIC_TAU, dynamic_tau) KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__,"Construction of NavierStokesMPITwoFluidsSolver finished.") def AddVariables(self): super(NavierStokesMPITwoFluidsSolver, self).AddVariables() self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__,"Variables for the Trilinos Two Fluid solver added correctly.") def ImportModelPart(self): ## Construct the distributed import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility(self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__,"MPI model reading finished.") def PrepareModelPart(self): super(NavierStokesMPITwoFluidsSolver,self).PrepareModelPart() ## Construct the MPI communicators self.distributed_model_part_importer.CreateCommunicators() def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): self._epetra_communicator = KratosTrilinos.CreateCommunicator() return self._epetra_communicator def _CreateScheme(self): domain_size = self.GetComputingModelPart().ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] # Cases in which the element manages the time integration if self.element_integrates_in_time: # "Fake" scheme for those cases in where the element manages the time integration # It is required to perform the nodal update once the current time step is solved scheme = KratosTrilinos.TrilinosResidualBasedIncrementalUpdateStaticSchemeSlip( domain_size, domain_size + 1) # In case the BDF2 scheme is used inside the element, the BDF time discretization utility is required to update the BDF coefficients if (self.settings["time_scheme"].GetString() == "bdf2"): time_order = 2 self.time_discretization = KratosMultiphysics.TimeDiscretization.BDF(time_order) else: err_msg = "Requested elemental time scheme \"" + self.settings["time_scheme"].GetString()+ "\" is not available.\n" err_msg += "Available options are: \"bdf2\"" raise Exception(err_msg) # Cases in which a time scheme manages the time integration else: err_msg = "Custom scheme creation is not allowed. Two-fluids Navier-Stokes elements manage the time integration internally." raise Exception(err_msg) return scheme def _CreateLinearSolver(self): linear_solver_configuration = self.settings["linear_solver_settings"] return trilinos_linear_solver_factory.ConstructSolver(linear_solver_configuration) def _CreateConvergenceCriterion(self): convergence_criterion = KratosTrilinos.TrilinosUPCriteria( self.settings["relative_velocity_tolerance"].GetDouble(), self.settings["absolute_velocity_tolerance"].GetDouble(), self.settings["relative_pressure_tolerance"].GetDouble(), self.settings["absolute_pressure_tolerance"].GetDouble()) convergence_criterion.SetEchoLevel(self.settings["echo_level"].GetInt()) return convergence_criterion def _CreateBuilderAndSolver(self): # Set the guess_row_size (guess about the number of zero entries) for the Trilinos builder and solver domain_size = self.GetComputingModelPart().ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] if domain_size == 3: guess_row_size = 20*4 else: guess_row_size = 10*3 # Construct the Trilinos builder and solver trilinos_linear_solver = self._GetLinearSolver() epetra_communicator = self._GetEpetraCommunicator() if self.settings["consider_periodic_conditions"].GetBool(): builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolverPeriodic( epetra_communicator, guess_row_size, trilinos_linear_solver, KratosFluid.PATCH_INDEX) else: builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolver( epetra_communicator, guess_row_size, trilinos_linear_solver) return builder_and_solver def _CreateSolutionStrategy(self): computing_model_part = self.GetComputingModelPart() time_scheme = self._GetScheme() linear_solver = self._GetLinearSolver() convergence_criterion = self._GetConvergenceCriterion() builder_and_solver = self._GetBuilderAndSolver() return KratosTrilinos.TrilinosNewtonRaphsonStrategy( computing_model_part, time_scheme, linear_solver, convergence_criterion, builder_and_solver, self.settings["maximum_iterations"].GetInt(), self.settings["compute_reactions"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool(), self.settings["move_mesh_flag"].GetBool()) def _CreateLevelSetConvectionProcess(self): # Construct the level set convection process domain_size = self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] linear_solver = self._GetLinearSolver() computing_model_part = self.GetComputingModelPart() epetra_communicator = self._GetEpetraCommunicator() if domain_size == 2: level_set_convection_process = KratosTrilinos.TrilinosLevelSetConvectionProcess2D( epetra_communicator, KratosMultiphysics.DISTANCE, computing_model_part, linear_solver) else: level_set_convection_process = KratosTrilinos.TrilinosLevelSetConvectionProcess3D( epetra_communicator, KratosMultiphysics.DISTANCE, computing_model_part, linear_solver) return level_set_convection_process def _CreateVariationalDistanceProcess(self): # Construct the variational distance calculation process maximum_iterations = 2 #TODO: Make this user-definable linear_solver = self._GetLinearSolver() computing_model_part = self.GetComputingModelPart() epetra_communicator = self._GetEpetraCommunicator() if self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2: variational_distance_process = KratosTrilinos.TrilinosVariationalDistanceCalculationProcess2D( epetra_communicator, computing_model_part, linear_solver, maximum_iterations, KratosMultiphysics.VariationalDistanceCalculationProcess2D.CALCULATE_EXACT_DISTANCES_TO_PLANE) else: variational_distance_process = KratosTrilinos.TrilinosVariationalDistanceCalculationProcess3D( epetra_communicator, computing_model_part, linear_solver, maximum_iterations, KratosMultiphysics.VariationalDistanceCalculationProcess3D.CALCULATE_EXACT_DISTANCES_TO_PLANE) return variational_distance_process
class CoupledRANSSolver(PythonSolver): def __init__(self, model, custom_settings): """RANS solver to be used with RANSFormulations This solver creates PythonSolver based on the RANSFormulations specified in custom_settings. Args: model (Kratos.Model): Model to be used in the solver. custom_settings (Kratos.Parameters): Settings to be used in the solver. """ self._validate_settings_in_baseclass = True # To be removed eventually super().__init__(model, custom_settings) model_part_name = self.settings["model_part_name"].GetString() if model_part_name == "": raise Exception( 'Please provide the model part name as the "model_part_name" (string) parameter!' ) if self.model.HasModelPart(model_part_name): self.main_model_part = self.model.GetModelPart(model_part_name) else: self.main_model_part = self.model.CreateModelPart(model_part_name) self.domain_size = self.settings["domain_size"].GetInt() if self.domain_size == -1: raise Exception( 'Please provide the domain size as the "domain_size" (int) parameter!' ) self.main_model_part.ProcessInfo.SetValue(Kratos.DOMAIN_SIZE, self.domain_size) self.formulation = FormulationFactory( self.main_model_part, self.settings["formulation_settings"]) self.formulation.SetConstants(self.settings["constants"]) self.formulation.SetIsPeriodic( self.settings["consider_periodic_conditions"].GetBool()) self.is_periodic = self.formulation.IsPeriodic() self.formulation.SetTimeSchemeSettings( self.settings["time_scheme_settings"]) self.formulation.SetWallFunctionSettings( self.settings["wall_function_settings"]) scheme_type = self.settings["time_scheme_settings"][ "scheme_type"].GetString() if (scheme_type == "steady"): self.is_steady = True else: self.is_steady = False self.is_converged = False self.min_buffer_size = self.formulation.GetMinimumBufferSize() self.move_mesh = self.settings["move_mesh"].GetBool() self.echo_level = self.settings["echo_level"].GetInt() Kratos.Logger.PrintInfo(self.__class__.__name__, "Solver construction finished.") @classmethod def GetDefaultParameters(cls): ##settings string in json format default_settings = Kratos.Parameters(""" { "solver_type": "CoupledRANS", "model_part_name": "FluidModelPart", "domain_size": -1, "model_import_settings": { "input_type": "mdpa", "input_filename": "unknown_name", "reorder": false }, "material_import_settings": { "materials_filename": "" }, "consider_periodic_conditions": false, "formulation_settings": {}, "wall_function_settings": {}, "echo_level": 0, "volume_model_part_name": "volume_model_part", "skin_parts" : [""], "no_skin_parts": [""], "assign_neighbour_elements_to_conditions": true, "move_mesh": false, "time_scheme_settings":{ "scheme_type": "steady" }, "time_stepping": { "automatic_time_step" : false, "CFL_number" : 1, "minimum_delta_time" : 1e-4, "maximum_delta_time" : 0.01, "time_step" : 0.0 }, "constants": {} }""") default_settings.AddMissingParameters(super().GetDefaultParameters()) return default_settings def AddVariables(self): self.formulation.AddVariables() if self.is_periodic: self.main_model_part.AddNodalSolutionStepVariable( KratosCFD.PATCH_INDEX) if (IsDistributedRun()): self.main_model_part.AddNodalSolutionStepVariable( Kratos.PARTITION_INDEX) Kratos.Logger.PrintInfo(self.__class__.__name__, "Solver variables added correctly.") def AddDofs(self): self.formulation.AddDofs() Kratos.Logger.PrintInfo(self.__class__.__name__, "Solver dofs added correctly.") def ImportModelPart(self): if (IsDistributedRun()): ## Construct the MPI import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() else: # we can use the default implementation in the base class self._ImportModelPart(self.main_model_part, self.settings["model_import_settings"]) def PrepareModelPart(self): if not self.main_model_part.ProcessInfo[Kratos.IS_RESTARTED]: ## Set fluid properties from materials json file materials_imported = self._SetPhysicalProperties() if not materials_imported: Kratos.Logger.PrintWarning( self.__class__.__name__, "Material properties have not been imported. Check \'material_import_settings\' in your ProjectParameters.json." ) ## Executes the check and prepare model process self._ExecuteCheckAndPrepare() ## Set buffer size self.main_model_part.SetBufferSize(self.min_buffer_size) if (IsDistributedRun()): self.distributed_model_part_importer.CreateCommunicators() self.formulation.PrepareModelPart() Kratos.Logger.PrintInfo(self.__class__.__name__, "Model reading finished.") def ExportModelPart(self): ## Model part writing name_out_file = self.settings["model_import_settings"][ "input_filename"].GetString() + ".out" Kratos.ModelPartIO(name_out_file, Kratos.IO.WRITE).WriteModelPart( self.main_model_part) Kratos.Logger.PrintInfo(self.__class__.__name__, "Model export finished.") def GetMinimumBufferSize(self): return self.min_buffer_size def Initialize(self): if (IsDistributedRun()): self.EpetraComm = KratosTrilinos.CreateCommunicator() self.formulation.SetCommunicator(self.EpetraComm) else: self.formulation.SetCommunicator(None) self.main_model_part.ProcessInfo[Kratos.STEP] = 0 # If needed, create the estimate time step utility if (self.settings["time_stepping"]["automatic_time_step"].GetBool()): self.EstimateDeltaTimeUtility = self._GetAutomaticTimeSteppingUtility( ) RansVariableUtilities.AssignBoundaryFlagsToGeometries( self.main_model_part) self.formulation.Initialize() Kratos.Logger.PrintInfo(self.__class__.__name__, self.formulation.GetInfo()) Kratos.Logger.PrintInfo(self.__class__.__name__, "Solver initialization finished.") def AdvanceInTime(self, current_time): dt = self._ComputeDeltaTime() new_time = current_time + dt self.main_model_part.CloneTimeStep(new_time) self.main_model_part.ProcessInfo[Kratos.STEP] += 1 return new_time def InitializeSolutionStep(self): self.formulation.InitializeSolutionStep() def SolveSolutionStep(self): self.formulation.SolveCouplingStep() self.is_converged = self.formulation.IsConverged() if not self.is_converged and not self.IsSteadySimulation( ) and self.echo_level > -1: msg = "Fluid solver did not converge for step " + str( self.main_model_part.ProcessInfo[Kratos.STEP]) + "\n" msg += "corresponding to time " + str( self.main_model_part.ProcessInfo[Kratos.TIME]) + "\n" Kratos.Logger.PrintWarning(self.__class__.__name__, msg) return self.is_converged def FinalizeSolutionStep(self): self.formulation.FinalizeSolutionStep() def Check(self): self.formulation.Check() def Clear(self): self.formulation.Clear() def IsSteadySimulation(self): return self.is_steady def IsConverged(self): return self.is_steady and self.is_converged def GetComputingModelPart(self): if not self.main_model_part.HasSubModelPart( "fluid_computational_model_part"): raise Exception("The ComputingModelPart was not created yet!") return self.main_model_part.GetSubModelPart( "fluid_computational_model_part") def _ComputeDeltaTime(self): # Automatic time step computation according to user defined CFL number if (self.settings["time_stepping"]["automatic_time_step"].GetBool()): delta_time = self.EstimateDeltaTimeUtility.EstimateDt() # User-defined delta time else: delta_time = self.settings["time_stepping"]["time_step"].GetDouble( ) return delta_time def _GetAutomaticTimeSteppingUtility(self): estimate_delta_time_utility = KratosCFD.EstimateDtUtility( self.GetComputingModelPart(), self.settings["time_stepping"]) return estimate_delta_time_utility def _ExecuteCheckAndPrepare(self): ## Check that the input read has the shape we like prepare_model_part_settings = Kratos.Parameters("{}") prepare_model_part_settings.AddValue( "volume_model_part_name", self.settings["volume_model_part_name"]) prepare_model_part_settings.AddValue("skin_parts", self.settings["skin_parts"]) if (self.settings.Has("assign_neighbour_elements_to_conditions")): prepare_model_part_settings.AddValue( "assign_neighbour_elements_to_conditions", self.settings["assign_neighbour_elements_to_conditions"]) else: warn_msg = "\"assign_neighbour_elements_to_conditions\" should be added to defaults of " + self.__class__.__name__ Kratos.Logger.PrintWarning( '\n\x1b[1;31mDEPRECATION-WARNING\x1b[0m', warn_msg) CheckAndPrepareModelProcess(self.main_model_part, prepare_model_part_settings).Execute() def _SetPhysicalProperties(self): # Check if the fluid properties are provided using a .json file materials_filename = self.settings["material_import_settings"][ "materials_filename"].GetString() if (materials_filename != ""): # Add constitutive laws and material properties from json file to model parts. material_settings = Kratos.Parameters( """{"Parameters": {"materials_filename": ""}} """) material_settings["Parameters"]["materials_filename"].SetString( materials_filename) Kratos.ReadMaterialsUtility(material_settings, self.model) # add wall law properties InitializeWallLawProperties(self.model) # initialize constitutive laws RansVariableUtilities.SetElementConstitutiveLaws( self.main_model_part.Elements) materials_imported = True else: materials_imported = False return materials_imported def Finalize(self): self.formulation.Finalize()
class NavierStokesMPITwoFluidsSolver(NavierStokesTwoFluidsSolver): @classmethod def GetDefaultSettings(cls): default_settings = KratosMultiphysics.Parameters("""{ "solver_type": "TwoFluids", "model_part_name": "", "domain_size": -1, "model_import_settings": { "input_type": "mdpa", "input_filename": "unknown_name", "reorder": false }, "material_import_settings": { "materials_filename": "" }, "distance_reading_settings" : { "import_mode" : "from_mdpa", "distance_file_name" : "no_distance_file" }, "maximum_iterations": 7, "echo_level": 0, "consider_periodic_conditions" : false, "time_order": 2, "compute_reactions": false, "reform_dofs_at_each_step": false, "relative_velocity_tolerance": 1e-3, "absolute_velocity_tolerance": 1e-5, "relative_pressure_tolerance": 1e-3, "absolute_pressure_tolerance": 1e-5, "linear_solver_settings": { "solver_type": "AmgclMPISolver", "tolerance": 1.0e-6, "max_iteration": 10, "scaling": false, "verbosity": 0, "preconditioner_type": "None", "krylov_type": "cg" }, "volume_model_part_name" : "volume_model_part", "skin_parts": [""], "no_skin_parts":[""], "time_stepping": { "automatic_time_step" : true, "CFL_number" : 1, "minimum_delta_time" : 1e-4, "maximum_delta_time" : 0.01 }, "move_mesh_flag": false, "formulation": { "dynamic_tau": 1.0 } }""") default_settings.AddMissingParameters(super(NavierStokesMPITwoFluidsSolver, cls).GetDefaultSettings()) return default_settings def __init__(self, model, custom_settings): self._validate_settings_in_baseclass=True # To be removed eventually # the constructor of the "grand-parent" (jumping constructor of parent) is called to avoid conflicts in attribute settings super(NavierStokesTwoFluidsSolver, self).__init__(model,custom_settings) self.element_name = "TwoFluidNavierStokes" self.condition_name = "NavierStokesWallCondition" self.element_has_nodal_properties = True self.min_buffer_size = 3 if (self.settings["solver_type"].GetString() == "TwoFluids"): self.element_name = "TwoFluidNavierStokes" ## Construct the linear solver self.trilinos_linear_solver = trilinos_linear_solver_factory.ConstructSolver(self.settings["linear_solver_settings"]) KratosMultiphysics.Logger.PrintInfo("NavierStokesMPITwoFluidsSolver","Construction of NavierStokesMPITwoFluidsSolver finished.") def AddVariables(self): super(NavierStokesMPITwoFluidsSolver, self).AddVariables() self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.PrintInfo("NavierStokesMPITwoFluidsSolver","Variables for the Trilinos Two Fluid solver added correctly.") def ImportModelPart(self): ## Construct the distributed import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility(self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() ## Sets DENSITY, VISCOSITY and SOUND_VELOCITY KratosMultiphysics.Logger.PrintInfo("NavierStokesMPITwoFluidsSolver","MPI model reading finished.") def PrepareModelPart(self): super(NavierStokesMPITwoFluidsSolver,self).PrepareModelPart() ## Construct the MPI communicators self.distributed_model_part_importer.CreateCommunicators() def AddDofs(self): super(NavierStokesMPITwoFluidsSolver, self).AddDofs() KratosMultiphysics.Logger.PrintInfo("NavierStokesMPITwoFluidsSolver","DOFs for the Trilinos Two Fluid solver added correctly.") def Initialize(self): ## Construct the communicator self.EpetraCommunicator = KratosTrilinos.CreateCommunicator() ## Get the computing model part self.computing_model_part = self.GetComputingModelPart() KratosMultiphysics.NormalCalculationUtils().CalculateOnSimplex(self.computing_model_part, self.computing_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE]) self.neighbour_search = KratosMultiphysics.FindNodalNeighboursProcess(self.computing_model_part) (self.neighbour_search).Execute() self.accelerationLimitationUtility = KratosMultiphysics.FluidDynamicsApplication.AccelerationLimitationUtilities(self.computing_model_part, 5.0) ## If needed, create the estimate time step utility if (self.settings["time_stepping"]["automatic_time_step"].GetBool()): self.EstimateDeltaTimeUtility = self._GetAutomaticTimeSteppingUtility() # Set the time discretization utility to compute the BDF coefficients time_order = self.settings["time_order"].GetInt() if time_order == 2: self.time_discretization = KratosMultiphysics.TimeDiscretization.BDF(time_order) else: raise Exception("Only \"time_order\" equal to 2 is supported. Provided \"time_order\": " + str(time_order)) ## Creating the Trilinos convergence criteria self.conv_criteria = KratosTrilinos.TrilinosUPCriteria(self.settings["relative_velocity_tolerance"].GetDouble(), self.settings["absolute_velocity_tolerance"].GetDouble(), self.settings["relative_pressure_tolerance"].GetDouble(), self.settings["absolute_pressure_tolerance"].GetDouble()) (self.conv_criteria).SetEchoLevel(self.settings["echo_level"].GetInt()) #### ADDING NEW PROCESSES : level-set-convection and variational-distance-process self.level_set_convection_process = self._set_level_set_convection_process() self.variational_distance_process = self._set_variational_distance_process() ## Creating the Trilinos incremental update time scheme (the time integration is defined within the TwoFluidNavierStokes element) self.time_scheme = KratosTrilinos.TrilinosResidualBasedIncrementalUpdateStaticSchemeSlip(self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE], # Domain size (2,3) self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE]+1) # DOFs (3,4) ## Set the guess_row_size (guess about the number of zero entries) for the Trilinos builder and solver if self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 3: guess_row_size = 20*4 elif self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2: guess_row_size = 10*3 ## Construct the Trilinos builder and solver if self.settings["consider_periodic_conditions"].GetBool() == True: self.builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolverPeriodic(self.EpetraCommunicator, guess_row_size, self.trilinos_linear_solver, KratosFluid.PATCH_INDEX) else: self.builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolver(self.EpetraCommunicator, guess_row_size, self.trilinos_linear_solver) ## Construct the Trilinos Newton-Raphson strategy self.solver = KratosTrilinos.TrilinosNewtonRaphsonStrategy(self.main_model_part, self.time_scheme, self.trilinos_linear_solver, self.conv_criteria, self.builder_and_solver, self.settings["maximum_iterations"].GetInt(), self.settings["compute_reactions"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool(), self.settings["move_mesh_flag"].GetBool()) (self.solver).SetEchoLevel(self.settings["echo_level"].GetInt()) (self.solver).Initialize() (self.solver).Check() self.main_model_part.ProcessInfo.SetValue(KratosMultiphysics.DYNAMIC_TAU, self.settings["formulation"]["dynamic_tau"].GetDouble()) def _set_level_set_convection_process(self): # Construct the level set convection process if self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2: level_set_convection_process = KratosTrilinos.TrilinosLevelSetConvectionProcess2D( self.EpetraCommunicator, KratosMultiphysics.DISTANCE, self.computing_model_part, self.trilinos_linear_solver) else: level_set_convection_process = KratosTrilinos.TrilinosLevelSetConvectionProcess3D( self.EpetraCommunicator, KratosMultiphysics.DISTANCE, self.computing_model_part, self.trilinos_linear_solver) return level_set_convection_process def _set_variational_distance_process(self): # Construct the variational distance calculation process maximum_iterations = 2 if self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2: variational_distance_process = KratosTrilinos.TrilinosVariationalDistanceCalculationProcess2D( self.EpetraCommunicator, self.computing_model_part, self.trilinos_linear_solver, maximum_iterations, KratosMultiphysics.VariationalDistanceCalculationProcess2D.CALCULATE_EXACT_DISTANCES_TO_PLANE) else: variational_distance_process = KratosTrilinos.TrilinosVariationalDistanceCalculationProcess3D( self.EpetraCommunicator, self.computing_model_part, self.trilinos_linear_solver, maximum_iterations, KratosMultiphysics.VariationalDistanceCalculationProcess3D.CALCULATE_EXACT_DISTANCES_TO_PLANE) return variational_distance_process
class TrilinosMeshSolverBase(MeshSolverBase): def __init__(self, model, custom_settings): super(TrilinosMeshSolverBase, self).__init__(model, custom_settings) KratosMultiphysics.Logger.PrintInfo( "::[TrilinosMeshSolverBase]:: Construction finished") @classmethod def GetDefaultSettings(cls): this_defaults = KratosMultiphysics.Parameters("""{ "linear_solver_settings" : { "solver_type" : "amgcl", "smoother_type":"ilu0", "krylov_type": "gmres", "coarsening_type": "aggregation", "max_iteration": 200, "provide_coordinates": false, "gmres_krylov_space_dimension": 100, "verbosity" : 0, "tolerance": 1e-7, "scaling": false, "block_size": 1, "use_block_matrices_if_possible" : true, "coarse_enough" : 5000 } }""") this_defaults.AddMissingParameters( super(TrilinosMeshSolverBase, cls).GetDefaultSettings()) return this_defaults #### Public user interface functions #### def AddVariables(self): super(TrilinosMeshSolverBase, self).AddVariables() self.mesh_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.PrintInfo( "::[TrilinosMeshSolverBase]:: Variables ADDED.") def ImportModelPart(self): KratosMultiphysics.Logger.PrintInfo("::[TrilinosMeshSolverBase]:: ", "Importing model part.") self.distributed_model_part_importer = DistributedImportModelPartUtility( self.mesh_model_part, self.settings) self.distributed_model_part_importer.ImportModelPart() KratosMultiphysics.Logger.PrintInfo("::[TrilinosMeshSolverBase]:: ", "Finished importing model part.") def PrepareModelPart(self): super(TrilinosMeshSolverBase, self).PrepareModelPart() # Construct the mpi-communicator self.distributed_model_part_importer.CreateCommunicators() KratosMultiphysics.Logger.PrintInfo("::[TrilinosMeshSolverBase]::", "ModelPart prepared for Solver.") def Finalize(self): super(TrilinosMeshSolverBase, self).Finalize() self.get_mesh_motion_solving_strategy().Clear( ) # needed for proper finalization of MPI #### Specific internal functions #### def get_communicator(self): if not hasattr(self, '_communicator'): self._communicator = TrilinosApplication.CreateCommunicator() return self._communicator #### Private functions #### def _create_linear_solver(self): return trilinos_linear_solver_factory.ConstructSolver( self.settings["mesh_motion_linear_solver_settings"]) def _create_mesh_motion_solving_strategy(self): raise Exception( "Mesh motion solver must be created by the derived class.")
class TrilinosNavierStokesSolverFractionalStep(NavierStokesSolverFractionalStep ): @classmethod def GetDefaultSettings(cls): ## Default settings string in Json format default_settings = KratosMultiphysics.Parameters(""" { "solver_type": "FractionalStep", "model_part_name": "", "domain_size": -1, "model_import_settings": { "input_type": "mdpa", "input_filename": "unknown_name" }, "material_import_settings": { "materials_filename": "" }, "predictor_corrector": false, "maximum_velocity_iterations": 3, "maximum_pressure_iterations": 3, "velocity_tolerance": 1e-3, "pressure_tolerance": 1e-2, "dynamic_tau": 0.01, "oss_switch": 0, "echo_level": 0, "consider_periodic_conditions": false, "time_order": 2, "compute_reactions": false, "reform_dofs_at_each_step": false, "pressure_linear_solver_settings": { "solver_type": "amgcl" }, "velocity_linear_solver_settings": { "solver_type": "amgcl" }, "volume_model_part_name" : "volume_model_part", "skin_parts":[""], "no_skin_parts":[""], "time_stepping": { "automatic_time_step" : false, "CFL_number" : 1, "minimum_delta_time" : 1e-4, "maximum_delta_time" : 0.01 }, "move_mesh_flag": false, "use_slip_conditions": true }""") default_settings.AddMissingParameters( super(TrilinosNavierStokesSolverFractionalStep, cls).GetDefaultSettings()) return default_settings def __init__(self, model, custom_settings): self._validate_settings_in_baseclass = True # To be removed eventually # Note: deliberately calling the constructor of the base python solver (the parent of my parent) super(NavierStokesSolverFractionalStep, self).__init__(model, custom_settings) self.element_name = "FractionalStep" self.condition_name = "WallCondition" self.min_buffer_size = 3 self.element_has_nodal_properties = True self.compute_reactions = self.settings["compute_reactions"].GetBool() self.main_model_part.ProcessInfo.SetValue( KratosMultiphysics.OSS_SWITCH, self.settings["oss_switch"].GetInt()) self.main_model_part.ProcessInfo.SetValue( KratosMultiphysics.DYNAMIC_TAU, self.settings["dynamic_tau"].GetDouble()) KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "Construction of TrilinosNavierStokesSolverFractionalStep solver finished." ) def AddVariables(self): ## Add variables from the base class super(TrilinosNavierStokesSolverFractionalStep, self).AddVariables() ## Add specific MPI variables self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "variables for the trilinos fractional step solver added correctly" ) def ImportModelPart(self): ## Construct the MPI import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "MPI model reading finished.") def PrepareModelPart(self): super(TrilinosNavierStokesSolverFractionalStep, self).PrepareModelPart() ## Construct MPI communicators self.distributed_model_part_importer.CreateCommunicators() def AddDofs(self): ## Base class DOFs addition super(TrilinosNavierStokesSolverFractionalStep, self).AddDofs() KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "DOFs for the VMS Trilinos fluid solver added correctly in all processors." ) def Initialize(self): ## Base class solver intiialization super(TrilinosNavierStokesSolverFractionalStep, self).Initialize() KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Solver initialization finished.") def Finalize(self): self._GetSolutionStrategy().Clear() def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): self._epetra_communicator = KratosTrilinos.CreateCommunicator() return self._epetra_communicator def _CreateScheme(self): pass def _CreateLinearSolver(self): # Create the pressure linear solver pressure_linear_solver_configuration = self.settings[ "pressure_linear_solver_settings"] pressure_linear_solver = trilinos_linear_solver_factory.ConstructSolver( pressure_linear_solver_configuration) # Create the velocity linear solver velocity_linear_solver_configuration = self.settings[ "velocity_linear_solver_settings"] velocity_linear_solver = trilinos_linear_solver_factory.ConstructSolver( velocity_linear_solver_configuration) # Return a tuple containing both linear solvers return (pressure_linear_solver, velocity_linear_solver) def _CreateConvergenceCriterion(self): pass def _CreateBuilderAndSolver(self): pass def _CreateSolutionStrategy(self): computing_model_part = self.GetComputingModelPart() epetra_communicator = self._GetEpetraCommunicator() domain_size = computing_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] # Create the pressure and velocity linear solvers # Note that linear_solvers is a tuple. The first item is the pressure # linear solver. The second item is the velocity linear solver. linear_solvers = self._GetLinearSolver() # Create the fractional step settings instance # TODO: next part would be much cleaner if we passed directly the parameters to the c++ if self.settings["consider_periodic_conditions"].GetBool(): fractional_step_settings = TrilinosFluid.TrilinosFractionalStepSettingsPeriodic( epetra_communicator, computing_model_part, domain_size, self.settings["time_order"].GetInt(), self.settings["use_slip_conditions"].GetBool(), self.settings["move_mesh_flag"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool(), KratosCFD.PATCH_INDEX) else: fractional_step_settings = TrilinosFluid.TrilinosFractionalStepSettings( epetra_communicator, computing_model_part, domain_size, self.settings["time_order"].GetInt(), self.settings["use_slip_conditions"].GetBool(), self.settings["move_mesh_flag"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool()) # Set the strategy echo level fractional_step_settings.SetEchoLevel( self.settings["echo_level"].GetInt()) # Set the velocity and pressure fractional step strategy settings fractional_step_settings.SetStrategy( TrilinosFluid.TrilinosStrategyLabel.Pressure, linear_solvers[0], self.settings["pressure_tolerance"].GetDouble(), self.settings["maximum_pressure_iterations"].GetInt()) fractional_step_settings.SetStrategy( TrilinosFluid.TrilinosStrategyLabel.Velocity, linear_solvers[1], self.settings["velocity_tolerance"].GetDouble(), self.settings["maximum_velocity_iterations"].GetInt()) # Create the fractional step strategy if self.settings["consider_periodic_conditions"].GetBool(): solution_strategy = TrilinosFluid.TrilinosFSStrategy( computing_model_part, fractional_step_settings, self.settings["predictor_corrector"].GetBool(), KratosCFD.PATCH_INDEX) else: solution_strategy = TrilinosFluid.TrilinosFSStrategy( computing_model_part, fractional_step_settings, self.settings["predictor_corrector"].GetBool()) return solution_strategy
class TrilinosNavierStokesSolverMonolithic( navier_stokes_solver_vmsmonolithic.NavierStokesSolverMonolithic): @classmethod def GetDefaultSettings(cls): ## Default settings string in json format default_settings = KratosMultiphysics.Parameters(""" { "solver_type": "trilinos_navier_stokes_solver_vmsmonolithic", "model_part_name": "", "domain_size": -1, "model_import_settings": { "input_type": "mdpa", "input_filename": "unknown_name" }, "material_import_settings": { "materials_filename": "" }, "formulation": { "element_type": "vms" }, "maximum_iterations": 10, "echo_level": 0, "consider_periodic_conditions": false, "compute_reactions": false, "reform_dofs_at_each_step": false, "relative_velocity_tolerance": 1e-5, "absolute_velocity_tolerance": 1e-7, "relative_pressure_tolerance": 1e-5, "absolute_pressure_tolerance": 1e-7, "linear_solver_settings": { "solver_type": "amgcl" }, "volume_model_part_name" : "volume_model_part", "skin_parts": [""], "no_skin_parts":[""], "time_stepping": { "automatic_time_step" : false, "CFL_number" : 1, "minimum_delta_time" : 1e-4, "maximum_delta_time" : 0.01 }, "time_scheme": "bossak", "alpha":-0.3, "move_mesh_strategy": 0, "periodic": "periodic", "regularization_coef": 1000, "move_mesh_flag": false, "turbulence_model_solver_settings": {} }""") default_settings.AddMissingParameters( super(TrilinosNavierStokesSolverMonolithic, cls).GetDefaultSettings()) return default_settings def __init__(self, model, custom_settings): self._validate_settings_in_baseclass = True # To be removed eventually # Note: deliberately calling the constructor of the base python solver (the parent of my parent) custom_settings = self._BackwardsCompatibilityHelper(custom_settings) super(navier_stokes_solver_vmsmonolithic.NavierStokesSolverMonolithic, self).__init__(model, custom_settings) self.formulation = navier_stokes_solver_vmsmonolithic.StabilizedFormulation( self.settings["formulation"]) self.element_name = self.formulation.element_name self.condition_name = self.formulation.condition_name self.element_integrates_in_time = self.formulation.element_integrates_in_time self.element_has_nodal_properties = self.formulation.element_has_nodal_properties scheme_type = self.settings["time_scheme"].GetString() if scheme_type == "bossak": self.min_buffer_size = 2 elif scheme_type == "bdf2": self.min_buffer_size = 3 elif scheme_type == "steady": self.min_buffer_size = 1 self._SetUpSteadySimulation() else: msg = "Unknown time_scheme option found in project parameters:\n" msg += "\"" + scheme_type + "\"\n" msg += "Accepted values are \"bossak\", \"bdf2\" or \"steady\".\n" raise Exception(msg) ## Construct the turbulence model solver if not self.settings["turbulence_model_solver_settings"].IsEquivalentTo( KratosMultiphysics.Parameters("{}")): self._turbulence_model_solver = CreateTurbulenceModel( self.main_model_part, self.settings["turbulence_model_solver_settings"]) self.condition_name = self._turbulence_model_solver.GetFluidVelocityPressureConditionName( ) KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "Using " + self.condition_name + " as wall condition") KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "Construction of TrilinosNavierStokesSolverMonolithic finished.") def AddVariables(self): ## Add variables from the base class super(TrilinosNavierStokesSolverMonolithic, self).AddVariables() ## Add specific MPI variables self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.Print( "Variables for the VMS fluid Trilinos solver added correctly in each processor." ) def ImportModelPart(self): ## Construct the MPI import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "MPI model reading finished.") def PrepareModelPart(self): # Call the base solver to do the PrepareModelPart # Note that his also calls the PrepareModelPart of the turbulence model super(TrilinosNavierStokesSolverMonolithic, self).PrepareModelPart() # Create the MPI communicators self.distributed_model_part_importer.CreateCommunicators() def Initialize(self): # If there is turbulence modelling, set the Epetra communicator in the turbulence solver if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.SetCommunicator( self._GetEpetraCommunicator()) # Call the base Initialize() method to create and initialize the strategy super(TrilinosNavierStokesSolverMonolithic, self).Initialize() KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Solver initialization finished.") def Finalize(self): self._GetSolutionStrategy().Clear() if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.Finalize() def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): self._epetra_communicator = KratosTrilinos.CreateCommunicator() return self._epetra_communicator def _CreateScheme(self): domain_size = self.GetComputingModelPart().ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] # Cases in which the element manages the time integration if self.element_integrates_in_time: # "Fake" scheme for those cases in where the element manages the time integration # It is required to perform the nodal update once the current time step is solved scheme = KratosTrilinos.TrilinosResidualBasedIncrementalUpdateStaticSchemeSlip( domain_size, domain_size + 1) # In case the BDF2 scheme is used inside the element, set the time discretization utility to compute the BDF coefficients if (self.settings["time_scheme"].GetString() == "bdf2"): time_order = 2 self.time_discretization = KratosMultiphysics.TimeDiscretization.BDF( time_order) else: err_msg = "Requested elemental time scheme " + self.settings[ "time_scheme"].GetString() + " is not available.\n" err_msg += "Available options are: \"bdf2\"" raise Exception(err_msg) # Cases in which a time scheme manages the time integration else: if not hasattr(self, "_turbulence_model_solver"): # Bossak time integration scheme if self.settings["time_scheme"].GetString() == "bossak": # TODO: Can we remove this periodic check, Is the PATCH_INDEX used in this scheme? if self.settings["consider_periodic_conditions"].GetBool( ) == True: scheme = TrilinosFluid.TrilinosPredictorCorrectorVelocityBossakSchemeTurbulent( self.settings["alpha"].GetDouble(), domain_size, KratosCFD.PATCH_INDEX) else: scheme = TrilinosFluid.TrilinosPredictorCorrectorVelocityBossakSchemeTurbulent( self.settings["alpha"].GetDouble(), self.settings["move_mesh_strategy"].GetInt(), domain_size) # BDF2 time integration scheme elif self.settings["time_scheme"].GetString() == "bdf2": scheme = TrilinosFluid.TrilinosGearScheme() # Time scheme for steady state fluid solver elif self.settings["time_scheme"].GetString() == "steady": scheme = TrilinosFluid.TrilinosResidualBasedSimpleSteadyScheme( self.settings["velocity_relaxation"].GetDouble(), self.settings["pressure_relaxation"].GetDouble(), domain_size) else: self._turbulence_model_solver.Initialize() if self.settings["time_scheme"].GetString() == "bossak": scheme = TrilinosFluid.TrilinosPredictorCorrectorVelocityBossakSchemeTurbulent( self.settings["alpha"].GetDouble(), self.settings["move_mesh_strategy"].GetInt(), domain_size, self.settings["turbulence_model_solver_settings"] ["velocity_pressure_relaxation_factor"].GetDouble(), self._turbulence_model_solver. GetTurbulenceSolvingProcess()) # Time scheme for steady state fluid solver elif self.settings["time_scheme"].GetString() == "steady": scheme = TrilinosFluid.TrilinosResidualBasedSimpleSteadyScheme( self.settings["velocity_relaxation"].GetDouble(), self.settings["pressure_relaxation"].GetDouble(), domain_size, self._turbulence_model_solver. GetTurbulenceSolvingProcess()) return scheme def _CreateLinearSolver(self): linear_solver_configuration = self.settings["linear_solver_settings"] return trilinos_linear_solver_factory.ConstructSolver( linear_solver_configuration) def _CreateConvergenceCriterion(self): if self.settings["time_scheme"].GetString() == "steady": convergence_criterion = KratosTrilinos.TrilinosResidualCriteria( self.settings["relative_velocity_tolerance"].GetDouble(), self.settings["absolute_velocity_tolerance"].GetDouble()) else: convergence_criterion = KratosTrilinos.TrilinosUPCriteria( self.settings["relative_velocity_tolerance"].GetDouble(), self.settings["absolute_velocity_tolerance"].GetDouble(), self.settings["relative_pressure_tolerance"].GetDouble(), self.settings["absolute_pressure_tolerance"].GetDouble()) convergence_criterion.SetEchoLevel( self.settings["echo_level"].GetInt()) return convergence_criterion def _CreateBuilderAndSolver(self): # Set the guess_row_size (guess about the number of zero entries) for the Trilinos builder and solver domain_size = self.GetComputingModelPart().ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] if domain_size == 3: guess_row_size = 20 * 4 else: guess_row_size = 10 * 3 # Construct the Trilinos builder and solver trilinos_linear_solver = self._GetLinearSolver() epetra_communicator = self._GetEpetraCommunicator() if self.settings["consider_periodic_conditions"].GetBool(): builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolverPeriodic( epetra_communicator, guess_row_size, trilinos_linear_solver, KratosFluid.PATCH_INDEX) else: builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolver( epetra_communicator, guess_row_size, trilinos_linear_solver) return builder_and_solver def _CreateSolutionStrategy(self): computing_model_part = self.GetComputingModelPart() time_scheme = self._GetScheme() linear_solver = self._GetLinearSolver() convergence_criterion = self._GetConvergenceCriterion() builder_and_solver = self._GetBuilderAndSolver() return KratosTrilinos.TrilinosNewtonRaphsonStrategy( computing_model_part, time_scheme, linear_solver, convergence_criterion, builder_and_solver, self.settings["maximum_iterations"].GetInt(), self.settings["compute_reactions"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool(), self.settings["move_mesh_flag"].GetBool())
class AdjointVMSMonolithicMPISolver(AdjointVMSMonolithicSolver): @classmethod def GetDefaultSettings(cls): # default settings string in json format default_settings = KratosMultiphysics.Parameters(""" { "solver_type": "trilinos_adjoint_vmsmonolithic_solver", "scheme_settings" : { "scheme_type": "bossak" }, "response_function_settings" : { "response_type" : "drag" }, "sensitivity_settings" : {}, "model_import_settings": { "input_type": "mdpa", "input_filename": "unknown_name" }, "linear_solver_settings" : { "solver_type" : "multi_level" }, "volume_model_part_name" : "volume_model_part", "skin_parts": [""], "dynamic_tau": 0.0, "oss_switch": 0, "echo_level": 0, "time_stepping" : { "automatic_time_step" : false, "time_step" : -0.1 }, "domain_size": -1, "model_part_name": "", "time_stepping": { "automatic_time_step" : false, "time_step" : -0.1 } }""") default_settings.AddMissingParameters( super(AdjointVMSMonolithicMPISolver, cls).GetDefaultSettings()) return default_settings def __init__(self, model, custom_settings): self._validate_settings_in_baseclass = True # To be removed eventually super(AdjointVMSMonolithicSolver, self).__init__(model, custom_settings) self.element_name = "VMSAdjointElement" if self.settings["domain_size"].GetInt() == 2: self.condition_name = "LineCondition" elif self.settings["domain_size"].GetInt() == 3: self.condition_name = "SurfaceCondition" self.min_buffer_size = 2 # construct the linear solver self.trilinos_linear_solver = trilinos_linear_solver_factory.ConstructSolver( self.settings["linear_solver_settings"]) KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "Construction of AdjointVMSMonolithicMPISolver finished.") def AddVariables(self): ## Add variables from the base class super(self.__class__, self).AddVariables() ## Add specific MPI variables self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "Variables for the AdjointVMSMonolithicMPISolver added correctly in each processor." ) def ImportModelPart(self): ## Construct the distributed import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ExecutePartitioningAndReading() KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "TrilinosNavierStokesSolverMonolithic", "MPI model reading finished.") def PrepareModelPart(self): super(self.__class__, self).PrepareModelPart() ## Construct the MPI communicators self.distributed_model_part_importer.CreateCommunicators() def AddDofs(self): super(self.__class__, self).AddDofs() KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "DOFs for the AdjointVMSMonolithicMPISolver added correctly in all processors." ) def Initialize(self): ## Construct the communicator self.EpetraCommunicator = TrilinosApplication.CreateCommunicator() ## Get the computing model part self.computing_model_part = self.GetComputingModelPart() domain_size = self.main_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] if self.settings["response_function_settings"][ "response_type"].GetString() == "drag": if (domain_size == 2): self.response_function = FluidDynamicsApplication.DragResponseFunction2D( self.settings["response_function_settings"] ["custom_settings"], self.main_model_part) elif (domain_size == 3): self.response_function = FluidDynamicsApplication.DragResponseFunction3D( self.settings["response_function_settings"] ["custom_settings"], self.main_model_part) else: raise Exception("Invalid DOMAIN_SIZE: " + str(domain_size)) else: raise Exception("invalid response_type: " + self.settings["response_function_settings"] ["response_type"].GetString()) self.sensitivity_builder = KratosMultiphysics.SensitivityBuilder( self.settings["sensitivity_settings"], self.main_model_part, self.response_function) if self.settings["scheme_settings"]["scheme_type"].GetString( ) == "bossak": self.time_scheme = TrilinosApplication.TrilinosResidualBasedAdjointBossakScheme( self.settings["scheme_settings"], self.response_function) elif self.settings["scheme_settings"]["scheme_type"].GetString( ) == "steady": self.time_scheme = TrilinosApplication.TrilinosResidualBasedAdjointSteadyScheme( self.response_function) else: raise Exception( "invalid scheme_type: " + self.settings["scheme_settings"]["scheme_type"].GetString()) if self.main_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] == 3: guess_row_size = 20 * 4 elif self.main_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] == 2: guess_row_size = 10 * 3 self.builder_and_solver = TrilinosApplication.TrilinosBlockBuilderAndSolver( self.EpetraCommunicator, guess_row_size, self.trilinos_linear_solver) self.solver = TrilinosApplication.TrilinosLinearStrategy( self.main_model_part, self.time_scheme, self.trilinos_linear_solver, self.builder_and_solver, False, False, False, False) (self.solver).SetEchoLevel(self.settings["echo_level"].GetInt()) (self.solver).Initialize() (self.response_function).Initialize() (self.sensitivity_builder).Initialize() self.main_model_part.ProcessInfo.SetValue( KratosMultiphysics.DYNAMIC_TAU, self.settings["dynamic_tau"].GetDouble()) self.main_model_part.ProcessInfo.SetValue( KratosMultiphysics.OSS_SWITCH, self.settings["oss_switch"].GetInt()) KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "Monolithic MPI solver initialization finished.")
class TrilinosMechanicalSolver(MechanicalSolver): """The base class for trilinos structural mechanics solver. See structural_mechanics_solver.py for more information. """ def __init__(self, model, custom_settings): # Construct the base solver. super().__init__(model, custom_settings) KratosMultiphysics.Logger.PrintInfo("::[TrilinosMechanicalSolver]:: ", "Construction finished") @classmethod def GetDefaultParameters(cls): this_defaults = KratosMultiphysics.Parameters("""{ "multi_point_constraints_used": false, "linear_solver_settings" : { "solver_type" : "amesos", "amesos_solver_type" : "Amesos_Klu" } }""") this_defaults.AddMissingParameters(super().GetDefaultParameters()) return this_defaults def AddVariables(self): super().AddVariables() self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.PrintInfo("::[TrilinosMechanicalSolver]:: ", "Variables ADDED") def ImportModelPart(self): KratosMultiphysics.Logger.PrintInfo("::[TrilinosMechanicalSolver]:: ", "Importing model part.") self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) self.distributed_model_part_importer.ImportModelPart() KratosMultiphysics.Logger.PrintInfo("::[TrilinosMechanicalSolver]:: ", "Finished importing model part.") def PrepareModelPart(self): super().PrepareModelPart() # Construct the mpi-communicator self.distributed_model_part_importer.CreateCommunicators() KratosMultiphysics.Logger.PrintInfo("::[TrilinosMechanicalSolver]::", "ModelPart prepared for Solver.") def Finalize(self): super().Finalize() self.get_mechanical_solution_strategy().Clear( ) # needed for proper finalization of MPI #### Specific internal functions #### def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): self._epetra_communicator = self._create_epetra_communicator() return self._epetra_communicator #### Private functions #### def _create_epetra_communicator(self): return TrilinosApplication.CreateCommunicator() def _create_convergence_criterion(self): convergence_criterion = convergence_criteria_factory.convergence_criterion( self._get_convergence_criterion_settings()) return convergence_criterion.mechanical_convergence_criterion def _create_linear_solver(self): return trilinos_linear_solver_factory.ConstructSolver( self.settings["linear_solver_settings"]) def _create_builder_and_solver(self): if self.settings["multi_point_constraints_used"].GetBool(): raise Exception("MPCs not yet implemented in MPI") if (self.GetComputingModelPart().NumberOfMasterSlaveConstraints() > 0): KratosMultiphysics.Logger.PrintWarning( "Constraints are not yet implemented in MPI and will therefore not be considered!" ) linear_solver = self.get_linear_solver() epetra_communicator = self._GetEpetraCommunicator() if (self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2): guess_row_size = 15 else: guess_row_size = 45 if self.settings["builder_and_solver_settings"][ "use_block_builder"].GetBool(): builder_and_solver = TrilinosApplication.TrilinosBlockBuilderAndSolver( epetra_communicator, guess_row_size, linear_solver) else: builder_and_solver = TrilinosApplication.TrilinosEliminationBuilderAndSolver( epetra_communicator, guess_row_size, linear_solver) return builder_and_solver def _create_linear_strategy(self): computing_model_part = self.GetComputingModelPart() mechanical_scheme = self.get_solution_scheme() linear_solver = self.get_linear_solver() builder_and_solver = self.get_builder_and_solver() return TrilinosApplication.TrilinosLinearStrategy( computing_model_part, mechanical_scheme, builder_and_solver, self.settings["compute_reactions"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool(), False, self.settings["move_mesh_flag"].GetBool()) def _create_newton_raphson_strategy(self): computing_model_part = self.GetComputingModelPart() solution_scheme = self.get_solution_scheme() linear_solver = self.get_linear_solver() convergence_criterion = self.get_convergence_criterion() builder_and_solver = self.get_builder_and_solver() return TrilinosApplication.TrilinosNewtonRaphsonStrategy( computing_model_part, solution_scheme, convergence_criterion, builder_and_solver, self.settings["max_iteration"].GetInt(), self.settings["compute_reactions"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool(), self.settings["move_mesh_flag"].GetBool())
class NavierStokesMPIEmbeddedMonolithicSolver( navier_stokes_embedded_solver.NavierStokesEmbeddedMonolithicSolver): @classmethod def GetDefaultParameters(cls): default_settings = KratosMultiphysics.Parameters("""{ "solver_type": "Embedded", "model_part_name": "", "domain_size": -1, "model_import_settings": { "input_type": "mdpa", "input_filename": "unknown_name" }, "material_import_settings": { "materials_filename": "" }, "distance_reading_settings" : { "import_mode" : "from_GID_file", "distance_file_name" : "distance_file" }, "distance_modification_settings": { }, "maximum_iterations": 7, "echo_level": 0, "consider_periodic_conditions": false, "time_order": 2, "time_scheme": "bdf2", "compute_reactions": false, "analysis_type": "non_linear", "reform_dofs_at_each_step": false, "relative_velocity_tolerance": 1e-3, "absolute_velocity_tolerance": 1e-5, "relative_pressure_tolerance": 1e-3, "absolute_pressure_tolerance": 1e-5, "linear_solver_settings": { "solver_type": "amgcl" }, "volume_model_part_name" : "volume_model_part", "skin_parts": [""], "no_skin_parts":[""], "time_stepping": { "automatic_time_step" : true, "CFL_number" : 1, "minimum_delta_time" : 1e-4, "maximum_delta_time" : 0.01 }, "move_mesh_flag": false, "formulation": { "element_type": "embedded_element_from_defaults", "dynamic_tau": 1.0 }, "fm_ale_settings": { "fm_ale_step_frequency": 0, "structure_model_part_name": "", "search_radius" : 1.0 } }""") default_settings.AddMissingParameters( super(NavierStokesMPIEmbeddedMonolithicSolver, cls).GetDefaultParameters()) return default_settings def __init__(self, model, custom_settings): self._validate_settings_in_baseclass = True # To be removed eventually # Note: deliberately calling the constructor of the base python solver (the parent of my parent) # TODO: ONCE THE FM-ALE WORKS IN MPI, IT WOULD BE POSSIBLE TO ONLY CALL THE BASE CLASS CONSTRUCTOR super( navier_stokes_embedded_solver.NavierStokesEmbeddedMonolithicSolver, self).__init__(model, custom_settings) self.min_buffer_size = 3 self.embedded_formulation = navier_stokes_embedded_solver.EmbeddedFormulation( self.settings["formulation"]) self.element_name = self.embedded_formulation.element_name self.condition_name = self.embedded_formulation.condition_name self.level_set_type = self.embedded_formulation.level_set_type self.element_integrates_in_time = self.embedded_formulation.element_integrates_in_time self.element_has_nodal_properties = self.embedded_formulation.element_has_nodal_properties self.historical_nodal_properties_variables_list = self.embedded_formulation.historical_nodal_properties_variables_list self.non_historical_nodal_properties_variables_list = self.embedded_formulation.non_historical_nodal_properties_variables_list KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "Construction of NavierStokesMPIEmbeddedMonolithicSolver finished." ) def AddVariables(self): super(NavierStokesMPIEmbeddedMonolithicSolver, self).AddVariables() self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "Variables for the Trilinos monolithic embedded fluid solver added correctly." ) def ImportModelPart(self): ## Construct the Distributed import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() ## Sets DENSITY, VISCOSITY and SOUND_VELOCITY KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "MPI model reading finished.") def PrepareModelPart(self): super(NavierStokesMPIEmbeddedMonolithicSolver, self).PrepareModelPart() ## Construct MPI the communicators self.distributed_model_part_importer.CreateCommunicators() def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): self._epetra_communicator = KratosTrilinos.CreateCommunicator() return self._epetra_communicator def _CreateScheme(self): domain_size = self.GetComputingModelPart().ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] # Cases in which the element manages the time integration if self.element_integrates_in_time: # "Fake" scheme for those cases in where the element manages the time integration # It is required to perform the nodal update once the current time step is solved scheme = KratosTrilinos.TrilinosResidualBasedIncrementalUpdateStaticSchemeSlip( domain_size, domain_size + 1) # In case the BDF2 scheme is used inside the element, the BDF time discretization utility is required to update the BDF coefficients if (self.settings["time_scheme"].GetString() == "bdf2"): time_order = 2 self.time_discretization = KratosMultiphysics.TimeDiscretization.BDF( time_order) else: err_msg = "Requested elemental time scheme \"" + self.settings[ "time_scheme"].GetString() + "\" is not available.\n" err_msg += "Available options are: \"bdf2\"" raise Exception(err_msg) # Cases in which a time scheme manages the time integration else: err_msg = "Custom scheme creation is not allowed. Embedded Navier-Stokes elements manage the time integration internally." raise Exception(err_msg) return scheme def _CreateLinearSolver(self): linear_solver_configuration = self.settings["linear_solver_settings"] return trilinos_linear_solver_factory.ConstructSolver( linear_solver_configuration) def _CreateConvergenceCriterion(self): convergence_criterion = KratosTrilinos.TrilinosMixedGenericCriteria([ (KratosMultiphysics.VELOCITY, self.settings["relative_velocity_tolerance"].GetDouble(), self.settings["absolute_velocity_tolerance"].GetDouble()), (KratosMultiphysics.PRESSURE, self.settings["relative_pressure_tolerance"].GetDouble(), self.settings["absolute_pressure_tolerance"].GetDouble()) ]) convergence_criterion.SetEchoLevel( self.settings["echo_level"].GetInt()) return convergence_criterion def _CreateBuilderAndSolver(self): # Set the guess_row_size (guess about the number of zero entries) for the Trilinos builder and solver domain_size = self.GetComputingModelPart().ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] if domain_size == 3: guess_row_size = 20 * 4 else: guess_row_size = 10 * 3 # Construct the Trilinos builder and solver trilinos_linear_solver = self._GetLinearSolver() epetra_communicator = self._GetEpetraCommunicator() if self.settings["consider_periodic_conditions"].GetBool(): builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolverPeriodic( epetra_communicator, guess_row_size, trilinos_linear_solver, KratosFluid.PATCH_INDEX) else: builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolver( epetra_communicator, guess_row_size, trilinos_linear_solver) return builder_and_solver def _CreateSolutionStrategy(self): computing_model_part = self.GetComputingModelPart() time_scheme = self._GetScheme() linear_solver = self._GetLinearSolver() convergence_criterion = self._GetConvergenceCriterion() builder_and_solver = self._GetBuilderAndSolver() return KratosTrilinos.TrilinosNewtonRaphsonStrategy( computing_model_part, time_scheme, linear_solver, convergence_criterion, builder_and_solver, self.settings["maximum_iterations"].GetInt(), self.settings["compute_reactions"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool(), self.settings["move_mesh_flag"].GetBool()) @classmethod def _FmAleIsActive(self): return False
class TrilinosNavierStokesSolverMonolithic( navier_stokes_solver_vmsmonolithic.NavierStokesSolverMonolithic): @classmethod def GetDefaultSettings(cls): ## Default settings string in json format default_settings = KratosMultiphysics.Parameters(""" { "solver_type": "trilinos_navier_stokes_solver_vmsmonolithic", "model_part_name": "", "domain_size": -1, "model_import_settings": { "input_type": "mdpa", "input_filename": "unknown_name" }, "material_import_settings": { "materials_filename": "unknown_materials.json" }, "formulation": { "element_type": "vms" }, "maximum_iterations": 10, "echo_level": 0, "consider_periodic_conditions": false, "time_order": 2, "compute_reactions": false, "reform_dofs_at_each_step": false, "relative_velocity_tolerance": 1e-5, "absolute_velocity_tolerance": 1e-7, "relative_pressure_tolerance": 1e-5, "absolute_pressure_tolerance": 1e-7, "linear_solver_settings" : { "solver_type" : "multi_level", "max_iteration" : 200, "tolerance" : 1e-8, "max_levels" : 3, "symmetric" : false, "reform_preconditioner_at_each_step" : true, "scaling" : true }, "volume_model_part_name" : "volume_model_part", "skin_parts": [""], "no_skin_parts":[""], "time_stepping": { "automatic_time_step" : false, "CFL_number" : 1, "minimum_delta_time" : 1e-4, "maximum_delta_time" : 0.01 }, "time_scheme": "bossak", "alpha":-0.3, "move_mesh_strategy": 0, "periodic": "periodic", "regularization_coef": 1000, "move_mesh_flag": false, "turbulence_model": "None" }""") default_settings.AddMissingParameters( super(TrilinosNavierStokesSolverMonolithic, cls).GetDefaultSettings()) return default_settings def __init__(self, model, custom_settings): self._validate_settings_in_baseclass = True # To be removed eventually # Note: deliberately calling the constructor of the base python solver (the parent of my parent) custom_settings = self._BackwardsCompatibilityHelper(custom_settings) super(navier_stokes_solver_vmsmonolithic.NavierStokesSolverMonolithic, self).__init__(model, custom_settings) self.formulation = navier_stokes_solver_vmsmonolithic.StabilizedFormulation( self.settings["formulation"]) self.element_name = self.formulation.element_name self.condition_name = self.formulation.condition_name self.min_buffer_size = 2 ## Construct the linear solver self.trilinos_linear_solver = trilinos_linear_solver_factory.ConstructSolver( self.settings["linear_solver_settings"]) KratosMultiphysics.Logger.Print( "Construction of TrilinosNavierStokesSolverMonolithic finished.") def AddVariables(self): ## Add variables from the base class super(TrilinosNavierStokesSolverMonolithic, self).AddVariables() ## Add specific MPI variables self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.Print( "Variables for the VMS fluid Trilinos solver added correctly in each processor." ) def ImportModelPart(self): ## Construct the MPI import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() KratosMultiphysics.Logger.PrintInfo( "TrilinosNavierStokesSolverMonolithic", "MPI model reading finished.") def PrepareModelPart(self): super(TrilinosNavierStokesSolverMonolithic, self).PrepareModelPart() ## Construct the MPI communicators self.distributed_model_part_importer.CreateCommunicators() def AddDofs(self): ## Base class DOFs addition super(TrilinosNavierStokesSolverMonolithic, self).AddDofs() KratosMultiphysics.Logger.Print( "DOFs for the VMS Trilinos fluid solver added correctly in all processors." ) def Initialize(self): ## Construct the communicator self.EpetraCommunicator = KratosTrilinos.CreateCommunicator() ## Get the computing model part self.computing_model_part = self.GetComputingModelPart() ## If needed, create the estimate time step utility if (self.settings["time_stepping"]["automatic_time_step"].GetBool()): self.EstimateDeltaTimeUtility = self._GetAutomaticTimeSteppingUtility( ) ## Creating the Trilinos convergence criteria self.conv_criteria = KratosTrilinos.TrilinosUPCriteria( self.settings["relative_velocity_tolerance"].GetDouble(), self.settings["absolute_velocity_tolerance"].GetDouble(), self.settings["relative_pressure_tolerance"].GetDouble(), self.settings["absolute_pressure_tolerance"].GetDouble()) (self.conv_criteria).SetEchoLevel(self.settings["echo_level"].GetInt()) ## Creating the Trilinos time scheme if (self.settings["turbulence_model"].GetString() == "None"): if self.settings["consider_periodic_conditions"].GetBool() == True: self.time_scheme = KratosTrilinos.TrilinosPredictorCorrectorVelocityBossakSchemeTurbulent( self.settings["alpha"].GetDouble(), self.computing_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE], KratosCFD.PATCH_INDEX) else: self.time_scheme = KratosTrilinos.TrilinosPredictorCorrectorVelocityBossakSchemeTurbulent( self.settings["alpha"].GetDouble(), self.settings["move_mesh_strategy"].GetInt(), self.computing_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE]) ## Set the guess_row_size (guess about the number of zero entries) for the Trilinos builder and solver if self.main_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] == 3: guess_row_size = 20 * 4 elif self.main_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] == 2: guess_row_size = 10 * 3 ## Construct the Trilinos builder and solver if self.settings["consider_periodic_conditions"].GetBool() == True: self.builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolverPeriodic( self.EpetraCommunicator, guess_row_size, self.trilinos_linear_solver, KratosCFD.PATCH_INDEX) else: self.builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolver( self.EpetraCommunicator, guess_row_size, self.trilinos_linear_solver) ## Construct the Trilinos Newton-Raphson strategy self.solver = KratosTrilinos.TrilinosNewtonRaphsonStrategy( self.main_model_part, self.time_scheme, self.trilinos_linear_solver, self.conv_criteria, self.builder_and_solver, self.settings["maximum_iterations"].GetInt(), self.settings["compute_reactions"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool(), self.settings["move_mesh_flag"].GetBool()) (self.solver).SetEchoLevel(self.settings["echo_level"].GetInt()) self.formulation.SetProcessInfo(self.computing_model_part) (self.solver).Initialize() KratosMultiphysics.Logger.Print( "Monolithic MPI solver initialization finished.") def Finalize(self): self.solver.Clear()
class MPIUPwSolver(UPwSolver): def __init__(self, model, custom_settings): super(MPIUPwSolver, self).__init__(model, custom_settings) KratosMultiphysics.Logger.PrintInfo( "MPIUPwSolver: ", "Construction of MPI UPwSolver finished.") def AddVariables(self): super(MPIUPwSolver, self).AddVariables() self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PARTITION_INDEX) def ImportModelPart(self): # Construct the import model part utility from KratosMultiphysics.mpi.distributed_import_model_part_utility import DistributedImportModelPartUtility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() def PrepareModelPart(self): super(MPIUPwSolver, self).PrepareModelPart() # Set ProcessInfo variables self.main_model_part.ProcessInfo.SetValue(KratosPoro.NODAL_SMOOTHING, False) # Construct the communicators self.distributed_model_part_importer.CreateCommunicators() KratosMultiphysics.Logger.PrintInfo("MPIUPwSolver: ", "Model reading finished.") def Initialize(self): self.computing_model_part = self.GetComputingModelPart() # Fill the previous steps of the buffer with the initial conditions self._FillBuffer() # Construct the communicator self.EpetraCommunicator = TrilinosApplication.CreateCommunicator() # Construct the linear solver self.linear_solver = self._ConstructLinearSolver() # Builder and solver creation builder_and_solver = self._ConstructBuilderAndSolver( self.settings["block_builder"].GetBool()) # Solution scheme creation self.scheme = self._ConstructScheme( self.settings["scheme_type"].GetString(), self.settings["solution_type"].GetString()) # Get the convergence criterion self.convergence_criterion = self._ConstructConvergenceCriterion( self.settings["convergence_criterion"].GetString()) # Solver creation self.solver = self._ConstructSolver( builder_and_solver, self.settings["strategy_type"].GetString()) # Set echo_level self.SetEchoLevel(self.settings["echo_level"].GetInt()) # Initialize Strategy if self.settings["clear_storage"].GetBool(): self.Clear() self.solver.Initialize() # Check if everything is assigned correctly self.Check() KratosMultiphysics.Logger.PrintInfo("MPIUPwSolver: ", "Solver initialization finished.") #### Specific internal functions #### def _ConstructLinearSolver(self): return trilinos_linear_solver_factory.ConstructSolver( self.settings["linear_solver_settings"]) def _ConstructBuilderAndSolver(self, block_builder): if (self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2): guess_row_size = 15 else: guess_row_size = 45 if (block_builder): builder_and_solver = TrilinosApplication.TrilinosBlockBuilderAndSolver( self.EpetraCommunicator, guess_row_size, self.linear_solver) else: builder_and_solver = TrilinosApplication.TrilinosEliminationBuilderAndSolver( self.EpetraCommunicator, guess_row_size, self.linear_solver) return builder_and_solver def _ConstructScheme(self, scheme_type, solution_type): if (scheme_type == "Newmark"): beta = self.settings["newmark_beta"].GetDouble() gamma = self.settings["newmark_gamma"].GetDouble() theta = self.settings["newmark_theta"].GetDouble() rayleigh_m = self.settings["rayleigh_m"].GetDouble() rayleigh_k = self.settings["rayleigh_k"].GetDouble() self.main_model_part.ProcessInfo.SetValue( KratosStructural.RAYLEIGH_ALPHA, rayleigh_m) self.main_model_part.ProcessInfo.SetValue( KratosStructural.RAYLEIGH_BETA, rayleigh_k) if (solution_type == "quasi_static"): if (rayleigh_m < 1.0e-20 and rayleigh_k < 1.0e-20): scheme = KratosPoro.TrilinosNewmarkQuasistaticUPwScheme( beta, gamma, theta) else: scheme = KratosPoro.TrilinosNewmarkQuasistaticDampedUPwScheme( beta, gamma, theta) else: scheme = KratosPoro.TrilinosNewmarkDynamicUPwScheme( beta, gamma, theta) else: raise Exception( "Apart from Newmark, other scheme_type are not available.") return scheme def _ConstructConvergenceCriterion(self, convergence_criterion): D_RT = self.settings["displacement_relative_tolerance"].GetDouble() D_AT = self.settings["displacement_absolute_tolerance"].GetDouble() R_RT = self.settings["residual_relative_tolerance"].GetDouble() R_AT = self.settings["residual_absolute_tolerance"].GetDouble() echo_level = self.settings["echo_level"].GetInt() if (convergence_criterion == "Displacement_criterion"): convergence_criterion = TrilinosApplication.TrilinosDisplacementCriteria( D_RT, D_AT, self.EpetraCommunicator) convergence_criterion.SetEchoLevel(echo_level) elif (convergence_criterion == "Residual_criterion"): convergence_criterion = TrilinosApplication.TrilinosResidualCriteria( R_RT, R_AT) convergence_criterion.SetEchoLevel(echo_level) elif (convergence_criterion == "And_criterion"): Displacement = TrilinosApplication.TrilinosDisplacementCriteria( D_RT, D_AT, self.EpetraCommunicator) Displacement.SetEchoLevel(echo_level) Residual = TrilinosApplication.TrilinosResidualCriteria(R_RT, R_AT) Residual.SetEchoLevel(echo_level) convergence_criterion = TrilinosApplication.TrilinosAndCriteria( Residual, Displacement) elif (convergence_criterion == "Or_criterion"): Displacement = TrilinosApplication.TrilinosDisplacementCriteria( D_RT, D_AT, self.EpetraCommunicator) Displacement.SetEchoLevel(echo_level) Residual = TrilinosApplication.TrilinosResidualCriteria(R_RT, R_AT) Residual.SetEchoLevel(echo_level) convergence_criterion = TrilinosApplication.TrilinosOrCriteria( Residual, Displacement) return convergence_criterion def _ConstructSolver(self, builder_and_solver, strategy_type): max_iters = self.settings["max_iteration"].GetInt() compute_reactions = self.settings["compute_reactions"].GetBool() reform_step_dofs = self.settings["reform_dofs_at_each_step"].GetBool() move_mesh_flag = self.settings["move_mesh_flag"].GetBool() if strategy_type == "newton_raphson": self.main_model_part.ProcessInfo.SetValue(KratosPoro.IS_CONVERGED, True) solving_strategy = TrilinosApplication.TrilinosNewtonRaphsonStrategy( self.main_model_part, self.scheme, self.linear_solver, self.convergence_criterion, builder_and_solver, max_iters, compute_reactions, reform_step_dofs, move_mesh_flag) else: raise Exception( "Apart from newton_raphson, other strategy_type are not available." ) return solving_strategy
class NavierStokesMPIEmbeddedMonolithicSolver( navier_stokes_embedded_solver.NavierStokesEmbeddedMonolithicSolver): @classmethod def GetDefaultSettings(cls): default_settings = KratosMultiphysics.Parameters("""{ "solver_type": "Embedded", "model_part_name": "", "domain_size": -1, "model_import_settings": { "input_type": "mdpa", "input_filename": "unknown_name" }, "distance_reading_settings" : { "import_mode" : "from_GID_file", "distance_file_name" : "distance_file" }, "maximum_iterations": 7, "echo_level": 0, "consider_periodic_conditions": false, "time_order": 2, "compute_reactions": false, "reform_dofs_at_each_step": false, "relative_velocity_tolerance": 1e-3, "absolute_velocity_tolerance": 1e-5, "relative_pressure_tolerance": 1e-3, "absolute_pressure_tolerance": 1e-5, "linear_solver_settings" : { "solver_type" : "multi_level", "max_iteration" : 200, "tolerance" : 1e-6, "max_levels" : 3, "symmetric" : false, "reform_preconditioner_at_each_step" : true, "scaling" : true }, "volume_model_part_name" : "volume_model_part", "skin_parts": [""], "no_skin_parts":[""], "time_stepping": { "automatic_time_step" : true, "CFL_number" : 1, "minimum_delta_time" : 1e-4, "maximum_delta_time" : 0.01 }, "periodic": "periodic", "move_mesh_flag": false, "formulation": { "element_type": "embedded_element_from_defaults", "dynamic_tau": 1.0 }, "fm_ale_settings": { "fm_ale_step_frequency": 0, "structure_model_part_name": "", "search_radius" : 1.0 } }""") default_settings.AddMissingParameters( super(NavierStokesMPIEmbeddedMonolithicSolver, cls).GetDefaultSettings()) return default_settings def __init__(self, model, custom_settings): self._validate_settings_in_baseclass = True # To be removed eventually # Note: deliberately calling the constructor of the base python solver (the parent of my parent) super( navier_stokes_embedded_solver.NavierStokesEmbeddedMonolithicSolver, self).__init__(model, custom_settings) self.min_buffer_size = 3 self.embedded_formulation = navier_stokes_embedded_solver.EmbeddedFormulation( self.settings["formulation"]) self.element_name = self.embedded_formulation.element_name self.condition_name = self.embedded_formulation.condition_name ## Construct the linear solver self.trilinos_linear_solver = trilinos_linear_solver_factory.ConstructSolver( self.settings["linear_solver_settings"]) KratosMultiphysics.Logger.PrintInfo( "NavierStokesMPIEmbeddedMonolithicSolver", "Construction of NavierStokesMPIEmbeddedMonolithicSolver finished." ) def AddVariables(self): super(NavierStokesMPIEmbeddedMonolithicSolver, self).AddVariables() self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.PrintInfo( "NavierStokesMPIEmbeddedMonolithicSolver", "Variables for the Trilinos monolithic embedded fluid solver added correctly." ) def ImportModelPart(self): ## Construct the Distributed import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility( self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() ## Sets DENSITY, VISCOSITY and SOUND_VELOCITY KratosMultiphysics.Logger.PrintInfo( "NavierStokesMPIEmbeddedMonolithicSolver", "MPI model reading finished.") def PrepareModelPart(self): super(NavierStokesMPIEmbeddedMonolithicSolver, self).PrepareModelPart() ## Construct MPI the communicators self.distributed_model_part_importer.CreateCommunicators() def AddDofs(self): super(NavierStokesMPIEmbeddedMonolithicSolver, self).AddDofs() KratosMultiphysics.Logger.PrintInfo( "NavierStokesMPIEmbeddedMonolithicSolver", "DOFs for the VMS Trilinos fluid solver added correctly.") def Initialize(self): ## Construct the communicator self.EpetraCommunicator = KratosTrilinos.CreateCommunicator() ## Get the computing model part self.computing_model_part = self.GetComputingModelPart() ## If needed, create the estimate time step utility if (self.settings["time_stepping"]["automatic_time_step"].GetBool()): self.EstimateDeltaTimeUtility = self._GetAutomaticTimeSteppingUtility( ) # Set the time discretization utility to compute the BDF coefficients time_order = self.settings["time_order"].GetInt() if time_order == 2: self.time_discretization = KratosMultiphysics.TimeDiscretization.BDF( time_order) else: raise Exception( "Only \"time_order\" equal to 2 is supported. Provided \"time_order\": " + str(time_order)) ## Creating the Trilinos convergence criteria self.conv_criteria = KratosTrilinos.TrilinosUPCriteria( self.settings["relative_velocity_tolerance"].GetDouble(), self.settings["absolute_velocity_tolerance"].GetDouble(), self.settings["relative_pressure_tolerance"].GetDouble(), self.settings["absolute_pressure_tolerance"].GetDouble()) (self.conv_criteria).SetEchoLevel(self.settings["echo_level"].GetInt()) ## Creating the Trilinos incremental update time scheme (the time integration is defined within the embedded element) self.time_scheme = KratosTrilinos.TrilinosResidualBasedIncrementalUpdateStaticSchemeSlip( self.main_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE], # Domain size (2,3) self.main_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] + 1) # DOFs (3,4) ## Set the guess_row_size (guess about the number of zero entries) for the Trilinos builder and solver if self.main_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] == 3: guess_row_size = 20 * 4 elif self.main_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE] == 2: guess_row_size = 10 * 3 ## Construct the Trilinos builder and solver if self.settings["consider_periodic_conditions"].GetBool() == True: self.builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolverPeriodic( self.EpetraCommunicator, guess_row_size, self.trilinos_linear_solver, KratosFluid.PATCH_INDEX) else: self.builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolver( self.EpetraCommunicator, guess_row_size, self.trilinos_linear_solver) ## Construct the Trilinos Newton-Raphson strategy self.solver = KratosTrilinos.TrilinosNewtonRaphsonStrategy( self.main_model_part, self.time_scheme, self.trilinos_linear_solver, self.conv_criteria, self.builder_and_solver, self.settings["maximum_iterations"].GetInt(), self.settings["compute_reactions"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool(), self.settings["move_mesh_flag"].GetBool()) (self.solver).SetEchoLevel(self.settings["echo_level"].GetInt()) (self.solver).Initialize() # For the primitive Ausas formulation, set the find nodal neighbours process # Recall that the Ausas condition requires the nodal neighbouts. if (self.settings["formulation"]["element_type"].GetString() == "embedded_ausas_navier_stokes"): number_of_avg_elems = 10 number_of_avg_nodes = 10 self.find_nodal_neighbours_process = KratosMultiphysics.FindNodalNeighboursProcess( self.GetComputingModelPart(), number_of_avg_elems, number_of_avg_nodes) KratosMultiphysics.Logger.PrintInfo( "NavierStokesMPIEmbeddedMonolithicSolver", "Solver initialization finished.")
class TrilinosNavierStokesSolverMonolithic(navier_stokes_solver_vmsmonolithic.NavierStokesSolverMonolithic): def __init__(self, model, custom_settings): # Call the serial base class constructor super().__init__(model,custom_settings) KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Construction of TrilinosNavierStokesSolverMonolithic finished.") def AddVariables(self): ## Add variables from the base class super(TrilinosNavierStokesSolverMonolithic, self).AddVariables() ## Add specific MPI variables self.main_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.PARTITION_INDEX) KratosMultiphysics.Logger.Print("Variables for the VMS fluid Trilinos solver added correctly in each processor.") def ImportModelPart(self): ## Construct the MPI import model part utility self.distributed_model_part_importer = DistributedImportModelPartUtility(self.main_model_part, self.settings) ## Execute the Metis partitioning and reading self.distributed_model_part_importer.ImportModelPart() KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__,"MPI model reading finished.") def PrepareModelPart(self): # Call the base solver to do the PrepareModelPart # Note that his also calls the PrepareModelPart of the turbulence model super(TrilinosNavierStokesSolverMonolithic, self).PrepareModelPart() # Create the MPI communicators self.distributed_model_part_importer.CreateCommunicators() def Finalize(self): self._GetSolutionStrategy().Clear() def _GetEpetraCommunicator(self): if not hasattr(self, '_epetra_communicator'): self._epetra_communicator = KratosTrilinos.CreateEpetraCommunicator(self.main_model_part.GetCommunicator().GetDataCommunicator()) return self._epetra_communicator def _CreateScheme(self): domain_size = self.GetComputingModelPart().ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] # Cases in which the element manages the time integration if self.element_integrates_in_time: # "Fake" scheme for those cases in where the element manages the time integration # It is required to perform the nodal update once the current time step is solved scheme = KratosTrilinos.TrilinosResidualBasedIncrementalUpdateStaticSchemeSlip( domain_size, domain_size + 1) # In case the BDF2 scheme is used inside the element, set the time discretization utility to compute the BDF coefficients if (self.settings["time_scheme"].GetString() == "bdf2"): time_order = 2 self.time_discretization = KratosMultiphysics.TimeDiscretization.BDF(time_order) else: err_msg = "Requested elemental time scheme " + self.settings["time_scheme"].GetString() + " is not available.\n" err_msg += "Available options are: \"bdf2\"" raise Exception(err_msg) # Cases in which a time scheme manages the time integration else: # Bossak time integration scheme if self.settings["time_scheme"].GetString() == "bossak": # TODO: Can we remove this periodic check, Is the PATCH_INDEX used in this scheme? if self.settings["consider_periodic_conditions"].GetBool() == True: scheme = TrilinosFluid.TrilinosPredictorCorrectorVelocityBossakSchemeTurbulent( self.settings["alpha"].GetDouble(), domain_size, KratosCFD.PATCH_INDEX) else: scheme = TrilinosFluid.TrilinosPredictorCorrectorVelocityBossakSchemeTurbulent( self.settings["alpha"].GetDouble(), self.settings["move_mesh_strategy"].GetInt(), domain_size) # BDF2 time integration scheme elif self.settings["time_scheme"].GetString() == "bdf2": scheme = TrilinosFluid.TrilinosBDF2TurbulentScheme() # Time scheme for steady state fluid solver elif self.settings["time_scheme"].GetString() == "steady": scheme = TrilinosFluid.TrilinosResidualBasedSimpleSteadyScheme( self.settings["velocity_relaxation"].GetDouble(), self.settings["pressure_relaxation"].GetDouble(), domain_size) return scheme def _CreateLinearSolver(self): linear_solver_configuration = self.settings["linear_solver_settings"] return trilinos_linear_solver_factory.ConstructSolver(linear_solver_configuration) def _CreateConvergenceCriterion(self): if self.settings["time_scheme"].GetString() == "steady": convergence_criterion = KratosTrilinos.TrilinosResidualCriteria( self.settings["relative_velocity_tolerance"].GetDouble(), self.settings["absolute_velocity_tolerance"].GetDouble()) else: convergence_criterion = KratosTrilinos.TrilinosMixedGenericCriteria( [(KratosMultiphysics.VELOCITY, self.settings["relative_velocity_tolerance"].GetDouble(), self.settings["absolute_velocity_tolerance"].GetDouble()), (KratosMultiphysics.PRESSURE, self.settings["relative_pressure_tolerance"].GetDouble(), self.settings["absolute_pressure_tolerance"].GetDouble())]) convergence_criterion.SetEchoLevel(self.settings["echo_level"].GetInt()) return convergence_criterion def _CreateBuilderAndSolver(self): # Set the guess_row_size (guess about the number of zero entries) for the Trilinos builder and solver domain_size = self.GetComputingModelPart().ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] if domain_size == 3: guess_row_size = 20*4 else: guess_row_size = 10*3 # Construct the Trilinos builder and solver trilinos_linear_solver = self._GetLinearSolver() epetra_communicator = self._GetEpetraCommunicator() if self.settings["consider_periodic_conditions"].GetBool(): builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolverPeriodic( epetra_communicator, guess_row_size, trilinos_linear_solver, KratosFluid.PATCH_INDEX) else: builder_and_solver = KratosTrilinos.TrilinosBlockBuilderAndSolver( epetra_communicator, guess_row_size, trilinos_linear_solver) return builder_and_solver def _CreateSolutionStrategy(self): computing_model_part = self.GetComputingModelPart() time_scheme = self._GetScheme() convergence_criterion = self._GetConvergenceCriterion() builder_and_solver = self._GetBuilderAndSolver() return KratosTrilinos.TrilinosNewtonRaphsonStrategy( computing_model_part, time_scheme, convergence_criterion, builder_and_solver, self.settings["maximum_iterations"].GetInt(), self.settings["compute_reactions"].GetBool(), self.settings["reform_dofs_at_each_step"].GetBool(), self.settings["move_mesh_flag"].GetBool())