Solver and ModelsΒΆ

A solver with it models is just a sequence of operations that are executed in a specific order. The job of the solver is to define the operations and sequence of operations. Additionally, the solver also defines the models that can be used to extend the solver functionality as sketched in the code snippet below.

@Solver
class IncompressibleFluidSolver:
    models: list[IncompressibleFluidModel]  # Additional physics models
    @Solver.operation(...)
    def momentum(self, ...): pass
    @Solver.operation(...)
    def continuity(self, ...): pass
    @Solver.operation(...)
    def update_turbulence(self, ...): pass


    def define_operations(self):
        # ...
        return operations

@IncompressibleFluidModel.register
class BoussinesqModel:
    @IncompressibleFluidModel.operation(...)
    def temperature_equation(self, ...): pass

@IncompressibleFluidModel.register
class PorosityModel:
    @IncompressibleFluidModel.operation(...)
    def add_momentum_source(self, ...): pass

@IncompressibleFluidModel.register
class RotatingReferenceFrame:
    @IncompressibleFluidModel.operation(...)
    def add_momentum_source(self, ...): pass

The example provides an overview but it gets more complex if a more complex/detailed solver is considered that is ideally composed of reusable compoenents and models.

The PressureVelocityCoupling supports different algorithms: SIMPLE, PISO, PIMPLE and the projection method. However, it also supports different strategies to solver the pressure equation in cases natural convection is present or not. This means that the models can influence the configuration of the operations of each model or the solver itself. This is solved by a 3 stage initialization process of the solver and models:

  1. read: Read configuration and initialize models and solver

  2. configure: Configure models and solver based on the read configuration (also is used for interaction with other domains in a multiphysics simulation)

  3. setup: Setup models and solver, allocate fields and data structures

@Solver
class IncompressibleFluidSolver:
#...
    @classmethod
    def read(cls):
        pU = PressureVelocityCoupling.read()
        turbulenceModel = TurbulenceModel.read()
        models = read_models(IncompressibleFluidModel)

        return cls(pU, turbulenceModel, models)

    def configure(self):
        # ... TBD

    def setup(self):
        # ... TBD

    def operations(self):
        # ... TBD

    def define_operations(self, domain_name: str | None = None) -> Operations:
        # ... TBD