Skip to content

Commit

Permalink
Offline driver initialisation refactor continued (cable_user%MetType) (
Browse files Browse the repository at this point in the history
…#498)

This change further consolidates the initialisation logic within the
offline drivers (in particular logic related to `cable_user%MetType`) to
remove code duplication and improve code clarity across each of the
drivers (see #425, #440, #469 and #472).

As part of the refactoring changes, the `cable_user%MetType = 'gpgs'`
namelist parameter is deprecated as it is equivalent to setting
`cable_user%MetType = 'gswp'` and `leaps = .TRUE.`.

## Type of change

- [x] Code refactor
- [x] New or updated documentation

## Checklist

- [x] The new content is accessible and located in the appropriate
section.
- [x] I have checked that links are valid and point to the intended
content.
- [x] I have checked my code/text and corrected any misspellings


<!-- readthedocs-preview cable start -->
----
📚 Documentation preview 📚:
https://cable--498.org.readthedocs.build/en/498/

<!-- readthedocs-preview cable end -->
  • Loading branch information
SeanBryan51 authored Nov 29, 2024
2 parents 9d26f1a + c78428c commit 8c970f2
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 273 deletions.
2 changes: 1 addition & 1 deletion documentation/docs/user_guide/inputs/cable_nml.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ applications. The following are annotated examples of cable.nml:
| cable_user%soil_thermal_fix | logical | .TRUE. .FALSE. | .FALSE. | Use alternative soil conductivity implementation. |
| cable_user%phenology_switch | character(len=20) | 'MODIS' 'climate' | 'MODIS' | Use prescribed MODIS phenology or climate dependant phenology. |
| cable_user%RunIden | character(len=10) | any string of max. 10 characters | 'STANDARD' | Run identifier string for input/output files. |
| cable_user%MetType | character(len=6) | '' 'gswp' 'gswp3' 'gpgs' 'plum' 'cru' 'site' 'bios' | ' ' | Type of input meteorological data. |
| cable_user%MetType | character(len=6) | '' 'gswp' 'gswp3' 'plum' 'cru' 'site' 'bios' | ' ' | Type of input meteorological data. |
| cable_user%soil_struc | character(len=20) | 'default' 'sli' | 'default' | Use default or soil-litter-iso soil model. |
| cable_user%POP_out | character(len=3) | 'epi' 'rst' 'ini' | 'rst' | POP restart file type. `'epi'` is end of year state `'rst'` is a standard restart file, `'ini'` is an initialisation restart file. |
| cable_user%POP_rst | character(len=50) | any string of max. 50 characters | ' ' | POP restart file directory. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@ Other content of potential interest: [obsolete and deprecated developer features

Enter obsolete user features in the table below:

| Feature name | <div style="width:150px"> Removal reason </div> | Replacement? | CABLE version | Pull Request |
| ------------ | ------------------------------------------------------- | ------------ | ------------- | ------------ |
| Namelist variable `filename%veg` | Now uses namelist file `pft_params.nml` | `pft_params.nml` | CABLE3 | N/A |
| Namelist variable `filename%soil` | Now uses namelist file `cable_soilparm.nml` | `cable_soilparm` | CABLE3 | N/A |
| exact feature syntax | short deprecation reason | current alternative if any | version number | [#pull request number](copy PR's URL) |
| Feature name | <div style="width:150px"> Removal reason </div> | Replacement? | CABLE version | Pull Request |
| ----------------------------------------------- | ----------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------ | --------------------------------------------------- |
| Namelist variable `filename%veg` | Now uses namelist file `pft_params.nml` | `pft_params.nml` | CABLE3 | N/A |
| Namelist variable `filename%soil` | Now uses namelist file `cable_soilparm.nml` | `cable_soilparm` | CABLE3 | N/A |
| Namelist variable `cable_user%MetType = 'gpgs'` | Redundant namelist option. | Set `cable_user%MetType = 'gswp'` and `leaps = .TRUE.` | CABLE main ([3e87bc3](https://github.com/CABLE-LSM/CABLE/commit/3e87bc321cdafdc81b3f8913bd2e96da3e597fbd)) | [#498](https://github.com/CABLE-LSM/CABLE/pull/498) |
| exact feature syntax | short deprecation reason | current alternative if any | version number | [#pull request number](copy PR's URL) |






Expand Down
141 changes: 140 additions & 1 deletion src/offline/cable_driver_init.F90
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,28 @@ MODULE cable_driver_init_mod
ncciy, &
gswpfile, &
globalMetfile, &
set_group_output_values
set_group_output_values, &
timeunits, &
exists, &
calendar
USE casadimension, ONLY : icycle
USE casavariable, ONLY : casafile
USE cable_namelist_util, ONLY : &
get_namelist_file_name, &
CABLE_NAMELIST, &
arg_not_namelist
USE cable_mpi_mod, ONLY : mpi_grp_t
USE cable_phys_constants_mod, ONLY : CTFRZ => TFRZ
USE cable_input_module, ONLY : open_met_file
USE CABLE_PLUME_MIP, ONLY : PLUME_MIP_TYPE, PLUME_MIP_INIT
USE CABLE_CRU, ONLY : CRU_TYPE, CRU_INIT
USE CABLE_site, ONLY : site_TYPE, site_INIT
IMPLICIT NONE
PRIVATE

INTEGER, PARAMETER :: CASAONLY_ICYCLE_MIN = 10
INTEGER, PARAMETER :: N_MET_FORCING_VARIABLES_GSWP = 8
!! Number of GSWP met forcing variables (rain, snow, lw, sw, ps, qa, ta, wd)

LOGICAL, SAVE, PUBLIC :: vegparmnew = .FALSE. ! using new format input file (BP dec 2007)
LOGICAL, SAVE, PUBLIC :: spinup = .FALSE. ! model spinup to soil state equilibrium?
Expand Down Expand Up @@ -87,6 +97,11 @@ MODULE cable_driver_init_mod
gw_params

PUBLIC :: cable_driver_init
PUBLIC :: cable_driver_init_gswp
PUBLIC :: cable_driver_init_plume
PUBLIC :: cable_driver_init_cru
PUBLIC :: cable_driver_init_site
PUBLIC :: cable_driver_init_default

CONTAINS

Expand Down Expand Up @@ -147,6 +162,10 @@ SUBROUTINE cable_driver_init(mpi_grp, trunk_sumbal, NRRRR)
CALL set_group_output_values()
END IF

IF (TRIM(cable_user%POPLUC_RunType) == 'static') THEN
cable_user%POPLUC= .FALSE.
END IF

! TODO(Sean): we should not be setting namelist parameters in the following if
! block - all options are all configurable via the namelist file and is
! unclear that these options are being overwritten. A better approach would be
Expand Down Expand Up @@ -189,4 +208,124 @@ SUBROUTINE cable_driver_init(mpi_grp, trunk_sumbal, NRRRR)

END SUBROUTINE cable_driver_init

SUBROUTINE cable_driver_init_gswp(mpi_grp, GSWP_MID, NRRRR)
!! Model initialisation routine (GSWP specific).
TYPE(mpi_grp_t), INTENT(IN) :: mpi_grp !! MPI group to use
INTEGER, ALLOCATABLE, INTENT(OUT), OPTIONAL :: GSWP_MID(:,:) !! NetCDF file IDs for GSWP met forcing
INTEGER, INTENT(IN), OPTIONAL :: NRRRR !! Number of repeated spin-up cycles

IF (cable_user%YearStart == 0) THEN
IF (ncciy == 0) THEN
IF (mpi_grp%rank == 0) THEN
PRINT*, 'undefined start year for gswp met: '
PRINT*, 'enter value for ncciy or'
PRINT*, '(CABLE_USER%YearStart and CABLE_USER%YearEnd) in cable.nml'
END IF
WRITE(logn,*) 'undefined start year for gswp met: '
WRITE(logn,*) 'enter value for ncciy or'
WRITE(logn,*) '(CABLE_USER%YearStart and CABLE_USER%YearEnd) in cable.nml'
STOP
END IF
cable_user%YearStart = ncciy
cable_user%YearEnd = ncciy
END IF

IF (.NOT. (PRESENT(GSWP_MID) .AND. PRESENT(NRRRR))) RETURN

IF (NRRRR > 1 .AND. (.NOT. ALLOCATED(GSWP_MID))) THEN
ALLOCATE(GSWP_MID(N_MET_FORCING_VARIABLES_GSWP, cable_user%YearStart:cable_user%YearEnd))
END IF

END SUBROUTINE cable_driver_init_gswp

SUBROUTINE cable_driver_init_site(site)
!* Model initialisation routine (site met specific).
! Site experiment, e.g. AmazonFace (spinup or transient run type).
TYPE (site_TYPE), INTENT(OUT) :: site

CHARACTER(len=9) :: str1, str2, str3

IF (.NOT. l_casacnp) THEN
WRITE(*,*) "MetType=site only works with CASA-CNP turned on"
STOP 991
END IF

CALL site_INIT( site )
WRITE(str1,'(i4)') cable_user%YearStart
str1 = ADJUSTL(str1)
WRITE(str2,'(i2)') 1
str2 = ADJUSTL(str2)
WRITE(str3,'(i2)') 1
str3 = ADJUSTL(str3)
timeunits="seconds since "//TRIM(str1)//"-"//TRIM(str2)//"-"//TRIM(str3)//"00:00"
calendar = 'standard'

END SUBROUTINE cable_driver_init_site

SUBROUTINE cable_driver_init_default(dels, koffset, kend)
!! Model initialisation routine (default met specific).
REAL, INTENT(OUT) :: dels !! Time step size in seconds
INTEGER, INTENT(OUT) :: koffset !! Timestep to start at
INTEGER, INTENT(OUT) :: kend !! No. of time steps in run

! Open met data and get site information from netcdf file.
! This retrieves time step size, number of timesteps, starting date,
! latitudes, longitudes, number of sites.
CALL open_met_file(dels, koffset, kend, spinup, CTFRZ)
IF (koffset /= 0 .AND. cable_user%CALL_POP) THEN
WRITE(*,*) "When using POP, episode must start at Jan 1st!"
STOP 991
END IF

END SUBROUTINE cable_driver_init_default

SUBROUTINE cable_driver_init_plume(dels, koffset, PLUME)
!* Model initialisation routine (PLUME specific).
! PLUME experiment setup using WATCH.
REAL, INTENT(OUT) :: dels !! Time step size in seconds
INTEGER, INTENT(OUT) :: koffset !! Timestep to start at
TYPE(PLUME_MIP_TYPE), INTENT(OUT) :: PLUME

CHARACTER(len=9) :: str1, str2, str3

CALL PLUME_MIP_INIT(PLUME)
dels = PLUME%dt
koffset = 0
leaps = PLUME%LeapYears
WRITE(str1,'(i4)') cable_user%YearStart
str1 = ADJUSTL(str1)
WRITE(str2,'(i2)') 1
str2 = ADJUSTL(str2)
WRITE(str3,'(i2)') 1
str3 = ADJUSTL(str3)
timeunits="seconds since "//TRIM(str1)//"-"//TRIM(str2)//"-"//TRIM(str3)//"00:00"

END SUBROUTINE cable_driver_init_plume

SUBROUTINE cable_driver_init_cru(dels, koffset, CRU)
!* Model initialisation routine (CRU specific).
! TRENDY experiment using CRU-NCEP.
REAL, INTENT(OUT) :: dels !! Time step size in seconds
INTEGER, INTENT(OUT) :: koffset !! Timestep to start at
TYPE(CRU_TYPE), INTENT(OUT) :: CRU

CHARACTER(len=9) :: str1, str2, str3

CALL CRU_INIT(CRU)
dels = CRU%dtsecs
koffset = 0
leaps = .FALSE. ! No leap years in CRU-NCEP
exists%Snowf = .FALSE.
! No snow in CRU-NCEP, so ensure it will be determined from temperature
! in CABLE
WRITE(str1,'(i4)') cable_user%YearStart
str1 = ADJUSTL(str1)
WRITE(str2,'(i2)') 1
str2 = ADJUSTL(str2)
WRITE(str3,'(i2)') 1
str3 = ADJUSTL(str3)
timeunits="seconds since "//TRIM(str1)//"-"//TRIM(str2)//"-"//TRIM(str3)//"00:00"

END SUBROUTINE cable_driver_init_cru

END MODULE cable_driver_init_mod
109 changes: 10 additions & 99 deletions src/offline/cable_mpimaster.F90
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,15 @@ MODULE cable_mpimaster

CONTAINS

SUBROUTINE mpidrv_master (comm, trunk_sumbal)
SUBROUTINE mpidrv_master (comm, trunk_sumbal, dels, koffset, kend, PLUME, CRU)

USE mpi

USE cable_def_types_mod
USE cable_IO_vars_module, ONLY: logn,gswpfile,ncciy,leaps,globalMetfile, &
output,check,&
patch_type,landpt,&
timeunits, exists, output, &
timeunits, output, &
calendar
USE cable_common_module, ONLY: ktau_gl, kend_gl, knode_gl, cable_user, &
cable_runtime, fileName, &
Expand Down Expand Up @@ -212,7 +212,7 @@ SUBROUTINE mpidrv_master (comm, trunk_sumbal)
! PLUME-MIP only
USE CABLE_PLUME_MIP, ONLY: PLUME_MIP_TYPE, PLUME_MIP_GET_MET,&
PLUME_MIP_INIT
USE CABLE_CRU, ONLY: CRU_TYPE, CRU_GET_SUBDIURNAL_MET, CRU_INIT
USE CABLE_CRU, ONLY: CRU_TYPE, CRU_GET_SUBDIURNAL_MET

USE landuse_constant, ONLY: mstate,mvmax,mharvw
USE landuse_variable
Expand All @@ -224,25 +224,27 @@ SUBROUTINE mpidrv_master (comm, trunk_sumbal)
INTEGER :: comm ! MPI communicator for comms with the workers
DOUBLE PRECISION, INTENT(IN) :: trunk_sumbal
!! Reference value for quasi-bitwise reproducibility checks.
REAL, INTENT(INOUT) :: dels !! Time step size in seconds
INTEGER, INTENT(INOUT) :: koffset !! Timestep to start at
INTEGER, INTENT(INOUT) :: kend !! No. of time steps in run
TYPE(PLUME_MIP_TYPE), INTENT(IN) :: PLUME
TYPE(CRU_TYPE), INTENT(IN) :: CRU

! timing variables
INTEGER, PARAMETER :: kstart = 1 ! start of simulation

INTEGER :: &
ktau, & ! increment equates to timestep, resets if spinning up
ktau_tot, & ! NO reset when spinning up, total timesteps by model
kend, & ! no. of time steps in run
ktau_tot = 0, & ! NO reset when spinning up, total timesteps by model
!CLN kstart = 1, & ! timestep to start at
koffset = 0, & ! timestep to start at
ktauday, & ! day counter for CASA-CNP
idoy, & ! day of year (1:365) counter for CASA-CNP
nyear, & ! year counter for CASA-CNP
ctime, & ! day count for casacnp
ctime = 0, & ! day count for casacnp
YYYY, & !
LOY, & ! Length of Year
maxdiff(2) ! location of maximum in convergence test

REAL :: dels ! time step size in seconds
CHARACTER :: dum*9, str1*9, str2*9, str3*9 ! dummy char for fileName generation

! CABLE variables
Expand Down Expand Up @@ -274,8 +276,6 @@ SUBROUTINE mpidrv_master (comm, trunk_sumbal)
TYPE (POP_TYPE) :: POP
TYPE(POPLUC_TYPE) :: POPLUC
TYPE (LUC_EXPT_TYPE) :: LUC_EXPT
TYPE (PLUME_MIP_TYPE) :: PLUME
TYPE (CRU_TYPE) :: CRU
TYPE (landuse_mp) :: lucmp
CHARACTER :: cyear*4
CHARACTER :: ncfile*99
Expand Down Expand Up @@ -329,56 +329,7 @@ SUBROUTINE mpidrv_master (comm, trunk_sumbal)

! END header

IF (TRIM(cable_user%MetType) .EQ. 'gswp' .OR. TRIM(cable_user%MetType) .EQ. 'gswp3') THEN
IF ( CABLE_USER%YearStart.EQ.0 .AND. ncciy.GT.0) THEN
CABLE_USER%YearStart = ncciy
CABLE_USER%YearEnd = ncciy
ELSEIF ( CABLE_USER%YearStart.EQ.0 .AND. ncciy.EQ.0) THEN
PRINT*, 'undefined start year for gswp met: '
PRINT*, 'enter value for ncciy or'
PRINT*, '(CABLE_USER%YearStart and CABLE_USER%YearEnd) &
in cable.nml'

WRITE(logn,*) 'undefined start year for gswp met: '
WRITE(logn,*) 'enter value for ncciy or'
WRITE(logn,*) '(CABLE_USER%YearStart and CABLE_USER%YearEnd) &
in cable.nml'

STOP
ENDIF
ENDIF

IF ( TRIM(cable_user%MetType) .EQ. 'gpgs' ) THEN
leaps = .TRUE.
cable_user%MetType = 'gswp'
ENDIF

! casa time count
ctime = 0

! Iinitialise settings depending on met dataset

! Open met data and get site information from netcdf file. (NON-GSWP ONLY!)
! This retrieves time step size, number of timesteps, starting date,
! latitudes, longitudes, number of sites.
IF ( TRIM(cable_user%MetType) .NE. "gswp" .AND. &
TRIM(cable_user%MetType) .NE. "gswp3" .AND. &
TRIM(cable_user%MetType) .NE. "gpgs" .AND. &
TRIM(cable_user%MetType) .NE. "plum" .AND. &
TRIM(cable_user%MetType) .NE. "cru" .AND. &
TRIM(cable_user%MetType) .NE. "gpcc") THEN
CALL open_met_file( dels, koffset, kend, spinup, CTFRZ )
IF ( koffset .NE. 0 .AND. CABLE_USER%CALL_POP ) THEN
WRITE(*,*)"When using POP, episode must start at Jan 1st!"
STOP 991
ENDIF
ENDIF

! Tell the workers if we're leaping
CALL MPI_Bcast (leaps, 1, MPI_LOGICAL, 0, comm, ierr)

! outer loop - spinup loop no. ktau_tot :
ktau_tot = 0
ktau = 0
SPINLOOP:DO
YEARLOOP: DO YYYY= CABLE_USER%YearStart, CABLE_USER%YearEnd
Expand All @@ -391,48 +342,8 @@ SUBROUTINE mpidrv_master (comm, trunk_sumbal)
ENDIF

IF ( TRIM(cable_user%MetType) .EQ. 'plum' ) THEN
! CLN HERE PLUME modfications
IF ( CALL1 ) THEN
CALL PLUME_MIP_INIT( PLUME )
dels = PLUME%dt
koffset = 0
leaps = PLUME%LeapYears
WRITE(str1,'(i4)') CurYear
str1 = ADJUSTL(str1)
WRITE(str2,'(i2)') 1
str2 = ADJUSTL(str2)
WRITE(str3,'(i2)') 1
str3 = ADJUSTL(str3)
timeunits="seconds since "//TRIM(str1)//"-"//TRIM(str2)//"-"//TRIM(str3)//" &
00:00"

ENDIF
kend = NINT(24.0*3600.0/dels) * LOY
ELSE IF ( TRIM(cable_user%MetType) .EQ. 'cru' ) THEN
! CLN HERE CRU modfications
IF ( CALL1 ) THEN

CALL CPU_TIME(etime)
CALL CRU_INIT( CRU )

dels = CRU%dtsecs
koffset = 0
leaps = .FALSE. ! No leap years in CRU-NCEP
exists%Snowf = .FALSE. ! No snow in CRU-NCEP, so ensure it will
! be determined from temperature in CABLE

WRITE(str1,'(i4)') CurYear
str1 = ADJUSTL(str1)
WRITE(str2,'(i2)') 1
str2 = ADJUSTL(str2)
WRITE(str3,'(i2)') 1
str3 = ADJUSTL(str3)
timeunits="seconds since "//TRIM(str1)//"-"//TRIM(str2)//"-"//TRIM(str3)//" &
00:00"


ENDIF

LOY = 365
kend = NINT(24.0*3600.0/dels) * LOY
ELSE IF (TRIM(cable_user%MetType) .EQ. 'gswp') THEN
Expand Down
Loading

0 comments on commit 8c970f2

Please sign in to comment.