Description |
This is an important update to facilitate the coding of the ROMS-JEDI interface. The development of the ROMS-JEDI interface is still private within JCSDA GitHub repositories. It is not ready for any application since it is still under development. However, several changes are made to improve ROMS.
- A new driver ROMS/Drivers/jedi_roms.h is added to facilitate JEDI to take direct control of the ROMS initialize, run, and finalize phases for the NLM, TLM, and ADM dynamical/numerical kernels. It is activated with new C-preprocessing option JEDI. It uses the same strategy as coupling where the ESMF/NUOPC library controls how the ROMS kernel is initialized, advanced, and terminated.
- All the ROMS modules are refactored to include a deallocation subroutine. For example, mod_ocean.F now includes allocate_ocean, deallocate_ocean, and initialize_ocean subroutines.
The destroying (deallocating) of all ROMS derived-type structures is essential in Object-Oriented Programming (OOP) for releasing memory space, avoiding memory leaks, and facilitating changing the size of the state arrays (regridding). Recall that all the ROMS derived-type objects include several pointer-variables. After a variable has been deallocated, it cannot be defined or referenced until it is allocated or assigned again.
- A new module ROMS/Utility/destroy.F is added to deallocate each variable in the derived-type structure separately. However, it is not used by default since the Fortran 2003 standard allows deallocating just the parent object to deallocate all array variables within its scope automatically. So, for example, to deallocate all the variables in the OCEAN(:) structure, we need:
IF (ng.eq.Ngrids) THEN
IF (allocated(OCEAN)) deallocate ( OCEAN )
END IF
We expect that all the Users of ROMS have at least a Fortran 2003 compiler. Otherwise, it is possible to activate the new C-preprocessing option SUBOBJECT_DEALLOCATION to deallocate each pointer variable within the structure object. For example:
IF (.not.destroy(ng, OCEAN(ng)%zeta, MyFile, &
& __LINE__, 'OCEAN(ng)%zeta')) RETURN
Here, the ROMS function destroy deallocates the free-surface pointer variable zeta in the OCEAN(ng) structure for nested grid ng.
By the way, the DEALLOCATE Fortran statement releases the space allocated for an allocatable variable or a pointer target and nullifies the pointer.
- The modules mod_param.F, mod_parallel.F, mod_iounits.F, and mod_scalars.F were slightly modified to avoid cyclic dependencies when compiling. It required to pass the Ngrids as argument in few allocation calls in read_phypar.F:
CASE ('Ngrids')
Npts=load_i(Nval, Rval, 1, Ivalue)
Ngrids=Ivalue(1)
IF (Ngrids.le.0) THEN
IF (Master) WRITE (out,290) 'Ngrids', Ngrids, &
& 'must be greater than zero.'
exit_flag=5
RETURN
END IF
got_Ngrids=.TRUE. ! Allocating variables in
CALL allocate_param ! modules that solely
CALL allocate_parallel (Ngrids) ! depend on the number
CALL allocate_iounits (Ngrids) ! nested grids
CALL allocate_stepping (Ngrids)
...
- The module mod_arrays.F is restructured into three distinct routines: ROMS_allocate_arrays, ROMS_deallocate_arrays, and ROMS_initialize_arrays. It cleans nicely the module roms_kernel_mod for all available drivers.
- Added the reporting of the river_file global attribute in output NetCDF files. In def_info.F, we have:
#ifndef ANA_PSOURCE
IF (exit_flag.eq.NoError) THEN
IF (LuvSrc(ng).or.LwSrc(ng).or.(ANY(LtracerSrc(:,ng)))) THEN
status=nf90_put_att(ncid, nf90_global, 'river_file', &
& TRIM(SSF(ng)%name))
IF (FoundError(status, nf90_noerr, __LINE__, MyFile)) THEN
IF (Master) WRITE (stdout,20) 'river_file', TRIM(ncname)
exit_flag=3
ioerror=status
END IF
END IF
END IF
#endif
Many thanks to John Wilkin for bringing this issue to my attention.
|
Description |
There have been two reports about the AVERAGES multi-file option failing during restart. I looked into the debugger again, and I could not reproduce the error. I tried eight different combinations with NTIMES, NAVG, and NDEFAVG. Thus, I don't know what specific set of values makes that logic fail.
However, I examined the possibility of adding the same logic used in history files to the time-averaging files. It turns out that augmenting the OutFiles is not that harmful when all the elements of the arrays in the derived type structure (T_IO) are not filled in some cases.
#ifdef AVERAGES
IF ((nAVG(ng).gt.0).and.(ndefAVG(ng).gt.0)) THEN
OutFiles=ntimes(ng)/ndefAVG(ng)
IF ((nAVG(ng).eq.ndefAVG(ng)).or. &
& (MOD(ntimes(ng),ndefAVG(ng)).ge.nAVG(ng))) THEN
OutFiles=Outfiles+1
END IF
CALL edit_file_struct (ng, OutFiles, AVG)
AVG(ng)%load=0 ! because delayed creation of NetCDF file
END IF ! due to time-averaging
#endif
#ifdef DIAGNOSTICS
IF ((nDIA(ng).gt.0).and.(ndefDIA(ng).gt.0)) THEN
OutFiles=ntimes(ng)/ndefDIA(ng)
IF ((nDIA(ng).eq.ndefDIA(ng)).or. &
& (MOD(ntimes(ng),ndefDIA(ng)).ge.nDIA(ng))) THEN
OutFiles=Outfiles+1
END IF
CALL edit_file_struct (ng, OutFiles, DIA)
DIA(ng)%load=0 ! because delayed creation of NetCDF file
END IF ! due to time-averaging
#endif
|