Search code examples
oopfortranfortran2003

A good OOP design for a solver with modern Fortran


I am designing a Fortran code for solving a PDE system.

The way it is designed right now is that I have a type Variable that has several attributes, the most important of which is the array val that stores the value.

Now I also have a solver class, which would perform calculations on a variable. I figured that passing the whole variable to the solver and working with variable%val each time I want to run it (several thousands of times during an exectution) would be inefficient, so I decided to to define pointer fields in the solver class to bind the to solver to the appropriate variable. For example

program example
    use variable
    use solvers

    type(Variable) T 
    type(Solver) solver_temperature

    !Contructors
    call T%create()
    call solver_temperature%create(T)

    call solver_temperature%solve()
end program example

And the solver module

module solvers
type Solver
    real*8, pointer :: T(:,:)

contains 
    procedure :: create
    procedure :: solve
end type

contains
    subroutine create(this,T)
        type(Solver) :: this
        type(Variable) :: T

        this%T => T%val
    end subroutine
end module

In my program I define different variable for different physical properties and different solvers that are associated with those variables in the way I showed above.

I am new to OOP in general, so my question is if that is a decent design? Especially from a performance point of view. How does this compare with making T just an array and passing it to a subroutine solve in terms of speed? Is there some regular way to do this?


Solution

  • I've been working with the OO features of Fortran for a year or so now, here are some extended comments masquerading as an answer.

    If you are simply concerned with raw execution speed then you are probably, in general (and based on argument and my experience rather than data), better to steer clear of the OO features; but then in many cases the same argument can be made that you are better to steer clear of anything added to the language after FORTRAN77.

    Arguments in favour of OO are stronger when founded on the issues of code design, comprehensibility, extendibility, that sort of thing. If these matter to you then you should be thinking about using the OO features.

    As Vladimir has already commented, there doesn't seem to be much point in using the variable pointer. Don't forget that most Fortran implementations do call-by-reference specifically to avoid the effort of copying (large volumes of) data around.

    Personally, I don't like the way you have defined your type-bound procedure create. I much prefer to implement that sort of operation as a function, so that I can write lines like this:

    t = solver%new()
    

    rather than your

    call T%create()
    

    Note this is a preference of mine, and it's more a question of style than of efficiency or correctness. I notice that you haven't declared the intents of the arguments to the subroutine create; perhaps because you've only posted a snippet of your code.

    Because OO is relatively new to Fortran (and, arguably, relatively unfamiliar to most people working in the domains where Fortran is widely used) there isn't much useful material to guide us in adopting it. I would recommend Scientific Software Design. It gives the topic decent coverage and makes the argument about why scientific and engineering programmers should adopt OO.