Skip to content

Convert jules_pftparm to a duplicate namelist #115

Description

@maggiehendry

Migrate jules_pftparm metadata to jules-shared #41 left an unresolved feature resulting from the implementation of the duplicate namelist functionality in LFRic apps, but not in JULES standalone. The presence of length keyword in the metadata causes the configurator tool to declare the variable as an array, which causes problems when trying to assign the value from config%jules_pftparm to jules_pftparm. For now length=: resides in jules-um & jules-standalone rather than jules-shared. This required an amendment in the parent metadata, for each item for example:
jules-um & jules-standalone

[namelist:jules_pftparm=a_wl_io]
length=:

And also amendments in jules-lfric

[namelist:jules_pftparm=a_wl_io]
fail-if=
!ns=

but this was unsatisfactory and a long term solution was required. After discussion, the best solution was to treat the jules_pftparm namelist in the same way as LFRic apps i.e. one per PFT, allowing the metadata to be as fully shared as possible. JULES standalone and the UM would also benefit from vastly improved management of the namelist inputs for different surface configurations. See the JULES wiki Redesigning JULES tile input which documents the issues. This issue explores this implementation in JULES standalone.

⚠️ Monstrous upgrade macro ⚠️

The upgrade macro has been made more complicated as a result of the need to correct many jules_pftparm items entries that are trigger ignored, before applying the macro required for this ticket. This reinforces the need for better management of this namelist. The reasons for these errors and how they have been rectified in this macro are:

  1. Upgrade macro was not robust as they only included existing configurations based on npft = [5, 9, 13] and have not included a default e.g. setting them all to missing data, which would be picked up by the validator macro or the checking routines in JULES at runtime.
    • Added a macro to fix the issue based on the existing macro or set to missing data e.g. fire_mort_io (vn5.3_t872), INFERNO (vn4.4_t136), radiation parameters for scaling against observations (no macro)
  2. Namelist has been copied from existing configurations with a different number of PFTs and the trigger ignored values have not been updated to the new configuration.
    • Where the item was of the form [x]*npft, the upgrade macro was robust, an upgrade macro didn't exist or the value was different from the upgrade macro and there weren't too may apps affected in Rose stem, I took a pragmatic approach and corrected these by hand e.g. rose-stem/app/loobos_jules_es_1p0*; vn5.5_t864, vn5.3_t766, vn4.8_t541
  3. Error when applying the upgrade macro, but existing upgrade macro is robust.
    • Repeated the existing upgrade macro in this upgrade macro.

The upgrade macro in this issue has been split into two. The first part of the macro (vn8.2_t115a) corrects the jules_pftparm namelist and the second (vn8.2_t115) converts the corrected namelist into one namelist per PFT. This is useful as the corrections to the namelist can easily be seen before they are split into separate namelists. These may need to be combined before it is merged to main and is a question for James Bruten (@james-bruten-mo), but it is very useful to have them as separate macros.

Rose stem tests with npft=9 with ncpft=4

This issue also highlighted the need to be able to identify the surface types present in a configuration when an example upgrade macro was tested so users had an example to follow to write upgrade macros after this issue was resolved. This is documented on the related issue #136, which now blocks this one as the affected Rose stem tests should be corrected before jules_pftparm is converted.

Original jules_pftparm method

Before this change the way that jules_pftparm items were read into JULES is illustrated here using the standalone method for a_wl_io as an example:

src/initialisation/standalone/params/init_pftparm.inc

SUBROUTINE init_pftparm_jules
USE pftparm_io, ONLY: jules_pftparm, init_pftparm_allocated
READ(namelist_unit, NML = jules_pftparm, IOSTAT = ERROR, IOMSG = iomessage)
CALL init_pftparm_allocated()
END SUBROUTINE init_pftparm_jules

src/science/params/pftparm_io_mod.F90

MODULE pftparm_io
REAL(KIND=real_jlslsm) :: a_wl_io(npft_max) = rmdi
NAMELIST  / jules_pftparm/ a_wl_io

CONTAINS

SUBROUTINE init_pftparm_allocated()
USE pftparm, ONLY: a_wl
a_wl(:)         = a_wl_io(1:npft)
END SUBROUTINE init_pftparm_allocated

src/science/params/pftparm_mod.F90

REAL(KIND=real_jlslsm), ALLOCATABLE :: a_wl(:) 
ALLOCATE( a_wl(npft))
a_wl(:)         = rmdi

Where USE pftparm, ONLY: a_wl is the value used in the JULES science code. All JULES tile namelist inputs pretty much follow this design.

Multiple instance jules_pftparm method

There are now multiple instances of jules_pftparm which are looped over when the namelist is read in by read_nml_jules_pftparm (JULES & UM versions both call the same routine). The members of jules_pftparm are now scalars rather than arrays. When each instance is read in, the instance is mapped to the correct position in the pftparm allocated arrays (pftparm_mod). It is therefore the pftparm_mod arrays that must be broadcast in the UM rather than jules_pftparm namelist when it is read. This means that the broadcasting does not happen in the same routine as the reading which breaks the UM Rose stem test that checks for namelist broadcasting.

ERROR: ./jules/src/science/params/pftparm_io_mod.F90 (read_nml_jules_pftparm)
Namelist "jules_pftparm" is read, but has no corresponding broadcast

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Checks completed with 1 failure                                              %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ERROR: Failed files:
 * ./jules/src/science/params/pftparm_io_mod.F90

src/initialisation/standalone/params/init_pftparm.inc

SUBROUTINE init_pftparm_jules
USE pftparm_io, ONLY: read_nml_jules_pftparm
CALL read_nml_jules_pftparm (nml_dir)
END SUBROUTINE init_pftparm_jules

src/science/params/pftparm_io_mod.F90

MODULE pftparm_io
REAL(KIND=real_jlslsm) :: a_wl_io = rmdi
NAMELIST  / jules_pftparm/ a_wl_io

CONTAINS

SUBROUTINE read_nml_jules_pftparm(unitnumber)
< Different wrapper depending on UM or JULES >
CALL read_nml_jules_pftparm_instances(unitnumber)
< UM version - Now the allocated arrays are filled, broadcast these to other processors >
END SUBROUTINE read_nml_jules_pftparm

SUBROUTINE read_nml_jules_pftparm_instances(unitnumber)
n = 0
DO ! loop over jules_pftparm instances
  READ (UNIT = unitnumber, NML = jules_pftparm, IOSTAT = errorstatus,        &
     IOMSG = iomessage)
  IF (errorstatus == IOSTAT_END) THEN
    EXIT
  ELSE IF (errorstatus == 0) THEN
    ! Map jules_pftparm instance to correct position in allocated array
    CALL init_pftparm_allocated()
  END IF
END DO
END SUBROUTINE read_nml_jules_pftparm_instances

SUBROUTINE init_pftparm_allocated()
USE pftparm, ONLY: a_wl
USE jules_surface_types_mod,  ONLY: map_nml_instance_to_tile_number
i = map_nml_instance_to_tile_number ( 'jules_pftparm', pft_name_io )
a_wl(i)         = a_wl_io
END SUBROUTINE init_pftparm_allocated
[FATAL ERROR] READ_NML_JULES_PFTPARM_INSTANCES: 
Error reading namelist JULES_PFTPARM
IoMsg: Cannot match namelist object name a_wl_io
Please check input list against code.
[FATAL ERROR] READ_NML_JULES_PFTPARM_INSTANCES:  Number of instances of jules_pftparm does not equal npft.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions