Skip to content

Tutorial: Creating the Python Solver file

Vicente Mataix Ferrándiz edited this page Aug 29, 2023 · 19 revisions

The purpose of this file is to act as an interface between your problem's script (also in python) file and the Kratos functions. We will create a class and functions already customized for our type of problem, so that the calls required in the .py from the problem become simpler. The file should be in the /MyLaplacianApplication/python_scripts folder.

pure_diffusion_solver.py

# Importing the required Kratos libraries
import KratosMultiphysics
import KratosMultiphysics.MyLaplacianApplication as Poisson

# Function to create the solver
def CreateSolver(Model, custom_settings):
    return PureDiffusionSolver(Model, custom_settings)

# Class for the PureDiffusionSolver
class PureDiffusionSolver(object):
    def __init__(self, Model, custom_settings):
        """
        Constructor of the PureDiffusionSolver class.

        Args:
        Model (KratosMultiphysics.Model): The Kratos model to work with.
        custom_settings (KratosMultiphysics.Parameters): User-defined settings for the solver.
        """
        # Default settings for the solver in JSON format
        default_settings = KratosMultiphysics.Parameters("""
        {
            "model_part_name"              : "Main",
            "model_import_settings"        : {
                "input_type"          : "mdpa",
                "input_filename"      : "unknown_name"
            },
            "echo_level"                   : 0,
            "buffer_size"                  : 2,
            "relative_tolerance"           : 1e-6,
            "absolute_tolerance"           : 1e-9,
            "maximum_iterations"           : 20,
            "compute_reactions"            : false,
            "reform_dofs_at_each_step"     : false,
            "calculate_norm_dx"            : true,
            "move_mesh_flag"               : false,
            "linear_solver_settings"       : {
                    "solver_type"     : "skyline_lu_factorization"
            }
        }""")

        # Overwrite the default settings with user-provided parameters
        self.settings = custom_settings
        self.settings.ValidateAndAssignDefaults(default_settings)

        # Retrieve the model part and domain size
        self.model_part  = Model[self.settings["model_part_name"].GetString()]
        self.domain_size = self.model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE]

        # Construct the linear solver
        import KratosMultiphysics.python_linear_solver_factory as python_linear_solver_factory
        self.linear_solver = python_linear_solver_factory.ConstructSolver(self.settings["linear_solver_settings"])

    def AddVariables(self):
        """
        Add the nodal solution step variables required by the solver.
        """
        self.model_part.AddNodalSolutionStepVariable(KratosMultiphysics.TEMPERATURE)
        self.model_part.AddNodalSolutionStepVariable(Poisson.POINT_HEAT_SOURCE)

    def AddDofs(self):
        """
        Add the degrees of freedom (DOFs) for the temperature variable to all nodes.
        """
        for node in self.model_part.Nodes:
            node.AddDof(KratosMultiphysics.TEMPERATURE)
        
        print("Variables for the Poisson solver added correctly")

    def GetMinimumBufferSize(self):
        """
        Get the minimum buffer size required for the solver.

        Returns:
        int: Minimum buffer size (1 in this case).
        """
        return 1

    def ImportModelPart(self):
        """
        Import the model part based on the specified input type.

        Raises:
        Exception: If input type is not "mdpa", as other options are not yet implemented.
        """
        # Model part reading
        if self.settings["model_import_settings"]["input_type"].GetString() == "mdpa":
            # Here could be the place to import restart data if required
            KratosMultiphysics.ModelPartIO(self.settings["model_import_settings"]["input_filename"].GetString()).ReadModelPart(self.model_part)
        else:
            raise Exception("Other input options are not yet implemented")

        # Set the buffer size
        self.model_part.SetBufferSize(self.settings["buffer_size"].GetInt())
        if self.GetMinimumBufferSize() > self.model_part.GetBufferSize():
            self.model_part.SetBufferSize(self.GetMinimumBufferSize())

    def Initialize(self):
        """
        Initialize the solver, including constructing the solution strategy and related objects.
        """
        # Creating the convergence criteria
        self.conv_criteria = KratosMultiphysics.DisplacementCriteria(
            self.settings["relative_tolerance"].GetDouble(),
            self.settings["absolute_tolerance"].GetDouble()
        )
        self.conv_criteria.SetEchoLevel(self.settings["echo_level"].GetInt())

        # Creating the time scheme
        self.time_scheme = KratosMultiphysics.ResidualBasedIncrementalUpdateStaticScheme()

        # Creating the builder and solver
        self.builder_and_solver = KratosMultiphysics.ResidualBasedBlockBuilderAndSolver(self.linear_solver)

        # Creating the solver strategy
        self.solver = KratosMultiphysics.ResidualBasedLinearStrategy(
            self.model_part,
            self.time_scheme,
            self.linear_solver,
            self.builder_and_solver,
            self.settings["compute_reactions"].GetBool(),
            self.settings["reform_dofs_at_each_step"].GetBool(),
            self.settings["calculate_norm_dx"].GetBool(),
            self.settings["move_mesh_flag"].GetBool()
        )

        self.solver.SetEchoLevel(self.settings["echo_level"].GetInt())
        self.solver.Initialize()

        print("Pure diffusion solver initialization finished")

    def Solve(self):
        """
        Solve the equations on the mesh using the solver strategy.
        """
        self.solver.Solve()

Project information

Getting Started

Tutorials

Developers

Kratos structure

Conventions

Solvers

Debugging, profiling and testing

HOW TOs

Utilities

Kratos API

Kratos Structural Mechanics API

Clone this wiki locally