Search code examples
fortranlarge-datasubroutine

Fortran subroutine: How to load data only on first call


I am programming a Fortran module, which is linked to external main program. I can only alter the subroutine. I have to detail a lot of data, but always the same. It takes too much time to do this on every call of the subroutine. How can I initialise the data only at the first call? Currently, this is the subroutine:

subroutine sdvini(statev,coords,nstatv,ncrds,noel,npt,layer,kspt)
implicit none  

integer imdat(100,100,50)

imdat(1,1,1:33)=(/1,8,13,24,48,72,111,148,156,165,182&
&,189,194,207,210,216,236,247,254,270,311,319,339,343,367,376&
&,393,397,421,438,447,473,492/)
.
. lots of data
. 

do something
return
end

Solution

  • This setting of values on the first call to a procedure and retaining the values can be performed by explicit initialization. We often use the term initialization, as in this question, to mean an assignment as part of a setting up process. However, initialization means something more precise in Fortran terms.

    An explicit initialization suitable for this question would be something like the very simple case

    integer, save :: i=1   ! SAVE attribute would be implied, but made explicit
    

    This is like having the assignment applied the first time the procedure is entered.

    We can also use a data statement:

    integer, save :: i
    data i /1/
    

    The SAVE attribute is what ensures that the value persists between entries to the procedure.

    For arrays the idea is the same, perhaps using array constructors and reshape.

    For very large arrays it is impractical to use data statements or initializers. Further, there are restrictions on what may appear in initializing a saved local variable. However, another idiom would be like

    subroutine sub
      logical, save :: firsttime=.TRUE.
      integer, save :: obj(100,100,50)
    
      if (firsttime) then
        obj = ...  ! Setting the value somehow, maybe even with a read
        firsttime = .FALSE.
      end if
    end subroutine