Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Offline driver initialisation refactor continued (cable_user%MetType) #498

Merged
merged 9 commits into from
Nov 29, 2024

Conversation

SeanBryan51
Copy link
Collaborator

@SeanBryan51 SeanBryan51 commented Nov 27, 2024

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

  • Code refactor
  • New or updated documentation

Checklist

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

📚 Documentation preview 📚: https://cable--498.org.readthedocs.build/en/498/

@SeanBryan51
Copy link
Collaborator Author

I won't have time to move the remaining occurrences of CALL1 to a shared initialisation routine before going on leave next week but I have noted them below:

  1. IF ( CALL1 ) THEN
    IF (cable_user%POPLUC) THEN
    CALL LUC_EXPT_INIT (LUC_EXPT)
    ENDIF
    ! vh_js !
    CALL load_parameters( met, air, ssnow, veg,climate,bgc, &
    soil, canopy, rough, rad, sum_flux, &
    bal, logn, vegparmnew, casabiome, casapool, &
    casaflux, sum_casapool, sum_casaflux, &
    casamet, casabal, phen, POP, spinup, &
    CEMSOIL, CTFRZ, LUC_EXPT, POPLUC )
    IF (check%ranges /= NO_CHECK) THEN
    WRITE (*, *) "Checking parameter ranges"
    CALL constant_check_range(soil, veg, 0, met)
    END IF
    IF ( CABLE_USER%POPLUC .AND. TRIM(CABLE_USER%POPLUC_RunType) .EQ. 'static') &
    CABLE_USER%POPLUC= .FALSE.
    ! Open output file:
    IF (.NOT.CASAONLY) THEN
    IF ( TRIM(filename%out) .EQ. '' ) THEN
    IF ( CABLE_USER%YEARSTART .GT. 0 ) THEN
    WRITE( dum, FMT="(I4,'_',I4)")CABLE_USER%YEARSTART, &
    CABLE_USER%YEAREND
    filename%out = TRIM(filename%path)//'/'//&
    TRIM(cable_user%RunIden)//'_'//&
    TRIM(dum)//'_cable_out.nc'
    ELSE
    filename%out = TRIM(filename%path)//'/'//&
    TRIM(cable_user%RunIden)//'_cable_out.nc'
    ENDIF
    ENDIF
    IF (RRRR.EQ.1) THEN
    CALL nullify_write() ! nullify pointers
    CALL open_output_file( dels, soil, veg, bgc, rough, met)
    ENDIF
    ENDIF
    ssnow%otss_0 = ssnow%tgg(:,1)
    ssnow%otss = ssnow%tgg(:,1)
    ssnow%tss = ssnow%tgg(:,1)
    canopy%fes_cor = 0.
    canopy%fhs_cor = 0.
    met%ofsd = 0.1
    CALL zero_sum_casa(sum_casapool, sum_casaflux)
    count_sum_casa = 0
    IF (cable_user%call_climate) CALL climate_init ( climate, mp, ktauday )
    IF (cable_user%call_climate .AND.(.NOT.cable_user%climate_fromzero)) &
    CALL READ_CLIMATE_RESTART_NC (climate, ktauday)
    spinConv = .FALSE. ! initialise spinup convergence variable
    IF (.NOT.spinup) spinConv=.TRUE.
    IF( icycle>0 .AND. spincasa) THEN
    PRINT *, 'EXT spincasacnp enabled with mloop= ', mloop
    CALL spincasacnp(dels,kstart,kend,mloop,veg,soil,casabiome,casapool, &
    casaflux,casamet,casabal,phen,POP,climate,LALLOC)
    SPINon = .FALSE.
    SPINconv = .FALSE.
    ELSEIF ( casaonly .AND. (.NOT. spincasa) ) THEN !.AND. cable_user%popluc) THEN
    CALL CASAONLY_LUC(dels,kstart,kend,veg,soil,casabiome,casapool, &
    casaflux,casamet,casabal,phen,POP,climate,LALLOC, LUC_EXPT, POPLUC, &
    sum_casapool, sum_casaflux)
    SPINon = .FALSE.
    SPINconv = .FALSE.
    ktau = kend
    ENDIF
    ENDIF ! CALL 1
  2. IF (( .NOT. CASAONLY ) .OR. (CASAONLY.AND.CALL1)) THEN
    CALL PLUME_MIP_GET_MET(PLUME, MET, YYYY, ktau, kend, &
    (YYYY.EQ.CABLE_USER%YearEnd .AND. ktau.EQ.kend))
    ENDIF
  3. IF (( .NOT. CASAONLY ).OR. (CASAONLY.AND.CALL1)) THEN
    CALL CRU_GET_SUBDIURNAL_MET(CRU, met, &
    YYYY, ktau, kend, &
    YYYY.EQ.CABLE_USER%YearEnd)
    ENDIF
  4. IF ( CALL1 ) THEN
    IF (cable_user%POPLUC) THEN
    CALL LUC_EXPT_INIT (LUC_EXPT)
    ENDIF
    ! vh_js !
    CALL load_parameters( met, air, ssnow, veg,climate,bgc, &
    soil, canopy, rough, rad, sum_flux, &
    bal, logn, vegparmnew, casabiome, casapool, &
    casaflux, sum_casapool, sum_casaflux, &
    casamet, casabal, phen, POP, spinup, &
    CEMSOIL, CTFRZ, LUC_EXPT, POPLUC )
    IF (CABLE_USER%POPLUC .AND. TRIM(CABLE_USER%POPLUC_RunType) .EQ. 'static') &
    CABLE_USER%POPLUC= .FALSE.
    ssnow%otss_0 = ssnow%tgg(:,1)
    ssnow%otss = ssnow%tgg(:,1)
    ssnow%tss = ssnow%tgg(:,1)
    canopy%fes_cor = 0.
    canopy%fhs_cor = 0.
    met%ofsd = 0.1
    IF (.NOT.spinup) spinConv=.TRUE.
    ! MPI: above was standard serial code
    ! now it's time to initialize the workers
    ! MPI: bcast to workers so that they don't need to open the met
    ! file themselves
    CALL MPI_Bcast (dels, 1, MPI_REAL, 0, comm, ierr)
    ENDIF
  5. IF ( CALL1 ) THEN
    ! MPI: need to know extents before creating datatypes
    CALL find_extents
    ! MPI: calculate and broadcast landpoint decomposition to the workers
    CALL master_decomp(comm, mland)
    ! MPI: set up stuff for new irecv isend code that separates completion
    ! from posting of requests
    ! wnp is set in master_decomp above
    ALLOCATE (inp_req(wnp))
    ALLOCATE (inp_stats(MPI_STATUS_SIZE, wnp))
    ALLOCATE (recv_req(wnp))
    ALLOCATE (recv_stats(MPI_STATUS_SIZE, wnp))
    CALL MPI_Comm_dup (comm, icomm, ierr)
    CALL MPI_Comm_dup (comm, ocomm, ierr)
    ! MPI: data set in load_parameter is now scattered out to the
    ! workers
    CALL master_cable_params(comm, met,air,ssnow,veg,bgc,soil,canopy,&
    & rough,rad,sum_flux,bal)
    IF (cable_user%call_climate) THEN
    CALL master_climate_types(comm, climate, ktauday)
    ENDIF
    ! MPI: mvtype and mstype send out here instead of inside master_casa_params
    ! so that old CABLE carbon module can use them. (BP May 2013)
    CALL MPI_Bcast (mvtype, 1, MPI_INTEGER, 0, comm, ierr)
    CALL MPI_Bcast (mstype, 1, MPI_INTEGER, 0, comm, ierr)
    ! MPI: casa parameters scattered only if cnp module is active
    IF (icycle>0) THEN
    ! MPI:
    CALL master_casa_params (comm,casabiome,casapool,casaflux,casamet,&
    & casabal,phen)
    IF ( CABLE_USER%CALL_POP ) CALL master_pop_types (comm,pop)
    END IF
    ! MPI: allocate read ahead buffers for input met and veg data
    CALL alloc_cbm_var (imet, mp)
    CALL alloc_cbm_var (iveg, mp)
    ! MPI: create inp_t types to scatter input data to the workers
    ! at the start of every timestep
    !CALL master_intypes (comm,met,veg)
    ! for read ahead use the new variables
    CALL master_intypes (comm,imet,iveg)
    ! MPI: create recv_t types to receive results from the workers
    ! at the end of every timestep
    CALL master_outtypes (comm,met,canopy,ssnow,rad,bal,air,soil,veg)
    ! MPI: create type for receiving casa results
    ! only if cnp module is active
    IF (icycle>0) THEN
    CALL master_casa_types (comm, casapool, casaflux, &
    casamet, casabal, phen)
    IF ( CABLE_USER%CASA_DUMP_READ .OR. CABLE_USER%CASA_DUMP_WRITE ) &
    CALL master_casa_dump_types( comm, casamet, casaflux, phen )
    WRITE(*,*) 'cable_mpimaster, POPLUC: ' , CABLE_USER%POPLUC
    IF ( CABLE_USER%POPLUC ) &
    CALL master_casa_LUC_types( comm, casapool, casabal)
    END IF
    ! MPI: create type to send restart data back to the master
    ! only if restart file is to be created
    IF(output%restart) THEN
    CALL master_restart_types (comm, canopy, air)
    END IF
    ! CALL zero_sum_casa(sum_casapool, sum_casaflux)
    ! count_sum_casa = 0
    ! CALL master_sumcasa_types(comm, sum_casapool, sum_casaflux)
    IF( icycle>0 .AND. spincasa) THEN
    PRINT *, 'EXT spincasacnp enabled with mloop= ', mloop, dels, kstart, kend
    CALL master_spincasacnp(dels,kstart,kend,mloop,veg,soil,casabiome,casapool, &
    casaflux,casamet,casabal,phen,POP,climate,icomm, ocomm)
    SPINconv = .FALSE.
    CASAONLY = .TRUE.
    ktau_gl = 0
    ktau = 0
    ELSEIF ( casaonly .AND. (.NOT. spincasa) .AND. cable_user%popluc) THEN
    CALL master_CASAONLY_LUC(dels,kstart,kend,veg,casabiome,casapool, &
    casaflux,casamet,casabal,phen,POP,climate,LUC_EXPT, POPLUC, &
    icomm, ocomm)
    SPINconv = .FALSE.
    ktau_gl = 0
    ktau = 0
    ENDIF
    ! MPI: mostly original serial code follows...
    ENDIF ! CALL1
  6. IF ( CALL1 ) THEN
    IF (.NOT.spinup) spinConv=.TRUE.
    ! MPI: bcast to workers so that they don't need to open the met
    ! file themselves
    CALL MPI_Bcast (dels, 1, MPI_REAL, 0, comm, ierr)
    ENDIF
  7. IF ( CALL1 ) THEN
    ! MPI: need to know extents before creating datatypes
    CALL find_extents
    ! MPI: receive decomposition info from the master
    CALL worker_decomp(comm)
    ! MPI: in overlap version sends and receives occur on separate comms
    CALL MPI_Comm_dup (comm, icomm, ierr)
    CALL MPI_Comm_dup (comm, ocomm, ierr)
    ! MPI: data set in load_parameter is now received from
    ! the master
    CALL worker_cable_params(comm, met,air,ssnow,veg,bgc,soil,canopy,&
    & rough,rad,sum_flux,bal)
    !mrd561 debug
    WRITE(logn,*) ' ssat_vec min',MINVAL(soil%ssat_vec),MINLOC(soil%ssat_vec)
    WRITE(logn,*) ' sfc_vec min',MINVAL(soil%sfc_vec),MINLOC(soil%sfc_vec)
    WRITE(logn,*) ' wb min',MINVAL(ssnow%wb),MINLOC(ssnow%wb)
    CALL flush(logn)
    IF (check%ranges /= NO_CHECK) THEN
    WRITE (logn, *) "Checking parameter ranges"
    CALL constant_check_range(soil, veg, 0, met)
    END IF
    IF (cable_user%call_climate) THEN
    CALL worker_climate_types(comm, climate, ktauday )
    ENDIF
    ! MPI: mvtype and mstype send out here instead of inside worker_casa_params
    ! so that old CABLE carbon module can use them. (BP May 2013)
    CALL MPI_Bcast (mvtype, 1, MPI_INTEGER, 0, comm, ierr)
    CALL MPI_Bcast (mstype, 1, MPI_INTEGER, 0, comm, ierr)
    ! MPI: casa parameters received only if cnp module is active
    IF (icycle>0) THEN
    CALL worker_casa_params (comm,casabiome,casapool,casaflux,casamet,&
    & casabal,phen)
    ! MPI: POP restart received only if pop module AND casa are active
    IF ( CABLE_USER%CALL_POP ) CALL worker_pop_types (comm,veg,pop)
    END IF
    ! MPI: create inp_t type to receive input data from the master
    ! at the start of every timestep
    CALL worker_intype (comm,met,veg)
    ! MPI: casa parameters received only if cnp module is active
    ! MPI: create send_t type to send the results to the master
    ! at the end of every timestep
    CALL worker_outtype (comm,met,canopy,ssnow,rad,bal,air,soil,veg)
    ! MPI: casa parameters received only if cnp module is active
    ! MPI: create type to send casa results back to the master
    ! only if cnp module is active
    IF (icycle>0) THEN
    CALL worker_casa_type (comm, casapool,casaflux, &
    casamet,casabal, phen)
    IF ( CABLE_USER%CASA_DUMP_READ .OR. CABLE_USER%CASA_DUMP_WRITE ) &
    CALL worker_casa_dump_types(comm, casamet, casaflux, phen)
    WRITE(logn,*) 'cable_mpiworker, POPLUC: ', CABLE_USER%POPLUC
    WRITE(*,*) 'cable_mpiworker, POPLUC: ', CABLE_USER%POPLUC
    CALL flush(logn)
    IF ( CABLE_USER%POPLUC ) &
    CALL worker_casa_LUC_types( comm, casapool, casabal)
    ! MPI: casa parameters received only if cnp module is active
    END IF
    ! MPI: create type to send restart data back to the master
    ! only if restart file is to be created
    IF(output%restart) THEN
    CALL worker_restart_type (comm, canopy, air)
    END IF
    ! Open output file:
    ! MPI: only the master writes to the files
    !CALL open_output_file( dels, soil, veg, bgc, rough )
    ssnow%otss_0 = ssnow%tgg(:,1)
    ssnow%otss = ssnow%tgg(:,1)
    canopy%fes_cor = 0.
    canopy%fhs_cor = 0.
    met%ofsd = 0.1
    ! CALL worker_sumcasa_types(comm, sum_casapool, sum_casaflux)
    !count_sum_casa = 0
    IF( icycle>0 .AND. spincasa) THEN
    WRITE(logn,*) 'EXT spincasacnp enabled with mloop= ', mloop
    CALL worker_spincasacnp(dels,kstart,kend,mloop,veg,soil,casabiome,casapool, &
    casaflux,casamet,casabal,phen,POP,climate,LALLOC, icomm, ocomm)
    SPINconv = .FALSE.
    CASAONLY = .TRUE.
    ktau_gl = 0
    ktau = 0
    ELSEIF ( casaonly .AND. (.NOT. spincasa) .AND. cable_user%popluc) THEN
    CALL worker_CASAONLY_LUC(dels,kstart,kend,veg,soil,casabiome,casapool, &
    casaflux,casamet,casabal,phen,POP,climate,LALLOC, &
    icomm, ocomm)
    SPINconv = .FALSE.
    ktau_gl = 0
    ktau = 0
    ENDIF
    ELSE
    IF (icycle.GT.0) THEN
    ! re-initalise annual flux sums
    casabal%FCgppyear =0.0
    casabal%FCrpyear =0.0
    casabal%FCnppyear =0.0
    casabal%FCrsyear =0.0
    casabal%FCneeyear =0.0
    ENDIF
    ENDIF !CALL1

