Avoid temporary arrays when using derived types

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?

3 Likes

@zaikunzhang ,

Look into ASSOCIATE construct:

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
10 Likes

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
2 Likes

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.

4 Likes

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.

Many thanks again!

2 Likes