Coding tips

User written subroutines usually contain local variables and arrays that store data required during a solve. Arrays that contain unchanging data (e.g. list of elements) should be defined once during the first call to USER1 and then used later. In order to preserve the values between calls, a FORTRAN SAVE statement is necessary. In practice, the cost of using a global SAVE statement for all of the variables in the subroutine is minimal, usually all significant arrays must be preserved between calls.

Array sizes should be defined with PARAMETER statements and then the limits checked when arrays are filled.

C   Maxelem is the maximum number of elements this routine can handle
C
        integer maxelem
        parameter (maxelem = 10000)
        ..
        integer elemlist(maxelem), numelem
        real newelemprop(maxelem)
        ..
C
C   Load arrays checking to see if array bounds are exceeded.
C
        call getelem(elemlist, numelem)
        if(numelem .gt. maxelem) then
C
C   handle the error, tell user what numelem is so that
C   maxelem can be changed
C
                print *,'Fatal Error: Parameter MAXELEM be > ' numelem
                ..
        end if

The use of the parameter MAXELEM in the above code achieves the following:

  1. The array size value is used in a number of places, by using a parameter, it is set in one place.
  2. The array limits are easily checked for overflow as they are filled.

The error handler informs the user what the minimum acceptable value of the parameter is.

Thermal solver is run with array bound checking turned off, as these checks are costly. If you assign values beyond the size of the array then you will be overwriting other variables. If this happens you must stop execution as all data is suspect.

In the above example, the array is filled by the routine getelem. A better approach is to pass the value of maxelem to the routine getelem so that it can check the array limit as it is loaded, this will also keep the checking inside the code that could over fill the array. A better version (part of the code) would be the following providing getelem does the appropriate checks:

C
C   Load arrays
C
        call getelem(elemlist, numelem, maxelem)

Always check array limits. It is easy to develop a routine and think that it will never be used on a model with more than 1000 elements. Some time later the code is reused, the models are bigger and the array overflows. If you are lucky the code will crash or give ridiculous answers, otherwise the answers may be significantly but not obviously wrong.

The following code provides a simple checking mechanism.

 subroutine boundcheck(value, limit, arrayname)
C
C   Checks array bounds
C
        integer value, limit
        character*40 arrayname
C
C
C
        if(value .gt. limit) then
                print ,' ** FATAL* Array size limit exceeded.'
                print *,' Array name : ',arrayname
                print *,'Requested size : ', value
                print *,'Declared size : ', limit
        end if
        return
        end