@ccarouge ccarouge marked this pull request as ready for review November 28, 2024 01:20
@ccarouge
Copy link
Member

@SeanBryan51 I know you are having issues testing all the changes but have you tried running benchab? The sites and the spatial runs should return identical results before and after.

@ccarouge
Copy link
Member

For gpgs, please add it as deprecated on this page: https://cable.readthedocs.io/en/latest/user_guide/other_resources/obsolete_and_deprecated_features/obsolete_and_deprecated_features/ In replacement, just put the "gswp + leap" reason.

@SeanBryan51
Copy link
Collaborator Author

Running it through benchcab now.

@SeanBryan51
Copy link
Collaborator Author

It looks like I forgot to update the stubs for the serial build - but it also made me realise the build-ci currently builds only the MPI executable (due to the default value of the mpi variant in the CABLE spack package definition). Something to note for the future.

@SeanBryan51 SeanBryan51 force-pushed the 425-offline-driver-initialisation-refactor-part3 branch from 7e6a8bb to 7a195f7 Compare November 28, 2024 03:53
Copy link
Member

@ccarouge ccarouge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems ok but let's see what benchcab thinks of it.

This is done as setting `cable_user%MetType = 'gpgs'` via the namelist
is equivalent to setting `cable_user%MetType = 'gswp'` and `leaps =
.TRUE.`.
…ser%YearEnd to cable_driver_init_gswp

