Errors when integer variable is output from one phase and used as an interstitial dimension in another
Description
When a dimension is output from the init or register phase of a scheme and then used as a dimension of an interstitial variable for the run phase of that same scheme or another, you get this build error:
Cannot find variable for dimension, <dimension var>, of <interstitial variable>, at...
Found <dimension var> from excluded source, 'suite', at...
Steps to Reproduce
In the capgen_test, make the following modifications:
- Add an integer output variable to temp_adjust_init Fortran:
subroutine temp_adjust_init (dim_inter, errmsg, errflg)
integer, intent(out) :: dim_inter
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errflg
errmsg = ''
errflg = 0
dim_inter = 3
end subroutine temp_adjust_init
metadata addition:
[ dim_inter ]
standard_name = dimension_for_interstitial_variable
units = count
dimensions = ()
type = integer
intent = out
- Add a new interstitial, intent(out) variable to the temp_adjust_run:
Fortran:
subroutine temp_adjust_run(foo, timestep, interstitial_var, temp_prev, temp_layer, qv, ps, &
to_promote, promote_pcnst, errmsg, errflg, innie, outie, optsie)
integer, intent(in) :: foo
real(kind_phys), intent(in) :: timestep
real(kind_phys), intent(inout),optional :: qv(:)
real(kind_phys), intent(inout) :: ps(:)
REAL(kind_phys), intent(in) :: temp_prev(:)
REAL(kind_phys), intent(inout) :: temp_layer(foo)
real(kind_phys), intent(in) :: to_promote(:)
real(kind_phys), intent(in) :: promote_pcnst(:)
integer, intent(out) :: interstitial_var(:)
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errflg
real(kind_phys), optional, intent(in) :: innie
real(kind_phys), optional, intent(out) :: outie
real(kind_phys), optional, intent(inout) :: optsie
!----------------------------------------------------------------
integer :: col_index
errmsg = ''
errflg = 0
interstitial_var = 3
if (size(interstitial_var) /= 3) then
errflg = 1
errmsg = 'interstitial variable not allocated properly!'
end if
if (.not. module_level_config) then
! do nothing
return
end if
do col_index = 1, foo
temp_layer(col_index) = temp_layer(col_index) + temp_prev(col_index)
if (present(qv)) qv(col_index) = qv(col_index) + 1.0_kind_phys
end do
if (present(innie) .and. present(outie) .and. present(optsie)) then
outie = innie * optsie
optsie = optsie + 1.0_kind_phys
end if
END SUBROUTINE temp_adjust_run
Metadata addition:
[ interstitial_var ]
standard_name = output_only_interstitial_variable
units = 1
dimensions = (dimension_for_interstitial_variable)
type = integer
intent = out
- Run the tests and observe the error.
@gold2718 @climbfuji @dustinswales
I have a question about desired functionality, friends!
Currently, in suite_objects.py (Group.manage_variable), we are excluding local variable types when we try to find the dimensions for a variable in the calling tree (~line 2340):
# Finally, make sure all dimensions are accounted for
emsg = self.add_variable_dimensions(local_var, _API_LOCAL_VAR_TYPES,
adjust_intent=True,
to_dict=self.call_list)
In this case, _API_LOCAL_VAR_TYPES is the list of types to exclude from the search (which is "suite" and "local").
My assumption is that we're excluding these types because we aren't sure if these variables have been initialized, so using them as dimensions is potentially problematic (I also imagine that before the register phase existed it didn't make sense to have allow suite-level variables to be dimensions).
My question is: do we wanted lessen this restriction (i.e allow dimensions to be suite-level variables) to allow for variables that are initialized in the register phase to be used to allocate variables in the init phase.
My thinking is that this will be useful for schemes that are reading in dimensions from a file and using those to allocate interstitial variables. For situations when the variable has not been properly initialized, Fortran should throw an error at runtime anyway.
Thoughts?
PS. I haven't actually figured out how to fully implement this, but thought I'd ask for feedback before burrowing further down this 🐰🕳️