top_left_banner  SimCon logo

WRF - Errors in OPTIONAL Arguments

OPTIONAL Violations in WRF - The Issue

An OPTIONAL violation occurs when an optional argument is accessed in its sub-program code without a check that the argument is present.

In WRF versions 3.6.1 and 3.4.1, there are:

  WRFV3.6.1 WRFV3.4.1
OPTIONAL arguments accessed without a check for presence 1,360 987
OPTIONAL, always present, accessed without a check 1,325 977
OPTIONAL, not always present, accessed without a check 35 10

OPTIONAL Violations and Compiler or Run-Time System Error Detection

If you access an optional argument which isn't present it crashes the program doesn't it?


This is a simple OPTIONAL violation:

PROGRAM opt_1 INTERFACE SUBROUTINE s_char(str) CHARACTER*(*), OPTIONAL :: str END SUBROUTINE s_char END INTERFACE CALL s_char END PROGRAM opt_1 SUBROUTINE s_char(str) CHARACTER*(*), OPTIONAL :: str CHARACTER*64 local_str local_str = "local_part "//str WRITE(6,*)local_str END SUBROUTINE s_char

The argument str is declared OPTIONAL and is not present in the call to s_char. However, it is always accessed in the code of s_char. This does not crash under ifort or gfortran. The output from the program is:


It does crash, on both of these compilers if the INTERFACE block is left out of the main program.

The code shown below:

PROGRAM opt_2 INTERFACE SUBROUTINE s_char(str) CHARACTER*(*),OPTIONAL :: str END SUBROUTINE s_char END INTERFACE CALL s_char("String is present") CALL s_char END PROGRAM opt_2 SUBROUTINE s_char(str) CHARACTER*(*), OPTIONAL :: str CHARACTER*64 local_str local_str = "local_part "//str WRITE(6,*)local_str END SUBROUTINE s_char

runs under both ifort and gfortran to generate the output:

local_part String is present local_part

If the INTERFACE block is ommitted, it crashes under ifort, but runs under gfortran with the result:

local_part String is present local_part String is present

The attributes of the optional argument are retained from the call where it is present to the next where it is absent.

Finding OPTONAL Errors in WRF

If you have not already done so, set up the WRF test environment as described here.

Change to the fpt/ directory and run fpt on WRFV3.6.1_vanilla.fsp or WRFV3.4.1_vanilla.fsp . Specify the argument %i to command fpt to run interactively, e.g.

$ cd fpt
$ fpt WRFV3.4.1_vanilla.fsp %i

The fpt run will pause to show the diagnostics which have been suppressed. Type a carriage return to continue. About 10,000 diagnostics for WRF3.6.1, or 6,200 for WRFV3.4.1, will stream past (They are all captured in the list file). The fpt run will pause with an interactive prompt.

Turn off paging. Otherwise fpt will pause after each reported OPTIONAL violation. Run the OPTIONAL argument check (Please see CHECK OPTIONAL ARGUMENTS).

FPT> paging off
FPT> check optional arguments

All of the unguarded optional arguments are reported. The report ends with the summary, e.g. for WRFV3.4.1:

Check for unguarded access to OPTIONAL arguments ================================================ Optional arguments: 2118 Not always present and with unguarded references (Errors): 10 Always present but with unguarded references (Warnings): 987 Arguments with possible unguarded references (Warnings): 1 Total number of unguarded references: 1767

Note that in WRFV3.4.1 there are only 10 arguments which are optional and which are sometimes not present in calls to the routines concerned. In WRFV3.6.1 there are 35. These are potential errors. The remaining unguarded optional arguments are always present in the calls. These are no more than maintenance traps.

Note also that the check made by fpt is not completely safe and may generate false positives (Though none have been found). The check is made for code protected by IF (PRESENT(...)) constructs. If a local variable is set equal to the logical value returned by PRESENT() and is itself used to guard references, this is not visible to the current version of fpt.

Does WRF Ever Access OPTIONAL Arguments which are Not PRESENT?

The command INSERT CHECK OF OPTIONAL ARGUMENTS modifies the code to insert a check for the presence of each optional argument at references where it appears to be unguarded. The accesses to optional arguments which are not present are counted, and are reported in the file fpt_optional_check.txt at the end of a run.

The script tools/WRFV3_fpt_experient.csh has been set up to run an experiment as follows:

  1. The fpt_output directories to which fpt will write re-engineered code are cleaned.
  2. An fpt run is made for a specific engineering change. The re-engineered files are written to the fpt_output directory structure.
  3. The output files are copied to a directory labelled with the name of the WRF version and the experiment so that they may be compared with un-modified files.
  4. The output files are copied to the build directories. A small number of modified Makefiles are also copied to these directories.
  5. The executable wrf.exe is built. The build procedure is almost identical to that distributed by UCAR.
  6. The wrf executable is re-named to label it with the experiment name and is moved to the <version>_run_test/WRFV3/main/ directory.
  7. A run of the ideal case em_b_wave is made with the new executable.
  8. The wrfout output file is compared with the file generated by a standard UCAR build.

This process is described in more detail in the wrf_experiments page. Note that the script tools/WRFV3_fpt_experiment.csh has two arguments, the WRF version and the experiment name.

Run the experiment check_optional, e.g.:

$ tools/WRFV3_fpt_experiment.csh WRFV3.6.1 check_optional

The WRF Fortran files built for this experiment are copied to the directories WRFV3.6.1_check_optional/WRFV3/... or WRFV3.4.1_check_optional/WRFV3/... . Compare these files with the original UCAR sources, and with WRFV3.6.1_vanilla/WRFV3... or WRFV3.4.1_vanilla/WRFV3... if you have already made the vanilla (Unchanged) run. We strongly recommend Beyond Compare from Scooter Software to make this comparison. Specify the rule that Fortran comments are delimited by "!" and that comments are unimportant differences.

In our runs, with gfortran and ifort, the wrfout output files are identical to those generated by a standard UCAR build, and the file fpt_optional_check.txt contains the message that no accesses to missing optional arguments are detected. In a run of em_b_wave, WRF does not access missing optional arguments. However, em_b_wave only exercises about 18% of the WRF code, so further tests are required to demonstrate that this never occurs.

Copyright ©1995 to 2023 Software Validation Ltd. All rights reserved.