MODULE iostart USE lmdz_abort_physic, ONLY: abort_physic PRIVATE INTEGER,SAVE :: nid_start INTEGER,SAVE :: nid_restart INTEGER,SAVE :: idim1,idim2,idim3,idim4 INTEGER,PARAMETER :: length=100 INTERFACE get_field MODULE PROCEDURE Get_field_r1,Get_field_r2,Get_field_r3 END INTERFACE get_field INTERFACE get_var MODULE PROCEDURE get_var_r0,Get_var_r1,Get_var_r2,Get_var_r3 END INTERFACE get_var INTERFACE put_field MODULE PROCEDURE put_field_r1,put_field_r2,put_field_r3 END INTERFACE put_field INTERFACE put_var MODULE PROCEDURE put_var_r0,put_var_r1,put_var_r2,put_var_r3 END INTERFACE put_var PUBLIC get_field,get_var,put_field,put_var PUBLIC Open_startphy,close_startphy,open_restartphy,close_restartphy, enddef_restartphy CONTAINS SUBROUTINE Open_startphy(filename) USE netcdf, ONLY: nf90_nowrite, nf90_noerr,nf90_open USE lmdz_phys_para IMPLICIT NONE CHARACTER(LEN=*) :: filename INTEGER :: ierr IF (is_mpi_root .AND. is_omp_root) THEN ierr = nf90_open (filename, nf90_nowrite,nid_start) IF (ierr/=nf90_noerr) THEN WRITE(6,*)' Pb d''ouverture du fichier '//filename WRITE(6,*)' ierr = ', ierr CALL abort_physic("", "", 1) ENDIF ENDIF END SUBROUTINE Open_startphy SUBROUTINE Close_startphy USE netcdf, ONLY: nf90_close USE lmdz_phys_para IMPLICIT NONE INTEGER :: ierr IF (is_mpi_root .AND. is_omp_root) THEN ierr = nf90_close (nid_start) ENDIF END SUBROUTINE close_startphy FUNCTION Inquire_Field(Field_name) USE netcdf, ONLY: nf90_noerr,nf90_inq_varid USE lmdz_phys_para IMPLICIT NONE CHARACTER(LEN=*) :: Field_name LOGICAL :: inquire_field INTEGER :: varid INTEGER :: ierr IF (is_mpi_root .AND. is_omp_root) THEN ierr=nf90_inq_varid(nid_start,Field_name,varid) IF (ierr==nf90_noerr) THEN Inquire_field=.TRUE. ELSE Inquire_field=.FALSE. ENDIF ENDIF CALL bcast(Inquire_field) END FUNCTION Inquire_Field SUBROUTINE Get_Field_r1(field_name,field,found) IMPLICIT NONE CHARACTER(LEN=*),INTENT(IN) :: Field_name REAL,INTENT(INOUT) :: Field(:) LOGICAL,INTENT(OUT),OPTIONAL :: found CALL Get_field_rgen(field_name,field,1,found) END SUBROUTINE Get_Field_r1 SUBROUTINE Get_Field_r2(field_name,field,found) IMPLICIT NONE CHARACTER(LEN=*),INTENT(IN) :: Field_name REAL,INTENT(INOUT) :: Field(:,:) LOGICAL,INTENT(OUT),OPTIONAL :: found CALL Get_field_rgen(field_name,field,size(field,2),found) END SUBROUTINE Get_Field_r2 SUBROUTINE Get_Field_r3(field_name,field,found) IMPLICIT NONE CHARACTER(LEN=*),INTENT(IN) :: Field_name REAL,INTENT(INOUT) :: Field(:,:,:) LOGICAL,INTENT(OUT),OPTIONAL :: found CALL Get_field_rgen(field_name,field,size(field,2)*size(field,3),found) END SUBROUTINE Get_Field_r3 SUBROUTINE Get_field_rgen(field_name,field,field_size,found) USE netcdf, ONLY: nf90_inq_varid,nf90_noerr,nf90_get_var USE dimphy USE lmdz_geometry USE lmdz_grid_phy USE lmdz_phys_para IMPLICIT NONE CHARACTER(LEN=*) :: Field_name INTEGER :: field_size REAL :: field(klon,field_size) LOGICAL,OPTIONAL :: found REAL,ALLOCATABLE :: field_glo(:,:) REAL,ALLOCATABLE :: field_glo_tmp(:,:) INTEGER,ALLOCATABLE :: ind_cell_glo_glo(:) LOGICAL :: tmp_found INTEGER :: varid INTEGER :: ierr,i IF (is_master) THEN ALLOCATE(ind_cell_glo_glo(klon_glo)) ALLOCATE(field_glo(klon_glo,field_size)) ALLOCATE(field_glo_tmp(klon_glo,field_size)) ELSE ALLOCATE(ind_cell_glo_glo(0)) ALLOCATE(field_glo(0,0)) ENDIF CALL gather(ind_cell_glo,ind_cell_glo_glo) IF (is_master) THEN ierr=nf90_inq_varid(nid_start,Field_name,varid) IF (ierr==nf90_noerr) THEN CALL body(field_glo_tmp) tmp_found=.TRUE. ELSE tmp_found=.FALSE. ENDIF ENDIF CALL bcast(tmp_found) IF (tmp_found) THEN IF (is_master) THEN DO i=1,klon_glo field_glo(i,:)=field_glo_tmp(ind_cell_glo_glo(i),:) ENDDO ENDIF CALL scatter(field_glo,field) ENDIF IF (PRESENT(found)) THEN found=tmp_found ELSE IF (.NOT. tmp_found) THEN PRINT*, 'phyetat0: Le champ <'//field_name//'> est absent' CALL abort_physic("", "", 1) ENDIF ENDIF CONTAINS SUBROUTINE body(field_glo) REAL :: field_glo(klon_glo*field_size) ierr=nf90_get_var(nid_start,varid,field_glo) IF (ierr/=nf90_noerr) THEN ! La variable exist dans le fichier mais la lecture a echouee. PRINT*, 'phyetat0: Lecture echouee pour <'//field_name//'>' IF (field_name=='CLWCON' .OR. field_name=='RNEBCON' .OR. field_name=='RATQS') THEN ! Essaye de lire le variable sur surface uniqument, comme fait avant field_glo(:)=0. ierr=nf90_get_var(nid_start,varid,field_glo(1:klon_glo)) IF (ierr/=nf90_noerr) THEN PRINT*, 'phyetat0: Lecture echouee aussi en 2D pour <'//field_name//'>' CALL abort_physic("", "", 1) ELSE PRINT*, 'phyetat0: La variable <'//field_name//'> lu sur surface seulement'!, selon ancien format, le reste mis a zero' END IF ELSE CALL abort_physic("", "", 1) ENDIF ENDIF END SUBROUTINE body END SUBROUTINE Get_field_rgen SUBROUTINE get_var_r0(var_name,var,found) IMPLICIT NONE CHARACTER(LEN=*),INTENT(IN) :: var_name REAL,INTENT(INOUT) :: var LOGICAL,OPTIONAL,INTENT(OUT) :: found REAL :: varout(1) CALL Get_var_rgen(var_name,varout,size(varout),found) var=varout(1) END SUBROUTINE get_var_r0 SUBROUTINE get_var_r1(var_name,var,found) IMPLICIT NONE CHARACTER(LEN=*),INTENT(IN) :: var_name REAL,INTENT(INOUT) :: var(:) LOGICAL,OPTIONAL,INTENT(OUT) :: found CALL Get_var_rgen(var_name,var,size(var),found) END SUBROUTINE get_var_r1 SUBROUTINE get_var_r2(var_name,var,found) IMPLICIT NONE CHARACTER(LEN=*),INTENT(IN) :: var_name REAL,INTENT(OUT) :: var(:,:) LOGICAL,OPTIONAL,INTENT(OUT) :: found CALL Get_var_rgen(var_name,var,size(var),found) END SUBROUTINE get_var_r2 SUBROUTINE get_var_r3(var_name,var,found) IMPLICIT NONE CHARACTER(LEN=*),INTENT(IN) :: var_name REAL,INTENT(INOUT) :: var(:,:,:) LOGICAL,OPTIONAL,INTENT(OUT) :: found CALL Get_var_rgen(var_name,var,size(var),found) END SUBROUTINE get_var_r3 SUBROUTINE Get_var_rgen(var_name,var,var_size,found) USE netcdf, ONLY: nf90_noerr,nf90_get_var,nf90_inq_varid USE dimphy USE lmdz_grid_phy USE lmdz_phys_para IMPLICIT NONE CHARACTER(LEN=*) :: var_name INTEGER :: var_size REAL :: var(var_size) LOGICAL,OPTIONAL :: found LOGICAL :: tmp_found INTEGER :: varid INTEGER :: ierr IF (is_mpi_root .AND. is_omp_root) THEN ierr=nf90_inq_varid(nid_start,var_name,varid) IF (ierr==nf90_noerr) THEN ierr=nf90_get_var(nid_start,varid,var) IF (ierr/=nf90_noerr) THEN PRINT*, 'phyetat0: Lecture echouee pour <'//var_name//'>' CALL abort_physic("", "", 1) ENDIF tmp_found=.TRUE. ELSE tmp_found=.FALSE. ENDIF ENDIF CALL bcast(tmp_found) IF (tmp_found) THEN CALL bcast(var) ENDIF IF (PRESENT(found)) THEN found=tmp_found ELSE IF (.NOT. tmp_found) THEN PRINT*, 'phyetat0: La variable champ <'//var_name//'> est absente' CALL abort_physic("", "", 1) ENDIF ENDIF END SUBROUTINE Get_var_rgen SUBROUTINE open_restartphy(filename) USE netcdf, ONLY: nf90_create,nf90_clobber,nf90_64bit_offset,nf90_noerr,nf90_strerror,& nf90_global,nf90_put_att,nf90_def_dim USE lmdz_phys_para, ONLY: is_master USE lmdz_grid_phy, ONLY: klon_glo USE dimphy, ONLY: klev, klevp1 USE lmdz_print_control, ONLY: lunout IMPLICIT NONE CHARACTER(LEN=*),INTENT(IN) :: filename INTEGER :: ierr IF (is_master) THEN ierr = nf90_create(filename, IOR(nf90_clobber,nf90_64bit_offset), & nid_restart) IF (ierr/=nf90_noerr) THEN WRITE(lunout,*)'open_restartphy: problem creating file '//trim(filename) WRITE(lunout,*)trim(nf90_strerror(ierr)) CALL abort_physic("open_restartphy", trim(nf90_strerror(ierr)), 1) ENDIF ierr = nf90_put_att (nid_restart, nf90_global, "title","Fichier redemmarage physique") ierr = nf90_def_dim (nid_restart, "index", length, idim1) ierr = nf90_def_dim (nid_restart, "points_physiques", klon_glo, idim2) ierr = nf90_def_dim (nid_restart, "horizon_vertical", klon_glo*klev, idim3) ierr = nf90_def_dim (nid_restart, "horizon_klevp1", klon_glo*klevp1, idim4) ! ierr = nf90_enddef(nid_restart) ENDIF END SUBROUTINE open_restartphy SUBROUTINE enddef_restartphy USE netcdf, ONLY: nf90_enddef USE lmdz_phys_para IMPLICIT NONE INTEGER :: ierr IF (is_master) ierr = nf90_enddef(nid_restart) END SUBROUTINE enddef_restartphy SUBROUTINE close_restartphy USE netcdf, ONLY: nf90_close USE lmdz_phys_para IMPLICIT NONE INTEGER :: ierr IF (is_master) ierr = nf90_close (nid_restart) END SUBROUTINE close_restartphy SUBROUTINE put_field_r1(pass, field_name,title,field) IMPLICIT NONE INTEGER, INTENT(IN) :: pass CHARACTER(LEN=*),INTENT(IN) :: field_name CHARACTER(LEN=*),INTENT(IN) :: title REAL,INTENT(IN) :: field(:) CALL put_field_rgen(pass, field_name,title,field,1) END SUBROUTINE put_field_r1 SUBROUTINE put_field_r2(pass, field_name,title,field) IMPLICIT NONE INTEGER, INTENT(IN) :: pass CHARACTER(LEN=*),INTENT(IN) :: field_name CHARACTER(LEN=*),INTENT(IN) :: title REAL,INTENT(IN) :: field(:,:) CALL put_field_rgen(pass, field_name,title,field,size(field,2)) END SUBROUTINE put_field_r2 SUBROUTINE put_field_r3(pass, field_name,title,field) IMPLICIT NONE INTEGER, INTENT(IN) :: pass CHARACTER(LEN=*),INTENT(IN) :: field_name CHARACTER(LEN=*),INTENT(IN) :: title REAL,INTENT(IN) :: field(:,:,:) CALL put_field_rgen(pass, field_name,title,field,size(field,2)*size(field,3)) END SUBROUTINE put_field_r3 SUBROUTINE put_field_rgen(pass, field_name,title,field,field_size) USE netcdf, ONLY: nf90_def_var,nf90_put_att,nf90_inq_varid,nf90_put_var USE lmdz_cppkeys_wrapper, ONLY: nf90_format USE dimphy USE lmdz_geometry USE lmdz_grid_phy USE lmdz_phys_para IMPLICIT NONE INTEGER, INTENT(IN) :: pass CHARACTER(LEN=*),INTENT(IN) :: field_name CHARACTER(LEN=*),INTENT(IN) :: title INTEGER,INTENT(IN) :: field_size REAL,INTENT(IN) :: field(klon,field_size) ! REAL :: field_glo(klon_glo,field_size) ! REAL :: field_glo_tmp(klon_glo,field_size) REAL ,ALLOCATABLE :: field_glo(:,:) REAL ,ALLOCATABLE :: field_glo_tmp(:,:) INTEGER,ALLOCATABLE :: ind_cell_glo_glo(:) ! INTEGER :: ind_cell_glo_glo(klon_glo) INTEGER :: ierr,i INTEGER :: nvarid INTEGER :: idim ! first pass : definition IF (pass==1) THEN IF (is_master) THEN IF (field_size==1) THEN idim=idim2 ELSE IF (field_size==klev) THEN idim=idim3 ELSE IF (field_size==klevp1) THEN idim=idim4 ELSE PRINT *, "erreur phyredem : probleme de dimension" CALL abort_physic("", "", 1) ENDIF ! ierr = nf90_redef (nid_restart) ierr = nf90_def_var (nid_restart, field_name, nf90_format,(/ idim /),nvarid) IF (LEN_TRIM(title) > 0) ierr = nf90_put_att (nid_restart,nvarid,"title", title) ! ierr = nf90_enddef(nid_restart) ENDIF ! second pass : write ELSE IF (pass==2) THEN IF (is_master) THEN ALLOCATE(ind_cell_glo_glo(klon_glo)) ALLOCATE(field_glo(klon_glo,field_size)) ALLOCATE(field_glo_tmp(klon_glo,field_size)) ELSE ALLOCATE(ind_cell_glo_glo(0)) ALLOCATE(field_glo_tmp(0,0)) ENDIF CALL gather(ind_cell_glo,ind_cell_glo_glo) CALL gather(field,field_glo_tmp) IF (is_master) THEN DO i=1,klon_glo field_glo(ind_cell_glo_glo(i),:)=field_glo_tmp(i,:) ENDDO ierr = nf90_inq_varid(nid_restart, field_name, nvarid) ierr = nf90_put_var(nid_restart,nvarid,RESHAPE(field_glo,(/klon_glo*field_size/))) ENDIF ENDIF END SUBROUTINE put_field_rgen SUBROUTINE put_var_r0(pass, var_name,title,var) IMPLICIT NONE INTEGER, INTENT(IN) :: pass CHARACTER(LEN=*),INTENT(IN) :: var_name CHARACTER(LEN=*),INTENT(IN) :: title REAL,INTENT(IN) :: var REAL :: varin(1) varin(1)=var CALL put_var_rgen(pass, var_name,title,varin,size(varin)) END SUBROUTINE put_var_r0 SUBROUTINE put_var_r1(pass, var_name,title,var) IMPLICIT NONE INTEGER, INTENT(IN) :: pass CHARACTER(LEN=*),INTENT(IN) :: var_name CHARACTER(LEN=*),INTENT(IN) :: title REAL,INTENT(IN) :: var(:) CALL put_var_rgen(pass, var_name,title,var,size(var)) END SUBROUTINE put_var_r1 SUBROUTINE put_var_r2(pass, var_name,title,var) IMPLICIT NONE INTEGER, INTENT(IN) :: pass CHARACTER(LEN=*),INTENT(IN) :: var_name CHARACTER(LEN=*),INTENT(IN) :: title REAL,INTENT(IN) :: var(:,:) CALL put_var_rgen(pass, var_name,title,var,size(var)) END SUBROUTINE put_var_r2 SUBROUTINE put_var_r3(pass, var_name,title,var) IMPLICIT NONE INTEGER, INTENT(IN) :: pass CHARACTER(LEN=*),INTENT(IN) :: var_name CHARACTER(LEN=*),INTENT(IN) :: title REAL,INTENT(IN) :: var(:,:,:) CALL put_var_rgen(pass, var_name,title,var,size(var)) END SUBROUTINE put_var_r3 SUBROUTINE put_var_rgen(pass, var_name,title,var,var_size) USE netcdf, ONLY: nf90_def_var,nf90_put_var,nf90_inq_varid,nf90_put_att USE lmdz_cppkeys_wrapper, ONLY: nf90_format USE dimphy USE lmdz_phys_para IMPLICIT NONE INTEGER, INTENT(IN) :: pass CHARACTER(LEN=*),INTENT(IN) :: var_name CHARACTER(LEN=*),INTENT(IN) :: title INTEGER,INTENT(IN) :: var_size REAL,INTENT(IN) :: var(var_size) INTEGER :: ierr INTEGER :: nvarid IF (is_master) THEN IF (var_size/=length) THEN PRINT *, "erreur phyredem : probleme de dimension" CALL abort_physic("", "", 1) ENDIF ! first pass : definition IF (pass==1) THEN ! ierr = nf90_redef (nid_restart) ierr = nf90_def_var (nid_restart, var_name, nf90_format,(/ idim1 /),nvarid) IF (LEN_TRIM(title)>0) ierr = nf90_put_att (nid_restart,nvarid,"title", title) ! ierr = nf90_enddef(nid_restart) ! second pass : write ELSE IF (pass==2) THEN ierr = nf90_inq_varid(nid_restart, var_name, nvarid) ierr = nf90_put_var(nid_restart,nvarid,var) ENDIF ENDIF END SUBROUTINE put_var_rgen END MODULE iostart