MODULE diawri !!====================================================================== !! *** MODULE diawri *** !! Ocean diagnostics : write ocean output files !!===================================================================== !! History : OPA ! 1991-03 (M.-A. Foujols) Original code !! 4.0 ! 1991-11 (G. Madec) !! ! 1992-06 (M. Imbard) correction restart file !! ! 1992-07 (M. Imbard) split into diawri and rstwri !! ! 1993-03 (M. Imbard) suppress writibm !! ! 1998-01 (C. Levy) NETCDF format using ioipsl INTERFACE !! ! 1999-02 (E. Guilyardi) name of netCDF files + variables !! 8.2 ! 2000-06 (M. Imbard) Original code (diabort.F) !! NEMO 1.0 ! 2002-06 (A.Bozec, E. Durand) Original code (diainit.F) !! - ! 2002-09 (G. Madec) F90: Free form and module !! - ! 2002-12 (G. Madec) merge of diabort and diainit, F90 !! ! 2005-11 (V. Garnier) Surface pressure gradient organization !! 3.2 ! 2008-11 (B. Lemaire) creation from old diawri !!---------------------------------------------------------------------- !!---------------------------------------------------------------------- !! dia_wri : create the standart output files !! dia_wri_state : create an output NetCDF file for a single instantaeous ocean state and forcing fields !!---------------------------------------------------------------------- USE oce ! ocean dynamics and tracers USE dom_oce ! ocean space and time domain USE zdf_oce ! ocean vertical physics USE ldftra_oce ! ocean active tracers: lateral physics USE ldfdyn_oce ! ocean dynamics: lateral physics USE traldf_iso_grif, ONLY : psix_eiv, psiy_eiv USE sol_oce ! solver variables USE sbc_oce ! Surface boundary condition: ocean fields USE sbc_ice ! Surface boundary condition: ice fields USE sbcssr ! restoring term toward SST/SSS climatology USE phycst ! physical constants USE zdfmxl ! mixed layer USE dianam ! build name of file (routine) USE zdfddm ! vertical physics: double diffusion USE diahth ! thermocline diagnostics USE lbclnk ! ocean lateral boundary conditions (or mpp link) USE in_out_manager ! I/O manager USE diadimg ! dimg direct access file format output USE diaar5, ONLY : lk_diaar5 USE iom USE ioipsl #if defined key_lim2 USE limwri_2 #endif USE lib_mpp ! MPP library USE timing ! preformance summary USE wrk_nemo ! working array IMPLICIT NONE PRIVATE PUBLIC dia_wri ! routines called by step.F90 PUBLIC dia_wri_state PUBLIC dia_wri_alloc ! Called by nemogcm module INTEGER :: nid_T, nz_T, nh_T, ndim_T, ndim_hT ! grid_T file INTEGER :: nid_U, nz_U, nh_U, ndim_U, ndim_hU ! grid_U file INTEGER :: nid_V, nz_V, nh_V, ndim_V, ndim_hV ! grid_V file INTEGER :: ndex(1) ! ??? INTEGER, SAVE, ALLOCATABLE, DIMENSION(:) :: ndex_hT, ndex_hU, ndex_hV !! * Substitutions # include "zdfddm_substitute.h90" # include "domzgr_substitute.h90" # include "vectopt_loop_substitute.h90" !!---------------------------------------------------------------------- !! NEMO/OPA 3.3 , NEMO Consortium (2010) !! $Id: diawri.F90 2355 2015-05-20 07:11:50Z ufla $ !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt) !!---------------------------------------------------------------------- CONTAINS INTEGER FUNCTION dia_wri_alloc() !!---------------------------------------------------------------------- INTEGER :: ierr !!---------------------------------------------------------------------- ! ALLOCATE( ndex_hT(jpi*jpj), ndex_hU(jpi*jpj), ndex_hV(jpi*jpj), STAT=dia_wri_alloc ) IF( lk_mpp ) CALL mpp_sum( dia_wri_alloc ) ! END FUNCTION dia_wri_alloc #if defined key_dimgout !!---------------------------------------------------------------------- !! 'key_dimgout' DIMG output file !!---------------------------------------------------------------------- # include "diawri_dimg.h90" #else !!---------------------------------------------------------------------- !! Default option NetCDF output file !!---------------------------------------------------------------------- # if defined key_iomput !!---------------------------------------------------------------------- !! 'key_iomput' use IOM library !!---------------------------------------------------------------------- SUBROUTINE dia_wri( kt ) !!--------------------------------------------------------------------- !! *** ROUTINE dia_wri *** !! !! ** Purpose : Standard output of opa: dynamics and tracer fields !! NETCDF format is used by default !! Standalone surface scheme !! !! ** Method : use iom_put !!---------------------------------------------------------------------- !! INTEGER, INTENT( in ) :: kt ! ocean time-step index !!---------------------------------------------------------------------- ! !! no relevant 2D arrays to write in iomput case ! END SUBROUTINE dia_wri #else !!---------------------------------------------------------------------- !! Default option use IOIPSL library !!---------------------------------------------------------------------- SUBROUTINE dia_wri( kt ) !!--------------------------------------------------------------------- !! *** ROUTINE dia_wri *** !! !! ** Purpose : Standard output of opa: dynamics and tracer fields !! NETCDF format is used by default !! !! ** Method : At the beginning of the first time step (nit000), !! define all the NETCDF files and fields !! At each time step call histdef to compute the mean if ncessary !! Each nwrite time step, output the instantaneous or mean fields !!---------------------------------------------------------------------- !! INTEGER, INTENT( in ) :: kt ! ocean time-step index !! LOGICAL :: ll_print = .FALSE. ! =T print and flush numout CHARACTER (len=40) :: clhstnam, clop, clmx ! local names INTEGER :: inum = 11 ! temporary logical unit INTEGER :: ji, jj, jk ! dummy loop indices INTEGER :: ierr ! error code return from allocation INTEGER :: iimi, iima, ipk, it, itmod, ijmi, ijma ! local integers REAL(wp) :: zsto, zout, zmax, zjulian, zdt ! local scalars !!---------------------------------------------------------------------- ! IF( nn_timing == 1 ) CALL timing_start('dia_wri') ! ! Output the initial state and forcings IF( ninist == 1 ) THEN CALL dia_wri_state( 'output.init', kt ) ninist = 0 ENDIF ! ! 0. Initialisation ! ----------------- ! local variable for debugging ll_print = .FALSE. ll_print = ll_print .AND. lwp ! Define frequency of output and means zdt = rdt IF( nacc == 1 ) zdt = rdtmin IF( ln_mskland ) THEN ; clop = "only(x)" ! put 1.e+20 on land (very expensive!!) ELSE ; clop = "x" ! no use of the mask value (require less cpu time) ENDIF #if defined key_diainstant zsto = nwrite * zdt clop = "inst("//TRIM(clop)//")" #else zsto=zdt clop = "ave("//TRIM(clop)//")" #endif zout = nwrite * zdt zmax = ( nitend - nit000 + 1 ) * zdt ! Define indices of the horizontal output zoom and vertical limit storage iimi = 1 ; iima = jpi ijmi = 1 ; ijma = jpj ipk = jpk ! define time axis it = kt itmod = kt - nit000 + 1 ! 1. Define NETCDF files and fields at beginning of first time step ! ----------------------------------------------------------------- IF( kt == nit000 ) THEN ! Define the NETCDF files (one per grid) ! Compute julian date from starting date of the run CALL ymds2ju( nyear, nmonth, nday, rdt, zjulian ) zjulian = zjulian - adatrj ! set calendar origin to the beginning of the experiment IF(lwp)WRITE(numout,*) IF(lwp)WRITE(numout,*) 'Date 0 used :', nit000, ' YEAR ', nyear, & & ' MONTH ', nmonth, ' DAY ', nday, 'Julian day : ', zjulian IF(lwp)WRITE(numout,*) ' indexes of zoom = ', iimi, iima, ijmi, ijma, & ' limit storage in depth = ', ipk ! WRITE root name in date.file for use by postpro IF(lwp) THEN CALL dia_nam( clhstnam, nwrite,' ' ) CALL ctl_opn( inum, 'date.file', 'REPLACE', 'FORMATTED', 'SEQUENTIAL', -1, numout, lwp, narea ) WRITE(inum,*) clhstnam CLOSE(inum) ENDIF ! Define the T grid FILE ( nid_T ) CALL dia_nam( clhstnam, nwrite, 'grid_T' ) IF(lwp) WRITE(numout,*) " Name of NETCDF file ", clhstnam ! filename CALL histbeg( clhstnam, jpi, glamt, jpj, gphit, & ! Horizontal grid: glamt and gphit & iimi, iima-iimi+1, ijmi, ijma-ijmi+1, & & nit000-1, zjulian, zdt, nh_T, nid_T, domain_id=nidom, snc4chunks=snc4set ) CALL histvert( nid_T, "deptht", "Vertical T levels", & ! Vertical grid: gdept & "m", ipk, gdept_1d, nz_T, "down" ) ! ! Index of ocean points CALL wheneq( jpi*jpj , tmask, 1, 1., ndex_hT, ndim_hT ) ! surface ! Define the U grid FILE ( nid_U ) CALL dia_nam( clhstnam, nwrite, 'grid_U' ) IF(lwp) WRITE(numout,*) " Name of NETCDF file ", clhstnam ! filename CALL histbeg( clhstnam, jpi, glamu, jpj, gphiu, & ! Horizontal grid: glamu and gphiu & iimi, iima-iimi+1, ijmi, ijma-ijmi+1, & & nit000-1, zjulian, zdt, nh_U, nid_U, domain_id=nidom, snc4chunks=snc4set ) CALL histvert( nid_U, "depthu", "Vertical U levels", & ! Vertical grid: gdept & "m", ipk, gdept_1d, nz_U, "down" ) ! ! Index of ocean points CALL wheneq( jpi*jpj , umask, 1, 1., ndex_hU, ndim_hU ) ! surface ! Define the V grid FILE ( nid_V ) CALL dia_nam( clhstnam, nwrite, 'grid_V' ) ! filename IF(lwp) WRITE(numout,*) " Name of NETCDF file ", clhstnam CALL histbeg( clhstnam, jpi, glamv, jpj, gphiv, & ! Horizontal grid: glamv and gphiv & iimi, iima-iimi+1, ijmi, ijma-ijmi+1, & & nit000-1, zjulian, zdt, nh_V, nid_V, domain_id=nidom, snc4chunks=snc4set ) CALL histvert( nid_V, "depthv", "Vertical V levels", & ! Vertical grid : gdept & "m", ipk, gdept_1d, nz_V, "down" ) ! ! Index of ocean points CALL wheneq( jpi*jpj , vmask, 1, 1., ndex_hV, ndim_hV ) ! surface ! No W grid FILE ! Declare all the output fields as NETCDF variables ! !!! nid_T : 3D CALL histdef( nid_T, "sst_m", "Sea Surface temperature" , "C" , & ! sst & jpi, jpj, nh_T, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) CALL histdef( nid_T, "sss_m", "Sea Surface Salinity" , "PSU" , & ! sss & jpi, jpj, nh_T, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) CALL histdef( nid_T, "sowaflup", "Net Upward Water Flux" , "Kg/m2/s", & ! (emp-rnf) & jpi, jpj, nh_T, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) CALL histdef( nid_T, "sosfldow", "downward salt flux" , "PSU/m2/s", & ! (sfx) & jpi, jpj, nh_T, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) CALL histdef( nid_T, "sohefldo", "Net Downward Heat Flux" , "W/m2" , & ! qns + qsr & jpi, jpj, nh_T, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) CALL histdef( nid_T, "soshfldo", "Shortwave Radiation" , "W/m2" , & ! qsr & jpi, jpj, nh_T, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) CALL histdef( nid_T, "soicecov", "Ice fraction" , "[0,1]" , & ! fr_i & jpi, jpj, nh_T, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) CALL histdef( nid_T, "sowindsp", "wind speed at 10m" , "m/s" , & ! wndm & jpi, jpj, nh_T, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) CALL histend( nid_T, snc4chunks=snc4set ) ! !!! nid_U : 3D CALL histdef( nid_U, "ssu_m", "Velocity component in x-direction", "m/s" , & ! ssu & jpi, jpj, nh_U, 1 , 1, 1 , - 99, 32, clop, zsto, zout ) CALL histdef( nid_U, "sozotaux", "Wind Stress along i-axis" , "N/m2" , & ! utau & jpi, jpj, nh_U, 1 , 1, 1 , - 99, 32, clop, zsto, zout ) CALL histend( nid_U, snc4chunks=snc4set ) ! !!! nid_V : 3D CALL histdef( nid_V, "ssv_m", "Velocity component in y-direction", "m/s", & ! ssv_m & jpi, jpj, nh_V, 1 , 1, 1 , - 99, 32, clop, zsto, zout ) CALL histdef( nid_V, "sometauy", "Wind Stress along j-axis" , "N/m2" , & ! vtau & jpi, jpj, nh_V, 1 , 1, 1 , - 99, 32, clop, zsto, zout ) CALL histend( nid_V, snc4chunks=snc4set ) IF(lwp) WRITE(numout,*) IF(lwp) WRITE(numout,*) 'End of NetCDF Initialization' IF(ll_print) CALL FLUSH(numout ) ENDIF ! 2. Start writing data ! --------------------- ! ndex(1) est utilise ssi l'avant dernier argument est diffferent de ! la taille du tableau en sortie. Dans ce cas , l'avant dernier argument ! donne le nombre d'elements, et ndex la liste des indices a sortir IF( lwp .AND. MOD( itmod, nwrite ) == 0 ) THEN WRITE(numout,*) 'dia_wri : write model outputs in NetCDF files at ', kt, 'time-step' WRITE(numout,*) '~~~~~~ ' ENDIF ! Write fields on T grid CALL histwrite( nid_T, "sst_m", it, sst_m, ndim_hT, ndex_hT ) ! sea surface temperature CALL histwrite( nid_T, "sss_m", it, sss_m, ndim_hT, ndex_hT ) ! sea surface salinity CALL histwrite( nid_T, "sowaflup", it, (emp - rnf ) , ndim_hT, ndex_hT ) ! upward water flux CALL histwrite( nid_T, "sosfldow", it, sfx , ndim_hT, ndex_hT ) ! downward salt flux ! (includes virtual salt flux beneath ice ! in linear free surface case) CALL histwrite( nid_T, "sohefldo", it, qns + qsr , ndim_hT, ndex_hT ) ! total heat flux CALL histwrite( nid_T, "soshfldo", it, qsr , ndim_hT, ndex_hT ) ! solar heat flux CALL histwrite( nid_T, "soicecov", it, fr_i , ndim_hT, ndex_hT ) ! ice fraction CALL histwrite( nid_T, "sowindsp", it, wndm , ndim_hT, ndex_hT ) ! wind speed ! Write fields on U grid CALL histwrite( nid_U, "ssu_m" , it, ssu_m , ndim_hU, ndex_hU ) ! i-current speed CALL histwrite( nid_U, "sozotaux", it, utau , ndim_hU, ndex_hU ) ! i-wind stress ! Write fields on V grid CALL histwrite( nid_V, "ssv_m" , it, ssv_m , ndim_hV, ndex_hV ) ! j-current speed CALL histwrite( nid_V, "sometauy", it, vtau , ndim_hV, ndex_hV ) ! j-wind stress ! 3. Close all files ! --------------------------------------- IF( kt == nitend ) THEN CALL histclo( nid_T ) CALL histclo( nid_U ) CALL histclo( nid_V ) ENDIF ! IF( nn_timing == 1 ) CALL timing_stop('dia_wri') ! END SUBROUTINE dia_wri # endif #endif SUBROUTINE dia_wri_state( cdfile_name, kt ) !!--------------------------------------------------------------------- !! *** ROUTINE dia_wri_state *** !! !! ** Purpose : create a NetCDF file named cdfile_name which contains !! the instantaneous ocean state and forcing fields. !! Used to find errors in the initial state or save the last !! ocean state in case of abnormal end of a simulation !! !! ** Method : NetCDF files using ioipsl !! File 'output.init.nc' is created if ninist = 1 (namelist) !! File 'output.abort.nc' is created in case of abnormal job end !!---------------------------------------------------------------------- CHARACTER (len=* ), INTENT( in ) :: cdfile_name ! name of the file created INTEGER , INTENT( in ) :: kt ! ocean time-step index !! CHARACTER (len=32) :: clname CHARACTER (len=40) :: clop INTEGER :: id_i , nz_i, nh_i INTEGER, DIMENSION(1) :: idex ! local workspace REAL(wp) :: zsto, zout, zmax, zjulian, zdt !!---------------------------------------------------------------------- ! IF( nn_timing == 1 ) CALL timing_start('dia_wri_state') ! 0. Initialisation ! ----------------- ! Define name, frequency of output and means clname = cdfile_name IF( .NOT. Agrif_Root() ) clname = TRIM(Agrif_CFixed())//'_'//TRIM(clname) zdt = rdt zsto = rdt clop = "inst(x)" ! no use of the mask value (require less cpu time) zout = rdt zmax = ( nitend - nit000 + 1 ) * zdt IF(lwp) WRITE(numout,*) IF(lwp) WRITE(numout,*) 'dia_wri_state : single instantaneous ocean state' IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~~ and forcing fields file created ' IF(lwp) WRITE(numout,*) ' and named :', clname, '.nc' ! 1. Define NETCDF files and fields at beginning of first time step ! ----------------------------------------------------------------- ! Compute julian date from starting date of the run CALL ymds2ju( nyear, nmonth, nday, rdt, zjulian ) ! time axis zjulian = zjulian - adatrj ! set calendar origin to the beginning of the experiment CALL histbeg( clname, jpi, glamt, jpj, gphit, & 1, jpi, 1, jpj, nit000-1, zjulian, zdt, nh_i, id_i, domain_id=nidom, snc4chunks=snc4set ) ! Horizontal grid : glamt and gphit CALL histvert( id_i, "deptht", "Vertical T levels", & ! Vertical grid : gdept "m", jpk, gdept_1d, nz_i, "down") ! Declare all the output fields as NetCDF variables CALL histdef( id_i, "sowaflup", "Net Upward Water Flux" , "Kg/m2/S", & ! net freshwater & jpi, jpj, nh_i, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) CALL histdef( id_i, "sohefldo", "Net Downward Heat Flux", "W/m2" , & ! net heat flux & jpi, jpj, nh_i, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) CALL histdef( id_i, "soshfldo", "Shortwave Radiation" , "W/m2" , & ! solar flux & jpi, jpj, nh_i, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) CALL histdef( id_i, "soicecov", "Ice fraction" , "[0,1]" , & ! fr_i & jpi, jpj, nh_i, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) CALL histdef( id_i, "sozotaux", "Zonal Wind Stress" , "N/m2" , & ! i-wind stress & jpi, jpj, nh_i, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) CALL histdef( id_i, "sometauy", "Meridional Wind Stress", "N/m2" , & ! j-wind stress & jpi, jpj, nh_i, 1 , 1, 1 , -99 , 32, clop, zsto, zout ) #if defined key_lim2 CALL lim_wri_state_2( kt, id_i, nh_i ) #else CALL histend( id_i, snc4chunks=snc4set ) #endif ! 2. Start writing data ! --------------------- ! idex(1) est utilise ssi l'avant dernier argument est diffferent de ! la taille du tableau en sortie. Dans ce cas , l'avant dernier argument ! donne le nombre d'elements, et idex la liste des indices a sortir idex(1) = 1 ! init to avoid compil warning ! Write all fields on T grid CALL histwrite( id_i, "sowaflup", kt, emp , jpi*jpj , idex ) ! freshwater budget CALL histwrite( id_i, "sohefldo", kt, qsr + qns , jpi*jpj , idex ) ! total heat flux CALL histwrite( id_i, "soshfldo", kt, qsr , jpi*jpj , idex ) ! solar heat flux CALL histwrite( id_i, "soicecov", kt, fr_i , jpi*jpj , idex ) ! ice fraction CALL histwrite( id_i, "sozotaux", kt, utau , jpi*jpj , idex ) ! i-wind stress CALL histwrite( id_i, "sometauy", kt, vtau , jpi*jpj , idex ) ! j-wind stress ! 3. Close the file ! ----------------- CALL histclo( id_i ) #if ! defined key_iomput && ! defined key_dimgout IF( ninist /= 1 ) THEN CALL histclo( nid_T ) CALL histclo( nid_U ) CALL histclo( nid_V ) ENDIF #endif IF( nn_timing == 1 ) CALL timing_stop('dia_wri_state') ! END SUBROUTINE dia_wri_state !!====================================================================== END MODULE diawri