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.")
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)
Example #3
0
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())
Example #4
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)