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 NavierStokesSolverMonolithic(FluidSolver): @classmethod def GetDefaultSettings(cls): ##settings string in json format default_settings = KratosMultiphysics.Parameters(""" { "solver_type": "navier_stokes_solver_vmsmonolithic", "model_part_name": "FluidModelPart", "domain_size": -1, "model_import_settings": { "input_type": "mdpa", "input_filename": "unknown_name", "reorder": false }, "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": true, "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" : false, "CFL_number" : 1, "minimum_delta_time" : 1e-4, "maximum_delta_time" : 0.01, "time_step" : 0.0 }, "time_scheme":"bossak", "alpha":-0.3, "velocity_relaxation":0.9, "pressure_relaxation":0.9, "move_mesh_strategy": 0, "periodic": "periodic", "move_mesh_flag": false, "turbulence_model_solver_settings": {} }""") default_settings.AddMissingParameters( super(NavierStokesSolverMonolithic, cls).GetDefaultSettings()) return default_settings def _BackwardsCompatibilityHelper(self, settings): ## Backwards compatibility -- deprecation warnings if settings.Has("stabilization"): msg = "Input JSON data contains deprecated setting \'stabilization\'.\n" msg += "Please rename it to \'formulation\' (and rename \'stabilization/formulation\' to \'formulation/element_type\' if it exists).\n" KratosMultiphysics.Logger.PrintWarning( "NavierStokesVMSMonolithicSolver", msg) settings.AddValue("formulation", settings["stabilization"]) settings.RemoveValue("stabilization") settings["formulation"].AddValue( "element_type", settings["formulation"]["formulation"]) settings["formulation"].RemoveValue("formulation") if settings.Has("oss_switch"): msg = "Input JSON data contains deprecated setting \'oss_switch\' (int).\n" msg += "Please define \'formulation/element_type\' (set it to \'vms\')\n" msg += "and set \'formulation/use_orthogonal_subscales\' (bool) instead." KratosMultiphysics.Logger.PrintWarning( "NavierStokesVMSMonolithicSolver", msg) if not settings.Has("formulation"): settings.AddValue( "formulation", KratosMultiphysics.Parameters(r'{"element_type":"vms"}')) settings["formulation"].AddEmptyValue("use_orthogonal_subscales") settings["formulation"]["use_orthogonal_subscales"].SetBool( bool(settings["oss_switch"].GetInt())) settings.RemoveValue("oss_switch") if settings.Has("dynamic_tau"): msg = "Input JSON data contains deprecated setting \'dynamic_tau\' (float).\n" msg += "Please define \'formulation/element_type\' (set it to \'vms\') and \n" msg += "set \'formulation/dynamic_tau\' (float) instead." KratosMultiphysics.Logger.PrintWarning( "NavierStokesVMSMonolithicSolver", msg) if not settings.Has("formulation"): settings.AddValue( "formulation", KratosMultiphysics.Parameters(r'{"element_type":"vms"}')) settings["formulation"].AddEmptyValue("dynamic_tau") settings["formulation"]["dynamic_tau"].SetDouble( settings["dynamic_tau"].GetDouble()) settings.RemoveValue("dynamic_tau") if settings.Has("turbulence_model" ) and settings["turbulence_model"].IsString(): if settings["turbulence_model"].GetString().lower() != "none": msg = "Ignoring deprecated \"turbulence_model\" (string) setting." KratosMultiphysics.Logger.PrintWarning( "NavierStokesVMSMonolithicSolver", msg) settings.RemoveValue("turbulence_model") return settings def __init__(self, model, custom_settings): self._validate_settings_in_baseclass = True # To be removed eventually custom_settings = self._BackwardsCompatibilityHelper(custom_settings) super(NavierStokesSolverMonolithic, self).__init__(model, custom_settings) self.formulation = 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 linear solver self.linear_solver = linear_solver_factory.ConstructSolver( self.settings["linear_solver_settings"]) ## Construct the turbulence model solver if not self.settings["turbulence_model_solver_settings"].IsEquivalentTo( KratosMultiphysics.Parameters("{}")): self._turbulence_model_solver = CreateTurbulenceModel( model, self.settings["turbulence_model_solver_settings"]) self.condition_name = self._turbulence_model_solver.GetFluidVelocityPressureConditionName( ) KratosMultiphysics.Logger.PrintInfo( "NavierStokesSolverMonolithic", "Using " + self.condition_name + " as wall condition") KratosMultiphysics.Logger.PrintInfo( "NavierStokesSolverMonolithic", "Construction of NavierStokesSolverMonolithic finished.") def AddVariables(self): ## Add base class variables self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.VELOCITY) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.ACCELERATION) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.MESH_VELOCITY) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PRESSURE) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.IS_STRUCTURE) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.DISPLACEMENT) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.VISCOSITY) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.DENSITY) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.BODY_FORCE) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.NODAL_AREA) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.NODAL_H) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.ADVPROJ) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.DIVPROJ) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.REACTION) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.REACTION_WATER_PRESSURE) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.EXTERNAL_PRESSURE) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.NORMAL) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.Y_WALL) self.main_model_part.AddNodalSolutionStepVariable(KratosCFD.Q_VALUE) # Adding variables required for the turbulence modelling if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.fluid_model_part = self.main_model_part self._turbulence_model_solver.AddVariables() if self.settings["consider_periodic_conditions"].GetBool() == True: self.main_model_part.AddNodalSolutionStepVariable( KratosCFD.PATCH_INDEX) KratosMultiphysics.Logger.PrintInfo( "NavierStokesSolverMonolithic", "Fluid solver variables added correctly.") def AddDofs(self): super(NavierStokesSolverMonolithic, self).AddDofs() # Adding DOFs required for the turbulence modelling if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.AddDofs() def PrepareModelPart(self): super(NavierStokesSolverMonolithic, self).PrepareModelPart() # Missing prepare model part operations required for the turbulence modelling if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.PrepareModelPart() def Initialize(self): 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 solution strategy if self.settings["time_scheme"].GetString() == "steady": self.conv_criteria = KratosMultiphysics.ResidualCriteria( self.settings["relative_velocity_tolerance"].GetDouble(), self.settings["absolute_velocity_tolerance"].GetDouble()) else: self.conv_criteria = KratosCFD.VelPrCriteria( 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 time integration scheme 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 self.time_scheme = KratosMultiphysics.ResidualBasedIncrementalUpdateStaticSchemeSlip( self.computing_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE], self.computing_model_part.ProcessInfo[ KratosMultiphysics.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) else: if not hasattr(self, "_turbulence_model_solver"): # Bossak time integration scheme if self.settings["time_scheme"].GetString() == "bossak": if self.settings["consider_periodic_conditions"].GetBool( ) == True: self.time_scheme = KratosCFD.ResidualBasedPredictorCorrectorVelocityBossakSchemeTurbulent( self.settings["alpha"].GetDouble(), self.computing_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE], KratosCFD.PATCH_INDEX) else: self.time_scheme = KratosCFD.ResidualBasedPredictorCorrectorVelocityBossakSchemeTurbulent( self.settings["alpha"].GetDouble(), self.settings["move_mesh_strategy"].GetInt(), self.computing_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE]) # BDF2 time integration scheme elif self.settings["time_scheme"].GetString() == "bdf2": self.time_scheme = KratosCFD.GearScheme() # Time scheme for steady state fluid solver elif self.settings["time_scheme"].GetString() == "steady": self.time_scheme = KratosCFD.ResidualBasedSimpleSteadyScheme( self.settings["velocity_relaxation"].GetDouble(), self.settings["pressure_relaxation"].GetDouble(), self.computing_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE]) else: err_msg = "Requested time scheme " + self.settings[ "time_scheme"].GetString() + " is not available.\n" err_msg += "Available options are: \"bossak\", \"bdf2\" and \"steady\"" raise Exception(err_msg) else: self._turbulence_model_solver.Initialize() if self.settings["time_scheme"].GetString() == "bossak": self.time_scheme = KratosCFD.ResidualBasedPredictorCorrectorVelocityBossakSchemeTurbulent( self.settings["alpha"].GetDouble(), self.settings["move_mesh_strategy"].GetInt(), self.computing_model_part.ProcessInfo[ KratosMultiphysics.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": self.time_scheme = KratosCFD.ResidualBasedSimpleSteadyScheme( self.settings["velocity_relaxation"].GetDouble(), self.settings["pressure_relaxation"].GetDouble(), self.computing_model_part.ProcessInfo[ KratosMultiphysics.DOMAIN_SIZE], self._turbulence_model_solver. GetTurbulenceSolvingProcess()) if self.settings["consider_periodic_conditions"].GetBool(): builder_and_solver = KratosCFD.ResidualBasedBlockBuilderAndSolverPeriodic( self.linear_solver, KratosCFD.PATCH_INDEX) else: builder_and_solver = KratosMultiphysics.ResidualBasedBlockBuilderAndSolver( self.linear_solver) self.solver = KratosMultiphysics.ResidualBasedNewtonRaphsonStrategy( self.computing_model_part, self.time_scheme, self.linear_solver, self.conv_criteria, 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.PrintInfo("NavierStokesSolverMonolithic", "Solver initialization finished.") def InitializeSolutionStep(self): if self._TimeBufferIsInitialized(): # If required, compute the BDF coefficients if hasattr(self, 'time_discretization'): (self.time_discretization).ComputeAndSaveBDFCoefficients( self.GetComputingModelPart().ProcessInfo) # Perform the solver InitializeSolutionStep (self.solver).InitializeSolutionStep() # Perform the turbulence modelling InitializeSolutionStep if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.InitializeSolutionStep() def FinalizeSolutionStep(self): super(NavierStokesSolverMonolithic, self).FinalizeSolutionStep() # Perform the turbulence modelling FinalizeSolutionStep if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.FinalizeSolutionStep() def Check(self): super(NavierStokesSolverMonolithic, self).Check() # Turbulence modelling check operations if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.Check() def _SetUpSteadySimulation(self): '''Overwrite time stepping parameters so that they do not interfere with steady state simulations.''' self.settings["time_stepping"]["automatic_time_step"].SetBool(False) if self.settings["formulation"].Has("dynamic_tau"): self.settings["formulation"]["dynamic_tau"].SetDouble(0.0)
class NavierStokesSolverMonolithic(FluidSolver): @classmethod def GetDefaultSettings(cls): ##settings string in json format default_settings = KratosMultiphysics.Parameters(""" { "solver_type": "navier_stokes_solver_vmsmonolithic", "model_part_name": "FluidModelPart", "domain_size": -1, "model_import_settings": { "input_type": "mdpa", "input_filename": "unknown_name", "reorder": false }, "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": true, "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": [""], "assign_neighbour_elements_to_conditions": false, "no_skin_parts":[""], "time_stepping" : { "automatic_time_step" : false, "CFL_number" : 1, "minimum_delta_time" : 1e-4, "maximum_delta_time" : 0.01, "time_step" : 0.0 }, "time_scheme":"bossak", "alpha":-0.3, "velocity_relaxation":0.9, "pressure_relaxation":0.9, "move_mesh_strategy": 0, "periodic": "periodic", "move_mesh_flag": false, "turbulence_model_solver_settings": {} }""") default_settings.AddMissingParameters( super(NavierStokesSolverMonolithic, cls).GetDefaultSettings()) return default_settings def _BackwardsCompatibilityHelper(self, settings): ## Backwards compatibility -- deprecation warnings if settings.Has("stabilization"): msg = "Input JSON data contains deprecated setting \'stabilization\'.\n" msg += "Please rename it to \'formulation\' (and rename \'stabilization/formulation\' to \'formulation/element_type\' if it exists).\n" KratosMultiphysics.Logger.PrintWarning( "NavierStokesVMSMonolithicSolver", msg) settings.AddValue("formulation", settings["stabilization"]) settings.RemoveValue("stabilization") settings["formulation"].AddValue( "element_type", settings["formulation"]["formulation"]) settings["formulation"].RemoveValue("formulation") if settings.Has("oss_switch"): msg = "Input JSON data contains deprecated setting \'oss_switch\' (int).\n" msg += "Please define \'formulation/element_type\' (set it to \'vms\')\n" msg += "and set \'formulation/use_orthogonal_subscales\' (bool) instead." KratosMultiphysics.Logger.PrintWarning( "NavierStokesVMSMonolithicSolver", msg) if not settings.Has("formulation"): settings.AddValue( "formulation", KratosMultiphysics.Parameters(r'{"element_type":"vms"}')) settings["formulation"].AddEmptyValue("use_orthogonal_subscales") settings["formulation"]["use_orthogonal_subscales"].SetBool( bool(settings["oss_switch"].GetInt())) settings.RemoveValue("oss_switch") if settings.Has("dynamic_tau"): msg = "Input JSON data contains deprecated setting \'dynamic_tau\' (float).\n" msg += "Please define \'formulation/element_type\' (set it to \'vms\') and \n" msg += "set \'formulation/dynamic_tau\' (float) instead." KratosMultiphysics.Logger.PrintWarning( "NavierStokesVMSMonolithicSolver", msg) if not settings.Has("formulation"): settings.AddValue( "formulation", KratosMultiphysics.Parameters(r'{"element_type":"vms"}')) settings["formulation"].AddEmptyValue("dynamic_tau") settings["formulation"]["dynamic_tau"].SetDouble( settings["dynamic_tau"].GetDouble()) settings.RemoveValue("dynamic_tau") if settings.Has("turbulence_model" ) and settings["turbulence_model"].IsString(): if settings["turbulence_model"].GetString().lower() != "none": msg = "Ignoring deprecated \"turbulence_model\" (string) setting." KratosMultiphysics.Logger.PrintWarning( "NavierStokesVMSMonolithicSolver", msg) settings.RemoveValue("turbulence_model") return settings def __init__(self, model, custom_settings): self._validate_settings_in_baseclass = True # To be removed eventually custom_settings = self._BackwardsCompatibilityHelper(custom_settings) super(NavierStokesSolverMonolithic, self).__init__(model, custom_settings) self.formulation = 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 NavierStokesSolverMonolithic finished.") def AddVariables(self): ## Add base class variables self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.VELOCITY) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.ACCELERATION) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.MESH_VELOCITY) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.PRESSURE) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.IS_STRUCTURE) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.DISPLACEMENT) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.BODY_FORCE) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.NODAL_AREA) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.NODAL_H) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.ADVPROJ) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.DIVPROJ) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.REACTION) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.REACTION_WATER_PRESSURE) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.EXTERNAL_PRESSURE) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.NORMAL) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.Y_WALL) self.main_model_part.AddNodalSolutionStepVariable(KratosCFD.Q_VALUE) # Adding variables required for the nodal material properties if self.element_has_nodal_properties: self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.DENSITY) self.main_model_part.AddNodalSolutionStepVariable( KratosMultiphysics.VISCOSITY) # Adding variables required for the turbulence modelling if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.AddVariables() # Adding variables required for the periodic conditions if self.settings["consider_periodic_conditions"].GetBool() == True: self.main_model_part.AddNodalSolutionStepVariable( KratosCFD.PATCH_INDEX) KratosMultiphysics.Logger.PrintInfo( self.__class__.__name__, "Fluid solver variables added correctly.") def AddDofs(self): super(NavierStokesSolverMonolithic, self).AddDofs() # Adding DOFs required for the turbulence modelling if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.AddDofs() def PrepareModelPart(self): super(NavierStokesSolverMonolithic, self).PrepareModelPart() # Missing prepare model part operations required for the turbulence modelling if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.PrepareModelPart() def Initialize(self): # If the solver requires an instance of the stabilized formulation class, set the process info variables if hasattr(self, 'formulation'): self.formulation.SetProcessInfo(self.GetComputingModelPart()) # Construct and initialize the solution strategy solution_strategy = self._GetSolutionStrategy() solution_strategy.SetEchoLevel(self.settings["echo_level"].GetInt()) solution_strategy.Initialize() # If there is turbulence modelling, set the new solution strategy as parent strategy if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.SetParentSolvingStrategy( solution_strategy) KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, "Solver initialization finished.") def InitializeSolutionStep(self): if self._TimeBufferIsInitialized(): # If required, compute the BDF coefficients if hasattr(self, 'time_discretization'): (self.time_discretization).ComputeAndSaveBDFCoefficients( self.GetComputingModelPart().ProcessInfo) # Perform the solver InitializeSolutionStep self._GetSolutionStrategy().InitializeSolutionStep() # Perform the turbulence modelling InitializeSolutionStep if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.InitializeSolutionStep() def FinalizeSolutionStep(self): super(NavierStokesSolverMonolithic, self).FinalizeSolutionStep() # Perform the turbulence modelling FinalizeSolutionStep if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.FinalizeSolutionStep() def Check(self): super(NavierStokesSolverMonolithic, self).Check() # Turbulence modelling check operations if hasattr(self, "_turbulence_model_solver"): self._turbulence_model_solver.Check() def _SetUpSteadySimulation(self): '''Overwrite time stepping parameters so that they do not interfere with steady state simulations.''' self.settings["time_stepping"]["automatic_time_step"].SetBool(False) if self.settings["formulation"].Has("dynamic_tau"): self.settings["formulation"]["dynamic_tau"].SetDouble(0.0) def _SetNodalProperties(self): # Get density and dynamic viscostity from the properties of the first element for el in self.main_model_part.Elements: rho = el.Properties.GetValue(KratosMultiphysics.DENSITY) if rho <= 0.0: raise Exception( "DENSITY set to {0} in Properties {1}, positive number expected." .format(rho, el.Properties.Id)) dyn_viscosity = el.Properties.GetValue( KratosMultiphysics.DYNAMIC_VISCOSITY) if dyn_viscosity <= 0.0: raise Exception( "DYNAMIC_VISCOSITY set to {0} in Properties {1}, positive number expected." .format(dyn_viscosity, el.Properties.Id)) kin_viscosity = dyn_viscosity / rho break else: raise Exception("No fluid elements found in the main model part.") # Transfer the obtained properties to the nodes KratosMultiphysics.VariableUtils().SetVariable( KratosMultiphysics.DENSITY, rho, self.main_model_part.Nodes) KratosMultiphysics.VariableUtils().SetVariable( KratosMultiphysics.VISCOSITY, kin_viscosity, self.main_model_part.Nodes)