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.")
Beispiel #6
0
 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
Beispiel #9
0
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()
Beispiel #12
0
    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)
Beispiel #13
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
Beispiel #15
0
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
Beispiel #19
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())
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.")
Beispiel #21
0
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())
Beispiel #22
0
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.")
Beispiel #26
0
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())