Suppose that I have a subroutine that revises arrays A and B by some intensive computation:
subroutine foo(A, B)
real, intent(inout) :: A(:, :), B(:, :)
! Do something intensive to revise A, B
end subroutine foo
Now, I would like to define a derived type DT consisting of A and B and rewrite foo into bar as follows.
subroutine bar(D)
type(DT), intent(inout) :: D
! Do something intensive to revise D%A, D%B
end subroutine bar
Here comes a problem. The calculation that revises A and B is truly intensive. So it would be cumbersome to write always D%A and D%B. To solve this problem, we may define temporary arrays A=D%A and B=D%B, work on A and B, and then set D%A=A, D%B=B before the end of the subroutine. However, if A and B are huge, this would not be ideal. So, what is the best practice in this situation?
subroutine bar(D)
type(DT), intent(inout) :: D
associate ( A => D%A, B => D%B )
! Do something intensive to revise D%A, D%B via associate-names of A and B!
end associate
end subroutine bar
How does one decide between the solution above and an internal subroutine, as illustrated below? I assume compilers would not make copies of the intent(in out) arguments.
subroutine bar(D)
type(DT), intent(inout) :: D
call foo(D%A,D%B)
contains
subroutine foo(A,B)
real, intent(in out) :: A(:,:), B(:,:)
! modify A and B
end suboutine calc
end subroutine bar
I would not even make the subroutine foo internal. I like to create such standalone procedures as much as possible that operate on arrays, no derived types. This makes them very reusable in all kinds of settings.
Then in the upper calls if it makes sense to use a derived type, then the member arrays can be passed as arguments as shown above.
Thank @FortranFan, @Beliavsky, and @certik all of you for the illuminating suggestions. I believe that each of them is quite useful under certain situations. I understand this problem better now. Considering my code, I guess I would more or less follow what @certik suggests, namely to implement the true calculations on arrays, and then use derived types only as “interfaces” between different components of the program.