Good programming practice: use internal procedures to take advantage of variables scope
<p>I am doing some coding in Fortran 95. I would like to know if using subroutines changing global variables defined in modules is considered bad programming practice. I tend to use only pure subroutines in general but in this case I cannot use "pure", right. As an alternative I could define variables in a subroutine and then use those variables in procedures internal to that subroutine, as in the example below. Is that acceptable?</p>

<pre><code> subroutine test(X, Y)  

  implicit none  

  integer, parameter(dp) :: kind(0.d0)
  integer, parameter(dp) :: r1d3 = 1._dp / 3._dp
  real(dp), intent(in) :: X(20)  
  real(dp), intent(out) :: Y(20)   

  real(dp) :: f1, f2, f3, f4, f5, f6, f7, f8, f9, f10  
  real(dp), dimension(20) :: g1, g2, g3, g4, g5, g6, g7, DX  

  real(dp) :: res(20), jac(20,20)  

  f1 = exp(- norm2(X(7:12)))
  g1 = X(1:6) - r1d3 * sum(X(1:3))

  ! code to calculate variables f1..., g1...   
  ! functions of X   

  ! f1 ... f10, g1 .. g7, are needed to compute both the residual and the jacobian

  call residual(X, res)  

  condition = ( norm2(res) &lt; tol )

  ! I do not want to calculate the jacobian if this is not needed. Should I?

  if (condition) then  
    call jacobian(X, jac)  

  end if  

  DX = -res  

  call gesv(jac, DX)   

  ! and so on

contains

   pure subroutine residual(X, res)
    ....
   end subroutine residual


   pure subroutine jacobian(X, jac)
    ....
   end subroutine jacobian
</code></pre>

<p>Is the code above decently written? I could have included the computation of both the residual and the jacobian in the same subroutine and do all the needed calculations of f1 ... g7 there, avoiding the definition of residual and jacobian as internal subroutines, but I only want to calculate the jacobian if needed. What do you think?</p>

<p>I thought the following alternative could also work:</p>

<pre><code>module EP_integration

   implicit none


   integer, parameter(dp) :: kind(0.d0)  
   real(dp), PRIVATE, SAVE :: f1, f2, f3, f4, f5, f6, f7, f8, f9, f10  
   real(dp), dimension(20), PRIVATE, SAVE :: g1, g2, g3, g4, g5, g6, g7  

contains

   pure subroutine calc_funcs(X, res)
     ! calculates f1 .. f10, g1 .. g10 as functions of X
     ! f1 ... f10, g1 .. g7, are needed to compute both the residual and the jacobian
    ....
   end subroutine calc_funcs

   pure subroutine residual(X, res)
    ....
   end subroutine residual

   pure subroutine jacobian(X, jac)
    ....
   end subroutine jacobian

end module EP_integration
</code></pre>

<p>or maybe <code>USE</code>ing the module in the main subroutine instead of using the attribute <code>SAVE</code>.</p>