Note prior to this change cable_user%YearStart and cable_user%YearEnd
was only initialised for the master process. This change now initialises
these variables over all processes so that the start and end year values
are consistent across the drivers.
@SeanBryan51 SeanBryan51 force-pushed the 425-offline-driver-initialisation-refactor-part3 branch from 7a195f7 to 2fcf258 Compare November 28, 2024 04:41
@SeanBryan51
Copy link
Collaborator Author

Benchcab runs are bitwise reproducible with main:

PBS log file:

2024-11-28 15:40:15,127 - INFO - benchcab.benchcab.py:380 - Running comparison tasks...
2024-11-28 15:40:15,151 - INFO - benchcab.benchcab.py:381 - tasks: 168 (models: 2, sites: 42, science configurations: 4)
2024-11-28 15:43:03,606 - INFO - benchcab.benchcab.py:391 - 0 failed, 168 passed

Benchcab version: 4.2.0

config.yaml:

realisations:
  - repo:
      git:
        branch: main
  - repo:
      git:
        branch: 425-offline-driver-initialisation-refactor-part3

modules: [
  intel-compiler/2021.1.1,
  netcdf/4.7.4,
  openmpi/4.1.0
]

Spatial (MPI) runs all execute as expected (note outputs do not reproduce as per issue #463).

Copy link
Member

@ccarouge ccarouge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's good for me.

@SeanBryan51 SeanBryan51 force-pushed the 425-offline-driver-initialisation-refactor-part3 branch from 2fcf258 to c78428c Compare November 28, 2024 05:22
Copy link
Contributor

@micaeljtoliveira micaeljtoliveira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SeanBryan51 I had another look and I have one suggestion and one question. Otherwise looks fine!

src/offline/cable_driver_init.F90 Show resolved Hide resolved
src/offline/cable_mpimaster.F90 Show resolved Hide resolved
@SeanBryan51 SeanBryan51 merged commit 8c970f2 into main Nov 29, 2024
7 checks passed
@SeanBryan51 SeanBryan51 deleted the 425-offline-driver-initialisation-refactor-part3 branch November 29, 2024 01:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants